TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Wait for edge not responding

Tue Jul 15, 2014 6:42 pm

All,

If you've seen my previous posts, you know the task of creating an RFID reader is starting to baffle me. I have attached my code below. Basically, I need the reader to constantly scan for cards and write the UID's to another file. That works perfectly. However, I also need to script to stop scanning and import "redbutton" when GPIO 23 is down. My attempt at that script is below, but is not working. I don't get any errors, and the script for scanning for cards continues. At first, I thought it was an indentation problem, but I did not have any success with whichever indentation level I used.

Where have I gone wrong with wait_for_edge?

Code: Select all

import RPi.GPIO as GPIO
import MFRC522
import signal
import glob
GPIO.setmode (GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(17, GPIO.OUT) ## Setup GPIO Pin 4 to OUT
GPIO.output(17,True) ## Turn on GPIO pin 17
MYFILE = glob.glob('/home/pi/RXRFID/newscans/*')[0]
import sys
from time import sleep
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

lcd = Adafruit_CharLCDPlate()

lcd.clear()
lcd.message("Begin Scanning\nPrs red to stop")

continue_reading = True

# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    continue_reading = False


# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:

    # Scan for cards
    (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

    # If a card is found
    if status == MIFAREReader.MI_OK:
        print "Card detected"
        print MYFILE
 # Get the UID of the card
        (status,uid) = MIFAREReader.MFRC522_Anticoll()

        # If we have the UID, continue
        if status == MIFAREReader.MI_OK:

            print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])

            # Write the card UID to a file
            with open(MYFILE, 'a') as f:
                uid_str = ",".join([str(x) for x in uid])
                f.write(uid_str+"\n")
                continue

            # This is the default key for authentication
            key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]

            # Select the scanned tag
            MIFAREReader.MFRC522_SelectTag(uid)

            # Authenticate
            status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)

            # Check if authenticated
            if status == MIFAREReader.MI_OK:
                MIFAREReader.MFRC522_Read(8)
                MIFAREReader.MFRC522_StopCrypto1()
            else:
                print "Authenticaion error"
            continue
          # Check for redbutton
            try:
                GPIO.wait_for_edge(23, GPIO.FALLING)
                import redbutton
            except KeyboardInterrupt:
                GPIO.cleanup()


User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Wait for edge not responding

Tue Jul 15, 2014 7:43 pm

I'm not sure exactly what you're trying to do, but I don't see the point of those 'continue' statements. Continue is used to jump back up to the top of the while loop, so I wouldn't expect any of your code to be executed after the f.write() line.

As always, sprinkling a few print() statements will help show what is going on.

Code: Select all

    import RPi.GPIO as GPIO
    import MFRC522
    import signal
    import glob
    GPIO.setmode (GPIO.BCM)
    GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(17, GPIO.OUT) ## Setup GPIO Pin 4 to OUT
    GPIO.output(17,True) ## Turn on GPIO pin 17
    MYFILE = glob.glob('/home/pi/RXRFID/newscans/*')[0]
    import sys
    from time import sleep
    from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

    lcd = Adafruit_CharLCDPlate()

    lcd.clear()
    lcd.message("Begin Scanning\nPrs red to stop")

    continue_reading = True

    # Capture SIGINT for cleanup when the script is aborted
    def end_read(signal,frame):
        global continue_reading
        continue_reading = False


    # Hook the SIGINT
    signal.signal(signal.SIGINT, end_read)

    # Create an object of the class MFRC522
    MIFAREReader = MFRC522.MFRC522()

    # This loop keeps checking for chips. If one is near it will get the UID and authenticate
    while continue_reading:

        print("Scanning for cards")
        # Scan for cards
        (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

        # If a card is found
        if status == MIFAREReader.MI_OK:
            print "Card detected"
            print MYFILE
     # Get the UID of the card
            (status,uid) = MIFAREReader.MFRC522_Anticoll()

            # If we have the UID, continue
            if status == MIFAREReader.MI_OK:

                print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])

                # Write the card UID to a file
                with open(MYFILE, 'a') as f:
                    uid_str = ",".join([str(x) for x in uid])
                    f.write(uid_str+"\n")
                    continue

                # This is the default key for authentication
                key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]

                # Select the scanned tag
                MIFAREReader.MFRC522_SelectTag(uid)

                # Authenticate
                print("Authenticating")
                status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)

                # Check if authenticated
                if status == MIFAREReader.MI_OK:
                    print("Reader status OK")
                    MIFAREReader.MFRC522_Read(8)
                    MIFAREReader.MFRC522_StopCrypto1()
                else:
                    print "Authenticaion error"
                continue
              # Check for redbutton
                print("Waiting for GPIO 23")
                try:
                    GPIO.wait_for_edge(23, GPIO.FALLING)
                    print("Falling edge detected on GPIO 23")
                    import redbutton
                except KeyboardInterrupt:
                    GPIO.cleanup()


TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: Wait for edge not responding

Tue Jul 15, 2014 8:22 pm

Well that does certainly spreads some light on the subject. I removed the erroneous "Continue" commands and made some progress. However, once the script detects a card, it stops scanning for cards and waits for GPIO 23. Once pressed, redbutton imports correctly, but I need the script to keep searching for cards until the user presses GPIO23.

How do I get this script to repeat until GPIO 23 is falling?

Updated script below:

Code: Select all

import RPi.GPIO as GPIO
import MFRC522
import signal
import glob
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(17, GPIO.OUT) ## Setup GPIO Pin 4 to OUT
GPIO.output(17,True) ## Turn on GPIO pin 17
MYFILE = glob.glob('/home/pi/RXRFID/newscans/*')[0]
import sys
from time import sleep
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

lcd = Adafruit_CharLCDPlate()

lcd.clear()
lcd.message("Begin Scanning\nPrs red to stop")

continue_reading = True

    # Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
        global continue_reading
        continue_reading = False


    # Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

    # Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

    # This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:
        print("Scanning for cards")
        # Scan for cards
        (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

        # If a card is found
        if status == MIFAREReader.MI_OK:
            print "Card detected"


User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Wait for edge not responding

Tue Jul 15, 2014 10:37 pm

You'll need to have a separate thread waiting on the GPIO edge, while your main thread is polling the card scanner. Right now you have

Code: Select all

GPIO.wait_for_edge(23, GPIO.FALLING)
which is going to 'block' - that is, stop the program and wait for the GPIO event, as you've seen. What you want is something like this:

Code: Select all

def handleRedButton(channel):
    global continue_reading
    continue_reading = False
    import redbutton
GPIO.add_event_detect(23, GPIO.FALLING, callback=handleRedButton)
somewhere near the top of your your code, rather than in the main loop. This will let RPi.GPIO check for the GPIO in the background (while your main loop is running) , and it will call your 'callback' function (handleRedButton()) when the event occurs.

This is a pretty good tutorial on how and why callbacks are a good idea: http://makezine.com/projects/tutorial-r ... nd-python/

When you get that working, you can read up on the evils of using global variables, and adjust the code accordingly. :)

TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: Wait for edge not responding

Wed Jul 16, 2014 1:54 pm

Now I'm even more confused.

I copied your code verbatim and pasted near the top of the script, before the scanning routine. The script runs and successfully stops scanning for cards when GPIO23 is down, however redbutton doesn't seem to be importing. I've tried putting the code snippet in different locations, and also tried debugging redbutton in case there was an error within that script.

Redbutton runs correctly if I run it directly, so my thought is that the problem must be somewhere in the card scanning script. I have attached both scripts below.

Code: Select all

Using username "pi".
pi@192.168.3.127's password:
Linux raspberrypi 3.12.22+ #691 PREEMPT Wed Jun 18 18:29:58 BST 2014 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Jul 16 08:22:49 2014 from timtacular.local
pi@raspberrypi ~ $ sudo nano greenbutton.py
pi@raspberrypi ~ $ cd RXRFID
pi@raspberrypi ~/RXRFID $ sudo nano greenbutton.py
  GNU nano 2.2.6                                          File: greenbutton.py

import RPi.GPIO as GPIO
import MFRC522
import signal
import glob
GPIO.setmode (GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(17, GPIO.OUT) ## Setup GPIO Pin 4 to OUT
GPIO.output(17,True) ## Turn on GPIO pin 17
MYFILE = glob.glob('/home/pi/RXRFID/newscans/*')[0]
import sys
from time import sleep
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

def handleRedButton(channel):
    global continue_reading
    continue_reading = False
    import redbutton
GPIO.add_event_detect(23, GPIO.FALLING, callback=handleRedButton)

lcd = Adafruit_CharLCDPlate()

lcd.clear()
lcd.message("Begin Scanning\nPrs red to stop")

continue_reading = True

# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    continue_reading = False

# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:

    print("Scanning for cards")
    # Scan for cards
    (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

    # If a card is found
    if status == MIFAREReader.MI_OK:
        print "Card detected"
        print MYFILE
 # Get the UID of the card
        (status,uid) = MIFAREReader.MFRC522_Anticoll()

        # If we have the UID, continue
        if status == MIFAREReader.MI_OK:


            print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])
            # Write the card UID to a file
            with open(MYFILE, 'a') as f:
                uid_str = ",".join([str(x) for x in uid])
                f.write(uid_str+"\n")

            # This is the default key for authentication
            key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]

            # Select the scanned tag
            MIFAREReader.MFRC522_SelectTag(uid)

            # Authenticate
            print("Authenticating")
            status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)

            # Check if authenticated
            if status == MIFAREReader.MI_OK:
                print("Reader status OK")
                MIFAREReader.MFRC522_Read(8)
                MIFAREReader.MFRC522_StopCrypto1()
            else:
                print "Authenticaion error"


redbutton:

Code: Select all

#!/usr/bin/python
import RPi.GPIO as GPIO ## Import GPIO library
GPIO.setmode(GPIO.BCM) ## Use board pin numbering
GPIO.setup(17, GPIO.OUT) ## Setup GPIO Pin 17 to OUT
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## Setup GPIO Pin 22 to IN
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP) ## Setup GPIO Pin 24 to IN
GPIO.output(17,False) ## Turn off GPIO pin 17
import shutil

from time import sleep
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate

lcd = Adafruit_CharLCDPlate()

lcd.clear()
lcd.message("Scanning stopped")

import os, subprocess
src = "/home/pi/RXRFID/newscans/"
dst = "/home/pi/RXRFID/upload"
listOfFiles = os.listdir(src)
for f in listOfFiles:
       fullPath = src + "/" + f
       subprocess.Popen("mv" + " " + fullPath + " " + dst,shell=True)


sleep(3)
lcd.clear()
lcd.message("Prs wht to start\nPrs Blue to upld")


User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: Wait for edge not responding

Wed Jul 16, 2014 2:13 pm

Hmmmmm. I'm not a fan of using import inline to run a script but I guess it works. Importing into a callback is perhaps not a good idea however. When the callback sets continue_reading to false, the while loop stops running and the next block of code is executed (in your case none, so the script ends.) Try moving the the 'import redbutton' to the bottom of the code (no indentation). That way it will run in the main thread after the scanning loop ends.
Last edited by Douglas6 on Wed Jul 16, 2014 2:15 pm, edited 1 time in total.

TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: Wait for edge not responding

Wed Jul 16, 2014 2:15 pm

That did the trick. Thank you!

Return to “Python”