Simple scrolling LED Sign for NeoPixel (WS2811) or LPN8806

  • 2014/03/16 Update: The source code to this is now on GitHub. Check the Arduino link at the top of each page of this site.

Yesterday evening, I coded up a simple scrolling message sign that uses addressable LED strips like the Adafruit NeoPixels (WS2811) or LPN8806. The code I created is built for NeoPixels, since those were the ones I had access to, but it would be trivial to make it work with the Adafruit LPN8806 library. Future versions will make this simpler.

First, let’s talk about LED signs.

The BetaBrite is a commercially available scrolling message sign that’s been around for ages. I bought one at SAM’S CLUB back in the late 1990s. The BetaBrite that I have uses an 80×7 array of LEDs. This is what I will be trying to replicate.

If you shop around (ahem, e-Bay), you can find 1 meter long WS2811 LED strips with 60 RGB LEDs for around $8-$9. If you had seven of those, you could make a 60×7 LED sign. It wouldn’t be able to show as many characters at the same time as a BetaBrite does, but it would be good enough to experiment with. (There are strips with 144 pixels per meter, but they are very expensive. And, when you get past 500 or so LEDs, you start running out of memory on the Arduino. I plan to fix this with some updates to the LED library, eventually.)

Consider this wonderful drawing as I discuss a few possible ways to present a sign made out of LED strips:

LED Sign ideas

A. At the top is an example of one of these LED strips with LED number 0 to “n”. One end hooks to the Arduino and power, and the other end can be used to daisy chain multiple strips together. The first LED will be 0, and they count up to the end of the last strip. If you have three 60 LED strips, you have LEDs 0 to 179. The green arrow shows the direction of the data (the LEDs count up in that direction).

B. Next is an example of how you might arrange multiple strips so they could make up an LED sign. Each strip is shown running left-to-right, so at the end of the first strip the cables go all the way back to the left to connect to the start of the next strip. Wiring them like this makes it real easy to do things with. Notice that the green arrow runs left-to-right on each row.

C. However, it would be much much easier to just connect them like this, without all the extra wires running around. But, this causes every other row to run in the opposite direction (again, see the green arrows). This means the software has to be smart enough to know how to reverse drawing the pixels for every other row.

ALSO, based on where you decide to make LED 0, that changes everything. In these drawings, we are hooking the Arduino up at the top left. But, if it was easier to hook up at the bottom right, the entire numbering system would be backwards.

I decided to write a simple LED message program that could handle all of this. It’s not pretty, but it (maybe) works. I configure it with the number of LEDs in use, and how many are in each row, then I set where the start pixel is (TOPLEFT, TOPRIGHT, BOTTOMLEFT or BOTTOMRIGHT). I support running the rows STRAIGHT (A) or ZIGZAG (B). It can even do something fun…

D. This is the only thing I have actually done. I had two 1 meter strips, so I decided to spiral them with 20 LEDs in each spiral before the next row starts. These 120 LEDs can be split up in my program as six rows of 20 LEDs each, and then (with a small enough font), a message can rotate around it.

If you’d like to try out my code, I have posted it to GitHub:

https://github.com/allenhuffman/LEDSign

I have only tested it in the D configuration, but I have done some debug prints that make me think it should be handling all the other variations. Until I have access to more LED strips, I won’t know for sure.

Anyone want to try it out and let me know how it works for you?

Poor documentation, and the code could be cleaned up and optimized quite a bit. Perhaps I will have that done when I reach version 1.0.

Here’s a video of my first working version:

78 thoughts on “Simple scrolling LED Sign for NeoPixel (WS2811) or LPN8806

        1. Allen Huffman Post author

          Sorry I missed this reply… Yes, my code should work with anything where you can say “set LED X to color Y”. That’s all it needs. The Adafruit libraries I use are the same calls for several types of LEDs they make the library for, so the changes are very minor to support them. If these LEDs use a different library, it will just require changing a few lines to call the library functions instead of the Adafruit functions. I’d be glad to help.

          Reply
          1. Allen Huffman Post author

            If you aren’t using LEDs supported by the Neopixels library, you should be able to replace the light on/off code with whatever works with your panel, and configure it that way.

        1. Allen Huffman Post author

          Cool. As long as you have the library and it uses the same API as the WS2811, it should work as long as a few things are configured.v

          #define PIN 6

          That pin should match whatever the working demos use based on how you have it wired up.

          #define LEDBRIGHTNESS 2

          If this is too low, you might not see anything. I ran it very low because I was powering mine from the Arduino 5v directly so I was limited.

          The rest is making sure the API library calls match. Look for places that start with “strip.” in the code (only a few places). Most important is probably the thing that defines what it is using:

          Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDS, PIN, NEO_GRB + NEO_KHZ800);

          Those parameters at the end may have to be changed to match what you have, so compare that with the example code you have that works.

          Also:

          strip.setPixelColor( xxxx , strip.Color(127,0,0) );

          and

          strip.show();

          Are those used in the examples you have that work?

          Reply
          1. Allen Huffman Post author

            Ah… The pattern is probably a config thing, based on how many lights per row and such. The not moving could be because by default no ENTER is sent from the Arduino IDE when you type in the window so the input never gets processed. There is a toggle in the terminal/serial console that makes it send CR at the end. If you can’t find it, I will install it and take a quick look on the system I am using right now.

          2. Allen Huffman Post author

            Found it. Bottom right of the COMx window has “No line ending” in a pull down. Change that to “Carriage return” and that should get the input coming in. It will print out on the screen what is going on. You can also uncomment:

            //#define DEBUG

            And it will print the banner to the screen sideways as characters, representing which LEDs would be turned on.

  1. herobattousai

    they follow the one you have on your diagram i believe they zigzag I can send you a photo if you want, its going into a crt helmet for a silver daftpunk cosplay.

    Reply
      1. herobattousai

        yes in atlanta My friend coded my helmet which is the gold one and he passed away before he could help me finish the silver one and I need all the help I can get

        Reply
    1. Allen Huffman Post author

      Comment out:

      Serial.print(“Enter message: “);
      msgLen = lineInput(message, MAXMSGLEN);

      And then add this (can be better, just for testing):

      strncpy(message, “This is your message”, MAXMSGLEN);
      msgLen = strlen(message);

      …that will make it just fire up and do that message over and over without stopping for input.

      Reply
      1. herobattousai

        aparently i am just a hand full of issues today lol making things so easy for you arent I sorry if I am a bother.
        Arduino: 1.8.3 (Windows 10), Board: “Arduino/Genuino Uno”

        LEDSign:197: error: stray ‘\342’ in program

        strncpy(message, “This is your message�, MAXMSGLEN);

        ^

        LEDSign:197: error: stray ‘\200’ in program

        LEDSign:197: error: stray ‘\234’ in program

        LEDSign:197: error: stray ‘\342’ in program

        LEDSign:197: error: stray ‘\200’ in program

        LEDSign:197: error: stray ‘\235’ in program

        C:\Users\Herobattousai\Documents\Arduino\LEDSign-master\LEDSign\LEDSign.ino: In function ‘void loop()’:

        LEDSign:197: error: ‘This’ was not declared in this scope

        strncpy(message, “This is your message�, MAXMSGLEN);

        ^

        C:\Users\Herobattousai\Documents\Arduino\LEDSign-master\LEDSign\LineInput.ino: At global scope:
        LineInput:17: error: expected initializer before ‘byte’

        byte lineInput(char *buffer, size_t bufsize)

        ^
        exit status 1
        stray ‘\342’ in program

        This report would have more information with
        “Show verbose output during compilation”
        option enabled in File -> Preferences

        Reply
        1. Allen Huffman Post author

          HTML copy/paste got that one. Let me see if this helps. Basically, instead of calling LineInput to read Serial input in to a buffer, we use string copy to copy a hard-coded string there, then set the length. The rest is the same.


          strncpy(message, “This is your message”, MAXMSGLEN);
          msgLen = strlen(message);

          Reply
          1. herobattousai

            evidently it doesn’t like me here and you have been very helpful I thank you for the help It just doesnt want me to post the code here it gives me an error message…..

  2. herobattousai

    that would be amazing in return I would love to repay you somehow in some form of fashion I do volunteer for a makerspace so if there is anything you need help with

    Reply
  3. David Duce

    Hello Allen, Great job on the code. I made some mods to allow entering message, R,G,B, and scroll speed through serial. below is the code.

    /*—————————————————————————*/
    // CONFIGURATION
    /*—————————————————————————*/
    // Adafruit NeoPixel library configuration.
    #define PIN 5

    // LED strip configuration.
    // Example: 7 1m 60-LED strips (similar to BetaBrite 80×7 display).
    #define LEDSTRIPS 1
    #define LEDSPERSTRIP 100
    #define LEDSPERROW 20

    // LED strip layout.
    // Where is LED 0? TOPLEFT, TOPRIGHT, BOTTOMLEFT, or BOTTOMRIGHT
    #define LAYOUTSTART TOPLEFT

    // If the strips run one direction, then reverse for the next row,
    // use ZIGZAG, else use STRAIGHT.
    #define LAYOUTMODE STRAIGHT

    int SCROLLSPEED = 100; // 100ms (1000=1 second)

    /*—————————————————————————*/
    // FUNCTIONS
    /*—————————————————————————*/
    String incomingByte;
    int Red1;
    int Grn1;
    int Blu1;
    char message[MAXMSGLEN];
    uint8_t msgLen;

    void setup()
    {
    #if defined(LEDBRIGHTNESS)
    strip.setBrightness(LEDBRIGHTNESS);
    #endif
    Serial.begin(9600);

    Serial.print(F(“LEDSign “));
    Serial.print(VERSION);
    Serial.println(F(” by Allen C. Huffman (alsplace@pobox.com)”));
    DEBUG_PRINTLN(F(“DEBUG MODE”));

    Serial.print(F(“Total LEDs : “));
    Serial.println(LEDS);

    Serial.print(F(“LEDs per row : “));
    Serial.println(LEDSPERROW);

    Serial.print(F(“Rows : “));
    Serial.println(ROWS);

    Serial.print(F(“Free memory : “));
    Serial.println(freeRam());
    Serial.println(“Enter message \”|\” Then colour R,G,B,(Scroll Speed in Milliseconds): “);
    Serial.flush();
    // Start up the LED strip
    strip.begin();

    // Update the strip, to start they are all ‘off’
    strip.show();
    } // end of setup()

    void loop() {
    // send data only when you receive data:
    if (Serial.available() > 2) {
    for( int i = 0; i 0)
    {
    uint8_t fontWidth, fontHeight, fontStartChar;
    uint8_t letter, fontByte, fontBit;
    uint8_t letterOffset;
    uint8_t row, col;
    uint8_t offset;
    char ch;
    uint8_t layoutStart, layoutMode;
    uint8_t colDir, rowDir;
    uint8_t colOffset, rowOffset;

    layoutStart = LAYOUTSTART;
    layoutMode = LAYOUTMODE;

    // If LED 0 starts at the bottom, we need to invert the rows when we
    // display the message.
    if (layoutStart==TOPLEFT || layoutStart==TOPRIGHT)
    {
    rowDir = DOWN;
    }
    else
    {
    rowDir = UP;
    }

    // If we start from the right side, we will be going backwards.
    if (layoutStart==TOPLEFT || layoutStart==BOTTOMLEFT)
    {
    colDir = RIGHT;
    }
    else
    {
    colDir = LEFT;
    }

    fontWidth = FONTWIDTH;
    fontHeight = FONTHEIGHT;
    fontStartChar = FONTSTARTCHAR;

    //Serial.print(F(“Font size : “));
    //Serial.print(fontWidth);
    //Serial.print(F(“x”));
    //Serial.println(fontHeight);
    //Serial.flush();

    // Loop through each letter in the message.
    for (letter=0; letter<msgLen; letter++)
    {
    // Scroll fontWidth pixels for each letter.
    for (offset=0; offset<fontWidth; offset++)
    // If you comment out the above for loop, and then just set offset
    // to 0, the sign will scroll a character at a time.
    //offset = 0;
    {
    // Loop through each row…
    for (row=0; row<ROWS && row<fontHeight ; row++)
    {
    letterOffset = 0;
    fontBit = offset;

    // If going down (starting at top), we will use the loop row,
    // else we will calculate a row that goes backwards.
    if (rowDir==DOWN)
    {
    rowOffset = row;
    }
    else
    {
    rowOffset = (fontHeight<ROWS ? fontHeight : ROWS)-1-row;
    }

    // Now loop through each pixel in the row (column).
    for (col=0; col=msgLen)
    {
    ch = ‘ ‘;
    }
    else // Otherwise, get the actual letter.
    {
    ch = message[letter+letterOffset];
    }

    // Get the appropriate byte from the font data.
    if (bitRead(pgm_read_byte_near(&font[FONTDATAOFFSET+
    (ch-fontStartChar)*fontHeight+rowOffset]),
    //(colDir==RIGHT ? 7-fontBit : 7-(fontWidth-1)+fontBit))==1)
    //(colDir==LEFT ? 7-fontBit : 7-(fontWidth-1)+fontBit))==1)
    7-fontBit)==1)
    {
    // 1 = set a pixel.
    strip.setPixelColor((row*LEDSPERROW)+colOffset,
    strip.Color(Red1,Grn1,Blu1));

    DEBUG_PRINT(F(“#”));
    }
    else
    {
    // 0 = unset a pixel.
    strip.setPixelColor((row*LEDSPERROW)+colOffset, 0);

    DEBUG_PRINT(F(” “));
    }

    // Move to next bit in the character.
    fontBit++;
    // If we get to the width of the font, move to the next letter.
    if (fontBit >= fontWidth)
    {
    fontBit = 0;
    letterOffset++;
    }
    } // end of for (col=0; col<LEDSPERROW; col++)

    DEBUG_PRINTLN();

    // If the LED strips are zig zagged, at the end of each row we
    // will reverse the direction.
    if (layoutMode==ZIGZAG)
    {
    // Invert direction.
    if (colDir==RIGHT)
    {
    colDir = LEFT;
    }
    else
    {
    colDir = RIGHT;
    }
    } // end of if (layoutMode==ZIGZAG)
    } // end of for (row=0; row<ROWS && row<fontHeight ; row++)
    strip.show();

    #if defined(DEBUG)
    for (uint8_t i=0; i<LEDSPERROW; i++) Serial.print(F("-"));
    Serial.println();
    #endif
    delay(SCROLLSPEED);
    } // end of for (offset=0; offset<fontWidth; offset++)
    } // end of for (letter=0; letter0)
    } // end of loop()

    // Simple utility function to return the current free RAM.
    unsigned int freeRam() {
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v – (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
    } // end of freeRam()

    /*—————————————————————————*/
    // End of LEDSign

    Reply
  4. David Duce

    #define VERSION “0.03”

    #include
    #include “LEDSign.h”

    // If using the TVout fonts, either include the individual header file for
    // the font you wish to use, or include this one to access them all. The
    // current version of this program has the font selected at compile time, so
    // there is no reason to include more than just that font, but in the future
    // I plan to update it so fonts can be selected.
    #include “fontALL.h” // Use the TVout fonts for this test.

    // If defined, this will print out the banner text to the Serial console.
    //#define DEBUG

    /*—————————————————————————*/
    // CONFIGURATION
    /*—————————————————————————*/
    // Adafruit NeoPixel library configuration.
    #define PIN 5

    // LED strip configuration.
    // Example: 7 1m 60-LED strips (similar to BetaBrite 80×7 display).
    #define LEDSTRIPS 1
    #define LEDSPERSTRIP 100
    #define LEDSPERROW 20

    // Example: 2 1m 60-LED strips, spiraled with 20 per row. (6 rows).
    //#define LEDSTRIPS 2
    //#define LEDSPERSTRIP 60
    //#define LEDSPERROW 20

    // LED strip layout.
    // Where is LED 0? TOPLEFT, TOPRIGHT, BOTTOMLEFT, or BOTTOMRIGHT
    #define LAYOUTSTART TOPLEFT

    // If the strips run one direction, then reverse for the next row,
    // use ZIGZAG, else use STRAIGHT.
    #define LAYOUTMODE STRAIGHT

    int SCROLLSPEED = 100; // 100ms (1000=1 second)

    // If defined, a strip.setBrightness(x) will be done. I use this so more
    // LEDs can be powered off an Arduino supply if they are all very dim/low
    // power. You should be using a proper power supply, however!
    #define LEDBRIGHTNESS 30

    // Specify which font to use. (These examples are for the TVout fonts.)
    const unsigned char *font = font4x6;
    //const unsigned char *font = font6x8;
    //const unsigned char *font = font8x8; // Blank row on top. Bad font.
    //const unsigned char *font = font8x8ext;

    // Set these defines to match the font data, or, if using the TVout
    // fonts, these values can be read from the first three bytes of
    // the file (and FONTDATAOFFSET is set to skip those first three
    // bytes).
    #define FONTWIDTH (pgm_read_byte_near(&font[0]))
    #define FONTHEIGHT (pgm_read_byte_near(&font[1]))
    #define FONTSTARTCHAR (pgm_read_byte_near(&font[2]))
    #define FONTDATAOFFSET 3

    /*—————————————————————————*/
    // DEFINES
    /*—————————————————————————*/
    // These defines are calculated.
    #define LEDS (LEDSPERSTRIP*LEDSTRIPS)
    #define ROWS (LEDS/LEDSPERROW)

    // Longest message we can display.
    #define MAXMSGLEN 80

    // Parameter 1 = number of pixels in strip
    // Parameter 2 = Arduino pin number (most are valid)
    // Parameter 3 = pixel type flags, add together as needed:
    // NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
    // NEO_KHZ400 400 KHz (classic ‘v1’ (not v2) FLORA pixels, WS2811 drivers)
    // NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
    // NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(LEDS, PIN, NEO_GRB + NEO_KHZ800);

    // IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
    // pixel power leads, add 300 – 500 Ohm resistor on first pixel’s data input
    // and minimize distance between Arduino and first pixel. Avoid connecting
    // on a live circuit…if you must, connect GND first.

    /*—————————————————————————*/
    // For the Adafruit LPN8806/NeoPixel libraries, three bytes of RAM are
    // used for each pixel. This crashes the Arduino, so we could easily do a
    // simple sanity check before initializing things… To do this, we’d
    // need to make the “strip” a global (which is is) and initialize it after
    // the check (if the check was successful).
    #if (LEDS*3>2000)
    #error USING UP OVER 2000 BYTES OF RAM!
    #endif

    /*—————————————————————————*/
    // A debug Serial.print()/Serial.println() macro.
    #if defined(DEBUG)
    #define DEBUG_PRINT(…) Serial.print(__VA_ARGS__)
    #define DEBUG_PRINTLN(…) Serial.println(__VA_ARGS__)
    #else // If not debugging, it will not be included.
    #define DEBUG_PRINT(…)
    #define DEBUG_PRINTLN(…)
    #endif

    /*—————————————————————————*/
    // FUNCTIONS
    /*—————————————————————————*/
    String incomingByte;
    int Red1;
    int Grn1;
    int Blu1;
    char message[MAXMSGLEN];
    uint8_t msgLen;

    void setup()
    {
    #if defined(LEDBRIGHTNESS)
    strip.setBrightness(LEDBRIGHTNESS);
    #endif
    Serial.begin(9600);

    Serial.print(F(“LEDSign “));
    Serial.print(VERSION);
    Serial.println(F(” by Allen C. Huffman (alsplace@pobox.com)”));
    DEBUG_PRINTLN(F(“DEBUG MODE”));

    Serial.print(F(“Total LEDs : “));
    Serial.println(LEDS);

    Serial.print(F(“LEDs per row : “));
    Serial.println(LEDSPERROW);

    Serial.print(F(“Rows : “));
    Serial.println(ROWS);

    Serial.print(F(“Free memory : “));
    Serial.println(freeRam());
    Serial.println(“Enter message \”|\” Then colour R,G,B,(Scroll Speed in Milliseconds): “);
    Serial.flush();
    // Start up the LED strip
    strip.begin();

    // Update the strip, to start they are all ‘off’
    strip.show();
    } // end of setup()

    void loop() {
    // send data only when you receive data:
    if (Serial.available() > 2) {
    for( int i = 0; i 0)
    {
    uint8_t fontWidth, fontHeight, fontStartChar;
    uint8_t letter, fontByte, fontBit;
    uint8_t letterOffset;
    uint8_t row, col;
    uint8_t offset;
    char ch;
    uint8_t layoutStart, layoutMode;
    uint8_t colDir, rowDir;
    uint8_t colOffset, rowOffset;

    layoutStart = LAYOUTSTART;
    layoutMode = LAYOUTMODE;

    // If LED 0 starts at the bottom, we need to invert the rows when we
    // display the message.
    if (layoutStart==TOPLEFT || layoutStart==TOPRIGHT)
    {
    rowDir = DOWN;
    }
    else
    {
    rowDir = UP;
    }

    // If we start from the right side, we will be going backwards.
    if (layoutStart==TOPLEFT || layoutStart==BOTTOMLEFT)
    {
    colDir = RIGHT;
    }
    else
    {
    colDir = LEFT;
    }

    fontWidth = FONTWIDTH;
    fontHeight = FONTHEIGHT;
    fontStartChar = FONTSTARTCHAR;

    //Serial.print(F(“Font size : “));
    //Serial.print(fontWidth);
    //Serial.print(F(“x”));
    //Serial.println(fontHeight);
    //Serial.flush();

    // Loop through each letter in the message.
    for (letter=0; letter<msgLen; letter++)
    {
    // Scroll fontWidth pixels for each letter.
    for (offset=0; offset<fontWidth; offset++)
    // If you comment out the above for loop, and then just set offset
    // to 0, the sign will scroll a character at a time.
    //offset = 0;
    {
    // Loop through each row…
    for (row=0; row<ROWS && row<fontHeight ; row++)
    {
    letterOffset = 0;
    fontBit = offset;

    // If going down (starting at top), we will use the loop row,
    // else we will calculate a row that goes backwards.
    if (rowDir==DOWN)
    {
    rowOffset = row;
    }
    else
    {
    rowOffset = (fontHeight<ROWS ? fontHeight : ROWS)-1-row;
    }

    // Now loop through each pixel in the row (column).
    for (col=0; col=msgLen)
    {
    ch = ‘ ‘;
    }
    else // Otherwise, get the actual letter.
    {
    ch = message[letter+letterOffset];
    }

    // Get the appropriate byte from the font data.
    if (bitRead(pgm_read_byte_near(&font[FONTDATAOFFSET+
    (ch-fontStartChar)*fontHeight+rowOffset]),
    //(colDir==RIGHT ? 7-fontBit : 7-(fontWidth-1)+fontBit))==1)
    //(colDir==LEFT ? 7-fontBit : 7-(fontWidth-1)+fontBit))==1)
    7-fontBit)==1)
    {
    // 1 = set a pixel.
    strip.setPixelColor((row*LEDSPERROW)+colOffset,
    strip.Color(Red1,Grn1,Blu1));

    DEBUG_PRINT(F(“#”));
    }
    else
    {
    // 0 = unset a pixel.
    strip.setPixelColor((row*LEDSPERROW)+colOffset, 0);

    DEBUG_PRINT(F(” “));
    }

    // Move to next bit in the character.
    fontBit++;
    // If we get to the width of the font, move to the next letter.
    if (fontBit >= fontWidth)
    {
    fontBit = 0;
    letterOffset++;
    }
    } // end of for (col=0; col<LEDSPERROW; col++)

    DEBUG_PRINTLN();

    // If the LED strips are zig zagged, at the end of each row we
    // will reverse the direction.
    if (layoutMode==ZIGZAG)
    {
    // Invert direction.
    if (colDir==RIGHT)
    {
    colDir = LEFT;
    }
    else
    {
    colDir = RIGHT;
    }
    } // end of if (layoutMode==ZIGZAG)
    } // end of for (row=0; row<ROWS && row<fontHeight ; row++)
    strip.show();

    #if defined(DEBUG)
    for (uint8_t i=0; i<LEDSPERROW; i++) Serial.print(F("-"));
    Serial.println();
    #endif
    delay(SCROLLSPEED);
    } // end of for (offset=0; offset<fontWidth; offset++)
    } // end of for (letter=0; letter0)
    } // end of loop()

    // Simple utility function to return the current free RAM.
    unsigned int freeRam() {
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v – (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
    } // end of freeRam()

    /*—————————————————————————*/
    // End of LEDSign

    Reply
    1. Daniel Fernandes

      Hi David, I have two questions:
      1) What complements the first #include that is empty, in version 0.03 of your sketch? that is, it looks like this:

      #define VERSION “0.03”

      #include
      #include “LEDSign.h”

      2) Is it possible to scroll the message on the Led strip without being through the Serial Monitor? Say, a message fixed in the sketch without having to type in the serial.

      Thanks

      Reply
      1. Allen Huffman Post author

        I can help with the input. I was just doing a test when I wrote this, otherwise it would be a routine you just call with a string.

        In the loop, there is this:

        Serial.print(“Enter message: “);
        msgLen = lineInput(message, MAXMSGLEN);

        That puts whatever you type in a character buffer called “message”. Instead of those two lines, you could do:

        strncpy(message, “This is my message”, MAXMSGLEN);
        msgLen = strlen(message);

        But it would be cleaner if you commented out (or removed) those two lines:

        //Serial.print(“Enter message: “);
        //msgLen = lineInput(message, MAXMSGLEN);

        and at the top of loop() you could change it to hard code a string instead:

        char *message = “This is my message.”;
        uint8_t msgLen = strlen(message);

        Then it would loop that forever. I really need to make a routine called DisplayMessage() or something and you just pass a string into that, then you could do:

        DisplayMessage(“Don’t Panic!”);

        I’ll have to do some updates when I get time.

        Reply
  5. David Duce

    For some reason the blog cuts this part out>>>>>>>>>>>>>>>>>>>

    } // end of setup()

    void loop() {
    // send data only when you receive data:
    if (Serial.available() > 2) {
    for( int i = 0; i 0)
    {

    Reply
  6. Edik

    Hey I’m using a WS2812B Neopixel LED strip, just one. It’s 5 meters in length, and has 300 LEDS in total. When I upload the code, nothing happens. Upload completes, but the lights don’t work. I’ve tested these lights elsewhere and they work. My Arduino also works, but I think it’s my configuration of the code, can anyone help?

    Reply
        1. Allen Huffman Post author

          The only config needed should be the ones that define the pins. If you can wire up the strips to the Arduino and they work with the samples, then we should be able to figure out what’s going on with my sketch,

          Reply
        2. Allen Huffman Post author

          I wonder if it’s just not getting ENTER on the text you type. That has hung some folks up before, as the program is waiting. You have to make sure the line endings are turned on in the Arduino console so it sends them when you type and send a line. Put “#define DEBUG” at the top of the sketch and you will see it print a ton of stuff and that will let you know if it’s working. It will print out what it would be sending to the LEDs.

          Reply
          1. Edik

            I tried that, it didn’t work. I put #define DEBUG at the top but it didn’t work. I’m using your 0.02 version

          2. Allen Huffman Post author

            Are you seeing the prompt where you type in your message and all that? If nothing happens past that, it’s not running for some reason.

      1. Edik

        Hey, So I used the Serial Monitor on Arduino IDE to send the message using the Prompt Enter Message: but nothing happens. I send the message, sends successfully but doesn’t display anything.

        Reply
        1. Allen Huffman Post author

          If you enter something like one letter “A” it should pause for a moment while it is talking tote LEDs, then return to the prompt again. If it doesn’t, it hasn’t gotten the input yet. There is a LINE ENDINGS box in the serial monitor that has to be set a certain way for Arduino to see input.

          Reply
          1. Edik

            Ok it works, but I want it to loop the current text forever until I send another text and then loop that one forever. How would I accomplish this? Thank you.

          2. Allen Huffman Post author

            Yeah I never finished up the code. It would be easy to replace the spot where it inputs the text and just hard code a string of text there instead. Are you much of a programmer?

      1. A.saiedy

        Hello there, I’ve been fiddling with the code to run my setup which is basically WS2812b 4 by 6 individual elements that i soldered as “B” configuration shown in your tutorial. The code runs and every thing but only one led lights. The first top-right LED in the array only. please help. Cheers

        Reply
        1. Allen Huffman Post author

          There is a define that sets the number of LEDs it will use. That must be changed to match how many you have. I usually suggest running one of the Adafruit samples to test things.

          Reply
  7. Daniel Fernandes

    Hi David! Is your code working?

    #define VERSION “0.03”

    #include
    #include “LEDSign.h”

    What is this “#include” empty at the beginning?
    Put a video of your sketch for everyone to see, please!

    Reply
      1. Daniel Fernandes

        Sorry Allen Huffman, is this last sketch yours?
        I would like to know what this sketch does; thank you

        Reply
  8. Kenny Walker

    Almost works for me. I’m using 7 strips of 60pixel Neopixels. All works well if I run the “strand test” ino. This program works(sort of). It does not put anything in the bottom two strips. I’ve specified the 4×6 font. I’m getting power from an external power supply.

    Am I missing something simple?

    Reply
    1. Allen Huffman Post author

      Maybe. Have you tried lowercase letters? I seem to recall one of the TV Out fonts was like the old dot matrix printers of the 80s and didn’t use bottom rows except for a few lowercase letters. Might be that.

      I am fairly sure I tested it with 8 strips.

      Reply
      1. Kenny Walker

        No joy on the fonts. I actually looked at the font files and none of the characters use the bottom row. I’ll just use the 6×8 font and add another strip.

        Thanks for this project.

        I have a holiday light show using LightshowPi. I modified that code to use MQTT to publish the current song name/artist. I’m running your(slightly modified to support MQTT) on a NodeMCU. When it receives an MQTT message with the new song name it updates the sign. Obviously I’m powering the strips from a beefy external supply. But it all works(on the bench). Now to move it to the yard.

        Reply
        1. ultraleadgroup

          am amazed to see this update. kindly show how I can do it, I have some nodeMCU I can use as this match what I search for.
          kindly give the code and the procedure. am not a coder yet, just learning by lay hands on these projecs type..

          Reply
        2. ultraleadgroup

          Thanks for this project you shared and yet replying time to time has helped to more and more. But my problem remained unsolved.

          I mistakenly shipped ws2811 12v 4packed*5meter strips from China. I purchased ws2812b, individual addresable. While paid, after shipping, it turned out to be 1 chip per 3 LEDs.

          Can it still run with this code?
          What do I do, how to modify the code or where can I get solution?

          I used strand examples , they sometimes just up and never blink, some slow…

          All I want to make is scrolling text through Bluetooth and Android.

          I have read bunch of …
          no understanding yet

          Thanks in advance

          Reply
          1. Allen Huffman Post author

            I have only worked with the two types of addressable LEDs listed in the article. If it treats three LEDs as one light source, you would probably just get a larger “fat pixel” display for the letters. The main thing is it must be supported by that LED library my code uses. I would start there and see if they are supported.

    1. Allen Huffman Post author

      There are two things I would love to do:

      1) Change the LED driver so it is far more memory efficient. Rather than every pixel taking a blog of memory for colors, I’d change each pixel to 4-bits (16 colors from a palette) or 8-bits (256 colors from a palette) which is more than enough for many uses. The driver would look up the palette values and send those to the LEDs, rather than sending out the values from the current LED glob. This could increase the number of pixels supported by 3X+ easily. This would require assembly (the LED drivers bit band using assembly) and is beyond my skillset.

      2) It would be trivial to add color support to my example code just by adding an escape sequence to the string, and having the parser set the colors as it renders. If I ever get the LED stuff again, I would revisit this project and add that.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.