我有以下脚本从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)
...在有效的卡片上阅读,我得到了:
警报撤防 门解锁 卡被录取 警报解除武装 门解锁 卡被录取
为什么你认为它经历了两次?
答案 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;,所以让我们坚持简单直到并且除非证明有必要增加复杂性! - )