【发布时间】:2018-03-17 01:18:46
【问题描述】:
我有 3 个 Arduino 传感器节点连接到运行 Python 的 PC,XBee 系列 1 无线电作为无线通信工具。波特率设置为 9600,并且所有地址(ATDL、ATDH、ATMY)都设置正确,因为所有 Arduino 传感器节点都能够正确地将数据发送到连接到我在 Python 上运行的 PC 的 XBee 协调器。连接到各自 Arduino 的 Xbee 无线电(有 2 个 Arduino Unos 和 1 个 Arduino Nano)被配置为终端设备。
我最近发现了一个问题,即 Arduino 上的任何更改在到达 PC 时都会延迟 5 秒,然后写入 CSV 文件。例如,我正在读取其中一个 Arduino 上的引脚状态,并在通过 XBee 将其传输到我的计算机后将此状态写入 CSV 文件。但是,我意识到当我在 08:30:30 (HH:MM:SS) 进行状态更改时,更改仅在 08:30:35 (HH:MM:SS) 时反映在 CSV 文件中。
请问为什么会出现这种情况,我应该如何解决?我分别有以下 Arduino 和 Python 代码。
Arduino(这些代码在 3 个 Arduino 节点上大致相同):
#include <SoftwareSerial.h>
#define IR 10 // IR sensor at D10 position
#define pirPin 9 // Input for HC-S501
#define LEDPinPIR 12 // LED at Pin 12 (PIR)
#define lightLED 11 // LED at Pin 11 (Relay, Neg.Logic - ON = Relay off)
SoftwareSerial xbee(2, 3); // RX, TX
int pirValue; // Place to store read PIR Value
int pirNum = 0;
int pirNumyes = 0;
int pirNumno = 0;
int sw_door = 0; //sw_door has been updated to "sw_relay" w.e.f 27-Feb-2018
int IR_val = 0;
char incomingByte;
unsigned long prevMillis = 0;
void setup() {
Serial.begin(9600);
xbee.begin(9600);
pinMode(pirPin, INPUT); // PIR sensor
pinMode(LEDPinPIR, OUTPUT); // Ultrasound sensor indicator
pinMode(lightLED, OUTPUT); // LED at Pin 11 (Relay, Neg.Logic - ON = Relay off)
pinMode(SW, INPUT); // Switch
digitalWrite(SW, LOW);
digitalWrite(LEDPinPIR, LOW);
}
void loop() {
unsigned long currentMillis = millis();
if((unsigned long)currentMillis - prevMillis == 1000){
//IR sensor "d" refers to door
if (digitalRead(IR) == LOW){
IR_val = 1;
String ID = "d";
String IRID = ID + IR_val;
Serial.print(IRID);
Serial.print(',');
xbee.print(IRID);
xbee.print(',');
}
else{
IR_val = 0;
String ID = "d";
String IRID = ID + IR_val;
Serial.print(IRID);
Serial.print(',');
xbee.print(IRID);
xbee.print(',');
}
// Motion sensor
pirValue = digitalRead(pirPin);
if (pirValue == HIGH) {
pirNumyes = 1;
Serial.print(pirNumyes);
Serial.print(',');
xbee.print(pirNumyes);
xbee.print(',');
digitalWrite(LEDPinPIR, HIGH);
}
else {
pirNumno = 0;
Serial.print(pirNumno);
Serial.print(',');
xbee.print(pirNumno);
xbee.print(',');
digitalWrite(LEDPinPIR, LOW);
}
// Switch
if(digitalRead(lightLED)== HIGH){
sw_door = 0;
Serial.print(sw_door);
Serial.println(',');
xbee.print(sw_door);
xbee.println(',');
}
else{
sw_door = 1;
Serial.print(sw_door);
Serial.println(',');
xbee.print(sw_door);
xbee.println(',');
}
prevMillis = currentMillis;
}
// Xbee to Arduino Added: 18-Feb-2018
if (xbee.available()){
incomingByte = xbee.read();
if(incomingByte == '1'){
digitalWrite(lightLED, HIGH);
//xbee.println("OK");
}
else if(incomingByte == '0'){
digitalWrite(lightLED, LOW);
//xbee.println("OK");
}
}
}
Python:
import threading
import time
import serial
import csv
# Arduino; Arduino is now replaced by XBee modules
arduino = serial.Serial('COM18', 9600, timeout=1) # Open serial port.
def acquire_data():
while True:
try:
data_in = arduino.readline() # read serial data from Arduino
except:
pass
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]
field8 = datasplit[7]
field9 = datasplit[8]
with open('abs_testing.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")]
writer.writerow(sensor_fields)
time.sleep(1)
def counting():
while True:
sum = 3 + 2
sum2 = sum*8
print sum2
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.daemon = False # May remove later. Unsure at the moment.
threading2.daemon = False # May remove later. Unsure at the moment.
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)
这里的多线程是通过一个查找 8*5 的愚蠢操作来实现的,因为稍后,这将扩展为一个实时机器学习函数,该函数决定何时打开/关闭灯。 raw_input() 函数证明数据可以传递回 Arduino 传感器节点。
非常感谢您的帮助! :)
【问题讨论】:
-
在你调用
writer.writerow()之后马上试试writer.sync()(我不知道API中是否有这个func调用,但你可以尝试找到类似的),看看是否问题仍然存在。也许它可能是带有缓冲 IO 的东西。 -
@phyloflash 非常感谢您的建议! ^^我会阅读更多关于该功能的内容,然后尝试一下~ ^^