我正在尝试通过XBees收集来自3个Arduino节点(连接到某些传感器)的数据。 3个Arduino节点分别连接到XBee Series 1无线电(终端设备),而协调器连接到我的PC(但稍后将连接到Raspberry Pi 2 B型)。
我在想,是否有办法在Raspberry Pi上用Python实现UART中断?这是因为,根据我的下面的代码,我采用轮询方法来读取从我的3个Arduino传感器节点传入的数据。每秒从3个Arduino传感器节点传入的数据,如下面的代码所示。
然而,我的民意调查方法导致了一些问题,因为我只做了#34; arduino.readline()"在我的代码的最开始,之后,我将继续在Python代码中做其他事情。
因此,我想知道是否有任何方法可以用Python实现UART中断,这样每当有传入数据时,我都会执行arduino.readline()并继续处理数据。
我的代码如下:(所有3个节点的Arduino代码大致相同。)
Python代码:
import threading
import logging
import time
import serial
import csv
# Arduino; Arduino is now replaced by XBee modules
arduino = serial.Serial('COM18', 9600, timeout=1) # Open serial port. By right, should check if it is open
def checker(field):
if 'b' in field:
field = field.replace('b', '')
if 't' in field:
field = field.replace('t', '')
return field
def make_backup(finalmatrix, field_send, flag): # Back up the 2 most-recent data.
matrix1 = [] # declares a list
matrix1.append(flag) # appends the counter 'flag'
matrix1.extend(field_send) # attaches the list to the end of current list; doesn't work with int
# finalmatrix is a list of list; if len(finalmatrix) == 2 means: finalmatrix == [[1,2], [3,4]]
if (len(finalmatrix) == 2):
finalmatrix = finalmatrix[1:] # Create a new list, take the 2nd mini-list in the list and put it in the new list
finalmatrix.append(matrix1) # appends the new matrix1
else:
finalmatrix.append(matrix1)
return finalmatrix
def acquire_data():
flag = 1
finalmatrix = []
count = 0
while True:
# data_in
start_time = time.time()
try:
data_in = arduino.readline() # read serial data from Arduino
# logging.warning(data_in) # debugger
except:
pass
global data_stripped
data_stripped = data_in.strip() # Removes spaces and \n
for data_stripped in arduino:
if data_stripped.startswith('b') and data_stripped.count(
',') == 3: # first char identifies where data is coming from; count commas to double-check incoming string
field = data_stripped.split(',') # split data to be put into 'boxes'
bed_sen = field[0] + ',' + field[1] + ',' + field[2] # We have 3 data sensor fields
bed_sen_fill = True # A flag to show that this if-statement has been completed
if data_stripped.startswith('t') and data_stripped.count(',') == 3:
field = data_stripped.split(',')
table_sen = field[0] + ',' + field[1] + ',' + field[2]
table_sen_fill = True
if data_stripped.startswith('d') and data_stripped.count(',') == 3:
field = data_stripped.split(',')
door_sen = field[0] + ',' + field[1] + ',' + field[2]
door_sen_fill = True
try:
if bed_sen_fill == True and table_sen_fill == True and door_sen_fill == True:
data_combi = bed_sen + ',' + table_sen + ',' + door_sen
break
except:
pass
if data_combi:
datasplit = data_combi.split(",")
field1 = datasplit[0]
field2 = datasplit[1]
field3 = datasplit[2]
field4 = datasplit[3]
field5 = datasplit[4]
field6 = datasplit[5]
field7 = datasplit[6] # To be deprecated in future; IR sensor no longer in use.
field8 = datasplit[7]
field9 = datasplit[8]
# Removes 'b', 't' chars in strings
field1 = checker(field1)
field2 = checker(field2)
field3 = checker(field3)
field4 = checker(field4)
field5 = checker(field5)
field6 = checker(field6)
field8 = checker(field8)
field9 = checker(field9)
##### Data Validity Check #####
field_send = [] # rearrange into list
field_send.append(field1)
field_send.append(field2)
field_send.append(field3)
field_send.append(field4)
field_send.append(field5)
field_send.append(field6)
field_send.append(field7)
field_send.append(field8)
field_send.append(field9)
if flag == 1:
finalmatrix = make_backup(finalmatrix, field_send, flag)
flag = flag + 1
else:
finalmatrix = make_backup(finalmatrix, field_send, flag)
flag = 1
# print finalmatrix
if (count == 2 and int(field1) > 1000 or field1 == ''): # If re-sends, 'b' will appear twice; light_val<1000 always.
field1 = (int(finalmatrix[0][1]) + int(finalmatrix[1][1])) / 2
# print ("Error1!")
if (count == 2 and field2.count('-') == 2 or len(field2) > 3 or field2 == ''): # If re-send, '-' will appear twice; field2 max 3 digits
field2 = (int(finalmatrix[0][2]) + int(finalmatrix[1][2])) / 2
# print ("Error2!")
if (count == 2 and len(field3) > 1 or field3.count('01') == 1 or field3.count('10') == 1 or field3.count('-') == 1 or field3 == ''): # Motion_sen is purely binary.
field3 = (int(finalmatrix[0][3]) + int(finalmatrix[1][3])) / 2
# print ("Error3!")
if (count == 2 and int(field4) > 1000 or field4 == ''): # If re-sends, 't' will appear twice; light_val<1000 always.
field4 = (int(finalmatrix[0][4]) + int(finalmatrix[1][4])) / 2
# print ("Error4!")
if (count == 2 and field5.count('-') == 2 or len(field5) > 3 or field5 == ''): # If re-send, '-' will appear twice; field5 max 3 digits
field5 = (int(finalmatrix[0][5]) + int(finalmatrix[1][5])) / 2
# print ("Error5!")
if (count == 2 and len(field6) > 1 or field6.count('01') == 1 or field6.count('10') == 1 or field6.count('-') == 1 or field6 == ''): # Motion_sen is purely binary.
field6 = (int(finalmatrix[0][6]) + int(finalmatrix[1][6])) / 2
# print ("Error6!")
if (count == 2 and len(field8) > 1 or field8.count('01') == 1 or field8.count('10') == 1 or field8.count('-') == 1 or field8 == ''): # Motion_sen is binary.
field8 = (int(finalmatrix[0][8]) + int(finalmatrix[1][8])) / 2
# print ("Error7!")
if (count == 2 and len(field9) > 1 or field9.count('01') == 1 or field9.count('10') == 1 or field9.count('-') == 1 or field9 == ''): # SW is binary too!
field9 = (int(finalmatrix[0][9]) + int(finalmatrix[1][9])) / 2
# print ("Error8!")
with open('abs_testdatadiscrep4.csv', 'ab') as csvfile: # 'ab' to remove newline char after each print
writer = csv.writer(csvfile)
sensor_fields = [field1, field2, field3, field4, field5, field6, field7, field8, field9,
time.strftime("%H%M%S")]
if time.time() - start_time >= 1:
writer.writerow(sensor_fields)
count = count + 1
if count == 2:
count = 2
print "My program took", time.time() - start_time, "to run"
time.sleep(0.5)
# print "My program took", time.time() - start_time, "to run"
def counting():
while True:
sum = 3 + 2
sum2 = sum * 8
time.sleep(0.2)
def on_light():
strin = '1'
arduino.write(strin.encode())
print "Confirm ON"
def off_light():
strin = '0'
arduino.write(strin.encode())
print "Confirm OFF"
# now threading1 runs regardless of user input
threading1 = threading.Thread(target = acquire_data)
threading2 = threading.Thread(target = counting)
threading1.start()
threading2.start()
while True:
if raw_input() == 't':
on_light()
print "ON"
if raw_input() == 'r':
off_light()
print "OFF"
time.sleep(1)
Arduino代码:
#include <SoftwareSerial.h>
#define lightPin A0 // Light Sensor at Arduino A0 pin
#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
#define LEDPinUS 13 // LED at Pin 13 (Ultrasound)
#define pirPin 9 // Input for HC-S501
#define LEDPinPIR 12 // LED at Pin 12 (PIR)
SoftwareSerial xbee(2, 3); // RX, TX
int light ; //Value from light sensor
String lightID = "0";
String distanceUS = "0";
String pirID = "0";
String comma = ",";
int maximumRange = 150; // Maximum range needed
int minimumRange = 0; // Minimum range needed
long duration, distance; // Duration used to calculate distance
int OOR = 0; // OOR = Out of Range
int pirValue; // Place to store read PIR Value
int pirNum = 0;
int pirNumyes = 0;
int pirNumno = 0;
void setup() {
Serial.begin(9600); //Baud rate must be the same as is on xBee module
xbee.begin(9600);
pinMode(lightPin, INPUT); // Light sensor
pinMode(trigPin, OUTPUT); // Ultrasound sensor
pinMode(echoPin, INPUT); // Ultrasound sensor
pinMode(LEDPinUS, OUTPUT); // Ultrasound sensor indicator
pinMode(pirPin, INPUT); // PIR sensor
pinMode(LEDPinPIR, OUTPUT); // Ultrasound sensor indicator
digitalWrite(LEDPinUS, LOW);
digitalWrite(LEDPinPIR, LOW);
}
void loop() {
// Light Sensor, "t" = table_sensors
light = analogRead(lightPin);
String ID = "t";
lightID = ID + light + comma; //20-Mar-18: Added ","; disabled ',' printed serially
// Ultrasound Sensor
digitalWrite(trigPin, LOW); // clears Trigger pin
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
// Calculate the distance (in cm) based on the speed of sound.
distance = duration / 58.2;
if (distance >= maximumRange || distance <= minimumRange) {
/* Send a negative number to computer and Turn LED ON
to indicate "out of range" */
OOR = -1;
distanceUS = OOR + comma; //20-Mar-18: Added ","; disabled ',' printed serially; removed "+ ID"
digitalWrite(LEDPinUS, HIGH);
} else {
/* Send the distance to the computer using Serial protocol, and
turn LED OFF to indicate successful reading. */
distanceUS = distance + comma; //20-Mar-18: Added ","; disabled ',' printed serially; removed "+ ID"
digitalWrite(LEDPinUS, LOW);
}
// Motion sensor
pirValue = digitalRead(pirPin);
if (pirValue == HIGH) {
pirNumyes = 1;
pirID = pirNumyes + comma; //20-Mar-18: Added ","; disabled ',' printed serially; removed "+ ID"
digitalWrite(LEDPinPIR, HIGH);
} else {
pirNumno = 0;
pirID = pirNumno + comma; //20-Mar-18: Added ","; disabled ',' printed serially; removed "+ ID"
digitalWrite(LEDPinPIR, LOW);
}
String together = lightID + distanceUS + pirID;
//Serial.println(together);
xbee.println(together);
delay(1000);
}
我试过在谷歌搜索答案,但我似乎找不到任何答案。我最接近的是来自Read serial data without high CPU use的类似StackOverflow帖子的答案。
但是,我可以问一下Raspberry Pi上是否有针对UART中断的Python实现?
非常感谢你的帮助! :)
答案 0 :(得分:0)
如果从RX
引脚到任何可用的GPIO
引脚都安装了一条额外的导线,则可以至少使用RpiGPIO
模块边缘中断来提醒您正在进行传输。它不会告诉您缓冲区已满,因此在服务GPIO
中断时必须检查缓冲区。至少这可以让您执行其他操作,而不是等待循环和/或轮询UART
以获取缓冲区数据。