Use Piicodev Button to call a program

Hi there, is there a way to use button to call another program in Pico?
The story is, I want to call a program when I press the button and stop the program when I release the button.
Not sure if there is a sample code to help me to do that.

Really appreciate for your help!

1 Like

Hey @Puzheng278952
Welcome to the forums

It depends what you mean by a “program”

If by program you just mean some code or a specific behaviour then yeah!, you can totally trigger code with a button press.

You search term here is “hardware interupt on the pico”. Here’s one that looked good Raspberry Pi Pico Interrupts Tutorial- Examples in MicroPython

A simple while(gpio.ispressed) might work too.

Good luck, feel free to ask any further questions.

Thank you @Pixmusix !
Yes a program is just another simply main.py file stored in Pico.
Now I can run main.py by pressing the button, but I cannot stop the program running by double pressing the button.

Any ideas will be much appreciated!

Thank you!

1 Like

Oh sorry I thought the idea was to run the program while the button was held down?
Is that still your preferred behavior?

Have a look at this page of the docs where it talks about external interrupts.
Notice that you can interrupt on the rising edge (button down) or the falling edge (button up).
You might choose the connect the same button to two different GPIOs to get the effect.

Can I clarify, is there anything stopping you from checking the button’s state in your pico’s loop?

# Backflips will be plentiful while the button is held down
while true:
   while(buttonGPIO.value()):
      # do a backflip

Would you prefer a double click to turn off the program? It’s possible but requires more code.

1 Like

Thanks for getting back to me @Pixmusix :slight_smile:

Sorry I didnt explain my question clearly, and I am truly a newbie to Pico and Python :rofl:. Please allow me to explain in more detail.

The hardware I have: Pi Pico, PiicoDev expansion board and PiicoDev Button. So all the hardware has been connected via PiicoDev connector.

The Python code I have stored in Pico is: main.py and test.py

What I am hoping to achieve is to autorun the main.py when Pico powered up, and call test.py when I press the button, and end test.py when I double press the button, then call test.py again when I single press it.

What I am asking might be a very silly question and can be done easily, apologise for my lack of understanding in Python.

Hope the above makes a bit more sense, really looking forward to hearing from you :slight_smile:

Is the problem that you cannot detect a button double press? If that’s the problem then show the code you are using, describe what you expected it to do, and describe what it actually does.

Or is the problem that you need to do something else when the program ends? Usually, ending a program is done by putting it in an endless do-nothing loop. If you are going to call test.py again at some later stage then it seems you need to run main.py again. That would just be a copy of the code you already have to to call test.py, with a change of the program name.

1 Like

Ahhhhh! That’s an i2c device :slight_smile:
The good news is that you won’t need any hardware interupt logic with an i2c button like the piicodev button.

Edit : This was in the title the entire time I just missed it oops

That’s super clear :slight_smile:
I second Jeff where we should establish we can read the button and get the correct behavior.
There are lot’s of ways to do this but I think the path you will find easiest is to create a variable called “shouldMyProgramRun”.

shouldMyProgramRun = False

if button.was_pressed:
   shouldMyProgramRun = True
if button.was_double_pressed:
   shouldMyProgramRun = False

print("should my program run?: ",shouldMyProgramRun)

The next thing I want to know is what is test.py?
What does it do? Is it a long program? Should it run once or should it run in a loop?

Thanks @Jeff105671 and @Pixmusix .

The button press can be detected.

What does test.py do is very simple. I have got a PiicoDev Buzzer connected as well. So in main.py, the buzzer starts playing ‘music’.
What does test.py do is, when I single press the button, run main.py, and when I double press the button, end main.py.
My problem is I dont know how to end main.py in test.py and I have no idea how to get main.py running again after it has been ended.

Maybe it will be easier if I just add a power switch to turn Pico on/off?

Ahhh.
If you double press when the music is only half way through do you expect it to stop playing immediately or would you be happy to let the audio play out until the end and then not repeat?

What happens if you just run main.py when the button is pressed in test.py, exactly like you are doing to run test.py when you press the button in main.py?

1 Like

What I am hoping for is to stop playing the music immediately when I double press the button. Then replay when I single press it.

When I press the button in test.py, the music will start playing and wont stop. Well, it stops eventually but won’t stop immediately.

Ok I see your problem.
When you press the button the pico starts working on the playing the music.
But the pico has to “stay focused” on keeping the music playing.
When you double press to stop, the pico isn’t listening because it’s too busy running test.py
Finally, when the music stops, the pico is free to focus back on the button and only now notices it was supposed to have stopped ages ago.

What you need is multithreading/multiprocessing.
One thread runs test.py and the other thread checks the button.

I’m sorry but I’ve never done non-blocking code in micropython but maybe someone else can assist.

No worries Jonny, really appreciate for your time and help. Good thing is now I know what is the problem :slight_smile:
I will keep searching see if there is any possible solution for it

1 Like

Possibly, but that’s nothing to do with playing music. It’s simply to do with how (or if) the button is being interrogated while the music is playing. Threading could be used to play the music, but it isn’t required unless, of course, OP doesn’t have access to the test.py code. That’s possible given that we haven’t seen any example of the code that is being used. But if it’s not required for a reason such as that then there will be much simpler ways of detecting the button press.

3 Likes

Hi @Puzheng278952,

As @Pixmusix said, multithreading could work, though there are also a couple of other options as @Jeff105671 mentioned.

I expect your PiicoDev Buzzer and PiicoDev Button code is very similar to that seen in our guides on both devices?

If you are able to send the code you’re using for both main.py and test.py, we can likely suggest some methods. This is the best path forward to allow us to give you accurate suggestions!

1 Like

@Puzheng278952 Suggest you have a look at using Asyncio in microython on the Pi Pico. It allows two separate processes to run at the same time or seem like they are running at the same time.
In a project I have, one process continually monitors a button and sets a global variable when the button is pressed. This process waits for 100ms at the end of the loop.
The other process does other stuff and also checks the variable and does something if it is set.

Happy to put some code together if you need.
Regards
Jim

PS the multithreading @Pixmusix suggested would be used in a more advanced system like a Pi 4 or 5 where the operating system handles the multithreading tasks.

2 Likes