I'd like to check with you if it's me doing something horribly wrong, or is it just a problem that should be fixed on Arduino side.
Here it is:
Lets say I want to capture some data on pin interrupt and then to process it in multiple steps
I want data to remain same during all my calculation sequence so interrupt has to be disabled at that time
But when I do detachInterrupt()- board crashes with MBED OS error code blinking orange LED
It was working fine on board library versions older then 1.3.0, but newest 1.3.0 and 1.3.1 result in same thing described above
Here is the simple sketch that hangs my board like a charm
#define int_pin 13 // Pin to listen
int num; // Super important variable
void int_fun(){
num += 1; // Some super useful super quick interrupt code
}
void setup() {
// put your setup code here, to run once:
attachInterrupt(digitalPinToInterrupt(int_pin), int_fun, CHANGE); // Attaching interrupt on setup
}
void loop() {
// put your main code here, to run repeatedly:
detachInterrupt(digitalPinToInterrupt(int_pin)); // Disabling interrup so it's not messing the data
delayMicroseconds(20); // Pretend we do some useful calculation with data we got from interrupt
attachInterrupt(digitalPinToInterrupt(int_pin), int_fun, CHANGE); // And now we want it back
delayMicroseconds(40); // Pretend we're executing some more code
// This sketch crashes Arduino Nano 33 BLE with MBED-Enabled Boards "library" of version 1.3.0 and most up-to-date 1.3.1
}
So what is the best solution for this issue then?
From what I can guess- is some kind of a semaphore- resetting bool flag before calculation and setting it inside the interrupt
Afterwards we can check the flag, and if it's true- that means we can't trust the result.
Just thinking about "most developers won't detach interrupt", so what's the better (or right) way?
If we're talking about capturing multiple values inside the interrupt and even saving them to separate set of variables will take few lines of code and therefore can be interrupted and variables will get out of "sync"
kaws:
If we're talking about capturing multiple values inside the interrupt and even saving them to separate set of variables will take few lines of code and therefore can be interrupted and variables will get out of "sync"
Are you worried about having multiple interrupts from the same source while you are still working on the interrupt with the first data set?
Here are a few points for thought
in the long run you need to have enough processing time to work on your data
in the ideal case you finish working on a data set when the next interrupt is triggered
if your interrupts come in bursts e.g. 3 interrupts every 1ms but your computation needs 10ms per interrupt but you will not have more than 5 interrupts in 100ms you can store your data in buffers
on the Cortex-M4 (the processor in the Nano 33 BLE) interrupts with the same priority cannot interrupt each other
two interrupt service routines should not use the same variables
interrupt service routines should not work on data but only read/write new data and set flags for the main code
If this does not help, could you please describe the issue you are foreseeing a bit better.
How are you capturing multiple values inside the interrupt?
What is the timing for your interrupts? e.g. random, every ms, bursts, ...
Do you have an example sketch and a scenario that would create the issue?
My thing is pretty simple- I need to dynamically measure a frequency on the given input
There is a square wave and i want to capture both falling and rising edge
Calculation requires time delta between two edges
So the interrupt have first to save previous timestamp and capture the new one.
It's done
Next in the code i need first to "save" thouse values from the set that is accessible by interrupt to some local variables which we'll be working with now
Those are, again, just two lines
After that we're good to go to further steps.
What I am worried about- is interrupt happening in the middle of two lines
So timestampLastISR (from the first line) in this case will get outdated and we'll get twice of a delta
Delta calculation can be moved to interrupt code itself, but I believe that interrupt code needs to be as quick as possible
I am expecting 10-1000hz frequency. But it also can be 0 for a while (if wheel is not spinning)
Not to often, around 2-3 times a second
It is only needed to show it to the user, and in some cases it's limiting the output level when frequency exceeds threshold. But there's nothing too accurate.
Yes, I am using BLE and something else that needs a lot of computational power It is u8g2 lib for OLED display (I think you are familiar with another forum thread of mine. It's all the same project, but this issue is not so critical)
I would simply use a software pulse counter in the interrupt service routine. This will make life a lot easier. Using micros will not give you any more precision. The error is +-1 transition/s. At 10Hz you have an error of +- 50ms/s (you get two transitions per Hz). So, no need for a microsecond timer.
You can use millis() in the main loop to take the counter value every second (or half) and display it and then clear it.
If you really want to use time capture, I recommend to have a look at the datasheet and learn how to use a timer for capture. This would allow you to measure much higher frequencies and free your processor from interrupts. The nRF52840 on the Nano 33 BLE has a whole collection of timers with capture function.
Yeah, timer is a great idea
I think millis() and micros() are so simple and handy that I got used to them too much and forgot that usual timers do even exist
Thanks