Debugging python code for explorer hat

would anyone be able to help me with my code for my explorer hat. when I touch button 1 the pattern starts with the leds. Then if i press button 2 whilst button 1 pattern is happening it does not switch over (it is the same if pattern 2 is running and i touch button 1(nothing happens))
could anyone suggest what i could do to make this work(so it switches over to the other pattern) code is below :

import explorerhat
import time

print(“press a button to start a pattern”)

while True:

if explorerhat.touch.one.is_pressed():
    
    while True:                           
        explorerhat.light.blue.on()
        time.sleep(0.2)
        explorerhat.light.yellow.on()
        explorerhat.light.blue.off()
        time.sleep(0.2)
        explorerhat.light.yellow.off()
        explorerhat.light.red.on()
        time.sleep(0.2)
        explorerhat.light.red.off()
        explorerhat.light.green.on()
        time.sleep(0.2)
        explorerhat.light.green.off()
        explorerhat.light.red.on()
        time.sleep(0.2)
        explorerhat.light.yellow.on()
        explorerhat.light.red.off()
        time.sleep(0.2)
        explorerhat.light.yellow.off()
        
if explorerhat.touch.two.is_pressed():
     
    while True:
        explorerhat.light.blue.on()
        explorerhat.light.red.on()
        time.sleep(0.4)
        explorerhat.light.yellow.on()
        explorerhat.light.green.on()
        explorerhat.light.red.off()
        explorerhat.light.blue.off()
        time.sleep(0.4)
        explorerhat.light.green.off()
        explorerhat.light.yellow.off()

explorerhat.pause()


Your use of while True basically means your light pattern will repeat forever once triggered, and the code will never reach the next if statement.

A while loop means you’re telling the interpreter to “keep doing this thing over and over.” A while True loop will always repeat while True is True, and since True is always True, that means it can only be broken out of with a break, return or by exiting the code altogether.

By way of example, if I told you to hop on your left leg with your eyes shut and your fingers in your ears until instructed to do otherwise, you’d never hear or see me telling you to stop.

If I told you to hop 10 times, you’d hop ten times and then be ready to receive your next instruction. This would be approach 1, and in pseudocode it would look something like:

forever:
    if touch one is pressed:
        run my first light pattern 10 times

    if touch two is pressed
        run my second light pattern 10 times

So after 10 runs of either light pattern, your program would be back to checking if either touch one or two is pressed. At the moment, it’s stuck permenantly.

An alternate approach is to split your code into two logical processes. Imagine I’ve told you to “hop on your left leg leg with your eyes shut and your fingers in your ears”, and I’ve told you to keep doing that until George, our hypothetical other process, pokes you with a stick.

George is instructed to do something like this:

forever:
    if touch one is pressed:
        poke pi2003 with a stick
    if touch two is pressed:
        poke pi2003 with a stick

So now every time a button is pressed, either button in this instance, despite me not being able to tell you what to do by waving my arms or shouting, George will poke you with his stick you’ll swap from hopping on your left leg to your right leg.

Explorer HAT has a George, albeit not in so many words, you can ask Explorer HAT to watch a button for you and run some code:

import explorerhat
import time

pattern = 0

def change_pattern(channel, event):
    global pattern
    pattern = channel

explorerhat.touch.pressed(change_pattern)

print("Press a button to start a pattern")

while True:
    if pattern = 1:
        explorerhat.light.blue.on()
        time.sleep(0.2)
        explorerhat.light.yellow.on()
        explorerhat.light.blue.off()
        time.sleep(0.2)
        explorerhat.light.yellow.off()
        explorerhat.light.red.on()
        time.sleep(0.2)
        explorerhat.light.red.off()
        explorerhat.light.green.on()
        time.sleep(0.2)
        explorerhat.light.green.off()
        explorerhat.light.red.on()
        time.sleep(0.2)
        explorerhat.light.yellow.on()
        explorerhat.light.red.off()
        time.sleep(0.2)
        explorerhat.light.yellow.off()

    if pattern = 2:
        explorerhat.light.blue.on()
        explorerhat.light.red.on()
        time.sleep(0.4)
        explorerhat.light.yellow.on()
        explorerhat.light.green.on()
        explorerhat.light.red.off()
        explorerhat.light.blue.off()
        time.sleep(0.4)
        explorerhat.light.green.off()
        explorerhat.light.yellow.off()

In this case, explorerhat.touch.pressed is our George. He will watch all of ExplorerHAT’s buttons and call the change_pattern function when one of them is pressed.

change_pattern is super simple, it just sets our pattern variable to the channel ( or button ) number. Press 1 and pattern will be set to 1. Etc!

Now, our while loop is where the magic happens. It doesn’t have to worry about who’s pressing what button anymore, so it can just check what number pattern we should be running and keep running the corresponding pattern.

thanks very much for the detailed explanation (it helped me understand the code a lot!)

just one problem which is probably just a stupid thing I am doing wrong

when I run the code in either python 2 or 3 it says that there is ivalid syntax with the = in this part

if pattern = 1:

I also assume it is happening with the second one but it only displays one error at a time.

what am i doing wrong
Thank you

Sorry I think that should be: if pattern == 11

= sets a value to a variable, whereas == checks for equality.

thanks so much your the best phil. you have been so helpfull

You’re welcome! Come and dug up this thread if you have any other troubles! Or if you want to share the results!

@gadgetoid Decided to dig up this thread to ask about dot hat as well as I am trying to do something similar with dot hat (displaying enviro phat readouts.) so far I have got this

mode=0
@touch.on(touch.CANCEL)
def change_mode(channel, event):
global mode
mode = channel

If that is correct
what would the version of

explorerhat.touch.pressed(change_pattern)

be on dot hat.

Thanks in advance

ps what I am trying to do is similar to what sandy did in bilge tank 42