I'm trying to create an automated robotic machine which detects various signals from operator and acts accordingly. It has 4 inputs (3 switches, 1 signal receiver) and 8 outputs (4 LEDs, 1 beeper, 1 gear fwd/bwd, 1 motor power, 1 transmitter ).
I'm using the python RPi.GPIO library to interact with the Raspberry pi 2 model b GPIO pins.
The first problem I ran into was with the `add_event_detect` function not detecting bidirectional change of state inputs correctly even after experimenting with various bouncetime values. Below is the code I ended up using to switch on/off an LED on receiving input from switch.
Not working reliably, slow to respond to changes or not responding to changes:
Code: Select all
# Adding event detect to the switch pin GPIO.add_event_detect(swtch, GPIO.BOTH, updateledstate, 100)
Working reliably, fast to respond to changes when function is invoked from a while loop every 10ms:
Code: Select all
# This method will be invoked when an event occurs def updateledstate(channel): global led global ledstate if GPIO.input(channel) == 0: # Turn off LED. if ledstate == 1: ledstate = 0 GPIO.output(led, ledstate) print "LED is OFF" if GPIO.input(channel) == 1: # Turn on LED. if ledstate == 0: ledstate = 1 GPIO.output(led, ledstate) print "LED is ON" while(True): updateledstate(swtch) time.sleep(0.01)
The second and more frustrating problem I've encountered is reacting to these inputs inside the above while loop. I have written idempotent programs that processes information or inputs sequentially and then processes outputs with database transactions to log change of state and other variables. With realtime programming that updates every 10 ms and produces outputs within 5 ms I'm at a loss as to how to react to various inputs without use of any database to refer to previous input states. I tried making do with primitive counters but the more complex the inputs the harder it gets to code and maintain. An example of this is when one of the switches is used to set a timer. Every change of state is detected as a single press of the pushbutton switch (and increments timer by 1s), if the switch is pressed continuously for 10s the timer is reset. Below is the extremely un-intuitive code I wrote inside the while loop to implement this timer switch.
Code: Select all
# inside while loop which is updated every 10 ms # Blue/Set timer button action. # pbval is a variable which contains the current input state # x, total_pbval are counters # timer_val is the current timer value in seconds if pbval == 0: # Turn off blue led. GPIO.output(led_blue, 0) total_pbval = 0 pbval_a = pbval, x if pbval == 1: # Turn on blue led. GPIO.output(led_blue, 1) total_pbval += 1 pbval_b = pbval, x if total_pbval >= 1000: print "BLUE button pressed for 10s. Proceed to reset timer." os.system("/bin/echo 0 > /root/timer.file") timer_val = 0 # Flash blue led and beeper for reset confirmation. for xi in xrange (3): GPIO.output(led_blue, 1) GPIO.output(beeper, 1) time.sleep(0.5) GPIO.output(led_blue, 0) GPIO.output(beeper, 0) time.sleep(0.5) if timer_val not in xrange (1, 601): if timer_val >= 601: timer_val = 0 os.system("/bin/echo 0 > /root/timer.file") elif timer_val < 0: timer_val = 0 os.system("/bin/echo 0 > /root/timer.file") timer_ok = 0 # Turn off amber led. GPIO.output(led_amber, 0) else: timer_ok = 1 # Turn on amber led. GPIO.output(led_amber, 1) # Set time. pbval_1 = pbval_a x_1 = pbval_a pbval_2 = pbval_b x_2 = pbval_b # Find change of state. if (x in pbval_a) and ( abs(x_1 - x_2) == 1 ): pbval_cur = pbval_1 pbval_last = pbval_2 elif (x in pbval_b) and ( abs(x_1 - x_2) == 1 ): pbval_cur = pbval_2 pbval_last = pbval_1 else: pbval_cur = 0 #pbval_last = 0 # Find if change is from 0 to 1: rising edge. if pbval_cur == 1 and pbval_last == 0: #we have rising edge. timer_val += 1 command = "/bin/echo %d > /root/timer.file" %timer_val os.system(command) if timer_val not in xrange (1, 601): if timer_val >= 601: timer_val = 0 os.system("/bin/echo 0 > /root/timer.file") elif timer_val < 0: timer_val = 0 os.system("/bin/echo 0 > /root/timer.file") timer_ok = 0 # Turn off amber led. GPIO.output(led_amber, 0) else: timer_ok = 1 # Turn on amber led. GPIO.output(led_amber, 1)