python - Python-Arduino 串行半双工:Arduino 读取以前的串行输入而不是当前的
问题描述
我正在使用 Python 3.7.5 和最新版本的串行库。我正在尝试通过 python 和 arduino 制作一个 RFID 认证设备。用户必须在连接到 arduino 的 RFID 中扫描他们的 ID,并且 arduino 必须将 UID 发送到 python 软件。在我的笔记本电脑中,正在运行一个监听串行的线程。它检查 UID,如果允许则发送“O”,如果不允许则发送“X”。在 arduino 中,程序会等待是否有数据通过串行发送,然后检查输入是否为“O”。如果 RX 为“O”,则 LED 必须亮绿色,否则为红色。
我的问题是,当我第一次扫描正确的 uid 时,它变成绿色,没问题。如果我扫描另一个正确的 uid,它会再次变绿,没问题。如果我扫描一个不正确的 uid,它会变成绿色,但在我的 python 代码中它应该是红色的。然后,如果我扫描一个正确的 uid,它会变成红色,而应该是绿色的。我尝试向arduino和python添加延迟以等待先前的输入清除,并尝试在传输后刷新但没有运气。
tl; dr arduino 输出结果 一个 uid 扫描延迟,我不知道还能做什么。
Python:
# Reads data from the serial monitor without interrupting the main thread
from serial import Serial
import time
from threading import Thread
class SerialListener:
def __init__(self, baudrate=9600, timeout=1):
try:
self.ser = Serial('/dev/ttyACM0', baudrate, timeout=timeout)
except:
self.ser = Serial('/dev/ttyACM1', baudrate, timeout=timeout)
self.stopped = False
self.paused = False
self.stream = ''
time.sleep(1) # Wait for serial buffer to reset
def start(self):
Thread(target=self.update, args=()).start()
return self
def update(self):
if not self.paused:
while True:
if self.stopped:
self.ser.close()
print("Serial Thread Stopped")
print("Serial Port Closed")
break
try:
self.stream = self.ser.readline().decode('utf-8')
except:
self.stream = self.ser.readline().decode('ascii')
self.stream = self.stream.rstrip()
def stop(self):
self.stopped = True
def pause(self):
self.paused = True
def flush(self):
self.ser.flush()
def readDistance(self):
try:
return float(self.stream)
except:
return -1 # Returns -1 if there is an error in reading
def readRFID(self):
return self.stream
def write(self, msg):
self.ser.write(msg.encode())
if __name__ == "__main__": # FOR DEBUGGING ONLY
uno = SerialListener().start()
uno.flush()
print("Serial Started")
uid = ''
while True:
uid = uno.readRFID()
if uid is not '':
uno.flush()
time.sleep(0.1)
if uid == "5BEE9F0D":
uno.write('O')
print("SHOULD BE GREEN")
else:
uno.write('X')
print("SHOULD BE RED")
print(uid)
uno.stop()
阿杜诺:
#include <MFRC522.h>
#define GREEN_LED 6
#define RED_LED 7
#define BUZZER 8
MFRC522 rfid(10, 9);
unsigned long timer = 0;
bool readStatus = false;
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
Serial.begin(9600);
SPI.begin();
rfid.PCD_Init();
for(int i = 0; i < 10; i++)
Serial.write('\n');
delay(5);
digitalWrite(RED_LED, HIGH);
}
void loop() {
while(!readStatus){
if(rfid.PICC_IsNewCardPresent()){
if(rfid.PICC_ReadCardSerial()){
byte uid[rfid.uid.size];
if((millis() - timer) > 1000){
for(int i = 0; i < rfid.uid.size; i++)
uid[i] = rfid.uid.uidByte[i];
for(int i = 0; i < sizeof(uid); i++){
if(uid[i] < 0x10)
Serial.print('0');
Serial.print(uid[i], HEX);
}
Serial.println();
readStatus = true;
timer = millis();
}
Serial.flush();
}
}
}
if(readStatus){
while(!Serial.available());
char rx = 'X';
while(Serial.available()){
rx = Serial.read();
}
if(rx == 'O'){
digitalWrite(GREEN_LED, HIGH);
digitalWrite(RED_LED, LOW);
tone(BUZZER, 2500);
delay(100);
noTone(BUZZER);
readStatus = false;
}
else{
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, LOW);
tone(BUZZER, 1000);
delay(50);
noTone(BUZZER);
delay(30);
tone(BUZZER, 1000);
delay(50);
noTone(BUZZER);
digitalWrite(RED_LED, HIGH);
readStatus = false;
}
}
}
输出:
Serial Started
SHOULD BE RED
05520320 // it is red
SHOULD BE RED
05520320 // it is red
SHOULD BE GREEN
5BEE9F0D // it is red
SHOULD BE GREEN
5BEE9F0D // it is green
SHOULD BE RED
05520320 // it is green
解决方案
好的,我通过修改 pyserial 中的超时并在读取之间添加 1 秒延迟解决了这个问题。
问题是由于我设置条件的方式,pyserial 不止一次地写入序列。
while True:
uid = uno.readRFID()
if uid is not '':
uno.flush()
time.sleep(0.1)
if uid == "5BEE9F0D":
uno.write('O')
print("SHOULD BE GREEN")
else:
uno.write('X')
print("SHOULD BE RED")
print(uid)
由于我设置的超时时间为 1,PySerial 将继续读取 UID,直到超时。这将导致 uid 在一秒钟内不等于 '' 并将不必要地多次向串行发送数据。
在 Arduino 中,它只从缓冲区中读取一个字节的字符,并在读取后从缓冲区中删除它读取的内容。然而,python 并没有只向串口发送 1 个字符,而是不止一次。这就是为什么 Arduino 在从 PREVIOUS 缓冲区读取字符而不是 python 发送到串行的新字符时输出不正确的原因
为了解决这个问题,我把超时设置得更小了,这样串口的输入就会在超时后清除。不要将超时值设置得太低,否则可能无法读取数据。
def __init__(self, baudrate=9600, timeout=0.5):
其次,我在主线程上从串行读取之间添加了延迟
uid = ''
while True:
while uid is '':
uid = uno.readRFID()
time.sleep(0.1)
if uid == "5BEE9F0D":
uno.write('O')
else:
uno.write('X')
print(uid)
time.sleep(1)
uid = ''
Arduino 中的代码有效,所以我没有改变它,唯一的问题是 python 代码本身。
推荐阅读
- node.js - 为发出事件添加附加参数 - Quasar
- javascript - 是否可以设置javascript原型?
- javascript - 从 RGB 转换为 L*ab 颜色时值不准确
- python - 我可以训练一个网络以获得另一个网络的输出吗?
- python - 将视频流从前端(angularjs)发送到后端(Django)
- react-native - react-native-ibm-mobilefirst 授权被重定向到未知 URL https://mfpredirecturi
- java - 引用第二个数组
- angular - 如何更改 mat 表中的列名和值
- php - WSO2 IS 5.9 注销:没有与提供的会话索引对应的已建立会话
- c - 如何抑制 PC lint 中符号的单个 MISRA 2004 规则