emba
Posts: 19
Joined: Sun Jul 29, 2012 8:54 pm

can someone please help debug my simple py prog?

Thu Aug 23, 2012 10:22 am

im trying to create a basic number guessing game which flashes an LED via GPIO with the LED flashing faster the closer you are to the number (its for teaching to others but im not that experienced myself, its a bit of one of them "i just have to stay one lesson ahead of the student situations" :P )

so far ive got the program to work but i can only either get the led to flash continually but it wont return to the guess prompt it just remains flashing, or i can get it to flash the led once then return to the prompt (thats where im at in the code youll see in a sec) what i want is for the LED to keep flashing and have it to return to the guess prompt, id guess im just missing something simple here so hopefully someone can put me right. heres the code as it stands (please dont shout at me for its messyness and lack of commenting, im just learning at the mo, ill clean it up once its working)

Code: Select all

#!/usr/bin/python
# Filename: pyth.py

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(7, GPIO.OUT)
GPIO.output(7, False)
GPIO.output(11, False)


def blink1():
	while True:
		GPIO.output(7, True)
		time.sleep(1)
		GPIO.output(7, False)

		time.sleep(1)
		
		main()

def blink2():
	while True:
		GPIO.output(11,True)
		time.sleep(0.1)
		GPIO.output(11, False)

		time.sleep(0.1)

		main()

def main():
	running=True
	while running:
	
		number = 23
		
		guess = int(input('Enter an integer : '))
		
		if guess == number:
			print('Congratulations, you guessed it.')
			running=False
		elif guess < 20:
			print('No, it is higher than that') 
			blink1()
		elif guess < 30:
			print('No, it is a little lower than that')
			blink2()
		elif guess < 40:
			print('No, it is a bit lower than that')
		elif guess < 60:
			print('No, it is a quite a bit lower than that')
		
		else:
			print('No, it is way lower than that')
		
		print('Done')

main()
any help is greatly appreciated

MadCow42
Posts: 106
Joined: Sun Jul 01, 2012 12:48 am

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 2:23 pm

You're asking the system to do two things at the same time. i.e., keep flashing the LED, and also look for input from the user.

To do that, you need to manage two separate processes. Otherwise, the system will wait for one thing to finish before doing the other. This is possible, and actually fairly easy in Python, but you'll need to use the threading module.

My recommendation is to do some research on threading. I'd run the user input in the "main" program, and start a separate thread that flashes the LED. You can communicate between the threads using flags and locked variables. (such as a variable to control the flashing speed).

I'd write some pseudo-code for you here, but it's a good learning experience. There's lots of documentation on python threading online. :)

(and yes, threading on the Pi works just fine. I'm using it to very successfully drive two stepper motors at the same time, completely independently of each other)

Kevin.

timhoffman
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 3:26 pm

On a side note. You are calling blink1 and blink2 from main, then in each of blink1 and blink2 you call main, and never drop out of the loops. If this code actually managed to run for a while you would probably run out of memory or blow out the stack (not a lot different in the end ;-).

Ignoring for a minute the blinking of leds, you should be terminating your loops in each of blink1 and blink2, (ie break after so many loops or have the while check true on some sentinal value etc..) and then have the functions return, back to the calling context - in this case main.

Cheers

Tim

emba
Posts: 19
Joined: Sun Jul 29, 2012 8:54 pm

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 3:33 pm

thanks for your advice, i asked on the python irc and they suggested the same thing or using event looping or blocking io, good job its a bank holiday as ive got a lot of reading to do

@tim

thanks for the tip, that was actually mainly because i was messing around with it to see if i could get it to work, it went through many iterations before that one with functions being called in many places and ways, that was just the code as it stood at post time, but its something ill bear in mind for the future, but how would one terminate the loop after say 5 loops? extend the final time.sleep then "break"? (sorry im fairly new to all this really, i think im in way over my head but hey its the way i learn best! :P )

EDIT:

well that was much easier than i thought itd be, a quick read on threading and i now have it working, now to read more and clean up the code. Thanks all!
Last edited by emba on Thu Aug 23, 2012 3:49 pm, edited 1 time in total.

trouch
Posts: 310
Joined: Fri Aug 03, 2012 7:24 pm
Location: France
Contact: Website

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 3:42 pm

as tim said, infinite recursive call between main and blink => stack death ;)

WebIOPi - Raspberry Pi REST Framework to control your Pi from the web
http://store.raspberrypi.com/projects/webiopi
http://code.google.com/p/webiopi/
http://trouch.com

emba
Posts: 19
Joined: Sun Jul 29, 2012 8:54 pm

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 4:02 pm

yeah that part is long gone now, calling main in the blink functions was just an attempt to get it to return me to the main prompt again, i now have it working with threads, i just need to find out how to kill them once the next is called as even when i ended the program the LEDs were still blinking away until i restarted the pi! ive a lot to learn!

MadCow42
Posts: 106
Joined: Sun Jul 01, 2012 12:48 am

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 5:57 pm

just a simple pseudo-code for you after all. :) (not efficient, can easily be improved/shortened

Code: Select all

import time, threading
from RPi import GPIO as GPIO

def blink_thread(sleepVar, sleepVarLock, killFlag):
    while 1:
        if killFlag.isSet():
            break
        sleepVarLock.acquire()
        sleepTime = sleepVar
        sleepVarLock.release()
        time.sleep(sleepTime)

        GPIO.blahblahblah to turn your GPIO on

        if killFlag.isSet():
            break
        sleepVarLock.acquire()
        sleepTime = sleepVar
        sleepVarLock.release()
        time.sleep(sleepTime)

        GPIO.blahblahblah to turn your GPIO off

if __name__ == "__main__":
    # start the blinker
    killFlag = threading.Event()
    killFlag.clear()
    sleepVar = 0.10
    sleepVarLock = threading.Lock()

    blinkThread = threading.Thread(target = blink_thread, args=(sleepVar, sleepVarLock, killFlag))
    blinkThread.start()

    while 1:
        # get your user input here
        blah blah blah user input
        blah blah blah, determine the new blink rate

        sleepVarLock.acquire()
        sleepVar = newSleepTimeYouCalculatedAbove
        sleepVarLock.release()

    killFlag.set()  # makes sure the second thread shuts down when you exit the program.
That's not debugged. use the sleepVarLock before/after you access the variable for read or write so that you don't have two threads trying to use it simultaneously. However, in reality you're only working with pseudo-threads, so it shouldn't be an issue with this particular use. Good form though.

The killFlag is there so you can shut down the other thread easily when you exit the program.

The blink function loop could be simplified by having a variable to tell you if the LED is currently on or off and flipping it... instead of duplicating the code.

EDIT: you're probably going to have an issue with the sleepVar above... the blink rate won't change when you change the value of sleepVar. The problem is that it gets passed into the thread by VALUE, not by REFERENCE... so when you change the variable value, the thread doesn't see it. I usually wrap the main program in a class, and use "self.sleepVar" or whatever as the variable to pass to the thread, so that you can pass it in by reference. Sorry... but if you know how to use classes it shouldn't be difficult to modify. To be simpler, you could also probably cheat by passing in the variable wrapped in a mutable object... like a list (not a tuple)... then extracting it after. i.e.: sleepVar = [0.10], and reference it in the function as sleepTime = sleepVar[0] and sleepVar[0] = 0.25 etc.


Enjoy!
Kevin

emba
Posts: 19
Joined: Sun Jul 29, 2012 8:54 pm

Re: can someone please help debug my simple py prog?

Thu Aug 23, 2012 9:57 pm

you sir are a true gent, thanks!

MadCow42
Posts: 106
Joined: Sun Jul 01, 2012 12:48 am

Re: can someone please help debug my simple py prog?

Fri Aug 24, 2012 12:59 am

emba wrote:you sir are a true gent, thanks!
:) Have fun!

BlackJack
Posts: 288
Joined: Sat Aug 04, 2012 8:28 am
Contact: Website

Re: can someone please help debug my simple py prog?

Fri Aug 24, 2012 7:25 am

Another way to communicate between the two threads would be a `Queue.Queue` object. It is already thread safe, so no need to create/use locks. You could pass the blink speed as numbers and `None` as special value to stop the thread.

Code: Select all

while not self.asleep():
    sheep += 1

timhoffman
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm

Re: can someone please help debug my simple py prog?

Fri Aug 24, 2012 1:44 pm

I would strongly recommend looking at Queue s as blackjack has mentioned. It generally means simpler code as is good general mechanism for send data to child threads.

BerryPicker
Posts: 177
Joined: Tue Oct 16, 2012 3:03 pm
Location: The East of England

Re: can someone please help debug my simple py prog?

Fri Dec 07, 2012 1:43 pm

MadCow42 wrote:My recommendation is to do some research on threading.
I found an informative and instructive article entitled "threading – Manage concurrent threads" here:
http://www.doughellmann.com/PyMOTW/threading/

Return to “Python”