2015-01-27 8 views
0

나는 나무 딸기 파이에 Arduino에서 직렬 포트를 읽을 수있는 아래의 스크립트가 있습니다. 의도는 Arduino rfid 출력을 모니터하고 특정 카드 번호가 식별되면 릴레이 보드에서 두 개의 다른 릴레이를 활성화하는 것입니다. 스크립트가 본질적으로 특정 카드 번호가 식별되면 두 번 실행됩니다. 왜 그렇게하는지 모르겠습니다. 유효한 카드가 읽기에RFID Arduino to Raspberry Pi 시리얼 읽기 파이썬 액션 두 번 실행

#!/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

'true while'에 있기 때문에 결코 빠져 나올 수 없기 때문에, 나는 ** 단지 ** 두 번만, 왜'ser.readline()'가 3 번째를 막고 있는지 짐작할 수 있습니다. 그것이 불려지는 시간이지만 나는 확실히 말할 수 없다. (나는 슬프게도 문제를 재현 할 수있는 HW가 없다.) –

+0

True에 대한 대안에 대한 제안 사항이 있습니까? 필자는 Python을 처음 사용하기 때문에이 스크립트를 실행하기위한 최선의 대안이 무엇인지 모릅니다. 끊임없이 Arduino 직렬 출력을 모니터해야합니다. –

+0

반복을 원하지 않을 때'중단 '하는 것이 가장 간단한 생각이지만, 그로 인해 모니터링이 중단됩니다. Arduino가 "stutters"하고 두 번 선을 보내는 경우, 예를 들어 마지막으로 본 '데이터'값의 'dict'을 사용하여이를 해결해야 할 수도 있습니다. 따라서 너무 빠르게 반복되는 것을 무시할 수 있습니다. 그걸 안내하는 답변에 몇 가지 코드가 필요합니까? 그렇게 알려 줘서 고마워! –

답변

0

ser.readline은 "stutter"하고 동일한 문자열을 두 번 반환 할 수 있습니다 (확실하지 않은 이유 - 버퍼링? 재시도?). 따라서 "너무 빠른"(300 초 이내) 중복을 무시하면 어떨까요? 예 :

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 :) ", 맛을 조정할 수 있습니다 (메모리로드와 CPU 노력 및 응답 속도의 균형). 그러나 이것은 합리적인 접근 방법 중 하나입니다. 더 복잡한 대안이 있습니다 (예 : 재구성 또는 잘라 내기를 위해 선택적으로 사용하는 항목의 로그 [목록]). 그러나 "엔터티는 필요 이상으로 곱하면 안됩니다."따라서 더 복잡성이 입증 될 때까지 단순성을 고집합시다.)

+0

Alex에게 감사드립니다. 첫 번째 읽기가 응답하지 않은 이후에 카드를 읽으므로 15 초로 시간을 낮 춥니 다. 일단 내렸을 때, 그것은 완벽하게 작동했습니다. –