我有一个 RPi (是的,我知道,也许有人认为这属于 RPi 站点,但我认为它通常与 Linux 相关,所以 StackOverflow 是正确的地方) 并且我'我使用 Python3 和 pySerial 通过 MAX485 在一些 Arduinos 之间进行通信.这或多或少是有效的,因为我发现我需要做一些奇怪的解决方法才能让一切“正常”工作。
如果我发送数据:
GPIO.output(23, 1) # Pulling transmit pin high to send
comport.write("Some data".encode()) # Writing data
comport.flush() # Flushing the buffer
GPIO.output(23, 0) # Pulling pin down to receive
Arduino 收到数据并立即响应,但由于 pySerial 不知何故还没有准备好,它什么也没有返回,我们有一个丢失的数据包。
但是,如果我这样尝试:
GPIO.output(23, 1)
comport.write("Some data".encode())
time.sleep(.001) # Add some delay of only 1ms
comport.flush()
GPIO.output(23, 0)
然后数据被发送和接收。这让我想到了一个问题:flush 命令是否正常工作?我尝试这样做:
GPIO.output(23, 1)
comport.write("Some data".encode())
time.sleep(.001) # Add some delay
# -- No flush --
GPIO.output(23, 0)
令人惊讶的是它也有效。似乎 sleep “取代”了 flush 命令。
为什么 pySerial 的缓冲区没有刷新?我知道,这可能是一种方法,但sleep 只会添加一段(通常)不必要的代码,导致整个代码等待(超过 500 行)并且这不是很好。
我已经在网上搜索过了,有人说是 USB TTL Adapter 不支持 flushing(这里不是这种情况,这个是板载的),其他人说可能是 Linux 内核错误,所以对我来说没有任何意义。
如果有人可以解释为什么 flush 命令不起作用以及如何让它起作用(如果有办法的话),我和这个问题的 future 访问者可能会非常高兴。
最佳答案
您没有具体说明,但我认为假设您在半双工模式下使用 MAX485 是公平的。如果是这种情况,那么您尝试做的事情将无法可靠地工作。
问题是什么?
半双工通信使用 same pair of wires向任一方向传输。但是一次只有一端可以传输。因此,这需要某种方式来协调当前传输的人员。
我相信你对这里的问题有一个很好的总结:
the Arduino receives the data and responds imediately, but because pySerial is somehow not ready yet, it becomes nothing back and there we have a lost packet.
然而,不是 PySerial 没有准备好,而是您的 MAX485 和 GPIO-23 的状态。
一切都在时机
这是从 Moxa 的一篇优秀技术说明中抄录的图片在半双工 485 上,标题为 The Secrets of RS-485 Half-duplex Communication
这张图片显示您需要在适当的时候更改 GPIO-23(这张图片中的 MASTER-RTS)的状态,否则您的通信将失败。该技术说明值得完整阅读,我相信很好地描述了您面临的挑战。
我该如何解决?
答案是,视情况而定。您的问题可能是太早或太晚切换 GPIO-23。如果可能,最简单但性能最低的方法是让您的 Arduino 在响应之前等待一段时间。这将允许您sleep() 一段时间以确保您的数据包已完成传输,然后在 Arduino 开始响应之前切换 GPIO-23 的状态。
如果此解决方案不可行或不可取,那么您将需要研究其他驱动 GPIO-23 的方法。在 SW 中还有很多其他方法可以做到这一点,有些方法会比其他方法更好。但请注意,仅使用 python 代码切换 GPIO-23 线永远不会 100% 可靠。如果需要高可靠性,几乎肯定需要某种硬件辅助。
最后一点,除非需要 RS-485,否则您可以考虑使用 RS-422 或什至 RS-232 的全双工。
关于linux - 串行端口未正确刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43681253/
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
我在OSX上(如果重要的话)。如果我使用RVM安装Ruby,它会默认将Bundler安装到@globalgemset假设我想要一个不同版本的bundler。我假设我需要做的就是执行geminstallbundler--version但是,这会将bundler安装到默认gemset并且RVM不会为其设置路径。因此,如果我键入bundler,它仍会启动一个与Ruby一起安装到@global中的bundler两个问题:如何将bundler安装到@globalgemset。将bundler安装到@globalgemset中的模式是否正确,或者我遗漏了什么 最佳答案
什么Ruby或RailsDSL会将字符串"mccdougal"格式化为"McDougal",同时留下字符串"McDougal"原样?将titleize传递给"McDougal"结果如下:"McDougal".titleize#=>"McDougal" 最佳答案 据我所知,没有可以处理这种情况的Rails助手。这是一个非标准的边缘案例,需要特殊处理。但是,您可以创建自定义字符串变形。您可以将这段代码放入初始化程序中:ActiveSupport::Inflector.inflections(:en)do|inflect|inflect.
我的一个模型中有一个名为sui的字段。它代表“标准用户标识符”。当该字段出现验证错误时,Rails会打印“Suiisrequired”或“Suiisalreadytaken”。如何告诉Rails'sui'.titleize是“SUI”?我查看了Inflector.human,但这并不完全正确。 最佳答案 在这种情况下,我使用custom_err_msg插入。安装后,您可以提供如下自定义错误消息:validates_presence_of:sui,:message=>'^SUIisrequired'当您将^放在开头时,Rails不会输
我有很多模型和关系。由于这个事实,在View/Controller中有很多调用,看起来像这样:@object.something.with_something.value链的某些部分最终可能为零,这完全没问题。检查终端对象是否存在的正确/干净/快速的方法是什么?正在调用类似的东西:@object.something.with_something.valueifdefined?@object.something.with_something.value还可以吗? 最佳答案 在本地,您需要使用&&运算符(不是defined?),但这很快
我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)