RPi.GPIO Button Help Please

Hello, all.

I was very pleasantly surprised to be find out about this newsgroup.

It would be appreciated if anyone here could help me with my GPIO problems.

I am building a device that has three arcade buttons ("Massive Arcade Buttons" from Adafruit) attached to a Raspberry Pi via the GPIO pins. The Pi is attached to a Blinkstick Pro that controls an analog LED light strip. The idea is that pushing a button will change the LED strip to the colour of that button and the Pi will record how much time the strip spends as each colour.

For quick develop purposes I replaced the code that changes the colour of the LED strip with a print statment. Once I have the buttons working I will go back to the colour changing code.

It does not work right now. All my variations of the code result in one of three problems. An error message stating "Conflicting edge detection already enabled for this GPIO channel", the script running then quiting in under one second, or sitting there being unresponsive to anything.

Here is the script. This very is unresponsive, unless I remove the sleep command. When I do that it runs and quits instantly.

import atexit import time from blinkstick import blinkstick import RPi.GPIO as GPIO

led = blinkstick.find_first() colour = 0 timered = 0 timeyellow = 0 timeblue = 0 timestamp = time.strftime("%H:%M:%S")

GPIO.setmode(GPIO.BCM) GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

def red_button(channel): colour = 1 while colour == 1: print "Red Button pressed" timered += 1

def yellow_button(channel): colour = 2 while colour == 2: print "Yellow Button pressed" timeyellow += 1

def blue_button(channel): colour = 3 while colour == 3: print "Blue Button pressed" timeblue += 1

GPIO.add_event_detect(23, GPIO.RISING, callback=yellow_button, bouncetime=200) GPIO.add_event_detect(22, GPIO.RISING, callback=red_button, bouncetime=200) GPIO.add_event_detect(24, GPIO.RISING, callback=blue_button, bouncetime=200)

while True: time.sleep(0.1)

def exit_handler(): print '\033[0;41;37mRed Team:\033[0m ', timered print '\033[0;103;30mYellow Team:\033[0m ', timeyellow print '\033[0;44;37mBlue Team:\033[0m ', timeblue flog = open('flag1log.text', 'a') flog.write(timestamp + '\n' + 'Red Team: ' + str(timered) + '\n' + 'Yellow Team: ' + str(timeyellow) + '\n' + 'Blue Team: ' + str(timeblue)

  • '\n') flog.close() atexit.register(exit_handler) GPIO.cleanup()

Would very much appreciate help getting this working. Thank you.

Reply to
John McKenzie
Loading thread data ...

On Fri, 28 Aug 2015 17:53:00 GMT, John McKenzie declaimed the following:

About time -- I could swear I'd mentioned it a few weeks ago in the Python group...

(OKAY -- it was only 8 days ago... Where I also pseudo-coded [since I don't have the hardware] a possible solution; did you even look at it?)

Of course it is unresponsive...

All of your button routines contain an infinite loop... "colour" will never change inside the callback routine... And the "OS" can't check for other buttons until you return from the any active callback.

This is an infinite loop so nothing written under it will ever be executed... That also means...

... the exit handler is never defined -- Python doesn't compile functions and then execute the "main" code... "def" IS an executable statement, you have to reach it to execute the definition of the function itself.

And these will not be executed either.

Removing the "while True" loop means the program DOES define the exit handler, then registers it, and THEN IMMEDIATELY executes the GPIO.cleanup() call and runs off the end of the program (ie; it ends)

Since you apparently didn't read or question my original response, I won't repeat it here.

I will suggest, however, that you put ALL "def" blocks immediately under your "import" statements... NO OTHER EXECUTABLE statements mixed into them. I suggest you put the registration of the exit handler as the first main line executable statement, before setting up the GPIO lines. Oh, and GPIO.cleanup() needs to be INSIDE the definition of the exit handler.

Lastly, I suggest you put simple print statements inside your button handler routines that print a message when they are entered, and (futile as they are currently) when they are supposed to exit.

--
	Wulfraed                 Dennis Lee Bieber         AF6VN 
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/
Reply to
Dennis Lee Bieber

On Sat, 29 Aug 2015 13:37:55 -0400, Dennis Lee Bieber declaimed the following:

Ah -- And I see you did respond in the Python group (my newsreader first runs the Earthlink server, and then does gmane, so I didn't see your response in the Python group until after replying here...

--
	Wulfraed                 Dennis Lee Bieber         AF6VN 
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/
Reply to
Dennis Lee Bieber

When I say I was surprised to find out I mean I found out because you mentioned it as did some one else in the same thread. Sorry if I should have given specific credit to who pointed me here.

It was only a little while ago that you mentioned it. As I stated in my reply I would only have time to work on this weekend and was happy you gave some info to work with.

I read your response several times. And I appreciate that you took time to write, hence me offering my thanks, stating I would repeat the question in the Pi newsgroup, and I would go work on it when I could, specifically this weekend.

Just because I asked the same question elsewhere does not mean I did not read you post. Your post gave me info to work with, not a for sure definitive solution, so I had to post the question elsewhere just in case. In fact I sat down now to work on it taking into account everything you said, but thought I should check this newsgroup to be up to date on everything.

While I intended to use what you said as a starting point your whole tone was "How dare you ask here, go ask in comp.sys.raspberry-pi so I do not have to look at how bad this is". Had no idea you would be here. If I did I would copied my thanks from the other group to here. But I still would have asked the same question.

You should know I may resort to asking for help on the Raspberry Foundation website. As much as I despise those web based BBSs I may register on their fourm. I will post the same question there and this is not an indication that I am ignoring you, your effort is appreciated, just that I am trying to get help from anywhere I can in order to better my chances of getting this working by a deadline I wish to meet.

In addition to your other posts thank you for the time it took to do this one. You explained some things a bit differently in this post and combined with the other post I feel I understand it better, so thanks for the extra stuff you wrote today.

Now I checked the postings here so off I go to work on it. Thanks for all your help.

Reply to
John McKenzie

On Sat, 29 Aug 2015 18:10:42 GMT, John McKenzie declaimed the following:

And I apologize for my apparent tone...

As my follow-up mentioned -- I discovered you'd posted in both AFTER I'd made the first comment here...

Guess I'd gotten so used to seeing people posting repeated demands (not you) at something like four hour intervals, that an 8-day gap gave an impression that you'd left Python without comment, and then came here.

I tend to follow this group just out of curiosity -- I'm not up-to-date on Linux, and my collection of small boards is a slew of Arduinos (2 UNO, a Due, and an Esplora), overpriced BASIC Stamps, Parallax Propeller boards, some bare PIC chips, and three TIVA boards (What was TI thinking of: a controller chip with 6 32-bit timers (splittable into 12 16-bit) AND 6

64-bit timers (splittable into 12 32-bit)? And the board uses a second one of the same chip just as the debug/programming interface! For
Reply to
Dennis Lee Bieber

Thanks for that. Appreciate your help, and it is all good now.

I have seen countless people with unreasonable expectations of how quickly they should get an answer to a question. That is totally understandable.

OK, everyone reading this, it turns out my ignorance of electronics, not just my ignorance of python, was the problem and I did something that is now clear to me as being very daft.

My code was for wiring that uses the 3.3v connector, but I had it wired to the ground pin. Needed to pull up in the pull_up_down commands and looking for falling edges in event detection.

My current issue is that if I push a button the LED strip lights up that colour without turning off the previous colour. If anyone wants to see the code feel free to ask here or by email, but the person who created the Blinkstick is looking at it and should get back to me with advice soon. I will post the final code and wiring when I have that working.

However, the buttons are responsive now and that is a very good thing.

Reply to
John McKenzie

On Sat, 05 Sep 2015 19:20:32 GMT, John McKenzie declaimed the following:

The most likely odds are that your code for button presses sets the output pin for that button/color -- but you are not unsetting the pins for the other colors.

--
	Wulfraed                 Dennis Lee Bieber         AF6VN 
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/
Reply to
Dennis Lee Bieber

Either keep track of what's switched on, and switch it off before the next switch-on event (unless it's for the same LEDs, in which case do nothing) or just switch all LEDs off every time there's a new switch-on event.

Reply to
Rob Morley

Hello, folks. Thanks for the continuing replies.

Dennis: I do not know if what you are saying applies to this situation. The pins are set for input only and the LED strip is control via USB using the Blinkstick Pro and LED adapter mentioned in my first post. Perhaps I am misunderstanding.

Rob: I tried adding a command to set the colour to nothing: led.set_color(name="black") and a command to turn off the LED altogether: led.turn_off() and doing nothing.

In all those cases, it was the same.

Removed the while loop from the colour changing and it does what is expected. The LED strip pulses once, but does not add colours when other buttons are pressed, it pulses the correct colour.

The following is what I am working with now and trying things on.

==Begin Code==

import atexit import time from blinkstick import blinkstick import RPi.GPIO as GPIO

led = blinkstick.find_first() colour = 0 time_red = 0 time_yellow = 0 time_blue = 0 timestamp = time.strftime("%H:%M:%S")

GPIO.setmode(GPIO.BCM) GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def red_button(channel): led.set_color(name="black") colour = 1 while colour == 1: led.pulse(red=255, green=0, blue=0, repeats=1, duration=3000, steps=50)

def yellow_button(channel): led.set_color(name="black") colour = 2 while colour == 2: led.pulse(red=255, green=255, blue=0, repeats=1, duration=3000, steps=50)

def blue_button(channel): led.set_color(name="black") colour = 3 while colour == 3: led.pulse(red=0, green=0, blue=255, repeats=1, duration=2000, steps=50)

GPIO.add_event_detect(22, GPIO.FALLING, callback=red_button, bouncetime=200) GPIO.add_event_detect(23, GPIO.FALLING, callback=yellow_button, bouncetime=200) GPIO.add_event_detect(24, GPIO.FALLING, callback=blue_button, bouncetime=200)

while True: if colour == 1: time_red += 1 elif colour == 2: time_yellow += 1 elif colour == 3: time_blue += 1 time.sleep(0.1)

def exit_handler(): print "\033[0;41;37mRed Team:\033[0m ", time_red print "\033[0;43;30mYellow Time:\033[0m ", time_yellow print "\033[0;44;37mBlue Time:\033[0m ", time_blue flog = open("flag1.log", "a") flog.write(timestamp + "\n" + "Red Team: " + str(time_red) + "\n" + "Yellow Team: " + str(time_yellow) + "\n" + "Blue Team: " + str (time_blue) + "\n") flog.close() GPIO.cleanup() atexit.register(exit_handler)

==End Code==

(For those looking at the above as an example if using buttons, remember GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_UP) and GPIO.add_event_detect(22, GPIO.FALLING, callback=red_button, bouncetime=200) are for wiring that uses ground. If instead of ground you wired up to 3.3v, use PUD_DOWN and GPIO.RISING instead.)

The creator of the Blinkstick suggested I remove the colour changing from the callbacks and put it under the while True loop in its own block of if and elif. This caused the buttons to be unresponsive.

So the while looping of the pulse command is needed to keep the colour pulsing, but it also seems to be the source of my problem.

Reply to
John McKenzie

On Wed, 09 Sep 2015 18:19:17 GMT, John McKenzie declaimed the following:

In normal callbacks, you must exit the callback before the framework will process additional events..

But since colour is never changed INSIDE this loop, the loop will never exit. To be more explicit -- WHEN DOES COLOUR CHANGE? Note that even if your framework does do real nested interrupts, "colour" is LOCAL to each callback. Nothing outside of the callback function can change the value, and the value never gets out of the callback function, so nothing can "turn it off".

Look for "global" in the Python reference manual.

Out of curiosity, put a "print(channel)" inside those callbacks; I'm interested in what value is being passed in. I still suspect it will be the pin number registered to the event, which means you only need ONE callback routine with an IF-comb to branch on the pin number. THAT alone might improve the code...

-=-=-=-=-

if channel == 22: led.pulse(red=255, green=0, blue=0, repeats=1, duration=3000, steps=50) elif channel == 23: ...

--
	Wulfraed                 Dennis Lee Bieber         AF6VN 
    wlfraed@ix.netcom.com    HTTP://wlfraed.home.netcom.com/
Reply to
Dennis Lee Bieber

Dennis, thanks.

I am all about better quality, more elegant code, but being a beginner at Python I wonder if I may need to keep it simpler, even if it overall worse, for the short term.

You are making curious too, will give the print statement a try.

We discussed global variables before and I complete forgot until MRAB in the Python group pointed it out and here you are coming to the same conclusion. So bad on me for not learning from previous postings because I was so focused on my button hardware/software problems.

Off to make things global.

Reply to
John McKenzie

Thanks to the help of several people, including Dennis who posts here and in the Python group, I improved the code and added features.

Ask if you want me to post it here, but you can find it in comp.lang.python under a thread started August 16th, 2015 entitled "RPI.GPIO Help".

Thanks.

Reply to
John McKenzie

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.