【问题标题】:Reading bytes from Arduino using Python使用 Python 从 Arduino 读取字节
【发布时间】:2020-11-18 13:52:34
【问题描述】:

我正在尝试在 Python 中从 Arduino 读取串行输入。我正在尝试做一个简单的任务 - 我的 Arduino 有一个按钮写入串行其状态。这是 Arduino 的代码:

const int ledPin = 7;
const int buttonPin = 2;
int buttonState= 0;
void setup() {
  Serial.begin(9600); 
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {
 buttonState = digitalRead(buttonPin);
 if(buttonState == LOW){ digitalWrite(ledPin, HIGH);} else digitalWrite(ledPin, LOW);
  Serial.println(buttonState); 
  delay(50);
}

在 Arduino 1.8.13 软件中使用串行监视器,我可以看到它打印 0 或 1。

我正在尝试用 Python 中的以下代码阅读它:

import serial

ser = serial.Serial('COM10', baudrate = 9600, timeout = 1)
 
t = 0
while t<10:
    arduinoData = ser.readline().decode()
    print(arduinoData)
    t+=1
print(type(arduinoData))
ser.close()

我读取了前 10 个输入并打印了 arduinoData 的类型,在这种情况下是字符串,因为我使用的是 .decode()。但是,我不能使用诸如arduinoData=='1' 之类的布尔运算符来做任何事情,即使它被解码为字符串。我尝试过使用.decode('ascii')、.decode('UTF-8') 无济于事。

如何检查值或如何废弃 .decode() 并将字节转换为简单整数然后使用布尔运算符? 我正在使用带有 Arduino Uno 的 python 3.9。

更新 1

我已经设法在 Python 中以这种方式将其从 str 转换为 int:

import serial

ser = serial.Serial('COM10', baudrate = 9600, timeout = 1)

t=0
while t<10:
    arduinoData = ser.readline().decode()
    print(arduinoData)
    t+=1
if(int(arduinoData) == 1):
    print("Input is 1")
ser.close()

这样我可以看到我的串行输入确实等于 1。但是,如果它不等于 1,我希望做一些事情。所以我将检查放入循环中,如下所示:

import serial

ser = serial.Serial('COM10', baudrate = 9600, timeout = 1)

t=0
while t<10:
    arduinoData = ser.readline().decode()
    print(arduinoData)
    if(int(arduinoData) == 1):
        print("Input is 1")
    t+=1

ser.close()

并得到以下错误:

Traceback (most recent call last):
  File "C:\Users\01132892\Desktop\Serial\SerialButtonPurple.py", line 12, in <module>
    if(int(arduinoData) == 1):
ValueError: invalid literal for int() with base 10: ''

我假设这是在循环内转换它的问题,但我不知道如何解决它。

【问题讨论】:

    标签: python arduino serial-port pyserial


    【解决方案1】:

    好的,我已经设法解决了这个问题。 请注意,要检查它是否在主循环中工作,如果未按下按钮(信号读取为 0),则按“a”键,如果信号为 1,则释放它。

    import serial
    import pynput
    
    ser = serial.Serial('COM10', baudrate = 9600, timeout = 1)
    
    from pynput.keyboard import Key, Controller
    keyboard = Controller()
    while 1:
        arduinoData = ser.readline().rstrip()
        print(arduinoData)
        if(arduinoData==b'0'):
            keyboard.press('a')
        else:
            keyboard.release('a')
    ser.close()
    

    我要感谢 ocrdu 建议使用 rstrip() 摆脱 EOL。

    【讨论】:

      【解决方案2】:

      我的 Python 不是那么好,但也许 ser.readline() 也返回 EOL?如果是这样,arduinoData 不只包含“1”。

      如果我是对的,如果你去掉 EOL,它应该可以工作。

      或者:让 Arduino 使用Serial.print(buttonState); 发送单个字节,并使用ser.read() 在 Python 中读取单个字节。发送和读取单个字节时不需要分隔符。

      【讨论】:

      • 嗨!当然你是对的——因为没有decode(),Python 会读到类似b'1\n\r' 的东西。但是,如果我要使用 Serial.print(buttonState),我认为我真的没有分隔符来标记个人读数
      • 如果您同时发送和读取单个字节,则不需要分隔符,而 ser.read() 读取单个字节。不要忘记投票和/或接受答案,这样问题就不会保持开放。只有在我有意义的情况下才接受,当然是 8-)。
      • 我会同时发送不同的参数(多个按钮),这样会更容易
      • 您编辑的答案与我的更新方式相似,遗憾的是它也有相同的错误(我将其附加到原始问题中)
      猜你喜欢
      • 1970-01-01
      • 2013-10-08
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      • 2014-05-10
      • 1970-01-01
      • 2022-11-01
      相关资源
      最近更新 更多