I'm attaching an interrupt to pin D2, which works fine (I can see that the interrupt is being called. However, I'm unable to read the actual pin state (HIGH/LOW) from within the interrupt. Here is the code:
The call digitalRead(2) in the ISR always returns HIGH (or it simply doesn't work), so I'm unable to detect the end of the pulse. I hope that I'm not doing something stupid here by reading the pin state right after the interrupt is triggered... If not, well, then there must be some bug.
I used uint32_t instead of int declarations to avoid any unintentional overflows and I added in noInterrupts() at start of isr() code and then Interrupts() at end of the ISR() and it worked (sort of?)... I did try the detachInterrupt() option inside the ISR() but that just froze things up.
gerrikoio:
I used uint32_t instead of int declarations to avoid any unintentional overflows and I added in noInterrupts() at start of isr() code and then Interrupts() at end of the ISR() and it worked (sort of?)... I did try the detachInterrupt() option inside the ISR() but that just froze things up.
Thanks for the tips. With these changes, were you able to correctly read a pin value from inside the interrupt? IMO this is very basic functionality, which one can see in tons of examples, so I'm inclined to think that the behaviour I'm observing is one of the quirks of the Arduino wrapper around the mbed OS. Maybe I should move to programming the board in mbed directly, and get rid of these quirks?
Yes it worked, as in pwm_value was updated. As to whether the values were correct, who knows. Anyway, IMHO, I think it is necessary to use noInterrupts() and Interrupts() as "bookends" in any ISR to ensure it functions correctly.
Interesting. However, I have decided to do it in mbed OS. I did some reading, and I like its capabilities. Unfortunately there're almost no examples or documentation around on how to interact with mbed OS from Arduino, and Nano 33 BLE can't be connected from mbed ide directly.
Anyway, at the end it wasn't that hard. Here's the code:
haplm:
Interesting. However, I have decided to do it in mbed OS. I did some reading, and I like its capabilities. Unfortunately there're almost no examples or documentation around on how to interact with mbed OS from Arduino, and Nano 33 BLE can't be connected from mbed ide directly.
Well done. That's really helpful.
I had done some small code experiments using mbed and discovered that many of the #includes you've used such as #include <mbed.h> are already in Arduino.h. Maybe check this out to confirm.
Also you can use namespace, as in "using namespace mbed;", meaning there's no need to use "mbed::" with your mbedos code. I believe, this too may already be included in Arduino. h.
Looks good. You've just demonstrated something to me. When reading through your code, I felt that the use of "mbed::" and "rtos::" really helped with understanding where the functions come from.
Yeah, those mbed, rtos, etc spaces help to understand where the functions are coming from. One flaw of the code is that variables in_steering_update_ok and in_steering_update_failed are not thread safe, but since they are just a temporary debug, I didn't bother.
It is going to be interesting when I'll be reading 2 PWM inputs, 7 digital pins, I2C and SPI interfaces, while having to output 2 PWM channels with minimum latency. Well, we will see.
BTW - I've just found that with a programmer, one can use the board in Mbed Studio directly (Mbed OS on Arduino Nano 33 BLE | Djynet). I guess that this is what I'm going to do once I get a programmer...
I've come across the same problem to the original post. It appears to me that interrupts fire ok when using RISING or FALLING but not CHANGE - here they only fire on a rising edge, therefore always reading 1 when reading the pin in the ISR.
gerrikoio:
I used uint32_t instead of int declarations to avoid any unintentional overflows and I added in noInterrupts() at start of isr() code and then Interrupts() at end of the ISR() and it worked (sort of?)... I did try the detachInterrupt() option inside the ISR() but that just froze things up.
I adapted the code as suggested but still the same result.
I have added a flag so the output is only printed when the interrupt has fired. Input is a 1Hz square wave from a sig gen (later to be a RC receiver).
My code:
volatile uint pwm_value = 0;
volatile uint prev_time = 0;
volatile int FLAG = LOW;
volatile bool lastState;
void setup() {
Serial.begin(115200);
// when pin D2 goes high, call the rising function
pinMode(2, INPUT);
lastState = digitalRead(2);
attachInterrupt(digitalPinToInterrupt(2), isr, CHANGE);
}
void loop() {
if (FLAG==HIGH){
FLAG = LOW;
Serial.print("PWM: ");
Serial.print(pwm_value);
Serial.print("\tLAST: ");
Serial.println(prev_time);
}
}
void isr() {
noInterrupts();
FLAG = HIGH;
int ts = micros();
bool state_now = digitalRead(2);
if (state_now == HIGH) {
prev_time = ts;
} else {
pwm_value = ts - prev_time;
}
interrupts();
}
Output with timestamps shows only rising edge triggering the interrupt:
Ah, nice. So CHANGE is now working? I need to try it... Generally, I have noticed that bugs are being actively worked on, which is good. I have hit something else, and found out that it is already fixed in mbed 6.0 beta 1. Now we just need to wait to ArduinoCore update to mbed 6.0
Works for me. Interestingly I've had a real jitter problem that seems to be caused by erroneous readings on the input (pretty sure caused by I terrupt latency) AND by erroneous outputs from servo.write().
I'm not really sure how it relates to the problems encountered here, but I've started a new thread explaining them as it really doesn't fit under this title.
Sure, I'll post the solution for Servo issues there. I have pointe you to this thread because I have mentioned it as well up there, but I agree that this thread is a bit mess.