[英]Python-Arduino Serial Half-Duplex: Arduino reads previous serial input instead of current
我正在使用 Python 3.7.5 和最新版本的串行庫。 我正在嘗試通過 python 和 arduino 制作一個 RFID 認證設備。 用戶必須在連接到 arduino 的 RFID 中掃描他們的 ID,並且 arduino 必須將 UID 發送到 python 軟件。 在我的筆記本電腦中,正在運行一個監聽串行的線程。 它會檢查 UID,如果允許則發送“O”,如果不允許則發送“X”。 在 arduino 中,程序然后等待是否有通過串行發送的數據,然后檢查輸入是否為“O”。 如果 RX 為“O”,則 LED 必須呈綠色亮起,否則呈紅色。
我的問題是,當我第一次掃描正確的 uid 時,它變成綠色,沒問題。 如果我掃描另一個正確的 uid,它會再次變為綠色,沒問題。 如果我掃描一個 INCORRECT uid,它會變成綠色,但在我的 Python 代碼中它應該是紅色的。 然后,如果我掃描正確的 uid,它會變成紅色,而應該是綠色。 我嘗試向 arduino 和 python 添加延遲以等待先前的輸入清除,並且還嘗試在傳輸后刷新但沒有運氣。
tl; dr arduino 正在輸出結果 ONE uid scan 很晚,我不知道還能做什么。
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 代碼本身。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.