Does Arduino's clock (millis) continue counting in the background during interrupts? - arduino

I have a quick question which apparently isn't said online from what I've read: I know millis() on an Arduino doesn't change during a custom interrupt, but does the associated timer still counts in the background?
My program is time-sensitive and I would like to know if I should increase its value (how?) each time one of my interrupts is handled so that the main program's clock doesn't drift.
Thanks in advance,
Regards,
Mister Mystère

The CPU-internal timer will count even when interrupts are disabled. BUT when the timer overflows an interrupt is generated which will increment some counter in the library. If that interrupt is blocked for a long time ... then you will have a drift.

The CPU timer is hardware and not affected by any interrupt flags. Once it overflows the overflow bit is set / an interrupt is triggered. If interrupts are blocked at that time this interrupt will be queued. The queue size is 1, that is your must allow interrupts before the next interrupt is triggered. Since the timer overflows roughly once per millisecond you will need to ensure that you never block interrupts for longer than ~1ms.
Anyway you will have a drift since the Arduino's clock is not that precise at all. See my experiment on crystal deviations.

Related

how to use esp32 ulp interrupt pulse counter and periodic wake up deepsleep mode

I am trying to measure power usage using dds353 kWh meter. This meter has a pulse output. I am interested in using the esp32 since I can periodically send the data over the internet to nodered dashboard.I am also very interested in using the esp32 in low power mode and periodically wake up to send data over mqtt. I have tried out examples from github using espressif idf but I would not mind an arduino equivalent. I would like to do hardware interrupt which when one of the rtc gpio pin goes high a counter is incremented while a seperate timer interrupt run and occasionally wakes up the main xtensia cores which fetches data from the rtc and sends it over. I have looked at the pulse counter examples and with my limited knowledge can not tell if the interrupts are triggered when the ulp is in sleep mode or only when it is on. I would really be glad if someone would show me how to basically use the ulp for counting pulses even when it is sleep mode and periodically wake up the main cores. I am ok with IDF or arduino examples
If you want to count pulses while in deep sleep youuse the ULP. Code on the ULP continues to execute when the board wakes up and goes to normal power mode. So when it is awake, it will still run the counter on the ULP processor unless you stop the ULP periodic wake up timer, ULP will keep waking up and running while the main CPU is active.
As you gave already checked with this example , it should be pretty close to what you need. The only difference seems to be that the example is set to wake up after a given number of pulses, rather than a fixed amount of time. However it should be easy to change that, by enabling deep sleep wake up from timer.For the Arduino you could check Some additional info:
ULP doesn't have GPIO interrupts. So you use deep sleep wake stub (small piece of code which runs immediately after deep sleep, prior to loading application from flash into RAM) you can increment the pulse counter variable, and go to sleep again. This way you can get low power consumption (~5uA) between pulses and moderate power consumption while running the wake stub (around 13mA), for a very short time.
So its up to you to experiment with your specific scenario.
You can use Pulse Counter(PCNT) feature in ESP32 to count the number of pulse in background, Understanding by using same you can able to do some periodic wake-up and read the count.. Its also possible to configure event when number of counts reached certain threshold and had lot of options,
For get information and available Interfaces and API's for Pulse Counter(PCNT) please follow below link, https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
Initially I faced lot of issue to make Pulse Counter(PCNT) work in Adrino IDE for ESP-32, After multiple attempt I make it working, And same sample code is uploaded in GitHub for reference. I have not use all the API's in the official documentation but but used few of them and are working..
I have created sample program for a water flow meter, there also we use to get pulse which needs to count to measure the water flow rate, understanding simile to kWh meter.
GitHub Sample code Path:- https://github.com/Embedded-Linux-Developement/Arduino_Sample_Programs/tree/main/ESP_32/Water_Flow_Pulse_counter_WithOut_Interrupt_Using_PCNT
I have not placing the code here, because its there in GitHub and not directly for the asked question, but simile one and can use it. Its a working code I tested in HW.
Hopes Its helpful,
Regards, Jerry James

Multiple timers or single task with multiple counter?

Assume you have some functions that must be called at different point in times but continuosly (constant task like each 250ms, each 2s, each 5 mins).
Is it better to use 4-5 timers each one dedicated to a task or is it better to code everything in the smaller task and then use a counter variable to run the other function?
e.g.
//callback each 250ms
void 250ms_TASK(){
if (counter % 8 != 0){ //250ms*8 = 2s
return;
}
// do 2 sec stuff
if (counter != 4800){ //250ms*4800 = 20min
return;
}
//do 20min stuff
counter = 0;
}
Assume also that you want to avoid/be bulletproof to situations like this:
before doing 2 secs stuff you MUST be sure that the 8th 250ms task is computed.
before doing 20 min stuff you MUST be sure that the 4800th 250ms and the 600th 2s task is computed.
The question is related to best practice and performance.
Moreover is it better to perform those calculations in the callback or use the callback to modify flags and perform the calculations in the main loop ?
I assume you are using STM32 since you tagged STM32.
Unless your application is very much time critical that you need to use preemptive and asynchronous timer interrupts (for example 5 mins task is very important so it should be called even while a separated 250ms callback task is running), using multiple timer interrupts is just waste of timers and you need to use as fewer interrupts as possible IMHO. Counting variable is not costly so it is okay to do that.
The real consideration is the length of tasks. The ISRs should be as short as possible so if the timer callback tasks are quite long you should use flags and use polling operation in the main loop. Polling flags is more preferable especially when you are using multiple callbacks in a single timer ISR. Imagine the moment that 250ms, 2s, and 20min callbacks should be called in the ISR and the ISR will take 3 times longer than usual.
By the way, if you decide to use a single timer, why not using SysTick? The SysTick timer is provided in every Cortex M MCUs and its operation is the same across the MCU families. You can easily configure this as 1ms interrupt timer very easily. As far as you use polling in the main loop 1ms interrupt must be fine. There are many tutorials on Systick (for example, part1 and part2)
The standard way to do this for tasks that aren't very time critical, is to implement a single timer, which triggers once every millisecond.
That timer then goes through a list of registered "software timers" and checks if it is time for them to be executed. If so, the timer then calls a function pointer which contains the timer-specific code. That is, a callback function called upon by the timer driver.
If these functions are kept minimal, for example just setting a flag, you can execute them from the main timer ISR.
You can make various arguments regarding power consumption and real timer requirement. It really depends on your application. But these question can deliver insightful answers for beginners, and even more experienced developers. The keyword here is scheduling.
The typical setup I prefer, bare metal real-time:
Main runs all low priority and idle tasks. Main bases these timings on the systick timer that ticks every 1 ms: if( (now - then) > delay ){ then = now; foo(); }
These tasks can be interrupted by everything, except in a critical zone (when using ISR threadspace data).
Low priority tasks are blinking LED's and handling communications.
There are peripheral interrupts and timers that set IRQ pending bits to signal real-time work is ready to be done. Eg: read uart or adc register before overrun.
The interrupt priorities and timers are setup in a way that the work is done in the correct order at the correct time. Eg: when processing ADC samples, and the hardware alarm IRQ arrives, this is handled immediately.
This way I have the DMA signal samples are ready to be processed, whilst a synchronized timer at a lower frequency set the IRQ-pending for the process loop. The process loop must run after the samples, thus has lower priority in the NVIC.
Advantage: Real time performance is not impeded when the communication channel is overflowed with data.
Disadvantage: The cpu never sleeps long.
The ISR's of the real time tasks may not exceed their time window. This is where Windowed Watchdog Timers are useful. Also, idle tasks will only run when there is time to spare. They might be late.
A similar option here is to use a real time operating system. Like ChibiOS.
However, when you're a battery application you don't want the MCU to wake up every second. You want the MCU to wake up only when work has to be done. You can do this in two ways.
Multiple hardware timers signal the wake-up event.
This requires multiple timers to keep running and might still use too much energy.
Tickless operation. You use one timer, the chip wakes up and does work when the time is reached. Then it reloads the timer compare with the time of the next deadline. If your intervals are long enough apart you can use the RTC for this to get ultra low power consumption.
Advantage: chip is allowed to go to sleep for longer period depending on workload.
Disadvantage: the design is a bit more complicated to implement and debug.
Similar option here is to use a tickless operating system.
Assuming you're not using a real time OS, I'd use a timer to do the time critical stuff (if it's handled with few clock cycles) and long timer counters through an interrupt and use non time critical stuff and longer periods in the main loop (with or without a watchdog timer/sleep).
The interrupts will interrupt the main loop stuff so you can be sure the time critical stuff happens when it needs to, the less time critical stuff happens whenever it can.
You could use a state machine in the main loop to do the logic stuff to make sure everything is done in the right order, things are checked, loaded, sensors read etc.
There is no right answer here, best practices would be to implement the design to meet the requirements, since requirements for a project vary from project to project there is no single right answer. One common solution will fail to work right for a wide array of products, as would another common solution. You could force one solution but that can add a lot of hacked up band-aids simply adding risk to the project, possibly lead to failure and or recalls or field upgrades that were unecessary that make the product and the company look bad. Do your system engineering and most of the time the correct solution will simply present itself, dont do your system engineering and the failures will simply present themselves.

Will a new interrupt while in function with nointerrupts() be queued and executed after interrupts()?

Will an AVR MCU (Arduino) remember all interrupts that happen while in nointerrupts() section?
void f1() {
noInterrupts();
// critical, time-sensitive code here
interrupts();
}
//now jump to queued interrupts if any
Will it execute them after interrupts()?
I ask this because after reading the datasheet, I have the feeling that all interrupts have their flag, so this could be no problem. But I'm not that experienced, and I'm missing something probably, because other tutorials always state vaguely that "don't stay there too long, since no interrupts at all may happen at that time".
Why?
I have a circular buffer where I put some packets from I2C (they are put whenever I2C interrupt occurs). I also read this buffer from the main loop once in a while, at unpredictable time and overwrite is allowed.
Also, I use the same buffer class (but different instances) in the opposite direction (I2C then triggers interrupt and reads).
My problem is: I would like to turn off interrupts during non-interrupt read/write, so I can be sure I will not be in a situation when I2C triggers and overwrites my item being currently read from normal, main loop.
I now kind of handle the situation with flags before and after read, so the interrupt first checks if the item is free, but I'm not confident in that approach, and I would like to make it work with noInterrupts() and interrupts() during main loop read.
Thank you.
Your approach seems normal. You need to disable interrupts to protect the buffer.
While the interrupts are disabled, interrupt flags will continue to be set but the handlers won't be called. When interrupts are enabled, the interrupt handlers will run.
The warning to not take too long with interrupts disabled is that two of the same type of interrupt may be triggered while disabled. If that happens, the single interrupt flag is set once, and there is no way to tell that there were two interrupts pending. The interrupt handler only runs once. Essentially, the first of the interrupts is lost.

Does the clearing of the specific interupt mask postpone or disregard interrupts while it's cleared?

I have a piece of code in Arduino (Avr) which I want to execute without it being interrupted by an interrupt that also operates on variables used in this piece of code. I don't want that interrupt to be lost while the piece of code is being executed; rather, I want to have the interrupt be postponed for a short time. I only want to postpone this one interrupt, not all interrupts.
Right now I'm clearing that interrupt mask and setting it again after the code is finished. Is this working? This is what the code looks like:
Piece of code I don't want being interrupted by that interrupt (timer1 overflow interrupt, in this case):
TIMSK1 = 0; //Set Timer1 Mask off. Just postponed ???? I hope so.
int c = buffer[reading_pointer];
reading_pointer = (reading_pointer + 1)%SIZE_OF_BUFFER;
something_on_buffer = false;
//buffer and something_on_buffer are set on Timer1 interrupt.
TIMSK1 |= (1 << TOIE1); //Enable timer1 again.
something_on_buffer and buffer are set also on Timer1, there would be a conflict if the interrupt executes in the middle of reading the buffer and setting something_on_buffer in this piece of code, and that's the reason I want to postpone Timer1 interrupts for this few lines of code. Just to be sure. How to do this? Is this the right way?
Your approach looks fine.
Generally, processors have a flag register for the interrupts, and a register to enable the interrupts. At each step, the processor checks the and of the flags and enable bits to see if it should run an interrupt. That is, the enable bits don't control whether the flag is set, only if the set flag induces the interrupt to run.
If you enable an interrupt by setting the bit and the flag is already set, the interrupt with run before the next machine instruction.
If the interrupt is not enabled, the flag bit can still be set by the condition.

Arduino encoder interrupts corrupting serial data

I have an Arduino Mega connected to a 6 axis robotic arm. All 6 interrupts are attached to encoders (one encoder pin on an interrupt, the other on a vanilla digital input). The interrupts are handled with this code:
void readEncoder1(){
//encoders is a 2d array, where the first d is the axis, and the two pin numbers
//first pin is on an interrupt (CHANGE), and second is a standard digital in
if (digitalRead(encoders[0][0]) == digitalRead(encoders[0][1])) {
positions[0]++;
} else {
positions[0]--;
}
if(servoEnable){
updatePositions(); //// compares positions[] to targets[] and adjusts motor speed accordingly
}
}
This is designed to keep the arm locked at a certain position- if the arduino detects that the position of the motor is off by a certain threshold, it updates the power going to the motor to keep the arm in position.
The problem is this, then -- if two or three (or more) axis are under load (requiring constant updating to stay in position) or they are moving, the Arduino will stop receiving intact commands on Serial input, several characters will be dropped. The interrupts are obviously running quite quickly, and for some reason this is causing commands to become corrupted. Is there any way around this? Architecturally, am I doing this right? My main instinct is to call updatePositions() in the main run loop at, say, 100 ms intervals, will this significantly reduce interrupt overhead? I guess what my question boils down to is how do I get reliable serial commands into the Arduino even if all 6 encoders are pulsing away?
Quadrature encoders were designed to be read by hardware counters. Pulse rates are generally high with the motor running at full speed. One megahertz is not unusual. The higher the number of pulses, the better the servo loop works and the more accurate you can position the motor.
Doing this is in software with a low-power cpu is, well, challenging. It will fall apart when the ISR takes longer than the interval between pulses. You'll lose pulses and thus position. Especially bad because there is no way you can detect this error condition. And that this loss happens when the robot is moving fast, the worst case condition to lose control.
You absolutely cannot afford to update the servo loop in the interrupt handler so get rid of that first. Keep the ISR to the bare minimum, only count the position and nothing else. The servo loop should be separate, driven by a timer interrupt or tick. You cannot properly control a robot with a 100 msec servo update unless it is big an sluggish, this needs to be a handful of milliseconds at most to get smooth acceleration and stable feedback.
There's a limited amount of wisdom in spending forty bucks to control thousands of dollars worth of robot hardware. Not being able to keep up in the servo loop is something you can detect, shut it down when the position error builds up too much. There's nothing you can do about losing pulses, that's a wreck. Get the hardware counters.
First rule of embedded systems:
Do as little as possible in interrupts.
In your case, just update the positions in the interrupt and run your position/speed control loop in the background or at a lower priority.
Aside: I assume you are aware that you are "losing" encoder pulses as you don't have an interrupt on one of the channels?
Also, interrupt-driven encoder-analysis is very noise-prone. If you get a noise pulse, you'll likely only see an interrupt for one of the edges as they'll be too close together to process both.
A more robust way is to use a state machine which watches all 4 transitions, but that requires either interrupts on both edges of both channels, or polling fast enough to not miss anything up the to rate you are expecting to see.

Resources