Go Down

Topic: (Pseudo) multi-tasking? (Read 2995 times) previous topic - next topic


Hi all,

I am trying to flash or maybe scroll a text on one line of the LCD and beep a piezo while running the rest of the loop().

delay() is out of the question I suppose, so I have to use millis()?
How to remove all calls to delay() and replace them by millis() without having a messy code? Especially with a lot of if() statements and functions... Do I have to set different lastRan1,2,3... = millis() variables for each if() and each functions?

Thanks for your help,


In the arduino application there is a blink without delay example, under the examples menu. This shows you what you need to do.



How to remove all calls to delay() and replace them by millis() without having a messy code?
Especially with a lot of if() statements and functions...

All code gets a little bit messy very fast. The trick is to "modularize" from the getgo, so the main
loops are easy to read, and don't look like spaghetti, and the "messiness" - meaning all those
nasty if() statements - get moved into function calls and out of the main loop.

There have been several threads here on "blink without delay" in the past month, that you
might look up.

I've also developed my own non-blocking delay routine, which allows something like pseudo-
multitasking, and which I intend to post here in a day or two, but it involves a lot of if..thens
plus state-machines. IOW, for my part, I've not found any magic ways to write painless code to
do complicated things.


Here's an example:

Please post technical questions on the forum, not by personal message. Thanks!

More info:


Loop() goes round and round.

For every action, everything watched, you set up within loop() an if to check if it is time or other condition to run that bit of code which should be kept short so the rest is not delayed.

Example: one action is to receive serial data. Get the characters 1 at a time and if possible, evaluate them as they come in. Even at 115200 baud there is a lot of microseconds between characters to do other tasks. If you buffer and wait for end of transmission then you are creating a longer task later.

What order you arrange your tasks can make a difference. Use Occam's Razor.

At the end of a task, consider writing in a return. That will start loop() over again immediately.

Each task, write as asynchronous code. As above, keep the steps short (make steps, not "now I will parse and lex the string, doh-de-doh!"), accomplish a little bit on the cycle and fast loop() cycling will become smooth tasking. You'll know when it's 'full'. Also if you can, avoid using floats or at least trim down on floating point operations where possible, Arduino has no FPU.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts



Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.


Use something line this: TaskScheduler
I think you are about 2 years too late for this party.

Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up