I have this code that I'd like to run to test the interrupt capabilities of my arduino nano esp32 - here the nano would just read and print the transmitter signals. Currently the problem seems like the interruptISR just won't be called.
#include <ESP32Servo.h>
const int receiverPin = 2;
volatile int startTime = 0;
volatile int currentTime = 0;
volatile int pulses = 0;
void setup() {
pinMode(receiverPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(receiverPin), interruptISR, CHANGE);
Serial.begin(9600);
}
void loop() {
int receiverSignal;
if (pulses <= 2000) {
receiverSignal = pulses;
}
Serial.println(receiverSignal);
}
void interruptISR() {
currentTime = micros();
if (startTime < currentTime) {
pulses = currentTime - startTime;
startTime = currentTime;
}
}
I tested this with a handful of pins but all seem to have the same issue, on the serial monitor I am getting a bunch of 0s, sometimes nothing at all. Nor transmitter or receiver are the issue, it works fine with pulseIn().
The problem is that it somehow worked perfectly fine once or twice before it stopped working entirely with the interrupt...
I'm probably missing the point. I don't have a Nano ESP32, but on an ESP32 devboard, building with Arduino IDE 1.8.13, the sizeof() both int and unsigned long is 4 bytes. Maybe Nano ESP32 is different?
Hi @alexaccountrelatedemails. It looks like there is a bug in the digitalPinToInterrupt and attachInterrupt functions that causes them to not work correctly with Arduino pin numbers.
You can work around the bug by doing this:
Select Tools > Pin Numbering > By GPIO number (legacy) from the Arduino IDE menus.
Change line 3 of your sketch from this:
const int receiverPin = 2;
to this:
const int receiverPin = D2;
Upload the sketch to your Nano ESP32 board.
Hopefully it will now work as expected.
I reported the bug to the developers:
Explanation
In case you are curious to understand the bug, I'll provide an explanation below. If you aren't interested in the boring details, you can skip reading the rest of this post.
The problem is that both functions do an Arduino pin number to GPIO number conversion.
You can see here that digitalPinToInterrupt passes the pin number to the conversion function digitalPinToGPIONumber:
So when you pass Arduino pin number 2 to the digitalPinToInterrupt function, it converts it to GPIO number 5 and returns that as the interrupt number (the interrupt number is the same as the GPIO pin number on ESP32). Everything is correct so far.
But you can see here that the attachInterrupt function also passes the interrupt number to the conversion function digitalPinToGPIONumber:
So now that interrupt number 5 is incorrectly treated as if it was an Arduino pin number and converted to the GPIO number for Arduino pin 5, which is 8. So the code actually attaches the interrupt on Arduino pin 5 instead of pin 2 as intended.
Changing the pin-Numbering to <By GPIO number (legacy)> in the tools tab did the trick. I even switched back to the default Arduino pin and checked the signals on D5 while having D2 read in the code and indeed it turned out it attached the interrupt to pin D5.
I was scratching my head and looking for answers for days, trying out everything... Thank you @ptillisch, much appreciated for the quick response.