Interrupt Queueing
Pin interrupts on Rpi pico with arduno-pico code
Confusion on implementing button interrupts on Pi Pico written in C - Stack Overflow
arduino ide - Raspberry Pi Pico locks up when I try to use interrupts - Stack Overflow
Videos
You are getting an infinite loop in void button_callback(). The main issue I see is in the while loop inside that function. It's hanging because when the interrupt occurs it's called but it never returns. while(1) creates an infinite loop that wont let the main loop continue (it is waiting on the function.) I would scrape the while loop and have the callback set a flag or modify a value. What little I know about interrupt service subroutines is that the functions should be as short and straightforward as possible, with a simple conditional and a flag. Something like this inside button_callback:
if(gpio == button){
buttonPressed =1;
} else if(gpio == buttontwo){
buttonTwoPressed = 1;
}
And that's all it needs. Similarly for your other functions with loops in them. The ISR is supposed to be a short bit of code that reacts to an event, and flips a flag or value, that the main loop then sees. I hope that helps you make some progress. Good luck.
Based on recommendation I removed the while loop in the callback.
void button_callback(uint gpio, uint32_t events)
{
printf("Interrupt occured at pin %d, with event %d\n", gpio, events);
if(gpio_get(button) == 0x000)
{
printf("Button one pressed.\n");
place_marker++;
printf("Place is %d.\n", place_marker);
} else if(gpio_get(buttontwo) == 0x000)
{
printf("Button Two Pressed.\n");
place_marker--;
printf("Place is %d.\n", place_marker);
} else
{
}
}
Does the mapping function digitalPinToInterrupt for the Pi Pico work? Can you try just using the interrupt number that corresponds to the pi?
attachInterrupt(9,readEncoder,RISING); //Or the number 0-25 which maps to that pin
https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__irq.html
You have the wrong pin to encoder in your example (maybe you incorrectly copy and pasted)?
attachInterrupt(digitalPinToInterrupt(**encA**),readEncoder,RISING);
void readEncoder() {
int bVal = digitalRead(**encB**); ...}
There is similar code on GitHub that you could modify and try instead.
https://github.com/jumejume1/Arduino/blob/master/ROTARY_ENCODER/ROTARY_ENCODER.ino
It might help you find a solution.
Also, https://www.arduino.cc/reference/en/libraries/rpi_pico_timerinterrupt/
The interrupt number corresponds to the pin (unless you have reassigned it or disabled it) so for pin 11 the code can be:
attachInterrupt(11, buttonPressed, RISING);
This works:
bool buttonPress = false;
unsigned long buttonTime = 0; // To prevent debounce
void setup() {
Serial.begin(9600);
pinMode(11, INPUT_PULLUP);
attachInterrupt(11, buttonPressed, RISING);
// can be CHANGE or LOW or RISING or FALLING or HIGH
}
void loop() {
if(buttonPress) {
Serial.println(F("Pressed"));
buttonPress= false;
} else {
Serial.println(F("Normal"));
}
delay(250);
}
void buttonPressed() {
//Set timer to work for your loop code time
if (millis() - buttonTime > 250) {
//button press ok
buttonPress= true;
}
buttonTime = millis();
}
See: https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__irq.html for disable, enable etc.
For those who see the in the future: I found a solution. The add_repeating_timer_ms and add_repeating_timer_us functions take callbacks which return a boolean value: if that bool is false, they stop the regularly firing timer. So you can set a repeating timer and cancel it after the first interrupt by returning false from the interrupt handler.
If there are only regular timer interrupts you will need to cancel the regular timer after the interrupt.