TransWikia.com

Is this a Python quirk or an imperfection in the Raspberry Pi input?

Raspberry Pi Asked by cornerpocket on October 20, 2020

I am running out of ideas to get this Python code working the way I want it to. Please take a look at my code and help me figure out what’s wrong, or if it’s a hardware issue with the Pi causing my issue.

Goal:
Use a fingerprint reader to start my car. Car is controlled via RPi GPIO pins and relays.

The setup:
I’m using a fingerprint reader module and a modified version of the Adafruit fingerprint reader script. I have a button wired into my dash in the car that when turned on, will activate the Ignition and Accessory circuits (Windows, Radio, cigarette lighter, etc.), and then the fingerprint reader will activate until a registered finger is placed, or the button is switched off again. the button is wired between GPIO 5 and a ground pin on the Raspberry Pi, and pulls the pin “LOW” when active. GPIO 5 is initially pulled up.

The problem:
I seem to be having issues getting a “button_state” variable to read reliably here. The following code is almost function perfect, but every time I switch the button “OFF” after the car is started, a repeated command happens where it will print “Accessories Off”, as it should, but then it prints “Accessories On”, followed by “Accessories Off” again. I really can’t understand why this part of the code is creating this unwanted repetition here, especially because “Accessories On” should only print if the button is on (0) but the button is clearly off (1)

This makes me wonder if the RPi pin is giving false signals and confusing the code, or is there something wrong with the flow of my Python code here?

The code:

import RPi.GPIO as io
import time
import adafruit_fingerprint
import serial
io.setwarnings(False)
io.setmode(io.BCM)
io.setup(5, io.IN, io.PUD_UP)
BUTTON = 5
ACC = 23
IGN = 27
START = 22
uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1)
finger = adafruit_fingerprint.Adafruit_Fingerprint(uart)
started = 0
ignition = 0

##################################################


# This block is pretty much straight from the Adafruit code, slightly 
# modified with my button checks, this segment seems to work fine

def get_fingerprint():
    while finger.get_image() != adafruit_fingerprint.OK:
        button_off = io.input(BUTTON)
        if button_off == 1:
            return False
        if button_off == 0:
            pass
    if finger.image_2_tz(1) != adafruit_fingerprint.OK:
        return False
    if finger.finger_fast_search() != adafruit_fingerprint.OK:
        return False
    return True

while True:

    button_off = io.input(BUTTON) ### Constantly checking for the button state because 
# when I dont it seems to just remember the state from a certain point instead of giving reliable updated readings

#Button is on
    if started == 0: #car is not started yet
        if ignition == 0: #Accessory and Ignition are not on
            if button_off == 0:
                print ("Accessories on") #This message displays after turning the button off... why?? The if statement clearly says 0 so I don't get why this part of the code would execute
                ignition = 1
        if ignition == 1:
            if button_off == 0:
                if get_fingerprint():
                    print("Car started.")
                    started = 1
    if started == 1:
        pass

#Button is off
    if button_off == 1:

        if ignition == 1: #should only do this once if the button was on, otherwise just continue polling the input state of the button.
            print("Accessories off") ###This statement works fine before the finger print, but will execute twice if I turn off the button after the finger sequence. Why?
            ignition = 0
            started = 0

One Answer

Thanks everyone for the suggestions. I suspected something like contact bounce wasn't the issue here because the button response works perfectly before the fingerprint sequence of the code executed, it was only after the get_fingerprint block returning True that the button would have the effect, making me think the python code was repeating somewhere it shouldn't.

To anyone googling this in the future or anyone interested in doing a similar project, here is the tweaked code that I got working with the help of a friend. Using a fingerprint reader compatible with the Adafruit fingerprint library and a switch, I can start my car using a fingerprint. I have the script boot at startup using crontab.

Some differences from my original code are the get_button() block, and reversing the negative logic to make it less confusing.

Here is the working code. I haven't field tested it extensively yet but everything appears to work perfect now.

import RPi.GPIO as io
import time
import adafruit_fingerprint
import serial
io.setwarnings(False)
io.setmode(io.BCM)

#GPIO Names
BUTTON = 5
ACC = 23
IGN = 27
START = 22
DOME = 20

#GPIO Setup
io.setup(BUTTON, io.IN, io.PUD_UP)
io.setup(ACC, io.OUT)
io.setup(IGN, io.OUT)
io.setup(START, io.OUT)
io.setup(DOME, io.OUT)
io.output(ACC, 1)
io.output(IGN, 1)
io.output(START, 1)
io.output(DOME, 1)

#UART/Fingerprint Setup
uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1)
finger = adafruit_fingerprint.Adafruit_Fingerprint(uart)

##################################################

def get_button():
    result = (not io.input(BUTTON))
    time.sleep(.1)
    return result

def get_fingerprint():
    while finger.get_image() != adafruit_fingerprint.OK: #Waiting for finger, loops
        if io.input(BUTTON) == 1: #Exit finger sequence if button off
            return False
    if finger.image_2_tz(1) != adafruit_fingerprint.OK:
        return False
    if finger.finger_fast_search() != adafruit_fingerprint.OK:
        return False
    return True

while True:

    car_on = get_button()

#Button is on
    if car_on:
        if io.input(IGN) == 1:
            io.output(IGN, 0) #Ignition and Accessory on
            io.output(ACC, 0)
        if get_fingerprint():
            io.output(ACC, 1) #Starter sequence
            time.sleep(.3)
            io.output(START, 0)
            time.sleep(.6)
            io.output(START, 1)
            time.sleep(.3)
            io.output(ACC, 0)
            while car_on:
                car_on = get_button() #Check for button off

        if io.input(BUTTON) == 1:
            io.output(IGN, 1) #Button Off = All Systems Off.
            io.output(ACC, 1)

Answered by cornerpocket on October 20, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP