Чтение байтов из Arduino с использованием Python

#python #arduino #serial-port #pyserial

#python #arduino #последовательный порт #pyserial

Вопрос:

Я пытаюсь прочитать последовательный ввод с Arduino на Python. Я пытаюсь выполнить простую задачу — на моем 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() удалить и преобразовать байты в простые целые числа, чтобы затем использовать логические операторы? Я использую python 3.9 с Arduino Uno.

ОБНОВЛЕНИЕ 1

Мне удалось преобразовать его из str в int этот способ в Python:

 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:Users1132892DesktopSerialSerialButtonPurple.py", line 12, in <module>
    if(int(arduinoData) == 1):
ValueError: invalid literal for int() with base 10: ''
  

Я предполагаю, что это проблема с преобразованием его внутри цикла, однако я понятия не имею, как ее решить.

Ответ №1:

Хорошо, мне удалось решить проблему. Пожалуйста, обратите внимание, что для проверки того, работает ли он в основном цикле, я нажимаю клавишу «a», если кнопка не нажата (считывание сигнала равно 0), и отпускаю ее, если сигнал равен 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); и прочитать отдельные байты в Python ser.read() . При отправке и чтении отдельных байтов разделитель не требуется.

Комментарии:

1. Привет! Конечно, вы правы — потому что без decode() Python читается что-то вроде b'1nr' . Однако, если бы я должен был использовать Serial.print(buttonState) , у меня не было бы делиметра, чтобы отмечать отдельные показания, я думаю

2. Вам не нужен разделитель, если вы одновременно отправляете и читаете отдельные байты, а ser.read() считывает отдельные байты. Не забудьте проголосовать и / или принять ответ, чтобы вопрос не оставался открытым. Принимаю только в том случае, если я понимаю, конечно, 8-).

3. Я буду отправлять разные параметры одновременно (несколько кнопок), так что будет проще

4. Ваш отредактированный ответ похож на мой обновленный способ, к сожалению, он также имеет ту же ошибку (я прикрепил ее к исходному вопросу)