agrobot_base/Python/bld300r/serial_test.py

205 lines
6.8 KiB
Python

import serial
import struct
import time
import crcmod
# Configuração da porta serial
ser = serial.Serial(
port='COM3', # Substitua pelo seu porto serial
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_TWO,
timeout=1
)
slave_address = 0x02 # Endereço do escravo
CodigosFuncoes = {
"GetParametro": 0x03,
"SetParametro": 0x06,
}
Parametros = {
"RPM_SP": 0x0056,
"RPM": 0x005F,
"Enabled": 0x0066,
"Breaked": 0x006A,
"Direction": 0x006D,
"AlarmeCode": 0x0076,
"NumPolos": 0x0086,
"Rampa": 0x008A,
"VelocidadeMaxAnalog": 0x0092,
"Current": 0x0096,
"ControleRS485": 0x00B6,
"Versao": 0x00BB,
"Voltage": 0x00C8,
"Temperature": 0x00D2
}
Parametros2 = {
"RPM_SP": (0x0056, 2),
"RPM": (0x005F, 2),
"Enabled": (0x0066, 2),
"Breaked": (0x006A, 2),
"Direction": (0x006D, 2),
"AlarmeCode": (0x0076, 2),
"NumPolos": (0x0086, 2),
"Rampa": (0x008A, 2),
"VelocidadeMaxAnalog": (0x0092, 2),
"Current": (0x0096, 4),
"ControleRS485": (0x00B6, 2),
"Versao": (0x00BB, 2),
"Voltage": (0x00C8, 4), # Exemplo de parâmetro que retorna 4 bytes
"Temperature": (0x00D2, 4) # Exemplo de parâmetro que retorna 4 bytes
}
def crc16(data: bytes):
crc = 0xFFFF
for pos in data:
crc ^= pos
for i in range(8):
if (crc & 1) != 0:
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return crc.to_bytes(2, byteorder='little')
def montar_comando(funcao, parametro, val):
function_code = CodigosFuncoes[funcao]
start_address = Parametros[parametro]
num_of_registers = val
command = bytearray([slave_address, function_code]) + start_address.to_bytes(2, byteorder='big') + num_of_registers.to_bytes(2, byteorder='big')
command += crc16(command)
return command
def enviar_comando(comando):
ser.write(comando)
time.sleep(0.1) # Pequena pausa para garantir o envio
resposta = ser.read(ser.inWaiting()) # Lê todos os dados disponíveis na porta
return resposta
def decifrar_resposta(resposta, funcao, parametro):
# Certifique-se de que a resposta é do tipo bytes
if isinstance(resposta, str):
resposta = bytes.fromhex(resposta)
resHex = resposta.hex()
#print(resposta)
#print(resposta.hex())
# Verifica o comprimento da resposta e o código da função
if len(resposta) >= 5 and resposta[1] == CodigosFuncoes[funcao]:
remetente = resposta[0]
# Extrai o número de bytes de dados
num_bytes = resposta[2]
# Verifica se o comprimento da resposta é consistente com o número de bytes de dados
if len(resposta) == 5 + num_bytes:
valor_raw = int.from_bytes(resposta[3:3 + num_bytes], byteorder='big')
valor = valor_raw # * 1 # Ajuste o fator de multiplicação conforme necessário
#print(f"Remetente: {remetente}, {parametro}: {valor}")
return (remetente, valor)
else:
print("Comprimento da resposta inconsistente com o número de bytes de dados.")
else:
print("Resposta inválida ou código de função incorreto.")
return (0, None)
def montar_comando_todos_parametros():
function_code = CodigosFuncoes["GetParametro"]
start_address = 0x0056
num_of_registers = 32
command = bytearray([slave_address, function_code]) + start_address.to_bytes(2, byteorder='big') + num_of_registers.to_bytes(2, byteorder='big')
command += crc16(command)
return command
def decifrar_resposta_todos_parametros(resposta):
# Certifique-se de que a resposta é do tipo bytes
if isinstance(resposta, str):
resposta = bytes.fromhex(resposta)
print(resposta.hex())
# Verifica o comprimento da resposta e o código da função
if len(resposta) >= 5 and resposta[1] == CodigosFuncoes["GetParametro"]:
remetente = resposta[0]
# Extrai o número de bytes de dados
num_bytes = resposta[2]
print(f"Remetente: {remetente}, num_Bytes: {num_bytes}")
# Verifica se o comprimento da resposta é consistente com o número de bytes de dados
if len(resposta) == 5 + num_bytes or True:
valores = {}
for parametro, (endereco, tamanho) in Parametros2.items():
offset = (endereco - 0x0056) * 2 + 3
if offset + tamanho <= len(resposta):
valor_raw = int.from_bytes(resposta[offset:offset + tamanho], byteorder='big')
valores[parametro] = valor_raw * 1 # Ajuste o fator de multiplicação conforme necessário
return (remetente, valores)
else:
print("Comprimento da resposta inconsistente com o número de bytes de dados.")
else:
print("Resposta inválida ou código de função incorreto.")
return (0, {})
try:
while True:
resultados = []
remetente = 0
res = enviar_comando(montar_comando("SetParametro", "ControleRS485", 1))
res = enviar_comando(montar_comando("SetParametro", "VelocidadeMaxAnalog", 500))
if (False):
for parametro in Parametros:
comando = montar_comando("GetParametro", parametro, 1)
res = enviar_comando(comando)
remetente, valor = decifrar_resposta(res, "GetParametro", parametro)
resultados.append((parametro, valor))
# Imprime todos os resultados em uma linha, separados por tabulações
linha_resultados = f"Remetente: {remetente}\t" + ("\t".join(f"{parametro}: {valor}" for parametro, valor in resultados))
print(linha_resultados)
d = 0
if (True):
if (d == 0):
d = 1
else:
d = 0
time.sleep(1)
res = enviar_comando(montar_comando("SetParametro", "Enabled", 1))
print(res.hex())
time.sleep(0.1)
res = enviar_comando(montar_comando("SetParametro", "Direction", d))
print(res)
time.sleep(0.1)
res = enviar_comando(montar_comando("SetParametro", "RPM_SP", 250))
print(res.hex())
time.sleep(5)
res = enviar_comando(montar_comando("SetParametro", "RPM_SP", 0))
print(res.hex())
time.sleep(1)
res = enviar_comando(montar_comando("SetParametro", "Enabled", 0))
print(res.hex())
time.sleep(1)
time.sleep(1)
except KeyboardInterrupt:
res = enviar_comando(montar_comando("SetParametro", "RPM_SP", 0))
print(res.hex())
time.sleep(0.1)
res = enviar_comando(montar_comando("SetParametro", "Enabled", 0))
print("Programa encerrado pelo usuário")
finally:
ser.close()