'Raspberry Pi Pico locks up when I try to use interrupts

I'm trying to use encoders to track the movement of three wheels on a robot, but as soon as any of the motors move the robot "locks up", it stops responding to commands, stops printing to the serial monitor, and just keeps spinning its wheels until I turn it off. I cut out everything except just the code to track one encoder and tried turning the wheel by hand to sus out the problem, but it still locked up. And even more strangely, now it will start spinning one of the wheels even though I've removed any code that should have it do that, even by mistake.

I used the Arduino IDE to program the pico since I've got no familiarity with python, but I can't find any information or troubleshooting tips for using interrupts with the pico that don't assume you're using micropython.

Here's the simplified code I'm using to try to find the problem. All it's meant to do is keep track of how many steps the encoder has made and print that to the serial monitor every second. Ive tried removing the serial and having it light up LEDs instead but that didn't help.

int encA = 10;
int encB = 11;
int count = 0;
int timer = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encA),readEncoder,RISING);
  timer = millis();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (timer - millis() > 5000) {
    Serial.println(count);
    timer = millis();
  }
}

void readEncoder() {
  int bVal = digitalRead(encB);
  if (bVal == 0) {
    count--;
  }
  else{
    count++;
  }
}


Solution 1:[1]

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/

Solution 2:[2]

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, Button_Pressed, RISING);

This works:

bool ButtonPress = false;
unsigned long button_time = 0; //To prevent debounce

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(11, INPUT_PULLUP);
  attachInterrupt(11, Button_Pressed, RISING); //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 Button_Pressed(){
  if (millis() - button_time > 250) //Set timer to work for your loop code time   
{
    //button press ok
    ButtonPress = true;
  } 
  button_time = millis();
}

See: https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__irq.html for disable, enable etc.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AORD
Solution 2 AORD