How to have a "config thread" and a "measure thread"?

I am looking for a way to configure the arduino (eg via serial port) while some regular loop functions continue to be executed. So basically I want a "measurement thread" and a "configuration thread".

So far I could find lots of introduction to running multiple functions (almost) at once, starting with timers if(millis()-previous_millis >= interval){do something} and later using thread libraries.

But I don't seem to find any previous work where someone realized some configuration thread which waits on valid user inputs while still continueing the other tasks.

So can someone please point me in the direction what to look for or provide some links? I am sure others have experienced the same situation.

No threads. Just Interrupts or occasional checking.

Pretty much by definition, anything having to do with user interaction, especially over a Serial connection, is not at all time-critical. A delay in processing user input, even of 100mSec, will not be noticed by the user. Using a separate thread, even if it were practical, would be overkill, and completely unnecessary. You can do exactly what you need to do with loop(), using polling.

Regards, Ray L.

I am looking for a way to configure the arduino (eg via serial port) while some regular loop functions continue to be executed.

Look at the BlinkWithoutDelay example. That carries out your "regular loop functions"

Now, at the end of the loop() function add in code to accept user input one character (if one is available) each time through loop() until user input is finished, perhaps signalled by a carriage return, and then act on it, but do not include any code that blocks loop() running freely.

This may help Serial input basics

I am still wondering how to access deeper menu structures with this 'read one character at the end of each loop' approach. Lets's call this function 'watch_serial()'

and let's assume my menu looks like this: "Select what to configure: (a)larms, [b)luetooth, (t)time, e(x)it" and the choices for alarm are "(0) turn alarm off, (1) change alarm time".

Then the watch_serial() function would have a couple of nested switch / case statements. But how to get rid of the idle time while wating for the user's input?

At this point I can only think of a couple of config functions (eg: void config_alarm(char command){} ) with quite a few static variables and the main_config function which receives the command chars and feeds them to the corresponding sub config functions, depending on the first character received - so also requireing static variables.

Does this sound like a good direction?

You just build a loop function that includes a menu system AND functions to maintain current operation. It's pretty standard practice.

As a rough guide something like this.

Read user input. Process user input. Update variables used for User interface as appropriate Update working parameters as appropriate Read other inputs (sensors etc..) Process your input Attend to outputs

"Select what to configure: (a)larms, [b)luetooth, (t)time, e(x)it" and the choices for alarm are "(0) turn alarm off, (1) change alarm time".

This sounds like a state machine to me.

Use switch/case to define the current state then wait for appropriate input and change state when you get it. For instance, "Select what to configure: (a)larms, [b)luetooth, (t)time, e(x)it" might be state zero. If the user enters an 'a' then set state to say 1, prompt "(0) turn alarm off, (1) change alarm time" and stay in that state until the user enters '0' or '1'. If they enter '0' turn off the alarm and set state back to 0. If they enter '1' change state to say 10, prompt to enter time, read characters each time round loop() until complete, set the alarm time and change state to 0.

The switch/case based on state ensures that only the code for that state is executed and acted upon. If necessary you can have dozens of states and multiple exit points to other states. For instance you could change state to a higher level in the menu if user input is not received in a given time.

But how to get rid of the idle time while wating for the user's input?

You don't wait. If they have not entered anything keep going round loop() until they do.

halfdome: But how to get rid of the idle time while wating for the user's input?

If I were to tell you I'm sending you a letter today in the mail, would that cause you to put your whole life on hold and wait by the mailbox until it gets there? Or would you simply come back each day after the post ran and check to see if it was there and then go back to what you were doing.

There shouldn't be any idle time. If the user hasn't entered a selection yet, then keep running and look again on the next pass.

@ KenF While everything you write makes sense, I still have no clue how to build your scheme with program code.

@UKHeliBob So your approach boils down to one "monitor_serial_input_and_pass_to_state_machine()" function and a "state_machine(char command)" function that has one huge switch/case block and static variables to remember the state. Am I following you so far?

Suggested reading: http://hacking.majenko.co.uk/finite-state-machine

There are libraries that will help you implement a Finite State Machine in your Arduino sketch:

AlxDroidDev: Suggested reading: http://hacking.majenko.co.uk/finite-state-machine

I was just reading that particular link when your post arrived. I am quite fascinated!

halfdome:
But I don’t seem to find any previous work where someone realized some configuration thread which waits on valid user inputs while still continueing the other tasks.

The simple trick is: NEVER WAIT FOR ANYTHING in your program!

Instead you’d write a Serial input function like:

boolean isSerialInputReady()
{
  if (Serial.available())
  {
     char c=Serial.read();
     // do the Serial processing as needed for that character
     // then return false (input not yet ready) or true (input ready)
  }
  return false;
}

After the function returns ‘true’, the input command should be available in a global variable / command buffer.

@UKHeliBob referred you to serial input basics in Reply #3

Have you studied how it collects data from the input buffer but does not wait for it.

You might also look at the more general business of "pretend multitasking" that is illustrated in the demo several things at a time

In general the philosophy within your code should be "if there is data I will act on it" rather than "I can't do anything until the data arrives"

...R

So your approach boils down to one "monitor_serial_input_and_pass_to_state_machine()" function and a "state_machine(char command)" function that has one huge switch/case block and static variables to remember the state. Am I following you so far?

That's about it apart from the need for static variables. You can do it with if/else rather than switch/case but it has always seemed to me that switch/case provided more readable and maintainable code.

A we have been saying, the important thing is to keep the program moving