Does Arduino need a real-time scheduler?

AndreAdrian:
My opinion: Arduino needs a better delay() function :grin:

The question RTOS or no RTOS does just heat up the discussion, but does not help the migration. This is my approach:
I want a better delay() function - this is a feeling. If I introspect this feeling I recognize

  • it is a waste of energy for me if delay() is just doing busy waiting.
  • I want/I need to do several things in parallel, but delay() does not allow me to do it.
  • I do not want to throw everything away because of a bigbang RTOS solution, I want to go step by step from here to there.

As a seasoned software engineer I have seen again and again that migration is the key. Here are my suggestions:

Migration step 1: Introduce event handling

The Arduino "core library" has the loop() function. An event handling Arduino program will have one only statement in the loop() function, the do_event() function. The do_event() function has to look after the events and has to service the events.
A useful vehicle to show that event handling is useful should be a keyboard scan library that provides its services within an event handling framework. The typical pocket calculator keyboard has arranged the keys between row and column lines. A 12 button keyboard needs 3+4=7 scan lines. The keyboard scan function is not trivial. Everybody expects to get:

  • key debouncing
  • key repeat (repetition)
  • 2-keys-rollover (Rapid typists may sometimes inadvertently press a key before releasing the previous one)
  • no electrical shortcircuit if two keys are pressed simultaneously
    To implement these functions, a timer is needed. The keyboard lib should provide a timeout functionality to the user. The function set of the keyboard lib is:
    button_register(): combine an event (key press) to a function (eventhandler)
    after(): after N milliseconds call a function
    every(): every N milliseconds call a function
    do_event(): check if there is a pending event and execute the eventhandler function. Needs to be called again and again within loop().

A simple Arduino program that fits nicely the event paradigma is a math trainer program. The Arduino displays a math question like "1 + 2 = ?" and the user should enter the correct answer within a time limit. In an event program there will be a keyboard event for every digit and a timeout event. If the user presses the digit "3", the button-3-event function will say "correct answer". The other button-event functions will say "wrong answer". And the timeout event-function will say "timeout".

Migration step 2: Create a event-driven LiquidCrystal lib

Everybody is using LiquidCrystal. But LiquidCrystal uses delay() and busy waiting is the nemesis to all real time programming. Thanks to the keyboard lib above, we have one-shot timer. And an event driven LCD output function does look like this:
do_lcd() {
switch (state) {
case 1: // do state 1 stuff
state=2; after(N, do_lcd); return; // set next state, use after to delay execution by N milliseconds, exit do_lcd()
case 2: // do state 2 stuff
state=3; after(M, do_lcd); return; // set next state, use after to delay execution by M milliseconds, exit do_lcd()
} }

The busy waiting version of do_lcd() was:
do_lcd() {
// do state 1 stuff
delay(N);
// do state 2 stuff
delay(M);
} }

The do_lcd() function is ugly, but it is working without busy waiting. If all Arduino users are annoyed by event handling uglyness, they are ready for phase 3 of the RTOS brainwash program:

Migration step 3: Show that multi-threading does look better

Multi threading is dangerous. The worst thing you can do with busy waiting is to freeze everything up. The worst thing in multi threading is that you literally tear apart your machine because thread 1 says "go left" and thread 2 says "go right" as fast as time-division multiplexing can do. But, if you have multi-threading and a multi-threaded version of delay(), the do_lcd() function will no longer look ugly, and you are still out of busy waiting land:

do_lcd() {
// do state 1 stuff
delay(N); // the multi-thread version of delay() will switch to another thread or will wait in the operating system
// do state 2 stuff
delay(M); // the multi-thread version of delay() will switch to another thread or will wait in the operating system
} }

I bet, everybody will be happy about a keyboard() lib. And they will learn that "fu**ing" event crap, because using a lib is better then writing a lib. And everybody who uses keyboard() will use after() and every(). And now the future is open: If you can live with the event programming uglyness, you never have to go to multi-threading land. Maybe you remember the X windows system, the GUI for UNIX and Linux? Well this was all done by using event programming, and it was done a long time before multi-threading was invented.

Well, I don't know exactly what you mean by this, do you condone one way or the other, but I for sure am not a software architect and there for will not write my own state machine, I expect this to be handled by the framework so I can focus on my logic level. I expect to write a couple of lines of code to get a couple of lines of logic nothing fancy nothing hard.