Hello and welcome to my eighth update on the Universal LED Animator. I have completed the project and the following few posts (two more to come) will present my finished work. The first thing to show is undoubtedly the code running on my Hero boards - RedBear Blends. It was all published to GitHub and will be further developed after the challenge.
My work environment
The Blend/Arduino side of this project has been developed using three Hero boards, RedBear Blends, with ATMega32U4's and Nordic's nRF8001 BLE modules. Each of them is basically an Arduino Leonardo with a BLE radio module. Code was written using the wonderful Sloeber IDE and (very messy) version control was maintaned with EGit. I seriously recommend Sloeber as the way to go with anything bigger than the smallest Arduino projects. I'm just amazed by how nice it can be to work with MCUs in this environment, and I think the only things I miss from Arduino IDE are GUI colours and loading times.
Funkboxing's FastLED Effects example
This project would be a lot less fancy without the wonderful collection of LED strip effects that I found here, and adapted to WS2812 LED's using recommendations I found in the comments. The amount of patterns is just overwhelming, and it definitely overwhelmed the Blend's memory when combined with the BLEPeripheral library (more on it later). In the end, I established that I could only use twelve distinct patterns, as more would simply not fit on the Flash. This will definitely have to be optimised in any new releases that I hope for in the future.
Fortunately, a huge advantage of Funkboxing's code is how customizable the patterns are - brightness, animation speed, and sometimes even colours can be changed in real time. Obviously, it also includes all the basic patterns, like assigning a single colour to all LEDs, fading it, and all animated rainbows you can imagine. Paired with a touchscreen-friendly web interface it allows for a ton of functionality. A bonus feature is accepting the HSV colour space by default, which is very nice for working with OpenCV, using a colour picker and making smooth colour transitions.
The original code was divided into several files for clarity, including a header file effects.h storing all the effect patterns - they were not altered by me, so all 30+ original effects are still available and each can be easily brought back into the code when other effects are removed, or other features optimised to make room in the Flash. The code itself runs in the standard Arduino main loop, first checking the BLE UART service for new transmissions, then running through the logic of the current LED pattern, proceeding to parse any new commands that were sent over BLE. Here is the loop itself:
void loop() { BLESerial.poll(); switch (ledMode) { case 999: break; case 1: one_color_allHSV(thishue); break; case 2: rainbow_fade(); break; case 3: rainbow_loop(); break; case 4: random_burst(); break; case 5: color_bounce(); break; case 6: color_bounceFADE(); break; case 7: ems_lightsONE(); break; case 8: random_color_pop(); break; case 9: flicker(); break; case 10: pulse_one_color_all(); break; case 11: flame(); break; case 12: rainbow_vertical(); break; } //---PROCESS HARDWARE SERIAL COMMANDS AND ARGS while (BLESerial.available() > 0) { inbyte = BLESerial.read(); switch (inbyte) { case 59: break; //---BREAK IF INBYTE = ';' case 100: //---"d" - SET DELAY VAR thisarg = BLEparseInt(); Serial.print(F("delay:")); Serial.println(thisarg); thisdelay = thisarg; break; case 115: //---"s" - SET STEP VAR thisarg = BLEparseInt(); thisstep = thisarg; break; case 104: //---"h" - SET HUE VAR thisarg = BLEparseInt(); thishue = thisarg; thisarg = BLEparseInt(); thissat = thisarg; Serial.print(F("H:")); Serial.print(thishue); Serial.print(F(" S:")); Serial.println(thissat); break; case 98: //---"b" - SET MAX BRIGHTNESS max_bright = BLEparseInt(); LEDS.setBrightness(max_bright); Serial.print(F("brightness change:")); Serial.println(max_bright); break; case 109: //---"m" - SET MODE thisarg = BLEparseInt(); change_mode(thisarg); Serial.print(F("mode change:")); Serial.println(thisarg); break; case 81: //---"Q" - COMMAND RETURN VERSION NUMBER Serial.print(VERSION_NUMBER); break; } } }
The library I'm using here is Sandeep Mistry's BLEPeripheral. I put it in the code to replace the HC-05 interface that was there before, as the Blend utilises the nRF8001 and in the future I either want to use that module on a separate PCB, wired to the Arduino, or ditch it entirely and use a different BLE module. Anyway, BLEPeripheral works great and offers a lot more features than the UART service that I'm using in this project - taking it up was very educational and what I learned will facilitate some other projects I've never thought I could finish.
The BLE command parser looks for every possible command-encoding byte, and there are not many: one each for mode change, setting up delay, step (not used in this release), hue and saturation (only together, i.e. you can't change saturation by itself), and one command to output the library version number to UART, useful for debugging your connections. There is no ParseInt() method in the library, so I used an optimised version of the default Arduino one (click the link, it's very educational). The protocol is obviously expandable - a nice-to-have feature that first comes to mind is adding a more colour picking options for multi-colour effects, like three pixels bouncing up and down, each with a customizable colour - currently only one is customizable.
Let's take a look at an effect, for example the bouncing pixel:
void color_bounce() { //-m5-BOUNCE COLOR (SINGLE LED) if (bouncedirection == 0) { idex = idex + 1; if (idex == LED_COUNT) { bouncedirection = 1; idex = idex - 1; } } if (bouncedirection == 1) { idex = idex - 1; if (idex == 0) { bouncedirection = 0; } } for (int i = 0; i < LED_COUNT; i++ ) { if (i == idex) { leds[i] = CHSV(thishue, thissat, 255); } else { leds[i] = CHSV(0, 0, 0); } } LEDS.show(); delay(thisdelay); }
All the basic pattern parameters are utilised here - thishue and thissat are colour data, and thisdelay is used to set the speed of the animation. LEDS.show() puts the colours on the strip itself. It is worth noting that the V (value, i.e. brightness) of the pixel is set to maximum - the brightness setting is saved using a FastLED library method and it's an absolute quantity, while the effects only utilise relative brightness. This works absolutely perfect until you start mixing colours at 1/255 brightness.
There are also some simple settings available in the common.h file:
//Setup and system variables taken from Funkboxing's example //SETTINGS //LED data pin #define LED_DT 6 //Serial connection parameters #define SERIAL_BAUDRATE 115200 #define SERIAL_TIMEOUT 5 // BLE pins #define BLE_REQ 9 #define BLE_RDY 8 #define BLE_RST 5 //Number of LEDs in the setup #define LED_COUNT 75 //Driver chip type #define LED_TYPE WS2811 //Driver chip color order #define COLOR_ORDER GRB.
I hope they're commented enough.
Video proof
Here's a proper demo of the Blends working together with the Beagle Bone Wireless, plus a sneak peek of the new web interface:
Top Comments