【问题标题】:Sending hex over serial with python使用python通过串行发送十六进制
【发布时间】:2013-03-22 12:37:29
【问题描述】:

这个周末我要做一个小项目。有一个太阳能电池逆变器(Danfoss ULX 3600i),我将尝试连接到我的 linux 机器,看看我是否可以从中获取数据,例如为统计数据创造了多少能量。上面有一个RJ45连接的输入,但是是RS485的。

我得到了通过电脑上的 USB 端口连接它的电缆,电脑和逆变器之间有一个 RS485 转换器。

然后我正在编写一个小的 python 代码来发出请求。但是我不知道如何正确发送数据。

import serial
import struct

ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=19200,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS
)

print(ser.isOpen())
thestring = "7E FF 03 00 01 00 02 0A 01 C8 04 D0 01 02 80 00 00 00 00 8E E7 7E"
data = struct.pack(hex(thestring))
#data = struct.pack(hex, 0x7E, 0xFF, 0x03, 0x00, 0x01, 0x00, 0x02, 0x0A, 0x01, 0xC8,      0x04, 0xD0, 0x01, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xE7, 0x7E)

ser.write(data)
s = ser.read(1)
print(s)
ser.close()

逆变器正在使用丹佛斯 ComLynx 协议(page 26 上是我要发送的数据):

编辑: 我现在可以发送请求,因为 Adam 4520 RS485 转换器上的 LED 灯闪烁一次,但是没有返回数据,但是当我在终端中执行 CTRL+C 时出现此错误:

dontommy@dtbeast:~/workspace/python_scripting/src$ ./sollar.py 
True
^CTraceback (most recent call last):
  File "./sollar.py", line 30, in <module>
    s = ser.readline().decode('utf-8')
  File "/usr/local/lib/python3.2/dist-packages/serial/serialposix.py", line 446, in read
    ready,_,_ = select.select([self.fd],[],[], self._timeout)
KeyboardInterrupt

【问题讨论】:

    标签: python usb hex rs485


    【解决方案1】:

    将“字符串”改写为

    thestring = "\x7E\xFF\x03\x00\x01\x00\x02\x0A\x01\xC8\x04\xD0\x01\x02\x80\x00\x00\x00\x00\x8E\xE7\z7E"
    

    你不需要打包,你可以说data=thestring然后发送。这只有在文档中的各种 id 与您设备上的完全匹配时才有效

    你需要弄清楚 python "struct" 是如何工作的,如何编码二进制以及如何将两个 4 位值放入一个 8 位字节中:线索,参见 >>和 运算符和结构包“B”格式

    【讨论】:

      【解决方案2】:

      在确定以下方案之前,我尝试了多种方案将十六进制字符的命令字符串转换为在 UART 远端被识别为十六进制的字节。我选择一次发送一个字节的字符串,因为远端一次不能处理超过四个字节,所以我无法发送整个字符串。单个 hex_byte 的格式类似于 C 中的 sprintf。

      import time
      import serial
      import sys
      import binascii
      import inspect
      
      
      # This function takes a command string and sends individual bytes.
      # It also reports the response.
      def send_command(cmd_name, cmd_string):
          print ("\ncmd_name:", cmd_name)
          print ("cmd_string:", cmd_string)
          cmd_bytes = bytearray.fromhex(cmd_string)
          for cmd_byte in cmd_bytes:
              hex_byte = ("{0:02x}".format(cmd_byte))
              #print (hex_byte)
              ser.write(bytearray.fromhex(hex_byte))
              time.sleep(.100)
      
          # wait an extra 3 seconds for DISP_ON_CMD
          if cmd_name == "DISP_ON_CMD":
              time.sleep(5.0)
          response = ser.read(32)
          print ("response:", binascii.hexlify(bytearray(response)))
          return
      
      # Code to put processor into factory mode.
      comm_init='c4c4'
      # Here's the list of command strings, captured as tuples.
      # The 16-bit Data and Msg CRCs are calculated via gen_crc.exe.
      heart_beat_cmd=      ("HEART_BEAT_CMD",      'a5a50a00010000003e1b')
      

      这是我在 Python 3.4.5 窗口中看到的内容。

      cmd_name: HEART_BEAT_CMD

      cmd_string: a5a50a00010000003e1b

      回复:b'a5a51a002a0054373031763200000c08201e0a040000e389f86b'

      我从来没有把输出解析成字节,但那将是一个很好的补充。

      【讨论】:

        【解决方案3】:

        免责声明:我对 python 和串口编程都很陌生。我知道这是一个非常古老的问题,可能已经解决了,但我想做我的一部分(我猜),也许在这个过程中学习!我知道关于 KeyboardInterrupt 问题第二部分的答案(或者至少我认为我知道。)所以这里是

        KeyboardInterrupt 基本上是当用户在程序仍在运行时点击“Control+C”。这使得程序停在它当时正在执行的那一行。因此

        File "./sollar.py", line 30, in <module>
            s = ser.readline().decode('utf-8')
        File "/usr/local/lib/python3.2/dist-packages/serial/serialposix.py", line 446, in read
            ready,_,_ = select.select([self.fd],[],[], self._timeout)
        

        因为那是它停止的地方(希望我是对的。)为避免这种情况,您可以使用“try.. except”

        while True:
            try:
                # your main code here
                break
            except KeyboardInterrupt:
                print("User interrupt encountered. Exiting...")
                time.sleep(3)
                exit()
            except:
                # for all other kinds of error, but not specifying which one
                print("Unknown error...")
                time.sleep(3)
                exit()
        

        这基本上可以帮助您以一种相当“干净的方式”退出程序。希望对您有所帮助。

        【讨论】:

          猜你喜欢
          • 2016-04-06
          • 1970-01-01
          • 1970-01-01
          • 2021-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-05
          • 2015-07-25
          相关资源
          最近更新 更多