首页 > 编程问答 >pySerialTransfer 双向通信问题

pySerialTransfer 双向通信问题

时间:2024-07-21 00:49:34浏览次数:8  
标签:python arduino serial-port serial-communication

我编写了一个最小的双向 python 和串行通信脚本,将整数发送到 arduino。然后,arduino 递增整数并通过串行将其发送回。

comm.py

from time import sleep
from pySerialTransfer import pySerialTransfer as txfer


class struct:
    control = 0

class receivestruct:
    status = 0


if __name__ == '__main__':
    try:
        testStruct = struct
        rstruct =receivestruct 
        link = txfer.SerialTransfer('COM7')
        
        link.open()
        sleep(2)
        
        counter = 0
    
        while True:
            sendSize = 0
            
            testStruct.control = counter
            
            sendSize = link.tx_obj(testStruct.control, start_pos=sendSize)
            
            link.send(sendSize)

            print('sent')
            #sleep(0.5)

            read_correctly = False
            while (read_correctly == False):
                try:
                    if not (link.available()):
                        pass

                    recSize = 0
                    # this section returns errors with can't read str as int 
                    rstruct.status = link.rx_obj(obj_type='i', start_pos=recSize)
                    counter = rstruct.status
                    recSize += txfer.STRUCT_FORMAT_LENGTHS['i']

                    print(rstruct.status)
                    read_correctly = True
                except:
                    pass

        
    except KeyboardInterrupt:
        link.close()

arduino.ino

#include "SerialTransfer.h"


SerialTransfer myTransfer;

uint32_t rcontrol;

uint32_t control;

void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}

void loop()
{
  if(myTransfer.available())
  {
    // use this variable to keep track of how many
    // bytes we've processed from the receive buffer
    uint16_t recSize = 0;

    recSize = myTransfer.rxObj(rcontrol, recSize);


    control = rcontrol + 1;
    uint16_t sendSize = 0;


    sendSize = myTransfer.txObj(control, sendSize);

    myTransfer.sendData(sendSize);
    
  }
}

现在,我认为这可以正常工作。然而,这里是控制台日志,似乎 python 没有正确读取增量值,并且每 n 次尝试才读取正确的增量值:

115
sent
115
sent
116
sent
116
sent
116
sent
116
sent
116
sent
116
sent
116
sent
116
sent
116
sent
117
sent
117
sent
117
sent
117
sent
117
sent
117
sent
117
sent
117
sent
117
sent
118
sent
118
sent
118
sent
118
sent
118
sent
118
sent
118
sent
118
sent
118
sent
119
sent
119
sent
119
sent
119
sent
119
sent
119
sent
119
sent
119
sent

我在这里尝试了 pySerialTransfer 的两种方式示例,但它似乎使用不再支持的库的过时版本。知道为什么我在双向串行通信中遇到这些问题吗?


问题出在 Python 脚本的接收循环中。你试图在每次循环迭代中读取数据,而无论数据是否可用,这会导致你读取旧数据或根本没有数据。

下面是改进后的 Python 脚本:

from time import sleep
from pySerialTransfer import pySerialTransfer as txfer


class struct:
    control = 0

class receivestruct:
    status = 0


if __name__ == '__main__':
    try:
        testStruct = struct
        rstruct = receivestruct
        link = txfer.SerialTransfer('COM7')

        link.open()
        sleep(2)

        counter = 0

        while True:
            sendSize = 0

            testStruct.control = counter

            sendSize = link.tx_obj(testStruct.control, start_pos=sendSize)

            link.send(sendSize)

            print(f'Sent: {counter}')

            # 等待数据可用
            while not link.available():
                pass

            recSize = 0

            # 读取数据
            rstruct.status = link.rx_obj(obj_type='i', start_pos=recSize)
            counter = rstruct.status
            recSize += txfer.STRUCT_FORMAT_LENGTHS['i']

            print(f'Received: {rstruct.status}')

    except KeyboardInterrupt:
        link.close()

改进说明:

  1. 等待数据可用: 在尝试读取数据之前,添加了一个 while not link.available(): pass 循环。这将确保只有在串行端口上有可用数据时才进行读取,从而避免读取到旧数据。

  2. 移除不必要的 try-except 块: 在接收循环中,你使用了一个 try-except 块来处理可能出现的错误。但是, link.rx_obj() 本身已经包含了错误处理机制,所以外部的 try-except 块是不必要的。

  3. 更清晰的打印语句: print('sent') print(rstruct.status) 改为更具描述性的 print(f'Sent: {counter}') print(f'Received: {rstruct.status}') ,以便更清晰地了解发送和接收的数据。

通过这些修改,你的 Python 脚本应该能够正确地接收 Arduino 发送的增量值,而不会出现重复或遗漏。

标签:python,arduino,serial-port,serial-communication
From: 78747462

相关文章

  • 从 python 中的字符串列表中提取 def 定义函数的标签
    我想使用Python中的正常def过程创建函数,并将标签分配给从字符串列表中提取的命名空间。如何实现这一点?这个问题的动机:我正在创建一个与sympy兼容的python函数库,供数学家用于符号计算实验。许多函数需要初始化具有相关标签的多个对象的系统,这些标签分别由用户提供的字......
  • 在 Raspberry Pi 4 上使用 Python 从具有 SPI 连接的 MT6816 磁性编码器读取
    我对这个领域完全陌生,并不真正知道自己在做什么并且需要帮助。我正在尝试使用MT681614位磁性编码器通过RaspberryPi的SPI连接读取绝对角度。我有以下问题:在硬件方面,是否只是简单地连接必要的连接(3.3V、MOSI、MISO、SCK、GND、CE01)?对于编码......
  • PythonW 不运行脚本。严重地
    因此,使用Windows10和Python3.6。我创建了一个.py脚本,它可以使用命令pythonmyscript.py在命令提示符下正常运行,但是当我制作该脚本的精确副本并为其赋予扩展名.pyw,并尝试使用pythonw运行它时命令pythonwmyscript.pyw,什么也没有发生......
  • 如何使用Python和Selenium模拟产品购买以获取库存信息
    我正在开发一项网络抓取服务,主要针对时尚行业。我的目标是提供有关产品的全面数据,包括库存水平。为了实现这一目标,我需要模拟购买以确定每种尺寸的产品的最大可用数量。我一直在使用Python和Selenium进行网络抓取部分,但在准确模拟购买方面面临着挑战检索股票信息的过程。......
  • 连接Python套接字的问题
    当我写“关闭”时,我试图让我的电报机器人关闭计算机。我不想将机器人连接到网站上的托管。我选择我的手机(AndroidRedmiNote10)作为托管。我在上面安装了Termux和Pydroid。我写了两个文件:main到我的电脑,client到我的手机。通过在计算机上运行这两个文件,一切正常。但是,当我在......
  • 如何修复导入 Numexpr Python 时的错误
    在Windows10Python3.7.9(IDLE)上,我成功安装了“pipinstallnumexpr”,但在“importnumexprasne”时出现错误:Traceback(最近一次调用):文件“<pyshell#21>”,第267行,位于将numexpr导入为ne文件“C:\Python379\lib\site-packages\numexpr_init_.py”......
  • 让 cpython 优化恒定条件
    我正在用Python编写需要尽可能高效运行的代码,但有时我需要深入挖掘调试语句。不要注释这些输入或输出(或者使用外部预处理器来处理代码,就像这里建议的那样Python相当于#ifdefDEBUG或这里如何在python中实现“#ifdef”?|||)我想在模块的开头定义一个变量......
  • 如何使用 for 循环在 python jupyter 笔记本中创建动态图?
    我正在学习本课关于用Python求解热方程。该课程指出,在求解热方程后,我们可以通过在循环中简单地调用pyplot.plot()来可视化解的动画图,其中下面的代码将动态绘制每次每个点的温度,从而得到一个动画情节(课程帖子中提供了动画情节的示例)。importnumpyfrommatplotlibi......
  • Python:动态爱心代码
    importrandomfrommathimportsin,cos,pi,logfromtkinterimport*CANVAS_WIDTH=640CANVAS_HEIGHT=480CANVAS_CENTER_X=CANVAS_WIDTH/2CANVAS_CENTER_Y=CANVAS_HEIGHT/2IMAGE_ENLARGE=11HEART_COLOR="#FF99CC"defcenter_......
  • 如何在 PYTHON 中查找输入数字的千位、百位、十位和个位中的数字?例如:256 有 6 个一、5
    num=int(input("Pleasegivemeanumber:"))print(num)thou=int((num//1000))print(thou)hun=int((num//100))print(hun)ten=int((num//10))print(ten)one=int((num//1))print(one)我尝试过这个,但它不起作用,我被困住了。代码几乎是正确的,但需......