【问题标题】:Serial missing data in RPI3 using Python使用 Python 在 RPI3 中串行丢失数据
【发布时间】:2019-07-08 17:43:19
【问题描述】:

我正在使用树莓派 3 和此代码向设备发送请求并接收来自的响应。

#!/usr/bin/python3.7    

import socket               # Import socket module
import thread
import time
import serial

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

input = '5A03010d0a75'    
print "Sending request... "+input
ser.write(input.decode("hex"))
print "Request sent."

output=""
while True:
  output += ser.read(1)
  #time.sleep(0.1)
  print "Reading... "+output.encode('hex')

它处理响应但缺少字节,它应该接收一个 56 字节长度的字符串而不是 53。

这是输出:

a5030119010000010001000a20120118180130090100020505030117501701051421000301040120010516039833630004060104c200007d

缺少 3 个字节

串行配置是制造商在文档中所说的。 此设备与我在 Delphi 中制作的其他应用程序配合得很好。

额外 这是我的 delphi 应用程序和这个 py 脚本的比较:

Delphi app
A5030119010000010001000A20120118180130090100020505030117501701051421000301040120010516039833630004060104C200007D
Python script
a503011901000001000100    1201181801300901000205050301175017010514210003010401  010516039833630004060104c200007d

【问题讨论】:

  • 如果您一次读取缓冲区中的所有内容而不是 1 个字节(从 serial.read(1) 中删除 1)会发生什么?那么在你的端口实例化中设置一个超时呢?
  • 我最好的猜测是您的打印速度减慢了循环速度,足以填充缓冲区,并且在某些迭代中它会溢出并丢弃数据。您是否尝试过仅在循环结束时打印?
  • 第一个想法,相同的输出,第二个想法使用while ser.inWaiting() > 0:并打印出循环,结果相同
  • 另外,更新到 py 3.7
  • 您的 Delphi 代码是否使用了某种流控制?你用的是什么驱动程序?你知道它的缓冲区大小吗?

标签: python linux serial-port raspberry-pi3


【解决方案1】:

解决方案是将最大字节设置为 serial.read() 方法 这应该与设备工作行为有关

#!/usr/bin/python3.7
#sudo python /home/testing.py

import serial
import time


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

input = '5A03010d0a75'    
print "Sending request... "+input
ser.write(input.decode("hex"))
print "Request sent."

output=""
time.sleep(1)
while ser.inWaiting() > 0:
  output += ser.read(10) #setting it to 10 will fix this problem

print "Reading... "+output.encode('hex')

【讨论】:

  • 这是我上面的first 建议。连同我的second 删除print 的技巧一起减少了计算开销,足以避免RX 缓冲区溢出。可能是一个意见问题,但我认为这里的大多数人都会同意,在这些情况下,您至少应该总是提及有用的 cmets。也许我太客气了,但对我来说,正确的方法,在这种情况下,应该是邀请有帮助的 cmets 的发起者先写一个答案。
  • 礼貌行为的一些例子:123
  • 对不起,如果我听起来很粗鲁,这不是我的意图,但我不知道你的第一个建议如何等同于这个答案,关于第二个,即使我把打印放在里面它有效,问题是设置最大字节,我仍在调查原因,但有效。无论如何,我当然感谢你的帮助。亲切的问候
  • 对不起,马丁,你是 100% 正确的,我太快下结论了。当您要求读取 10 个字节而不是 1 个字节时,您的代码工作的原因是您减少了很多开销(在这种情况下,循环上没有做任何事情的迭代次数,只是浪费时间)。我上面的第一条评论是朝那个方向写的,但实际上我错了,因为serial.read(1)serial.read() 完全相同。我错误地认为serial.read() 的意思是读取 RX 缓冲区中可用的尽可能多的数据。请接受我的道歉。
  • 如果您想改进您的代码,您可以将ser.read(10) 替换为ser.read(ser.inWaiting())。这应该读取 RX 缓冲区中可用的所有数据,将 while 循环上的迭代减少到最低限度。这就是我应该在上面的评论中写的。
猜你喜欢
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多