Yet another WS2812 driver, uses the BusrtSPI library. Less features than the PixelArray library but I felt like making my own version.

Dependencies:   BurstSPI

Dependents:   WS2812Text cylon

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wsDrive.h Source File

wsDrive.h

00001 #ifndef __wsDrive_h__
00002 #define __wsDrive_h__
00003 
00004 #include "BurstSPI.h"
00005 
00006 /****************************************************************
00007 * An alternative WS2811/2812 driver using the BusrtSPI library
00008 * Credit for the inspiration goes to Jacob for his pixelArray library
00009 * http://developer.mbed.org/users/JacobBramley/code/PixelArray/
00010 *
00011 * This version was written mainly to help me understand what was going on
00012 * While the end result is the same the code is completely from scratch.
00013 *
00014 *****************************************************************/
00015 
00016 
00017 /** A structure used to hold a single pixel or a pixel colour
00018 *
00019 * Each colour can be set to any value between 0 and 255.
00020 * 0 = off, 255 = full brightness.
00021 *
00022 * Note, lots of LEDs on bright will use a lot of power, make sure your supply can cope.
00023 *
00024 * @param G The green component
00025 * @param R The red component
00026 * @param B The blue component
00027 */
00028 typedef struct pixelInfo {
00029     unsigned char G;
00030     unsigned char R;
00031     unsigned char B;
00032 } pixelInfo;
00033 
00034 typedef struct pixelInfo16 {
00035     int16_t G;
00036     int16_t R;
00037     int16_t B;
00038 } pixelInfo16;
00039 
00040 
00041 /** Drives a WS2812 LED chain
00042 *
00043 * An alternative WS2811/2812 driver using the BusrtSPI library
00044 *
00045 * Credit for the inspiration goes to Jacob for his pixelArray library
00046 * http://developer.mbed.org/users/JacobBramley/code/PixelArray/
00047 *
00048 * This version was written mainly to help me understand what was going on and is a little more basic.
00049 * While the end result is muc the same the code is completely from scratch.
00050 *
00051 *  BurstSPI is used to generate the timing so support is limited to the parts supported by that library.
00052 *
00053 *  Also note that while all 3 SPI pins are specified only the MOSI pin is actually needed and should connect to the data in on the LEDs
00054 *
00055 *  Example code to run a single lit led along a chain
00056 *
00057 *  @code
00058 *
00059 *  #include "mbed.h"
00060 *  #include "wsDrive.h"
00061 *
00062 *  // update period in ms
00063 *  #define updatePeriod 100
00064 *  // number of LEDs
00065 *  #define chainLen 8
00066 *
00067 *  DigitalIn dummy(MOSI,PullDown); // first activate the pulldown on the pin.
00068 *  wsDrive ledDriver(MOSI,MISO,CLK); // create the SPI bus. You can normally list the MISO and CLK as NC but some mbed library versions don't like that
00069 *
00070 *  // pixel storage buffer
00071 *  pixelInfo pixelData[chainLen];
00072 *
00073 *  Timer updateRateTimer;
00074 *
00075 *  void blankBuffer(pixelInfo *Ptr)
00076 *  {
00077 *     memset( (void *)Ptr, 0, chainLen*sizeof(pixelInfo) );
00078 *  }
00079 * 
00080 *  void setPixel(unsigned int index, pixelInfo *colourToUse) {
00081 *    if (index < chainLen) {
00082 *      pixelData[index].R = colourToUse->R;
00083 *      pixelData[index].G = colourToUse->G;
00084 *      pixelData[index].B = colourToUse->B;
00085 *    }
00086 *  }
00087 *
00088 *  void clearPixel(unsigned int index) {
00089 *    if (index < chainLen) {
00090 *      pixelData[index].R = 0;
00091 *      pixelData[index].G = 0;
00092 *      pixelData[index].B = 0;
00093 *    }
00094 *  }
00095 *
00096 * int main () {
00097 *
00098 *   int litLed = 0;
00099 *
00100 *   pixelInfo colour;
00101 *   colour.R = 0x80;
00102 *   colour.G = 0x00;
00103 *   colour.B = 0x00;
00104 *
00105 *   // Tell the driver where the data is stored
00106 *   ledDriver.setData(pixelData, chainLen);
00107 *
00108 *   // Set the buffer to the pattern we want
00109 *   blankBuffer(pixelData);
00110 *   setPixel(litLed, &colour);
00111 *
00112 *   updateRateTimer.start();
00113 *   while (true) {
00114 *
00115 *     ledDriver.sendData(); // send the LED data
00116 *
00117 *     // modify the buffer ready for the next update
00118 *     clearPixel(litLed);
00119 *     litLed++;
00120 *     if (litLed == chainLen)
00121 *       litLed = 0;
00122 *     setPixel(litLed, &colour);
00123 *
00124 *     // wait until the correct time since the last update...
00125 *     while (updateRateTimer.read_ms() < updatePeriod) {
00126 *     }
00127 
00128 *    updateRateTimer.reset();
00129 *    }
00130 * }
00131 * @endcode
00132 *
00133 * Troubleshooting:
00134 *
00135 * If the LEDs aren't lighting up correctly then check that your power supply is up to the job (or decrease the brightness you are using)
00136 *
00137 * Also check the supply voltage, on paper when running off 5V the WS2812 needs 4V on the data in pin to detect a high. Mbed based boards rarely output much over 3.1V.
00138 * This problem is normally indicated by the very first pattern send on power up being displayed but then no further updates being recieved. Dropping the supply voltage
00139 * to about 4.2 - 4.3 V will normally fix this problem without any meaningful impact on the LED output.
00140 *
00141 */
00142 class wsDrive : private BurstSPI
00143 {
00144 public:
00145     /** create the driver
00146     */
00147     wsDrive(PinName mosi, PinName miso, PinName clk);
00148 
00149     /** Set the data pointer
00150 
00151     Before data can be sent the driver must be given a pointer to the pixel data to use.
00152     Setting this is normally a one time operation unless you want to switch between buffers.
00153 
00154     @param dataStart The start of an array of pixelInfo items. This will be sent to the chain in order.
00155     @param dataLen   The length of the array.
00156     */
00157     void setData(pixelInfo *dataStart, uint16_t dataLen);
00158 
00159     void setData(pixelInfo16 *dataStart, uint16_t dataLen);
00160 
00161 
00162     /** Sends the data to the LEDs
00163     * setData() must be called prior to this.
00164     */
00165     void sendData();
00166 
00167 private:
00168 
00169     void sendByte(unsigned char value);
00170     void sendPixel(pixelInfo *pixToSend);
00171     void sendPixel(pixelInfo16 *pixToSend);
00172 
00173     pixelInfo *pixArray;
00174     pixelInfo16 *pixArray16;
00175     uint16_t pixelLen;
00176 
00177 };
00178 
00179 #endif