减少Arduino和Python之间的差距

时间:2018-03-15 01:56:00

标签: python arduino xbee

我有3个Arduino传感器节点连接到运行Python的PC,XBee Series 1无线电作为无线通信的工具。波特率设置为9600,并且所有地址(ATDL,ATDH,ATMY)都设置正确,因为所有Arduino传感器节点都能够正确地将数据发送到连接到我在Python上运行的PC的XBee协调器。连接到相应Arduinos的Xbee无线电(有2个Arduino Unos和1个Arduino Nano)被配置为终端设备。

我最近发现了一个问题,即Arduino上的任何更改在到达PC时会滞后5秒,并写入CSV文件。例如,我正在读取其中一个Arduinos上的引脚状态,并在通过XBee将其传输到我的计算机后将其写入CSV文件。但是,我意识到当我在08:30:30(HH:MM:SS)实现状态更改时,更改仅在08:30:35(HH:MM:SS)的CSV文件中反映出来。

请问为什么会这样,我该如何解决?我分别为Arduino和Python提供了以下代码。

Arduino(这些代码在3个Arduino节点上大致相同):

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)

的Python:

import my_code

多线程在这里实现了一个愚蠢的操作,找到8 * 5,因为稍后,这将扩展到实时机器学习功能,确定灯应该打开/关闭的时间。 raw_input()函数证明数据可以被中继回Arduino传感器节点。

非常感谢你的帮助! :)

1 个答案:

答案 0 :(得分:0)

关于可能改进的一些想法:

  • 在Arduino上将Serial()波特率提高到115200。
  • 在Arduino上将XBee波特率提高到115200(或者使用软件串口将其提高到115200)。
  • 在运行Python的PC上将波特率提高到115200(它绝对可以处理该速率,并且每个设备上的速率都不需要匹配)。
  • 删除或缩小sleep(1)中的acquire_data()
  • 检查终端设备上的睡眠配置。他们有可能一次睡几秒钟吗?您是否可以将它们配置为路由器以消除可能导致延迟的原因?
  • 更改发送代码以创建单个字符串(请参阅下文),然后发送。然后,您可以轻松地将其首先发送到XBee,然后单独发送到串行输出。如果Serial()接口未被缓冲,则可以将XBee数据包计时(请参阅ATRO设置)并将响应作为多个数据包发送(效率较低)。尝试将ATRO从默认值3增加到20,看看是否有帮助。
  • 现在你每秒发送一次。如果您更频繁地检查I / O并且仅在输入更改时发送了响应(或者自上次传输以来已经过了5秒),该怎么办?

您的每秒发送一次,所以平均而言,您将在I / O更改后发送0.5秒。您可以在Arduino上添加一些时序代码,以打印出组装和发送数据所需的毫秒数(这可能会导致一些延迟)。或者尝试这个替换代码:

char buffer[16];

pirValue = digitalRead(pirPin);
digitalWrite(LEDPirPIN, pinValue);

sprintf(buffer, "d%u,%u,%u,\n",
    digitalRead(IR) == LOW,
    pirValue == HIGH,
    digitalRead(lightLED) == LOW);
xbee.print(buffer);
Serial.print(buffer);