205 lines
6.8 KiB
Python
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()
|