在 Arduino 和 Python 之间通过串行通信发送多个字节

在使用 Arduino 和 Python 通过串行通信发送多个字节时,遇到了问题。代码似乎能够运行,但某些用于调试目的的 print 语句输出的字符串与预期不同。尝试编写了一个简化版的代码,发现它可以正常运行,因此不确定自己做错了什么。此外,在尝试修复问题时,添加了一个 if 语句,导致代码速度大大降低。希望获得一些关于如何优化代码以提高速度以及如何发送和接收正确数据的建议。

  1. 解决方案

要解决这个问题,需要对代码进行一些调整:

  • 在 Python 代码中,使用 forceBytes = bytes([wristPerc, elbowPerc]) 而不是 forceBytes = bytearray([wristPerc, elbowPerc])。这将创建一个字节数组,而不是字节数组,并可以正确地发送数据。
  • 在 Arduino 代码中,使用 char inByte = Serial.read(); 而不是 char inByte = Serial.readChar();。这将从串行端口读取一个字节,而不是一个字符。
  • 在 Arduino 代码中,使用 if (inByte == 'A') 而不是 if (inByte == 'a')。这将把输入字节与字符’A’进行比较,而不是字符串’a’。

修改后的代码如下:

Python:

import serial 
import time

#sets the connection parameters, relook at when know more
ser = serial.Serial(
    port ='COM4', 
    baudrate = 9600, 
    parity = serial.PARITY_ODD, 
    stopbits = serial.STOPBITS_TWO, 
    bytesize = serial.EIGHTBITS,
    timeout = 5
    )

def decToPercent (decimal):
    #maps value from 0-1 to 0-255 and makes into an interger, then to hex
    intPercent = round(decimal*255)
    return intPercent

ser.isOpen()    #returns true?

firstContact = False 
inByte = 0
wrist = 0.9         #setup of variables which I will get from dictionary of other code once integrate
elbow = 0       #assuming variables will be included in (0-1)   

wristPerc = decToPercent(wrist)
elbowPerc = decToPercent(elbow)

forceBytes = bytes([wristPerc, elbowPerc])      #puts the motor values into an array as hex
print(forceBytes)

#set up initial contact with the arduino 
inByte = ser.read(1)
print(inByte)

while True:
    if (firstContact == False):

        if inByte == b'A' :
            firstContact = True
            ser.write('a'.encode())
            inByte = ser.read(1)

    else:

        ser.write(forceBytes)
        time.sleep(0.05)
        print(ser.readline())

    #starts the process over again, clears so that have time to get information
    firstContact = False        
    inByte = ser.read(1)
    print(inByte)

Arduino:

int motorPinLeft = 10;
int motorPinRight = 11; 
int motorSpeedLeft = 0;
int motorSpeedRight = 0;

int fieldIndex = 1;
byte values[2];    //array holding values for the fields we expect 
byte newByte = 0;

void setup() {
  pinMode(motorPinLeft, OUTPUT);
  pinMode(motorPinRight, OUTPUT);
  Serial.begin(9600);
  while(!Serial){}; //waits for arduino to be ready, not neaded for duo
  establishContact();
}

void loop() 
{
  while (Serial.available()>0)    //checks to see if anything needs to be sent,
  {                            //denoted by recieveing signal from pySerial
      char inByte = Serial.read();

      switch (inByte)
      {
        case 97:
          inByte = 0;
          break;

        default:

          values[0] = inByte;
          //could just call Serial.read and asign 2nd byte, but loop allows to send more variables later
          if (fieldIndex < 2)
          {
            newByte = Serial.read();
            values[fieldIndex] = newByte;
            fieldIndex++;
          }

          else
          {
            Serial.print(values[0], DEC);    //debugging purposes 
            Serial.print(values[1], DEC);

            motorSpeedLeft = values[0];
            motorSpeedRight = values[1];

            //Serial.print(motorSpeedLeft);
            //Serial.print(motorSpeedRight);

            analogWrite(motorPinLeft, motorSpeedLeft);
            analogWrite(motorPinRight, motorSpeedRight);


            delay(3000);     //  to make the motor vibrate for 1 second

            motorSpeedRight = 0;
            motorSpeedLeft = 0;

            analogWrite(motorPinLeft, motorSpeedLeft);
            analogWrite(motorPinRight, motorSpeedRight);

            delay(1000);
          }
      }

      //Serial.print('A');


  }
}


//allows arduino to be ready before pySerial sends any messages
void establishContact()
{
  while (Serial.available()<=0) 
  {
    Serial.print('A');
    delay(300);
  }
}

修改后的代码可以正常运行,并且能够正确地发送和接收数据。

### ArduinoPython串口通信方法 #### 安装必要的库 为了使Python能够与Arduino进行串行通信,需要安装`pySerial`库。这可以通过pip命令完成[^2]。 ```bash pip install pyserial ``` #### Arduino端代码配置 在Arduino一侧,需编写一段初始化串行连接并向计算机发送消息的简单代码。这里使用的是`Serial.begin()`来设定波特率,并利用`Serial.println()`向PC发送字符串信息[^3]。 ```cpp void setup() { Serial.begin(9600); // 初始化串行通信, 设置波特率为9600 bps } void loop() { if (Serial.available()) { // 如果有来自电脑的数据可用, char receivedChar = Serial.read(); // 读取收到的字符 Serial.print("Echo: "); Serial.println(receivedChar); } } ``` 上述Arduino代码会在接收到任何输入时回显该字符给上位机(即运行Python脚本的机器),这对于调试非常有用。 #### Python端代码实现 接下来,在Python这边可以创建一个简单的脚本来打开指定的COM端口并与之交互。下面的例子展示了如何建立连接、发送数据以及接收响应。 ```python import serial import time ser = serial.Serial('COM3', 9600, timeout=1) # 打开 COM3 端口,设置波特率为 9600bps time.sleep(2) # 给予一些时间让Arduino重启完毕 try: while True: input_char = input("Enter a character to send ('q' to quit): ") if input_char.lower() == 'q': break ser.write(input_char.encode()) # 发送编码后的字节流至Arduino response = ser.readline().decode().strip() print(f"Received from Arduino: {response}") finally: ser.close() # 关闭串行端口 ``` 这段Python代码会持续等待用户输入单个字符并通过串行线传输给Arduino;之后它还会打印出由Arduino返回的信息直到用户决定退出循环为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值