[vinod] wanted to familiarize himself with AVR assembly programming, but wanted to do something a little more ambitious than simply blinking an LED. While the completed build does blink a few LEDs, we love that e decided to implement multitasking on his microcontroller.
The program [vinod] came up with uses round robin scheduling to give one of the seven programmed tasks a little bit of compute time every time a timer is triggered. Although it’s extremely simple compared to “real-life” real-time operating systems like VxWorks, it’s still an impressive achievement.
In the video after the break, [vinod] shows off his task-switching with seven LEDs. The white LED is a PWM task, while the six other LEDs are simple toggling tasks that switch a LED on and off at set intervals independent of each other. This would be hard – if not impossible – to do without some sort of scheduling. Nice work, [vinod].
[youtube=http://www.youtube.com/watch?v=HmduLzdfMhE&w=470]
you might as well use protothreads: http://www.sics.se/~adam/pt/
Protothreading & Arduino Example/tutorial:
http://harteware.blogspot.com/2010/11/protothread-and-arduino-first-easy.html
Protothreads are not real threads, but the ideas is pretty smart. Instead of making multiple real threads, you have a code that “looks” like linear code, but in reality it’s switching, breaking, and jumping all over the place.
Pretty clever because you don’t need separate stacks then. However, if you make a mistake, debugging could be hard.
I’ve used “µC/OS-II” on an AVR before. But I don’t think an multi tasking OS belongs on a small device like that. Caused more problems then it solved really.
+1 and hat tip to @vinod.
But “hard – if not impossible – to do” is joke, yes?
FreeRTOS has an AVR port and I have succesfully ran it on a mega32. FreeRTOS can be a little bit overwhelming for simple microcontroller stuff, though, so it’s cool to have more alternatives. But I think on a microcontroller cooperative multitasking is more practical than preemptive.
It is a nice project. Unfortunately Vinods proof of concept doesn’t show if tasks could themselves use interrupts too.
His blog post claims that “we feel all the tasks are running in parallel and also purely independent”, but that is not completely the case.
In his example the “tasks” use a simple (nested) decrement loop for their timing. That means that the LEDS only consitently blink at the same frequency so long as each task gets presicely the right amount of run time.
Note that the per-task run time is actually dependant on the amount of tasks. So if one would add a task (for yet another LED), the blink frequency of all LEDs would actually decrease.
Also, if his AVR would use (other) interrupts, for example to trigger on an I/O pin, which would contain code that sometimes needs to run, but not continuously, this round-robin context switching would need to support (to some degree) a dynamic amount of tasks. This could imply (and for performance reasons it should imply) a variable run time interval per task.
I would be very interested in seeing a real life application, including some triggering on I/O pins and serial communication of some sort.
i’d say he is using variable time slices each running faster then you can see, and the led blinking could eaisly be timed with system timer ticks,,,
the flashing speed will only change/glitch if the task switching slows down to a crawl from possibly a blocking command such as waiting for something that SHOULD respond right away.
CODE:
// task module “led_1”
newtime = time;
if ((newtime – oldtime) > FLASH_INTERVAL)
{
state = digitalRead(pin3);
newstate = !state;
digitalWrite(pin3) = newstate;
}
oldtime = time;
nexttask();
// end of task “led_1”
modules could be loaded into ram and added to tasklist as desired.
TRUE multitasking is WAY more complicated then what i have written a module for.
but at 1MHz or more, flashing LEDs at the max speed your eyes can see would never be affected by how many tasks are being run, unless your making a (multiplexed) 2 dimentional LED matrix of maybe 10 or 100 LEDs and each has it’s own subroutine, but at that point ask why… why not write whole display at once… lol “conway’s game of…”
…or of course your decoding ir remote control codes and you hold down the button for more then (max LED on/off time), which would screw it up
but i still stand that for small bits of simple, fast code, RRobin is the way to go. for simple stuff using 1 – 10 modules.
i meant to say “if signal from remote stops unexpectedly” aka low battery in remote aka “too far away” aka “3/10 bits” aka waiting for remaning bits
OMG PUSH TO ARDUINO PLEASE.
You should take a look at this!
http://concurrency.cc/
“Parallel programming for makers and artists” :)
More advanced version of the posted link.
This can be done with virtual timers and no multitasking. It’s not “very hard”, just moderately difficult.
This is quite impressive for someone who previously didn’t know about AVR assembly programming. Good hacking!
I handle multiple tasks two ways on micros, I dont feel a need for a rtos on a micro.
My favorite way:
http://www.mculabs.com/snippets/slice.html
And if I need things to work more out of order:
http://www.mculabs.com/snippets/ptask.html
I use utask for multiple tasks. It supports 8, 16 and 32-bit uCs.
http://utask.sourceforge.net/
I was just wonder about this starting a few days ago. I was trying to cycle through the colors of an RGB LED while fading out a white one with PWM that started at 255 when the color cycle started. I couldn’t figure out how to do it, and figured something like this was the problem. Can round-robin solve something like this?