RFID Arduino到Raspberry Pi串口读取python动作运行两次

时间:2015-01-27 01:23:45

标签: python arduino raspberry-pi rfid

我有以下脚本从Raspberry Pi上的Arduino读取串口。目的是让Pi监控Arduino rfid输出,并在识别出特定的卡号时,激活继电器板上的两个不同的继电器。发生的事情是,当识别出特定的卡号时,脚本基本上会运行两次。我无法弄清楚为什么会这样做。

#!/usr/bin/python # -*- coding: utf-8 -*-

import serial
import time
import RPi.GPIO as GPIO

ser = serial.Serial('/dev/ttyACM0', 9600)
GPIO.setmode(GPIO.BCM)
# init list with pin numbers
pin_assignments = {'Disarm Alarm': 18, 'Unlock Door': 23}
GPIO.setup(18, GPIO.OUT)
GPIO.setup(23, GPIO.OUT)
GPIO.output(18, GPIO.HIGH)
GPIO.output(23, GPIO.HIGH)
while True:
    try:
        data = ser.readline() .decode("utf-8*)

        if "12 34 56 78" in data:
            time.sleep(2)
            GPIO.output(18, GPIO.LOW) # Disarm alarm
            print('Alarm Disarmed')
            time.sleep(1)
            GPIO.output(23, GPIO.LOW) # Unlock door
            print('Door Unlocked')
            time.sleep(3)
            GPIO.output(18, GPIO.HIGH)
            GPIO.output(23, GPIO.HIGH)
            print('Card Admitted')
        time.sleep(1)

        if data == 'no card select':continue

    except ser.SerialTimeoutException:
        print('Data could not be read')
        time.sleep(1)

...在有效的卡片上阅读,我得到了:

警报撤防 门解锁 卡被录取 警报解除武装 门解锁 卡被录取

为什么你认为它经历了两次?

1 个答案:

答案 0 :(得分:0)

问题似乎是ser.readline可以"口吃"并返回相同的字符串两次(不确定为什么 - 缓冲?重试?)。那么忽视"太快" (在300秒内)重复? E.g:

import time
history = {}

while True:
    try:
        data = ser.readline().decode("utf-8")
        when = history.get(data, None)
        if when is not None and (time.time()-when) < 300:
            continue
        history[data] = time.time()

并且其余代码保持不变。基本上,这会在5分钟内忽略数据行的相同重复(调整阈值以适应)。

有任何缺点吗?是的,history不断增长,无用地记忆。需要定期重新构建/修剪以仅保留最近条目!

例如,扩展以上......:

import time
history = {}
last_update = time.time()

while True:
    if time.time() - last_update > 600:  # 10 minutes, let's rebuild
        deadline = time.time() - 301
        history = dict((d,t)
                       for d, t in history.items()
                       if t > deadline)
        last_update = time.time()

    try:
        data = ser.readline().decode("utf-8")
        when = history.get(data, None)
        if when is not None and (time.time()-when) < 300:
            continue
        history[data] = time.time()

同样,重建的600(10分钟)周期和301(一个超过300 :)以及#34;哪些条目值得保留&#34;,可以调整以品尝(平衡内存负载与CPU工作量和响应度)。但这是一种合理的方法。有更多精炼的替代品(例如,有选择地用于重建或修剪的条目的日志[列表]) - 但是,&#34;实体不能超过必要性&#34;,所以让我们坚持简单直到并且除非证明有必要增加复杂性! - )