Are you ready to mod your ELEV-8 v3? This tutorial will show you how to build a set of fully programmable running lights composed of bright RGB LEDs. Completing this advanced tutorial will require custom PCBs, individual components from 3rd party vendors, and soldering equipment. Although this tutorial requires surface-mount soldering, if you've never done any surface mount soldering before, this tutorial is easy enough to follow that you can succeed if you have a steady hand.
To build and install running lights for your ELEv-8 v3, you will need parts and supplies from several different sources.
The PCBs are available as a shared project from OSH Park, a community batch PCB service provider. This PCB must be ordered in multiples of 3. This means that in order to get 4—one for each boom—you will have to order 6 PCBs. It may take approximately two weeks for your PCBs to be fabricated since they are made to order.
The soldering techniques shown in this project make both traditional soldering with an iron, and also reflow soldering. A syringe of low-temperature soldering paste makes it easy to surface-mount solder with a hobby-grade heat gun or a small electric frying pan.
*Once an electric frying pan, baking pan, pizza stone, or other kitchen utensil has been used for soldering, never use it for preparing food again! Solder and soldering paste can be hazardous to ingest.
To build the running lights, you will be soldering LEDs, capacitors, and voltage regulators to the PCBs. The quantities shown are for 4 running lights. To build up six running lights (2 spares), multiply each of the following quantities by 1.5:
To install the running lights, you will need some additional hardware, header pins, and cables:
Finally, to aid in the assembly and install process, you will need:
The first step in building running lights for the ELEV-8 v3 is to solder the surface-mount components to the printed circuit boards. If you don't know what to expect when reflow soldering, take time to watch some YouTube videos to understand how it works before proceeding.
If you accidentally add too much soldering paste, wipe the excess away with a paper towel or cotton swab. Do not try to wash the soldering paste away with water or cleaning solution. It is okay if it is messy or smeared - simply leave the smudge for now, since it is much easier to remove after the PCBs have been reflowed later in this tutorial.
Once the SMD components have been placed on the PCBs, they are ready to be reflowed.
Reminder! Once an electric frying pan, baking pan, pizza stone, or other kitchen utensil has been used for soldering, do not ever use it for preparing food again! Solder and soldering paste can be hazardous to ingest.
Before you proceed, use your masking tape and marker to label each board "1", "2", "3" and "4" to correspond with the ELEV-8 v3 boom that each PCB will eventually be installed on:
Next, you will be soldering the LED's on the front edge of the PCBs. Look carefully at the two pictures below. The WS2812B LEDs have a triangular notch that marks pin 1.
If you install the LEDs backwards, they (and any LED in the chain after one that is backwards) will fail, and potentially be damaged
To attach the LEDs to the front edge of the PCB:
Next you will be installing the headers.
Finally, you will be solder-bridging the jumpers on the PCB.
Follow these instructions carefully. Configuring these jumpers incorrectly could destroy the LED modules and your ELEV-8 v3 Flight Controller!
Your boards must be labeled 1, 2, 3 and 4 before proceeding.
If you haven't done so already, follow the directions here (http://learn.parallax.com/elev-8-v3-quadcopter-assembly-guide/step-22-install-software [14]) to download the ELEV-8 v3 firmware using SimpleIDE. Make sure you understand how to upload firmware to your ELEV-8 v3. This project was tested with firmware version 1.0.2 and 1.0.3.
A list of files will appear on the left side of the window.
#define LED_COUNT 2
#define LED_COUNT 21
static long LEDModeColor;
static short RunningLightModeStep; //LED Running light mode setting and counter variables static char RunningLightMode;
UpdateFlightLEDColor(); //Test for flight mode change----------------------------------------------- if( FlightEnabled == 0 ) {
if( (Radio.Rudd < -750) && (-350 < Radio.Thro) && (Radio.Thro < 350) ) //is the left stick pushed straight to the left?
{
if( (Radio.Aile > 750) && (-350 < Radio.Elev) && (Radio.Elev < 350) ) //is the right stick pushed straight to the right?
{
RunningLightModeStep++; // add to the counter
if (RunningLightModeStep >= 325) // have the sticks been held there for 1.5 seconds?
{
RunningLightModeStep = 0; // reset the counter
RunningLightMode++; // increment to the next running light mode
if (RunningLightMode > 1) RunningLightMode = 0; // This must be set for the number of different modes
for( int i=0; i <= RunningLightMode; i++ ) // x short beep(s) to indicate the mode
{
BeepHz(4500, 100);
waitcnt( CNT + 5000000 );
}
loopTimer = CNT; // because the beeper overruns the main loop timer, it must be reset
}
}
}
for( int i=0; i<led_count; i++ )
int idx = (LEDColorTable[FlightMode & 3] & LEDBrightMask) >> LEDBrightShift; // get the color representing the current flight mode if(RunningLightMode == 0) //Dim Running Lights { LEDValue[0] = Color; LEDValue[1] = LEDValue[6] = LEDValue[11] = LEDValue[16] = idx; LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = LED_Green & LED_Quarter; LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = LED_Green & LED_Quarter; LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = LED_Red & LED_Quarter; LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = LED_Red & LED_Quarter; } if(RunningLightMode == 1) //Standard Running Lights { LEDValue[0] = Color; LEDValue[1] = LEDValue[6] = LEDValue[11] = LEDValue[16] = idx; LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = LED_Green; LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = LED_Green; LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = LED_Red; LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = LED_Red; }
DO NOT CONNECT YOUR ELEV-8's Battery. Make sure the propellers have been removed from your ELEV-8 quadcopter before continuing.
Now you are ready to test your running lights.
Make sure that your work surface is clear of any metal including wire, tools, or hardware. The Power Distribution Board, Running Light PCBs and Flight Controller all have exposed electrical connections that can easily short across exposed metal surfaces or objects.
Double check all of your connections, making sure that the correct PCBs are in the order shown. Connecting the running light PCBs incorrectly can permanently damage the running lights and your Flight Controller!
Your running lights should all be glowing:
Now that your ELEV-8 Flight Controller has been updated with modified firmware for your LEDs, and you've tested them to make sure they work, you are ready to install the Running Light PCBs onto the booms underneath the motors. You will match each numbered PCB with the boom of the same number.
Make sure the Running Light that you numbered in a previous step matches the boom it is being installed on! Failure to do so may permanently damage your Running Lights or Flight Controller!
Installing the 3-pin cables into the booms of your ELEV-8 v3 can be tricky. It requires you to partially disassemble your ELEV-8 v3 and to work slowly and carefully as you feed cables through the booms.
It is possible to simply run the cables along the outside of the booms and zip-tie them. If you choose to zip-tie the cables to the outside of your ELEV-8's booms, simply connect them in the same manner as you did when you tested them in a prior step.
To install the cables inside of the booms:
Now that you have modified the hardware and firmware for the ELEV-8 v3, it is necessary to test its functionality to make sure it is safe to fly. Yes, do this every time you made hardware and/or firmware modifications!
DO NOT SKIP THIS PROCEDURE! Flying with untested firmware is dangerous and can cause severe injury or property damage or loss.
If you have not done so already, REMOVE YOUR PROPELLERS before proceeding!
If your ELEV-8 v3 fails to pass any of the steps below, STOP - disconnect the ELEV-8 v3's battery and return to prior steps to begin troubleshooting the problem.
Pay close attention to the RGB LED on the Flight Controller. During this process, it should continue to flash/alternate colors. Except during power-up, arming and disarming, if the LED stops flashing, there is a problem with your code and it is not safe to fly.
The Propeller microcontroller on the Flight Controller has a system clock that takes approximately 53 seconds to roll back over to zero and start again. Testing for 90 seconds ensures that the rollover will not cause a lock-up.
If your ELEV-8 v3 passed all of the above tests, it should be safe to re-install the propeller blades when you are ready to fly.
For your first flight with modified firware and hardware, follow all safety precautions.
Fly gently, close to the ground, and away from any people, objects, or structures until you are confident that your ELEV-8 v3 is performing normally.
The edits you made to your Flight Controller's firmware to test the Running Lights provide two different modes for the running lights: Dim and Bright. To switch between modes, you will use your transmitter's sticks while the ELEV-8 v3 is disarmed.
To change Running Light modes, push and hold the sticks straight outward to the sides for at least 1.5 seconds:
The Flight Controller will beep a number of times indicating the mode. It will cycle through all of the modes that are programmed into the firmware.
The code provided earlier in this tutorial sets the running lights as follows:
The RGB (Red, Green, Blue) LEDs used in the Running Lights are WS2812B modules. Each module contains a small microchip, a red LED, a green LED, and a blue LED:
Each module has only 4 connections: +5VDC, ground, an input, and an output. The output of one WS2812B can be connected to the input of the next WS2812B. You can chain hundreds of WS2812B modules together as long as you have enough power for the modules and a microcontroller fast enough to drive them.
The WS2812B modules look for a series of 24 bits. The first 8 bits tell the module how bright its green LED will be lit. The next 8 bits represent the brightness of the red LED, and the last 8 bits represent the brightness of the blue LED. The bits are simply pulses. When the WS2812B sees a pulse that is on for 0.35 µs and off for 0.8 µs, it interprets that as a 0 (zero), and when it sees a pulse that is on for 0.7 µs and off for 0.6 µs, it interprets that as a 1 (one).
When the WS2812B receives another 24 bits, it passes them on to the next WS2812B. That module will see those 24 bits as its commands for setting its color. Any additional commands will then be passed to the next WS2812B module:
The ELEV-8 v3 Flight Controller Firmware includes a driver that generates all of the necessary pulses to drive WS2812B LED modules, since there is a WS2812B right on the board. All you have to do is edit the ELEV-8 v3 firmware to let the Flight Controller know how many LED modules are attached and what color each module should be. So, one of the firmware modifications was to tell the Flight Controller how many LED modules are attached, by editing this line in the file elev8-main.h:
#define LED COUNT 2
...to read:
#define LED COUNT 21
That let the driver support the 20 Running Light LEDs (5 on each boom) plus the first one on the Flight Controller itself:
The function at the end of the elev8-main.cpp file named ALL_LED tells the driver what color to set each LED. LEDValue[] is an array that holds values for each LED. Setting the value of LEDValue[0] will set the color of the LED on the Flight controller itself. LEDValue[1] will set the color of the first LED on the Running Lights (see the diagram above).
To set an LED to a specific color, assign a 24-bit value to the LEDValue array element. For example, if you set LEDValue[1] = 0xFF0000, LED 1 will turn green:
This is very similar to the way web browsers set colors. If you use an HTML color picker such as the one available at http://htmlcolorcodes.com/color-picker/ you can find the hexadecimal code for any color. To make it work for the WS2812B LED modules, you have to switch the Red and Green bits. HTML expects the bits to be in RRGGBB order, and the WS2812B expects them in GGRRBB order.
Here are some additional modes that can be added into the ALL_LED function at the end of the elev8-main.cpp file. Remember to change the line earlier in the code to state the total number of functions.
CAUTION! Remember to always re-test your ELEV-8 [15] to make sure it is safe to fly after making any firmware modifications!
if( (Radio.Rudd < -750) && (-350 < Radio.Thro) && (Radio.Thro < 350) )
{
if( (Radio.Aile > 750) && (-350 < Radio.Elev) && (Radio.Elev < 350) )
{
RunningLightModeStep++;
if (RunningLightModeStep >= 325)
{
RunningLightModeStep = 0;
RunningLightMode++;
if (RunningLightMode > 4) RunningLightMode = 0; //This must be set for the number of different modes
for( int i=0; i <= RunningLightMode; i++ )
{
BeepHz(4500, 100);
waitcnt( CNT + 5000000 );
}
loopTimer = CNT;
}
}
}
Stealth Mode - this turns off ALL of the LEDs including the one on the flight controller.
if(RunningLightMode == 2) //Stealth Mode
{
for( int i=0; i<led_count; i++) LEDValue[i] = 0;
}
Motor Response Mode - when armed, the color of each boom will change from green to red as the speed of its corresponding motor changes. It is a very dim white when disarmed.
if(RunningLightMode == 3) //Motor Speed Visualization
{
int mot1 = ((Motor[OUT_FL] << 8) - (Prefs.MinThrottle << 8)) / (Prefs.MaxThrottle - Prefs.MinThrottle);
int mot2 = ((Motor[OUT_FR] << 8) - (Prefs.MinThrottle << 8)) / (Prefs.MaxThrottle - Prefs.MinThrottle);
int mot3 = ((Motor[OUT_BR] << 8) - (Prefs.MinThrottle << 8)) / (Prefs.MaxThrottle - Prefs.MinThrottle);
int mot4 = ((Motor[OUT_BL] << 8) - (Prefs.MinThrottle << 8)) / (Prefs.MaxThrottle - Prefs.MinThrottle);
LEDValue[0] = Color;
if( FlightEnabled )
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = ((256 - mot1) << 16) | ((mot1 - 1) << 8);
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = ((256 - mot2) << 16) | ((mot2 - 1) << 8);
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = ((256 - mot3) << 16) | ((mot3 - 1) << 8);
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = ((256 - mot4) << 16) | ((mot4 - 1) << 8);
} else
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = 0x040404;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = 0x040404;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = 0x040404;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = 0x040404;
}
}
Police Lights Mode - Fun, but use this mode responsibly!
if(RunningLightMode == 4) //Police Lights
{
LEDValue[0] = Color;
if( counter & 0b01000000 ) // use a bitmask on the system counter to create a longer delay
{
if ( counter & 0b00100000 ) // use a bitmask on the system counter to create a medium delay
{
if ( counter & 0b00001000 ) // use a bitmask on the system counter to create a short delay
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = LED_Blue;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = 0;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = 0;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = 0;
} else
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = 0;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = 0;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = 0;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = LED_Red;
}
} else
{
if ( counter & 0b00010000 )
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = 0;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = LED_Blue;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = 0;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = 0;
} else
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = 0;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = 0;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = LED_Red;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = 0;
}
}
} else
{
if ( counter & 0b00100000 )
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = 0;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = LED_Blue;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = LED_Red;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = 0;
} else
{
LEDValue[1] = LEDValue[2] = LEDValue[3] = LEDValue[4] = LEDValue[5] = LED_Blue;
LEDValue[6] = LEDValue[7] = LEDValue[8] = LEDValue[9] = LEDValue[10] = 0;
LEDValue[11] = LEDValue[12] = LEDValue[13] = LEDValue[14] = LEDValue[15] = 0;
LEDValue[16] = LEDValue[17] = LEDValue[18] = LEDValue[19] = LEDValue[20] = LED_Red;
}
}
}
Links
[1] https://oshpark.com/shared_projects/Ycc6C6G5
[2] http://www.chipquik.com/store/product_info.php?products_id=440001
[3] https://www.parallax.com/product/700-10011
[4] http://www.digikey.com/product-detail/en/1655/1528-1104-ND/5154679
[5] https://www.adafruit.com/products/1655
[6] http://www.digikey.com/product-detail/en/texas-instruments/UA78M05CDCYR/296-12290-1-ND/416584
[7] http://www.digikey.com/product-detail/en/GRM188R71E104KA01D/490-1524-1-ND/587865
[8] http://www.digikey.com/product-detail/en/CL21A226MAQNNNE/1276-2908-1-ND/3890994
[9] https://www.parallax.com/product/570-80061
[10] https://www.parallax.com/product/570-80300
[11] https://www.parallax.com/product/451-04001
[12] https://www.parallax.com/product/800-00240
[13] https://www.parallax.com/product/800-00160
[14] http://learn.parallax.com/elev-8-v3-quadcopter-assembly-guide/step-22-install-software
[15] http://running-lights-your-elev-8-v3/saftey-test-after-customizing