And this is where it takes off. Other functionality can come from other code already debugged and ready. It allows a toolbox of sketches that could be made into libraries but don’t have to be.
To be fair - in programming, words often carry meanings that differ from everyday language and without being pedantic, “task” typically suggests concurrency or parallel execution, not just a unit of work. So when someone says “functions run as tasks,” many programmers will assume each runs in its own thread, coroutine, or process.
I can give you other examples with implicit technical meanings like “thread,” which doesn’t mean a discussion thread or a long, thin strand of fiber used to stitch pieces of fabric together but a sequence of instructions running concurrently; “class,” which refers to a code structure defining objects, not a group of students; “event,” which signals a specific condition in a program rather than a social happening; “object,” which means an instance of a class; “state,” which refers to stored data representing the current condition of a system; or “context,” which defines the scope or environment in which code executes.
Each of these terms takes on a specialized sense in programming discussions, understood intuitively by experienced developers.
Having a common language facilitates written asynchronous conversations where it’s easy to get lost otherwise.
I have posted many examples showing parallel execution with non-blocking code versus serial execution with blocking code.
And as far as assume… ass/u/me.
Over 40 years ago, Main Loop Programming was showing the difference between Turn-Based Games and Real-Time Sims on 1 MHz 6502 toys with 64K RAM or less. I first did it with a VIC-20 and an article in Creative Computing, then used it at work.
It doesn’t HAVE to be completely parallel for Tasks To Run At The Same Time. It just has to be Effective.
Last Version of the Latest Example:
// DelayOrNoDelayWithLoopCount V1.1 by GoForSmoke 6/21/25 --
// replacing jumper for mode selection with serial commands
// cleaned up a lot of variable names and comments
// make sure that your Serial Monitor only sends \n or \r end of line!
// DelayOrNoDelayWithLoopCount V1 by GoForSmoke 6/20/25 --
// LoopCount sketch lines added to run like the Status Blink as a parallel Task
// Serial Monitor output improved and more verbose -- Uno speed up to 64K range.
// DelayOrNoDelay V1 by GoForSmoke 6/3/25 -- some changes to...
// DualActionDelayMillis v1.1 by GoForSmoke 11/18/24 -- made for Uno R3
// expect: ground pin 7 to run delay mode, not grounded runs timer mode
// expect: enter key in Serial Monitor to pause action, unpause action
// code revised 2/7/25 -- now using arrays and function calls + status led
// note that Arduino millis is +/-1 and that printing takes time as well!
// line taken from my 2024 NoBlockLoopCounterLT sketch.
extern volatile unsigned long timer0_millis; // might be faster than millis()
// end line taken
const byte statusBlinkPin = 13; // Uno board LED pin13 to run as status led
byte statusBlinkState = 0; // led13 0=OFF, not-0=ON
unsigned long statusBlinkStart;
const unsigned int statusBlinkInterval = 500;
const byte tasks = 2;
byte mode = 1; // 0 runs delay mode, 1 runs time mode
const unsigned long interval[ tasks ] = { 3000000, 700000 }; // for 2 timings, both modes wait time
unsigned long start[ tasks ]; // for 2 timings, timer mode
byte started[ tasks ] = { 0, 0 };
byte task = 0;
byte pause; // paused if 1
void usage()
{
Serial.println( F( "\n\n Dual Action Delay Millis 2/7/25 \n" )); // now shows version
Serial.println( F( " Enter D or d in Serial monitor to run delay mode." ));
Serial.println( F( " Enter T or t in Serial monitor to run time mode." ));
Serial.println( F( " Enter P or p in Serial monitor to pause data scrolling." ));
Serial.println( F( " While paused, P, p, or Enter will end pause." ));
Serial.println( F( " Loop count will print, status led13 blink, in Time Mode only." ));
}
// function taken from my 2024 NoBlockLoopCounterLT sketch.
void LoopCounter() // tells the average response speed of void loop()
{ // inside a function, static variables keep their value from run to run
static unsigned long count; // only this function sees this
static bool lastBit10Set; // only this function sees this
word millis16 = timer0_millis;
count++; // adds 1 to count after any use in an expression, here it just adds 1.
bool currentBit10Set = millis16 & 0x0400; // leverage integral to bool implicit promotion
if (currentBit10Set != lastBit10Set) // 1 second
{
// Serial.print( millis16 ); // 16-bit binary into decimal text, many micros
// Serial.write('\t');
Serial.print( F( "Loops " )); // added for demo, not from the taken code
Serial.println( count ); // 32-bit binary into decimal text, load of cycles!
count = 0; // don't forget to reset the counter
lastBit10Set = currentBit10Set;
}
}
// end function taken
void setup()
{
Serial.begin( 115200 ); // run serial fast to clear the output buffer fast
// set Serial Monitor to match
pinMode( statusBlinkPin, OUTPUT ); // LOW by default
statusBlinkState = 0;
statusBlinkStart = millis();
usage();
}
void SerialEntry() // change mode or stop the scrolling to allow highlight and copy (ctrl-C) for paste (ctrl-V)
{
char ch;
if ( Serial.available())
{
switch ( ch )
{
case 'D' : // set delay mode
case 'd' :
mode = 0;
break;
case 'T' : // set time mode
case 't' :
mode = 1;
break;
case 'P' : // pause toggle
case 'p' :
if ( pause == 1 ) pause = 0;
else pause = 2; // since after the P there's a \n
break;
case '\n' : // make sure that your Serial Monitor only sends \n or \r end of line!
case '\r' :
if ( pause > 0 ) pause--;
}
started[ 0 ] = started[ 1 ] = 0; // re-init timer mode
}
}
// this code came from an older sketch
void statusBlinker() // will not run properly in delay mode
{
if ( millis() - statusBlinkStart >= statusBlinkInterval )
{
statusBlinkState = !statusBlinkState;
digitalWrite( statusBlinkPin, statusBlinkState );
statusBlinkStart += statusBlinkInterval;
}
}
// end older sketch code
void delayModeTiming( )
{
Serial.print( F( "Delay " ));
Serial.print( task );
Serial.write( ' ' );
Serial.print( interval[ task ] / 1000 );
Serial.print( F( " ms now: " ));
Serial.println( millis());
delayMicroseconds( interval[ task ] );
Serial.print( F( "End Delay " ));
Serial.print( task );
Serial.print( F( " End time " ));
Serial.println( millis());
}
void timerModeTiming( ) // uses micros timing for closer precision, but shows millis time!
{
if ( started[ task ] == 0 ) // initialize timer only prints info line at the start
{
started[ task ] = 1; // locked
Serial.print( F( "Timer " ));
Serial.print( task );
Serial.print( F( " Wait " ));
Serial.print( interval[ task ] / 1000 );
Serial.print( F( " ms now: " ));
Serial.println( millis());
start[ task ] = micros(); // loaded
return;
}
if ( micros() - start[ task ] >= ( interval[ task ] ))
{
started[ task ] = 0;
Serial.print( F( "Timer " ));
Serial.print( task );
Serial.print( F( " End time " ));
Serial.println( millis());
}
}
void loop()
{
if ( mode == 1 ) // time mode
{
LoopCounter(); // the function runs as a task.
}
if ( mode == 1 ) // run time mode
{
timerModeTiming( );
}
else
{
delayModeTiming( );
}
// running 1 timer per loop, there could be many so just 1 per
task = !task; // ! changes 0 to 1, ! changes 1 to 0, ! is NOT
// started[ task ] and interval[ task ] control the action
if ( mode == 1 ) // run status blinker
{
statusBlinker();
}
SerialEntry();
}
RTOS is no more parallel than is non-blocking code such as this.
Do people who code with RTOS write “Tasks”?
Oh dear oh dear..
I was writing Object based code when I wrote Forth. Every Forth word is a code Object and that for me was 1983 but I was using Forth79 and AFAICR Forth was released around 1970.
There were other OOP Languages, did they use Classes?
I think we can get lost in specifics and miss generalities and chances to learn something new to ourselves, like Forth.
since this is a forum for Arduino, shouldn't you use terminology consistent with C++ otherwise it's confusing for those asking for help
many of us are familiar with the inconsistent use of terminology between languages.
Nope.
Beginners aren’t loaded down with terminology.
ANYONE who knows the subject well can read the post and figure out what it says.
If you’re in between then insist on Your Definitions Over All,
right. -kinda my point, in a C++ context as this forum and the programming category, it likely means what I said.
In your context “object” means a self-contained unit of code with defined behavior ( each Forth word is an independent, reusable entity).
In a compilation context, an object file is the intermediate binary output produced by a compiler after translating source code into machine code but before linking. It contains compiled code, data, and metadata such as symbol tables and relocation information.
@GoForSmoke It's always fun watching two titans duke it out, but let's not lose sight of the fact (I think it's a fact) that the primary user audience of the forum is relatively new and naive.
I have over 50 yrs, multiple os's and languages under my belt so when someone talks about an object I know the difference between aa C++ thing and the output of the compiler.
I am in total agreement that words are important and I also might be guilty of assuming too much but let's keep the audience in mind.
Do we need to add a page of definitions?
Should the 'How to get the most from the forum' have a point added re definitions?
"untrained in the software arts" might be more descriptive, less pejorative. But, YMMV.
but they often use it incorrectly.
when kids in robotics use techno-babble, i insist they explain what it means. They Bell Labs Writers course empahasised using simple terminolgy that is clearly understood.
The definition I see is
showing a lack of experience, wisdom, or judgment.
how is that pejorative? They are lacking in experience.
I'm not saying we need to use the exact precise book terminology all the time. We don't need to and the human brain is fairly flexible and we will get it most of the time even with the wrong word.
What I was saying is that I've seen some discussions in the forum go south just because of a misunderstanding in the terms used in one ask and people arguing just because they were talking about two different things.
That's where having a common, agreed upon, language could help.
In Forth it works really well and very simple.
And code kinda does work the same from underneath. Viva la diff….
It is the ideas and how we use them to reach goals that I care of.
good focus
I do that every time I post a beginner-friendly example.
And I think that noting or defining simple terms actually adds useful content for those new to the subject, mostly beginners.
Is something a task by one definition and not by others is like knowing the name of a bird when knowing about the bird is what’s important (Richard Feynman).
I think it’s great to know the definitions and maybe the differences for literacy but what we can DO with the code, call it what we may, is the payoff.
I learned the term “state machine” months after I wrote my first.
Why not? Some new people actually read the How To Post info!
For sure, we call it people arguing past each other, and it is up to us to realize that is happening and then the hard part might be getting the other to see it that way.
When conversation turns to debate, that’s when terms and use matter most. But that doesn’t mean “one side has to win”… both can be wrong and both can be right.
To me, I work in logic not comments that (to me) suck creative energy better used in the debug.
Same here.
I learned "automat" first (en/ge), based on vending machines telling it all.