Drawbacks of delay - arduino

With the following:
Serial.begin(9600);
I am printing two values:
Serial.print(Input);
Serial.println(Output);
delay(100);
I am measuring temperature and PWM signal.
What are the drawbacks of using delay?

Here are a couple of drawbacks of using delay :
Inaccuracy
Unable to multitask
There is one good way to go make a delay without using delay(), it's by using millis(). See here for great examples of why millis() is better than delay() and how to maximize its capability.

It is usually fine to use delay() in simple programs. However, imagine you have 4 tasks:
T1 which you want to execute every 2s
T2 which you want to execute every 3s
T3 which you want to execute every 3.5s
Serial read task, which should read serial input as soon as it arrives
How would you deal with that using delay()? It is much better to use approach based on millis() or micros() functions, like here, or use the elapsedMillis library, which under the hood does the same, but makes a code a bit more readable.
The main idea, is that you want to have a sort of timers, that store a time elapsed from last reset. You check the state of these timers in every iteration of the loop() function, and if they finish, you execute associated task:
void loop() {
if(isTimerDone(Tim1)) {
T1();
resetTimer(Tim1);
}
if(isTimerDone(Tim2)) {
T2();
resetTimer(Tim2);
}
if(isTimerDone(Tim3)) {
T3();
resetTimer(Tim3);
}
readSerialPort();
}
That way it is very easy to change timing for each task, as it is independent of other tasks. It is also easy to add more tasks to the program.
It is also true, that delay() (but also millis()) are innacurat,e in a sense that you are not guaranteed to have an exact timing. To be sure that a task is executed exactly after given time, you need to use interrupts, like in here (Arduino Playground on Timer1).

Related

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.

How do I measure how long operations take on an Arduino Mega?

I'm writing code that requires me to have certain code run at exact times (Like a loop taking 8ms long) on an Arduino Mega. I'm trying to figure out how to calculate this by finding out how long it takes for a Mega to make one calculation and multiplying it by the # of calculations in a certain block of code. Is this the correct way of approaching this problem? How do I even count how many calculations are going on?
One of the simplest ways to implement a timer is by using millis() in your loop() function and comparing it against the last time your code ran, something like this:
long loopTime = 0;
loop()
{
if (millis() - loopTime >= 8)
{
// Do the stuff here that you want to happen every 8ms
// ...
//
// Keep track of the last time this code ran, so we'll run it
// again 8 ms from now
loopTime = millis()
}
// Do other stuff here
}
Note that this will not be precise, because the millis() function doesn't guarantee an exact figure. If you require absolute precision you'd need to use some sort of external hardware timer to generate an interrupt every 8 ms. Interrupt programming gets a bit more complex, but the timing loop technique shown above should work for most things that don't require absolute precision.

Which is a better option for multitasking in arduino - millis( ) or Scheduler Library?

I have an application wherein I want to flash( trigger for a sec) a solenoid every 10 seconds and at the same time receive a serial input to rotate a servo motor.
The delay() creates conflicts so I have gone through the millis() function which is easy to understand.But in the arduino website they have something called the Scheduler library which looks pretty damn easy( haven't tried it though).
So which is better and efficient option to consider, is it millis() or Scheduler?
Thank you,
The Scheduler library uses millis() as well to calculate the delay between tasks.
To link a function to the sheduler, it needs to have a void f(void) prototype.
So to be able to add a function that returns something or has parameters, you need to wrap it in another function of void f(void) prototype.
IMHO, a sheduler library is usefull to organize your code when you have multiple tasks (This library has a maximum of 10 tasks, but you can change it).
In your case, you only have two tasks. It may be better to just use your own little sheduler using millis().
If you want to stay with millis(), then
Simple Multi-tasking in Arduino
will be of help. It covers:- adding a loopTimer to see how slow your loop/tasks are running, removing delays from your code and third party libraries, reading serial input without blocking and sending serial prints without blocking and giving important tasks more time.
Finally it transfers the code unchanged to the ESP32 to add remote control.
The basic code is
void loop() {
callTask_1(); // do something
callTask_2(); // do something else
callTask_1(); // check the first task again as it needs to be more responsive than the others.
callTask_3(); // do something else
}
The trick is that each callTask..() method must return quickly so that the other tasks in the loop get called promptly and often. The rest of the instructable covers how to keep your tasks running quickly and not holding everything up, using a temperature controlled, stepper motor driven damper with a user interface as a concrete example.

Computation during analogRead on Arduino

The Arduino A/D converter takes about 0.1ms according to the manual. Actually, my tests show that on an Uno I can execute about 7700 per second in a loop.
Unfortunately analogRead waits while the reading is being performed, making it difficult to get anything done.
I wish to interleave computation with a series of A/D conversions. Is there any way of initiating the analogRead, then checking the timing and getting the completed value later? If this needs to be low-level and non-portable to other versions, I can deal with that.
Looking for a solution that would allow sampling all the channels on an Arduino on a regular basis, then sending data via SPI or I2C. I am willing to consider interrupts, but the sampling must remain extremely periodic.
Yes, you can start an ADC conversion without waiting for it to complete. Instead of using analogRead, check out Nick Gammon's example here, in the "Read Without Blocking" section.
To achieve a regular sample rate, you can either:
1) Let it operate in free-running mode, where it takes samples as fast as it can, or
2) Use a timer ISR to start the ADC, or
3) Use millis() to start a conversion periodically (a common "polling" solution). Be sure to step to the next conversion time by adding to the previously calculated conversion time, not by adding to the current time:
uint32_t last_conversion_time;
void setup()
{
...
last_conversion_time = millis();
}
void loop()
{
if (millis() - last_conversion_time >= ADC_INTERVAL) {
<start a new conversion here>
// Assume we got here as calculated, even if there
// were small delays
last_conversion_time += ADC_INTERVAL; // not millis()+ADC_INTERVAL!
// If there are other delays in your program > ADC_INTERVAL,
// you won't get back in time, and your samples will not
// be regularly-spaced.
Regardless of how you start the conversion periodically, you can either poll for completion or attach an ISR to be called when it is complete.
Be sure to use the volatile keyword for variables which are shared between the ISR and loop.

Need an Arduino Sketch that uses digital write for a certian number of seconds

I need a simple way to run a program using digital write for a certain number of seconds.
I am driving two DC Motors. I already have my setup complete, and have driven the motors using pause() and digitalWrite(). I will be making time measurements in milliseconds
Adjustable runtime, and would preferable have non-blocking code.
You could use a timer-driven interrupt triggering code execution which will handle the output (decrementing required time value and eventually switching off the output) or use threads.
I would suggest using threads.
Your requirement is similar to a "blinking diodes" case I described in a different thread
If you replace defines setting time intervals and use variables instead you could use this code to drive outputs or simplify the whole code by using only one thread working the same way aforementioned timer interrupt would work.
If you would like to try timer interrupt-driven approach this post gives a good overview and examples (but you have to change OCR1A to about 16 to get overflow each 1ms) .

Resources