Small Lamp NoeBoat with Arduino Uno R3 and FreeRTOS
I am a fan of super tiny stuff written in C, and also a fan of Operating System. FreeRTOS is a super tiny real-time operating system, I was able to run also on a Arduino UNO R3 with only 2Kb of RAM.
So I decided to use it to write a small project: you can find the code on Github, but lets start from the beginning.
When my tiny child was 12 month olds, we got a nice wooden toy resembling a Noe Boat, with wooden animal to put inside. It is an Imaginarium toy, there are plenty of variants on Amazon. After some time my child grow up, the glue went away and the toy opened in two parts.
So I decided to fill it with led and try to create a very simple Arduino project based on LEDs and a small piezo speaker. Initially I considered smaller boards like ESP8266, but they was too underpowered for my targets (mostly because running at 3.3v and not able to deliver bright leds).
To ease prototyping and also have fun, I decided to use FreeRTOS to set up all the mechanics.
I started with a simple 'bouncing ball' effect, you can run on all the leds. Then I added a potentiometer to change the intensity of the leds.
It was not easy to tune memory management. Also Arduino IDE is unable to easily embed libraries, so I ended up including FreeRTOS AVR port in a hidden "src" folder, to be able to deliver the full pack. I hacked (tuned) a bit FreeRTOS to get rid of loop() function & reduce minimal stack size, all to save some memory (all suggested in the README, no magic here).
On the side image, you see the wiring: we used small adhesive breadboard to avoid soldering, placing them near the boat 'windows'.
As you imagine C++ is an horrible language for prototyping, but (1) it is faster than java to compile and (2) there is finally a foreach construct with implicit typying. So you can dare to write something like this:
const uint8_t OrderedLeds[]={3,/*5,*/10,9,11,6}; for(auto currentLed: OrderedLeds ){ analogWrite(currentLed,dimValue); }
Which is a tiny improvements and save you a few keystokes if you want to change the type of the array, reduce the risk of indexing errors, etc.
The 1.0.x version is a work in progress, two effect are present right now.
For changing the leds effect, we ended up using an high priority thread which at every button press start the correct thread and stop the old one.
This approach is dynamic and avoid using message passing, and works well so far, as you can see on the right; it enables you to design reusable function tasks, keeping all the logic inside them and allocate the necessary stuff on the stack of every function (like declaring local variables). Heap memory allocation in C++ is a risky business, so we tried to avoid it as much as possible, and we manage to do it so far.
/** This is an high priority task. We try to detect a button press every 200 milliseconds, because human are slow. * We NEED to delay to give a chance to all the system to run. */ void TaskModeSwitch(void *pvParameters){ Serial.println(F("Task Mode Switch Ready")); for(;;){ delay(200); if(buttonPressed()){ switch (CurrentMode) { case CyclePot: // Switch to new mode Serial.println(F("Switch to CyclePot")); // Kill old Task vTaskDelete(fadeDance_Handler1); // Create fadeTaskFadeSyncro_Handler xTaskCreate(TaskFadeSyncro, "SYNC", FaderStackSize, NULL, 0, &fadeTaskFadeSyncro_Handler); // Init new mode CurrentMode=Fading; break; case Fading: Serial.println(F("Come back to Fading")); vTaskDelete(fadeTaskFadeSyncro_Handler); xTaskCreate(TaskFadeCycle, "DNC", FaderStackSize, NULL, 0, &fadeDance_Handler1); CurrentMode=CyclePot; break; default: break; }}
} }
Stay tuned, more updates will come!