Bigger is better: Build an Arduino-powered monster scrolling LED sign for about $15 a foot


Would you do with a massive full color animated LED display? How about…

  • Read your Tweets in giant 140 char gulps from a block away
  • Add English sub-titles to the Eiffel Tower
  • Display a live-updating, 45 digit long countdown of the number of atoms left in the known universe

What if you could build the display however long you needed it, for only about $15/foot?

What if it was really easy to build and used everyone’s favorite low cost micro-controller so you could easily change the software to do whatever you wanted?

Well you can! Read on for details and perfunctory video!

Perfunctory video….

UPDATE 3/14/2018:
This sign could be yours!
I am moving, so I am giving this sign away to the first person who (1) can convince me they will do something cool with it, and (2) can come pick it up from NYC (it is LONG!). Give me your idea in the comments below!

Build One

My sign is 12 feet long with 2,688 RGB pixels. It can display scrolling text at 80 frames per second. You can make your sign as long or short as you like.



(Click on pics to zoom)

The build is so simple, that you should be able to figure it out from looking at the pictures. Stick the strips to something, add some power, connect the Arduino data out pins to the strips’ data in pins.

The secret sauce is in the software. You can read about the parallel processing technique used here.

Code Drop

Simple text scroller


Here is a very short and simple Arduino Sketch to get you started….

It will scroll Jabberwocky across any WS2812B Neopixel strips attached to digital pins 1-7.  The code is clean and should be easy to understand and modify.

Full blown multi-effect demo


Once you get bored of Lewis Carroll, try the full demo to get some ideas on how to do fancy effects like…

  • Multi-color
  • Custom fonts
  • Gamma correction
  • Sprite graphics with animation

So much is possible, and it is super fun to find a use for all your old-school demo scene hacks!


Q: Wait, how are you driving this huge display from an Arduino? How do you fit a 8,064 byte buffer into only 1k of RAM?

Do not try to fit all the pixels into a buffer. That would be impossible. Instead, generate the pixels (and, in fact, the individual bits of the bytes of the pixels) on the fly the moment they are transmitted to the LEDs.

That’s kinda the whole point of the project.

You can read more about it here. Now you can drive an infinite length of pixels with a finite (and and extremely small) amount of RAM.

Q: Why do you keep whining about how bright it is? We get it!

Seriously, dude, you do not understand how bright this monster is until you see it in person. The “All Your Base” display has given every member of my family a migraine at least once when they accidentally glanced at it. Get yourself a pair of gas welding googles and some SPF45 sunscreen if you plan on building one of these. Once it is built, you can always crank down the brightness and/or mount it far away from humans.

Q: What is your sign made of?

I used a few a strips of plywood with a couple of aluminum angles glued to the top and bottom to make it more rigid and look nicer…

2016-05-03 16.10.512016-05-03 17.14.172016-05-03 17.21.492016-05-11 13.27.382016-05-11 16.22.38

(click to zoom)

But you can use anything that you can stick LED strips to. If you are going for cheap and easy, 7 strips fit almost perfectly onto a 2×4…

2016-05-11 15.16.39

Walls, I-beams, Airstream trailers, suspension bridges… would all work great too!

Q: Where does the $15/foot come from?

The majority of the cost for a big sign comes from the LED strips. The 60 LED/meter strips regularly sell for $5/meter. The display is 7 strips high, so the strip cost comes out to about $11/foot.

The other variable costs are power and structure.

300 Watt supply can drive a 15 feet of display, for a cost of about $1.70/foot.

A top-of-the-line 2×4 costs about $1/foot – or you can stick the strips to an existing structure for free.

Finally, you will need one Arduino per sign, and the Pro Mini goes for $3-$15 a pop depending on how long you are willing to wait for it to arrive.

Q: Couldn’t you just connect all the strips end-to-end and drive them with a single pin?

Yes, but it would more than 7x slower. That is a huge difference visually.

The code for driving the serpentine pattern bit-by-bit would also be much hairier and less efficient.

Q: Couldn’t you just use a BeagleBone and drive the strips in parallel using ledSCAPE on the PRU? 

This works great, but a BeagleBone costs at least $40 (more often $55), runs complicated and vindictive Linux, outputs 3.3 volts, and it not as widely known and loved as the humble Arduino.

You can get a Arduino Pro Mini for about $5, connect the led strips directly to the 5 volt pins, and have a running sign as quickly as you can download the sketch (2 seconds)!

Q: Will this run on on other boards besides Arduino Uno?

It should work on any board that…

  1. Uses any 8-bit AVR
  2. Has at least 7 pins connected to a single port
  3. Runs at 16Mhz

This includes the Arduino Pro Micro, which is particularly well suited and super cheap.

Q: How big a power supply do I need?

That depends on how long a sign you want to build and what brightness/color/content you want to display.

In the worst case, if you are turning on every pixel with full brightness white, you need about 0.25 watts per pixel. But you would never want to do that because it would incinerate all nearby life.

Normal text only has about 20% of the pixels on at any given moment, and 50% bright white is looks almost nearly as bright as 100% but uses half the power.

Switching from white to colors can drop power by 2/3rds, and a dim red text display can use so little power that a 10′ long sign can run off a USB port.

Q: What is the longest sign I can make?

The limiting factors are…

  1. Power. You need a big enough supply.
  2. Voltage drop. You need to be able to get enough voltage to the pixels that are farthest away from the power supply connections. These will typically be to ones on the middle of the display if the power connections are on the ends.
  3. Refresh rate. It takes about 25us per column to refresh the display, so the longer it gets, the slower your frame rate will be.
  4. Physical constraints. Can you get it down your stairs? Can you find something that long that wont break when you pick it up?

I made my sign only 12′ long because is the longest thing that can make it down my stairs. 400 pixels long also gives 80 frames per second refresh rate, which is just fast enough for nice animations.

I’d love to make a 100 foot long sign if you can find me a long enough surface to mount it on, and tell me what it should say!

Q: Why did you use 96 Pixel/Meter strips rather than 60 Pixel/Meter?

Because I had a bunch left over from another project, and they happen to look very nice. But 60 Pixel/meter strips also look nice and are much cheaper.

Q: Where can I get really, really long strips?

The longest strips I’ve seen for sale are only 5 meters long and the cheapest are typically 1 meter long, so I splice them together.

Q: How do you splice them?

I made a simple jig to keep everything perfectly aligned and at the correct pitch while I solder away…

2016-05-11 13.17.41

Q: Why did you only use 7 of the bits? Why not make the sign a full 8 rows tall?

  1. I had a nice 7 pixel font sitting on my desk from a recent project and didn’t want to waste time making/finding/converting an 8 pixel high font.
  2. I wanted to keep the RX pin (Digital Pin #0 on the UNO) free so that the sign could be driven by sending serial data from a laptop connected to the Uno.
  3. I cut the plywood infill just ever so slightly too narrow to fit 8 strips. That’s why there is a blue margin above and below the strips.

Q: Can I get the schematic and gerbers for the custom PCB?

That’s just a crappy Radio Shack perf board to hold the wires together and make something that I could plug and unplug. It has no parts. If you were using an Arduino Pro Mini, you could solder the data wires directly into the board and then twist the power wires together with a wire nut.

2016-05-13 22.30.262016-05-13 22.30.35

Q: How can I slow down the scrolling speed?

Like this…

Higher numbers, slower scrolling.

Q: I want to build a sign that is 14 pixels high, can I just wire the inputs for each set of two strings to one output pin?

Sure thing! Or groups of three for a 21 pixel tell display!

But your display is going to look blocky because you have not increased the vertical resolution.  It would be possible to drive a taller display using more pins and higher resolution, it would take a little work – mostly making a taller font.



    • bigjosh2

      Yes, those should work. The current version of the software only drives the first 7 rows, that it should be very easy to change it to do all 8, although you’ll probably want to use fonts that look better with 8 pixels.

      • rvbcrs

        Sorry, bit of a noob here, but if I understand correctly you connected 7 strings (in parallel) these matrix boards only use 1 data line (serial). How do I set that in code? And how to connect these matrix?

        • bigjosh2

          I used Neopixel strips, which are much, much cheaper than these panels. There are 7 strips on my sign, each is a single row running the whole length of it.

  1. Pieter

    What would it take to have a much taller sign, say 28 rows using multiple Arduino units, or is there a better way?

  2. Ramon

    So I got 20 meter of WS2812 strings here and going to try to build one myself! I have one question, I would love to use an ESP8266 instead of a Arduino Uno, this because it is an arduino only faster and has integrated WiFi! But I’m not able to get the code working for the ESP8266. Is there a possability you can make the code working for this great $3 dollar Wifi arduino?

    • bigjosh2

      ESP8266’s are very handy little boards, but are a completely different kind of computer so none of this code applies. I’ve seen people get get WS2812b working with ESP8266, so maybe you can check out how they are doing it and try to apply this on-the-fly technique, though the ESP has 96KB of RAM (compared to UNO’s 2K) , so maybe tricks won’t be necessary.

        • bigjosh2

          Even though it can use the Arduino IDE, it is still a very different computer and no sketches that depend on the specific hardware or precise timing will work on the ESP. This WS2812B code depends on both specific hardware and precise timing, so it would take a rewrite to get it to run on the ESP.

        • bigjosh2

          An alternative would be to use an ESP connected to an ATTINY via a serial connection. I purposely left the RX pin on the AVR for just such a purpose. ATTINYs only cost a dollar or two, so unless you are looking to make thousands of these, then this will likely be the best solution. Do you have access to an ATTINY programmer (or and Arduino UNO, which can be used to program them)?

          • rvbcrs

            Thanks! I don’t mind getting a Arduino Mini or Micro or ATTINY for this purpose, but it somehow feels like missing out to have a Arduino and the ESP only for wireless serial communication, while the ESP would be fast enough and perfectly capable of doing the same as the Arduino can :)

            I will try things like Adafruit NeoPixel or FasLED libraries for now, but hoped I could use your code :) maybe if you ever have time :)

            Thanks for your response! I really love the display!

  3. Dustin Schaper

    What are the chances of getting something like this to run off something solar based? Nothing too large, maybe like a 2foot sign.

    • bigjosh2

      You can run *anything* off solar if you have enough panels! How many panels depends on how many LEDs you want, how long you want them to run (from only when panels are in full sun to 24 hours).

  4. Kyle Baity

    I’m assuming you loaded this string of text to display into your Arduino already. Have you come up with a way to load whatever text you want, on the fly? Thinking from example, how about live sports scores or stock market prices or anything like that? Or is that outside of the scope of your project? Just thinking it could be really awesome to have a row of this in an office setting, rotating through automatically updated scores or stock prices, or even showing what is now playing on your Spotify on a connected computer?

    • bigjosh2

      One of the benefits of using only a 7-bit font was to leave the bottom bit free for serial input (it happens to land on the RX pin on the Arduino). You could connect this to the serial port of a computer or RaspberryPi to get text to scroll. The serial-in code would be straight forward, and I’d also make the scroll speed dependent on how full the input buffer was to keep the scrolling nice and smooth and continuous.

  5. John Wills (@webcompanion)

    Awesome project Josh, I just built a 9.5 foot long version this weekend. Your code works like a charm. Did you post some of the other parts of your code somewhere to do the other techniques in your YouTube demo video like the graphics, countdown timer, etc? And for creating your fonts and graphics are you using some sort of graphical interface to help create those objects or are you coding it all by hand? Thanks!

    • bigjosh2

      I just built a 9.5 foot long version this weekend
      Cool! Post a picture!
      Did you post some of the other parts of your code somewhere to do the other techniques in your YouTube demo video like the graphics, countdown timer, etc?
      The code for the demo that is running in the youtube video is here.
      And for creating your fonts and graphics are you using some sort of graphical interface to help create those objects or are you coding it all by hand?
      The brutal code for munging the fonts and graphics into C code that I can cut/paste into the Arduino sketch is here. I typically google for whatever font or graphic I want, and then just hack up this code to be able to read the format.

  6. exarchianTed

    this is a great project and I decided to build it. I got all the materials together but I have a big problem. I’m not too sure how to solve it. My LEDs have 4 wires, not 3 like yours. I looked up more they all appear to have 4 wires. Any advice?

  7. exarchian

    this is a great project and I decided to build it. I got all the materials together but I have a big problem. I’m not too sure how to solve it. My LEDs have 4 wires, not 3 like yours. I looked up more they all appear to have 4 wires. Any advice?

    • bigjosh2

      Sounds like you do not have WS2812B strips which always have 3 connections. Maybe you have APA102 strips that have a data and clock line? Or maybe you got old school 3-color LED strips where the whole strip has to be the same color?

  8. Nikos

    this is great work for some of us who really not familiar whith programming….
    only writing simple things depend on logic things…thanks for sharing….
    my question is how to make steps with steady speed on time and not advancing when the message reaches the end…



    • bigjosh2

      Probably simplest way is just to add enough spaces at the end of the message string to fill the display. A more robust way would be to change the `sendstring()` function to automatically pad spaces at the end of the LEDs when it gets to the end of the messages string. An _even more_ robost way would be to change the `sendchar()` function to take both a starting and ending column and then have `sendstring()` exactly fill `PIXELS` number of columns… but this whole program is really just a demo of the parallel computing scheme in the previous post, so simplest is probably best! :)

  9. amanzimdwini

    I just built myself a little proof-of-concept display (1m / 30 pix each / 7 strips) and am now trying to figure out how to control the scrolling speed of the display. Adding delay loops seems to not work; changing the PIXEL variable does ?? And the display steadily accelerates – very noticeable for short messages. However, Right now I don’t see where that is in the code – have to jump over it again. Any hints?

    I’d also like to change it (like some of the previous commentators mentioned) based on external input too – if anyone has code, would you please share? I’m reading up on it right now & will share what I find.

    Another idea: passing a new COLOR into the display when the messages change. That one I nearly have already…

    Anyway, GREAT project! Just ordered 7 strips of 96*2m for a real display. Let the fun begin.

    • bigjosh2

      The limiting factor for the maximum scroll speed is the number of pixels long the display is as defined by the #define PIXELS. The current code just runs at maximum speed since my display is pretty long and I like to go fast. If you want to slow it down, you can either make the PIXEL count larger than your actual display (and larger than your string) or you could add a delayMicroseconds() inside the loop that steps though the columns (that would be here).

      • Rick

        I am having the same problem running the code on a 1 metre x 60.
        it accelerates the last half of the message, to the point where it is a blurr.
        any thoughts?

        • bigjosh2

          This behavior is intentional- just because I like the way it looks. :)

          If you prefer to have the end of the message scroll at a constant rate, you can pad the end of your string with spaces.

    • Brian

      I am just curious if you’ve been able to successfully update the scrolling message based on serial data received. I’d love to be able to look at the code that can do this, but I haven’t been able to find any examples.

      • alanlapp

        Hi Josh

        I build a larger version with 21 rows, each data line controlling 3 rows.

        The font looks a little ‘thin’ now. How would i repeat each column so it effectively makes the font ‘fatter’? Would i just sendstring twice in the last while loop (at the end of the script) with the jabberwocky?



  10. TomHammond

    Hi Josh,

    I am getting ready to build one of these as well! Thanks for the build instructions.

    However, I cannot get the SimpleScroll.ino to do anything on the WS2812 strip. I upload the code and nothing shows on the strip. I connected the strip to digital pin 1 on my Mega2560. I don’t have all seven strips connected, but I should at least see lights on one connected strip, right?

    I know that the strip works, as I can run the “strandtest” example sketch that is included when installing the Adafruit_NeoPixel library. It lights up the strip just fine.

    Do you know why nothing shows on the strip when I run SimpleScroll.ino?

    Thanks much for your help!

    • bigjosh2

      The example program is hard-coded for an Uno and uses PORTD bits 1-7. I looks like these show up on thew Mega all over the place. For a test, you can try connecting your string to digital pin #19 on the Mega and you should see something with the unmodified SimpleScroll.ino.

      If you are going to use the Mega going forward, you probably want to move the pins to a port where they are all available and lined up in a nice row. It looks like PORTF shows up on analog pins 0-7, so just change `PORTD` to `PORTF` and `DDRD` to DDRF` at the top of the program. Recompile and download and you should be able to connect strings to analog pins 1-7 on the Mega- unless there is something else different about the Mega that I don’t know about! LMK how it works out!

      • TomHammond

        Pin 19 did the trick! It is animating the strip, even if just one line. :) Thanks!

        May I ask one more question? I intend to add a W5100 ethernet shield to the Mega2560 to have it read a txt file on a website to get the text to display. If I am using that shield instead an ESP8266, then pin 0 Rx isn’t needed for this type of application, correct? I hope to combine the “read txt file from webpage” code with your “scrolling marque” code into a single sketch where it queries the txt file, then shows it on the marquee. Does this sound doable?

        Thanks again, Josh!

        • bigjosh2

          It looks like that shield uses the SPI pins for communication, so there should not be any conflict.
          As much as I love Arduino, if you are going to start doing weby stuff, you might want to consider using a BeagleBone. It has a built in Ethernet port and can drive a lot of WS2812B strings using the handy LEDscape software. It runs linux, so grabbing the contents of a text file from dropbox (my fav place to keep text files to be read by devices) could be as easy as a one line “curl” script. That is exactly how this project works, albeit with slightly older LEDs than WS2812B!

          • TomHammond

            My marquee will be outdoors as a “tune to” sign for my Christmas lights. I could use BBB to drive a lot of pixels to make a bigger sign that’s readable from the road, but it would be very expensive. Instead, I’m making a 30 pixel/meter marquee that’s 13-16′ long with diffusers to spread the pixels (about 1,000-1200). That result a 9″ tall display with fewer pixels, but “large” pixels to connect the dots in the letters better. I am sure it shouldn’t be hard to do the web stuff with Arduino. Plus, a complicated OS like Linux could get corrupted with outdoor power outages and other issues. Thanks for the tip, though!

  11. TomHammond

    I noticed in the video that the text scroll is from right-to-left, with the Arduino’s data lines being connected to the “end” of the marquee, as if the text is flowing into the Arduino. Can the scroll direction changed through software?


      • TomHammond

        Hi Josh,

        That sounds easy enough, thank you!

        I am busy building the outdoor enclosure for the 15′ display. Tonight, I hope to merge your code with the Ethernet library. This way, the display will show text pulled from a file on a website. So far, so good!

        Thanks again for your help,

      • Yuliana

        Hello Josh,

        I tried to do this but it did not work for me. Could you help? I am trying to make it go from left to right?

    • Jonny Walker

      I have spent ages trying to get the scrolling direction to change however I can’t seem to work out! I know it is probably something simple but I have tried everything (I think…). This is my main loop at the moment :

      void loop() {

      const char *m = jabberText;

      while (*m) {

      for( uint8_t step= 1 ; step < INTERCHAR_SPACE+FONT_WIDTH; step–) { // step though each column of the 1st char for smooth scrolling


      sendString( m , step , 255, 255, 255 ); // Nice and not-too-bright blue hue


      delay (100);





      • bigjosh2

        Depending on which way you want to scroll (there are at least 4 ways), you need some combination of switching the order that m reads the string chars out, switching to order that step reads the cols in each char, and/or flipping the font upside down.

        To switch the direction of m, you would initialize it as…

        const char *m = jabberText+strlen(jabberText);

        …test it as….

        while (m>=jabberText) {

        …and update it as…


        To run step backwards, you do something like…

        for( uint8_t step= INTERCHAR_SPACE+FONT_WIDTH-1; step >0 ; step–) {

        Try those out and see if you can get what you are looking for (that code not tested, so might have some typos).

  12. Bobby

    Hi Josh,

    I want to build a smaller version of what you did, but I can’t find led strips for around $11 per foot. In addition, when shopping for the led strips, I can’t tell which can be individually controlled and which cannot. Ideally I’d want rgb, but I could settle for single color if it’s a lot cheaper.

    Any suggestions?


    • bigjosh2

      You can find them for as cheap as $3 per meter (about 3 feet) on by searching for WS2812B Led Strips, but note that the really cheap ones are often poor quality (article forthcoming!). As long as they are WS2812B compatible, then they are individually addressable and RGB controllable.

      • Bobby

        Thanks for the reply! I actually found some on ebay, 10 meters for $50. It helped knowing the specific name of the leds to make sure I didn’t get one that couldn’t be individually programmed. My next question is if there is a simpler guide for learning how to program the leds? I’ve read all the links you posted in this article and am still confused. I’ve done basic coding on the Arduino, but nothing like this.
        Finally, I’m using 60 led/meter strips so I was wondering if it would look better to leave a little space between the strips in the rows. In your pictures, using 96 led/meter strands right next to each other looks good because they make an almost perfect grid. I’m using less density, so I was wondering if you’ve made signs with lower density leds in the past and how you spaced the rows?

        Thanks again!

        • bigjosh2

          >My next question is if there is a simpler guide for learning how to program the leds?

          Start with the SimpleScroll sketch. Get that working and start playing around with making changes to get closer to what you want. There is likely no need to have to muck around with all the very complicated code that sends the data to the pixels, there are functions in there to send text and patterns that you can use.

          > I’m using 60 led/meter strips so I was wondering if it would look better to leave a little space between the strips in the rows.

          60 led/M strips stacked right on top of each other would make for wide/fat letters. I’ve seen signs like this and they look fine. If you want skinnier letters, you can either use higher density strips or larger vertical spacing between strips.

        • Tom Hammond

          Hi Bobby,

          I am also using 60 led/meter strips. I spaced the rows at 1-5/16″ to keep the “grid” of leds. Because the leds are further apart on the strip, I am criss-crossing vertical cardboard strips to isolate each led to form a “square”. That way I can have fewer leds (mine uses 945 for a 15′ sign), but the pixels will appear large.

          Hope this helps,

  13. Chris

    great project!

    Is ist possible to run your code on WS2811 stripes and if not any suggestion where to start modifying it?

    Best regrads,

    • bigjosh2

      Should be straightforward. It is possible that it will just work based on the “high-speed” mode (not sure I understand how that is selected, does it automatically detect it?) If not, or if you must run in low speed mode, then I’d start by changing the values for all the timing constants to match those on the WS2811 data sheet.

  14. David M Reynolds

    Hey Josh – thanks for making this, it’s just what I’m after. I have just built my little 24” version and loaded up the sketch on my Uno, but even with the unmodified vanilla code I’m getting what appears to be a totally random collection of LEDs firing in random RGB values. It slows down if I add a delay() – so at least I know the code is doing something. I’m definitely using 0-7 etc – but just can not get my head round what’s going wrong! Have you ever seen anything like that before?!

    • bigjosh2

      First step would be to attach a single strip to pin 6 and run the strandtest` example from the AdaFruit Neopixel library. If that DOESN’T work, then try following the troubleshooting suggestions there for normal (power, connections, etc) Neopixel problems. If that DOES work, then we have bigger problems, so come back and report your findings either way!

    • bigjosh2

      Very easy! Instead of…

      void loop() {
        const char *m = jabberText;
        while (*m) {      
            for( uint8_t step=0; step<FONT_WIDTH+INTERCHAR_SPACE  ; step++ ) {   // step though each column of the 1st char for smooth scrolling
               sendString( m , step , 0x00, 0x00 , 0x40 );    // Nice and not-too-bright blue hue

      …which scrolls, you’d just write…

      void loop() {
               sendString( jabberText , 0 , 0x00, 0x00 , 0x40 );    // Nice and not-too-bright blue hue
               while (1);
  15. Max

    Hey , great project but as I’m building it myself I noticed something really weird.

    All the text is mirrored on the LEDs, so to ready it you have to look at the bed of the ledstrips. Can you help me what i did wrong? :S

    • bigjosh2

      Sounds like the Arduino is connected upside and the strip is backwards. Make sense? To fix, you can disconnect the 7 data lines form the Arduino, rotate it 180 degrees, and then reconnect the lines. Next take the whole sign and rotate it 180 degrees. Text should be forward!

      • Max

        That’s what I thought, but if I rotate the whole strip i would have the wires connected against the arrows and they won’t work? As the ws2812b has arrows pointing one direction?

        • bigjosh2

          The Arduino pins are always connected to the “Data In” side of the strips, you just turn the Arduino around so that the strip that was connected to pin 1 is now connected to pin 7 and vice versa. Then you turn that whole assembly (the Arduino still attached to the strips) around.

          • Max

            Thanks That helped alot!

            I’m now struggling with SimpleMessageSystem to function with it ; I’ve got it running ish but the 3rd led from upper and both down are flickering if I try to add the SmS. any thoughts?

          • Max

            I was wondering how you could possibly code it so it simply displays what is recieves via SimpleMessageSystem, would you mind helping me out?

            my current code is ”

            id setup() {
            PIXEL_DDR |= onBits; // Set used pins to output mode

            char messageChar[] = “123456”;

            void loop() {

            // CMD SMS

            if (messageBuild() > 0 ) { // Checks to see if the message is complete and erases any previous messages
            sendString(messageChar, 0, 0x40, 0x40, 0x40);



            But I’m totally new to the cli sei thing, my code sometimes changes the leds but really buggy..


  16. yuliana


    Such a great project! I was wondering if you ever wrote the article or the code for the live tweet or stock information? I would like an example or guidance as to how to do that.


    • bigjosh2

      Many people have done this – it is not hard using either an ESP or Bluetooth board. It will probably be a while before I could write a good article on it, but if you are willing to try I can support your efforts – especially if you will document them for others!

      • yuliana

        Thank you, I sure will. Another question, I cannot get for the speed of the strings to slow down. I have tried raising the number of pixels but that does nothing, any help?

        thank you

  17. Brian

    Thanks a lot for sharing this. I am inspired to try my hand and making a 6′-wide version of this sign. I’ve ordered the parts, and can’t wait until they arrive! Eventually, I’d like to be able to have the sign display a message that’s sent to it from a serial connection to a PC, so that it acts like a type of scoreboard. Can you point me in the right direction of where I can read/learn about how to update the message the sign displays dynamically?

    • bigjosh2

      The basic idea is to read serial data using the RX pin on the Arduino (pin D0) and use that data to update the display.

      How you update the display is really dependent on how you want it to work.

      Do you want a ticker tape where any letters coming in on the serial line are scrolled onto the display in real time?

      Or maybe a sign that displays a static message, and what that message says is updated atomically over the serial port.

      Or maybe the sign is a counter that increments with each byte received on the serial line?

      All do-able, but different code.

      • Brian

        Hi again. I’ve been working on the sign and seem to be stuck at the beginning. My sign displays the Jabberwocky message just fine, so I know I have everything connected right. Here’s what I want it to do: there is a scoring program (for track and field) running on my PC. I can configure what information it sends to a “scoreboard” via serial data. Right now, I have it set up to just send out the time of day (but eventually I will change it to something like “1st place: John Doe 12.12 s.” I messed around with another Arduino (one that’s not attached to my sign), and I was able to confirm that the Arduino is receiving the information from the scoring program, and I was able to echo it back out to the serial monitor.

        Where I am stuck is how to take that serial data received and have my sign display it. (I chuckle when I write this, because I do realize that that’s basically the entirety of the project). I certainly don’t expect you to write a tailor-made program that will do exactly what I want, but maybe you can point me in the right direction. Do you know of any projects that have used your basic design (with the 7 row font, etc) and had it relay serial data?

        Could/should I consider using software serial to receive the data so I can possibly use the serial monitor for debugging? Or maybe switch to a Mega?

  18. Stefan

    Hi Josh,
    Thanks for sharing your project and sample code for scrolling. I built it and it works fine.
    I am struggling with other animations, like text dropping in from the top or simply just appearing, I.e. some of the stuff you are showing in your video.
    Any chance you would share the code? Donations are definitely an incentive option. ;)
    Please let me know if that’s an option.

    • bigjosh2

      Yes, I intentionally left the RX pin on the Arduino free so it could read real time serial data either from a computer or maybe an ESP or something like that. I don’t have this sign anymore to play with, but it should not be hard to set that pin up to be a serial in and display data coming in.

  19. Heiko Pikner

    Hi Josh,
    Thanks for sharing your project and sample code. I built a big text message screen and it works just fine, except there are small problem. Randomly some entire row are sifted to right one pixel. It happened once about 3 – 5 minutes or something like that. The sifted row seems random. Sometimes it is first, sometimes some other row. If this happens, it’s hard to read the text.

    I’m using Arduino Mega (Port F).

    Do you have some good ideas that could be further investigated? Thanks again for great work.


    • bigjosh2

      This is interesting. Do you ever see a dot of the wrong color in the display, or only that extra space as shown? Which side of your sign are you sending the data into – the beginning (the side shown in the picture) or the end (the other far side)? Does the extra dot always end up in the leftmost edge column as shown, or sometimes near the center of the display?

      • Heiko

        I have not seen any wrong color dot yet (Wiring seems ok). That extra space is the only problem. Yes, I am sending data from the beginning (the side shown in the picture). Yes, the extra dot always end up in the leftmost edge column as shown. I haven’t never seen it near the center of the display.

        LED strips:

        My test code main loop:

        void loop()

        sendString( “Twas brillig, and the slithy toves ” , 0 , 0x1f, 0x1f, 0x1f );

        sendString( “The jaws that bite, the claws that catch!” , 0 , 0x1f, 0x1f, 0x1f );

        • bigjosh2

          Everything looks good.

          Hmmm… the whole beauty of this code is that it sends all the bits on all the pins simultaneously, so hard to see how one string is randomly ending up differently than the others! And confirm that it happens on different rows and not always the same row? Maybe these pixels have marginal timing and we are right on the edge?

          Any patterns you’ve noticed, like the skipped row always has a lit dot on the would-be leftmost column?

          Can you try using the color r=0, g=0, b=0x80? This way we can see if the top bit of the last blue pixel is bleeding into the extra column.


    • bigjosh2

      It should self-power on USB! :) Just plug the Ardunio into USB and make sure the display you run uses less power than the Arduino can supply (all dim red good). Report back if it works!

      • alanlapp

        Hi Josh,

        I have built two iteration of these signs. Great Project. Is there any way I can put a time condition in the arduino programming to display message 1 at a certain time of day, message 2 at another time of day etc…. Also, beyond the macro marquee script, do you have any other scripts for this project with more graphic effects.. for example white text on a green background, etc.


        Alan Lapp.

        • bigjosh2

          Is there any way I can put a time condition in the arduino programming to display message 1 at a certain time of day, message 2 at another time of day etc

          Yes, but the best way depends on how accurate you want it to be. If you don’t care if it is off by a few seconds per day then you can just check the `millis()` function to see how long it has been since the program started and use that to switch. If you want to be acrruate to a few seconds per month, you can get a DS3231 add on board for a couple bucks. If you want it to be accurate to less than a second every thousand years or so, you can get a GPS board!

  20. bigjosh2

    for example white text on a green background

    This is certainly possible, but it would require changing the `sendBitx8()` function since it now assumes that a `0` bit in the `row` parameter means send a `0`. You could add a `background` parameter here and have it substitute these color bits where ever the `row` bit is `0`.

    LMK if you *really* need this and I can try to add it.

    • Jon

      Hello Josh,
      I would be interested in trying to setup a Background color. And I don’t quite follow how to adjust the sendBitx8() code to do so.

      • bigjosh2

        This section

        "OFF_%=: \n\r"                                // (1 cycles)    Note that we land here becuase of breq, which takes takes 2 cycles
              "out %[port], __zero_reg__ \n\t"              // (1 cycles) - set the output bits to 0x00 based on the bit in colorbyte. This is phase for T0H-T1H
                                                            // ==========
                                                            // (5 cycles) - T0H

        …sends the background color bits. Right now it sends zeros (black), but you could change it to send a different color by mirroring the code above that sends the foreground color.

  21. Dallas

    Hi Josh,

    i do like your display message look very cool i have question what i need to change in your sketch if i have 8 LED strips ( 8 pixel )

    Thank you

    • bigjosh2

      All you’d need to do is change `onBits` to have all 8 bits on…

      static const uint8_t onBits=0b11111110; // Bit pattern to write to port to turn on all pins connected to LED strips.
      // If you do not want to use all 8 pins, you can mask off the ones you don't want
      // Note that these will still get 0 written to them when we send pixels
      // TODO: If we have time, we could even add a variable that will and/or into the bits before writing to the port to support any combination of bits/values

      Of course to actually see anything in the new extra row, you’d need to make a new font that is 8 pixels high.

      • Dallas

        Thanks for quick reply, i did changed it to Bits=0b11111111; and did worked only on aliens, i did changed font still didn’t work #define FONT_WIDTH 5 to #define FONT_WIDTH 8 too wide.

  22. lampenschakelen

    Hi Josh,

    Did somebody already make you project with esp8266 and a web interface?
    so it very easliy to change the tekst? wich led did you buy?

    Are the 60 leds in a meter also fine? or do i need 144 leds in a meter.
    because is see many leds close together iam wondering wich leds you used.

    Best regards,

    • bigjosh2

      >Did somebody already make you project with esp8266 and a web interface?
      I have not seen a web interface yet, but would not be hard to do. Try and report back on your results!
      >wich led did you buy?
      I usually buy from AliExpress, but you can buy from places like Adafruit if you want to be sure they will be high quality.
      >Are the 60 leds in a meter also fine?
      You can use any pitch you like. If you use 60 LED ber meter then the the display will look more stretched, but you can then compensate by putting more space between adjacent strips.

  23. Pierre


    Trying to do the project with a mega using 1m long, 60led/m strings. I changed PORTD to PORTF and DDRD to DDRF per a previous comment you made. I changed PIXELS to 60 and it goes way too fast, unreadable. Had to change it to 1000. Also the first led in the string (closest to the Arduino) always shows a faint green but the rest work as expected. Any input appreciated.

    • Pierre

      Ok, got the first led thing figured out – I guess alligator clips weren’t good enough, once wiring was soldered that was ok. With pixels set to 60 I have to add 300ms of delay to the main loop.

      I can’t get simplescroll to look as smooth as your video regardless of what I set PIXELS or the delay to. When slowed down enough I can see that instead of scrolling the message one column at a time it’s moving one font width at a time. If I look close enough between each step I can see the led’s flicker color. Almost as if each column is drawn full speed but the delay is only affecting each character.

      • bigjosh2

        Sounds like the pixels are not latching the updates when stepping across? Try increasing the value of `RES` from 50000 to maybe 100000 or more and see if that helps?

    • bigjosh2

      To slow things down, try setting the PIXELS back to the correct value of 60, and then instead use a `delay()` in the `loop()`. The `delay()` should go after the `sei()` command, and the bigger the number, the slower the scrolling will go. Start with `delay(100)` and see how that goes – that will add a 100 millisecond delay between each step. Report back how it works out!

  24. Manmeet Singh

    Hi josh
    I have 12 v 5 meter strips with 30 pixel density from your reccomended seller. I am running one strip to test with fadecandy and a desktop generic 450 watt Chinese power supply. Your qn an ans say 300 watt for 2688 pixel and I assume 20 percent pixel on at an average as you are using 1/3 peak power requirement . My supply rating is 15 Amp at 12 volt. So above strip i have uses 9 amp . Am i safe to connect two strips. I hv not tried yet. I want to power three strips from two. Any reccomendation. As my calculation say 27 amp. And on internet people say somepowersupllies have high voltage spikes when they start. Is it true for desktop smps. My one day testing did not give any problem with one strip on at full wite. My strips are three leds connectd to one ws2811 chip. So three leds light in grups. So doing text is not required. I only want cool fadecandy animations.

  25. abmiller84

    Josh, first off, awesome project. I’m new to all of this but I’ve seen a lot of recommendations online about using resistors between the I/O pin and the data input on the LED(green wire). I guess it protects against voltage spikes. It doesn’t look like you used any, just wondering what your opinion is on that. Thanks.

    • bigjosh2

      Ahh! This is a topic of much controversy! I personally do not use them in production projects and have never had a problem.

      The best argument I have heard in favor of them is that if you do connect something horribly wrong, then maybe you have less of a chance of blowing the input pin on the first pixel in the chain. I’d counter: If you are connecting things horribly wrong then (1) you want something to fail fast so you know what you did wrong, and (2) who is to say you will connect the resistor right?

      There is one argument that it can help lower the slope of the edges on that line, and dampen out ringing. This is true, but…. if the ringing is an issue then probably other better ways to mitigate than intentionally mushing up your signal.

  26. Rizki

    hi josh, I’m rizki from indonesia.
    can i ask something about your code. i want make it and i use arduino pro mini and i will add a modul like Bluetooth (hc-05), how can i compare software serial lib with your code and make pin 8,9 as rx and tx, i want to change the text and color of the scroll text by my phone via Bluetooth communication. and i do my best, and worked. but there are so long time the arduino to receive data. i want that color and text working with fast when i send data from my phone. please help me

    • bigjosh2

      You will have a hard time using the HC-05 with SoftSerial at the same time as running the sign since Softserial will not work while the sign is scrolling, and really no way to tell the Bluetooth module to not send data then.

      Maybe if you were doing something where you are looking at the sign and it pauses scrolling occasionally, and then you see the pause and send the Boothtooth data during the pause?

  27. lackmorrison (@InstaFry)

    Hey Josh, great and helpful project! In some comments you mentioned that you left ‘8th bit’ for serial RX pin to get data from outside and I am wondering, what if i want external data source AND a 8pixel high font. Is this possible? How can it be achieved? Thanks.

    • bigjosh2

      Anything is possible!

      The parallel bit processing code that makes this work just requires that all LED pins be on the same PORT. I picked the ones used here because they happened to be in a nice row on the headers of the Arduino UNO, but you could use other pins as well if you didn’t mind having the wires look less organized.

      You could also do SoftSerial on a different pin, but you would some kind of control to keep the sender from transmitting exactly when the LEDs are updating since the LED update must turn off interrupts when running which would block the SoftSerial.

      You could even use a clocked serial port like an I2C on any free pins. If the Ardunno is the master, then it will be able to control the connection so data is only transferred between LED updates.

  28. Jeff

    Looks like you’re using PORTD, which uses pins 0-7. If I wanted to use 8 strips instead of 7, I would simply use pin 0. But what if I need to use pin 0 for receiving a custom message from another device? How could I set this up in order to achieve 8 strips and still receive serial data?

    • bigjosh2

      To use the parallel processing technique shown here, you need all the strings to be on the same PORT register. PORTB is the only PORT that has all 8 bits available as outputs on an Arduino Uno, so you have to use PORTB if you want 8 strings. If you also to have communication, you can use use one of the pins on another port using something like SoftSerial, but you have to use some kind of a protocol to control when the serial communication happens. The pixel processing is very timing sensitive, and so is SoftSerial, so you’d want to do something to make sure they don’t both happen at the same time. Could be something like having the Arduino code send a special byte out every time it finishes a pixel frame. The connected device would then send it’s data during that window before the next frame starts.

      • Jeff

        According to the port register reference here:

        … PORTD uses 8 pins (pins 0 -7, which is what I have my 8 strips hooked up to). It also looks like PORTB uses even less, only 6 pins (pins 8-13).

        I was able to test this using PORTD (basically not modyfing anything) and simply only changing onBits=0b11111110 to onBits=0b11111111, which enables the 8th strip/pin that you were not using in your example, and the MacroMarquee example works like a charm, on all 8 strips. I’d attach a pic or a video but I don’t see an option to….

        So that being said, if I’m correct and I can indeed use PORTD to run all 8 strips, then my only problem is sending over a custom message string to the UNO to display. I can’t use the RX pin because that’s pin 0 and is being used by the 8th strip now. I really wish I could configure PORTD to use pins 1-8 instead of 0-7, or something similar. But it sounds like theres a way to configure another pin as the RX pin via SoftSerial or something? I dont know much about it, do you know of an example or some resources on it? Also, I just want to send a message, then basically restart the whole scrolling process, so the sending of the message shouldn’t interfere timing-wise with the scrolling at all. And if sending a message does mess up the display temporarily until its fully received and restarted, thats ok with me. I dont plan to spam messages, I just want a way to update the message without having to update the hard-coded string in the sketch and re-upload the whole sketch again.

        Does that make sense? Let me know if anything isnt clear, and again, thanks for taking the time to give me your thoughts on adjusting this. Been working on it for almost a year and finally got to the point where I can fire it up. Hate to get stuck here, ya know?

        • bigjosh2

          Sorry, I misstyped. The only port with all 8 bits available on the Uno headers is PORTD – and this is the port the code uses.

          If you want to get data into the Uno, you will need to use a different way than the normal RX and TX pins since those are connected to the pixel strips.

          One way would be to something like the SoftSerial library…

          …which lets you do serial communications using other pins besides the normal RX and TX.

          The caveat as that you will not be able to just use SoftSerial normall while data is being scrolled to the pixels. There are ways around this depending on the application. You you only want to update the display between scrolls, then yuo could have the code to a full scroll, then send a special char out the softserial port (like ‘?’) that tells the progam on the other side “Hey, I just stopped scrolling for a second. if you want to send me anything, now is the time, but do it fast!”. Then you listen for any incoming data and if none found then you go back to scrolling again.

          Make sense?

          • Jeff

            Gotcha. Yeah that makes sense in theory, but I’m no expert at the sketch code so I’ll have to play around with it. But I think I know enough to have a general idea of what I need to do now at least. Thanks again for the info, I’ll post an update if/when I get everything working!

    • bigjosh2

      You don’t need an exact build sheet – this is just a framework. It is simple enough that you can build it anyway you want using whatever materials you have!

      Cost is really dependent on you and what materials and LED strips you pick.

  29. Jeff

    So you hard-coded your text like this:

    const char *m = “Twas brillig, and the slithy toves “……etc…..

    …and I have a custom string sent over via wifi and stored in a variable like this:

    String str = “my custom text”;

    I figured the easiest way to make this work is to swap out your hardcoded value of m for the value of str, but the compiler complains because of converting a string to a char array. Theres a function to do this, but I guess Im a little confused how to use it properly to get this to work. I just want m to have the value of my text instead of the jabberwocky text. Any recommendations for how to do this? It seems when I find an example online, people are using a seemingly random arbitrary number for the buffer size. I’m not sure if this is supposed to be the size of my custom text (as in character length) or something else. Either way, str.length() didnt seem to work, so Im not sure what exactly its looking for and how to set it properly. Any thoughts?

      • Jeff

        Hey Josh, sorry for the delay, my code is up on Github now for you to take a look at. The README file has all the details on my set up. Here’s my repo:

        In my README file you’ll find my TODO list. You can ignore item #1 for now, I think I have a solution for that, but need some more time to test it out. But my original question pertains to item #2. Basically, I have my custom message text sent over to my UNO and stored in a String var called str. Your hardcoded text seems to be stored in a char array though. So the question becomes, how can I convert my String text over to a char array? Please keep in mind I’m brand new to pointers, and I don’t know how they work or how the * symbol works, and where it’s needed, etc. If there’s another way to get this String text displayed without converting, I’m all ears as well. Again, a lot of this is new to me so I’m sure there’s a way to do these things, I just need a little guidance on what the best approach might be.

        Please let me know if you have any questions or something doesn’t make sense. Thanks again for taking a look for me, I really appreciate it!

        • bigjosh2

          I’ve sent you a pull request on Github with proposed changes to your Uno sketch. The new code reads the bytes form the serial port into a char[] rather than a String which simplifies things.

          I used the readBytesUntil() function to ready bytes from the serial port into the str buffer until it sees a carrier return character (\r), or fills the buffer. This makes it easy to test by just sending a new string using a terminal program and pressing enter at the end.

          I have not tested this code, but the general idea should work. LMK!

          • Jeff

            I tested your code Josh and its somewhat working. So I have a few questions for you regarding your changes:

            1) First of all whats the benefit of using #define instead of a typical variable declaration? Any particular reason you chose to do it this way?

            2) #define STRINGBUFFER_LEN 200. Why did you choose 200 as the buffer length? What does this represent, is it just an arbitrary number or does it represent memory or number of characters or something like that? Im getting some but not all of the response headers from my server, so it seems like maybe Im only getting the first 200 characters. So maybe this needs to be increased so I can receive everything instead of just a portion? Is there any kind of limit on what the max of this can be?

            3) Some of characters also look gibberish-y, they are partly alphanumeric, but somewhat messed up. Could this be due to an incorrect baud setting for the serial stuff? I’m using 115200 for everything, but maybe that needs to be changed? If so, which serial, the main Serial or the virtualSerial, or both? And what would the new baud rate need to be?

          • bigjosh2

            Why did you choose 200 as the buffer length?
            Seemed long enough. You can make it longer, but you can not make it so long that you run out of memory. The Uno has a total of 2K bytes of memory, but some is it also for other variables in the program and the stack. If you make the buffer to large then either the program will not compile, or it will crash randomly.

          • bigjosh2

            Some of characters also look gibberish-y, they are partly alphanumeric, but somewhat messed up.

            My guess is that interrupts are getting turned off and messing up the receipt of the serial data. Do you ever see messed up chars when sending text directly from the program rather than reading it from the serial?

    • alanlapp

      Hi Jeff,

      I have built 3 iterations for my retail store. I was working on the same problem as you and ran into the same problem. Josh’s help with a solution would be great.

      I did not notice that the arduino wifi when “listening in wifi mode”, it cannot run the code to run the strips at the same time…so i tried with two arduinos, one for wifi communication, and the second arduino running the led code and also listening on serial pin0, but again i ran into the same type of problem where the second arduino would hang on the interrupt. Help Josh!

      • Jeff

        @alanlapp – Scroll up to my previous comment, Josh gave me a pretty good idea of a solution to make the 2 arduinos work together without interrupting. And I plan to post some code and updates if/when I fully get this working so look for that, though it may take me a while, time to work on this is somewhat limited…

        Josh – I haven’t fully connected my Uno to my wifi module yet, so I think I really need to get all that setup first and do a full test before I mess with the code any farther, and that may take me a while, so I’ll post back with progress and some code later on when I have an update. Thanks again for being so responsive and bearing with me, I’ll keep you posted!

        • alanlapp

          Sounds interesting. What i did instead since i needed to install them is i power the strips though the power supplies, and the arduinos via a wired usb (all three boards work through a usb hub) back to a central computer. From there, i use teamviewer anywhere in the world to update the code. To bad there wasnt a way in the arduino ide to program timed msgs. Other than that, it solves my problem in the short term…

        • alanlapp

          Hi Josh,

          Do you or anyone else in this thread know if there is an arduino environment where you can test what comes out of the pins without having to build out the whole system.

          I want to do more testing with the led signs without changing code, sending it, and standing in front of it to ensure it is doing exactly what i want.



          • bigjosh2

            Not sure I understand the question, but I often just connect a couple of strings to an arduino on my desk to see how things are working. Looks like this…

          • Ralph Richardon

            I built a 1 meter long by 7 string display. Your code works perfectly.
            I got it to scroll slowly to be readable. Is there a way to change the color of the text while it is scrolling?

          • bigjosh2

            The color of the of the text is controlled in this line

            sendString( m , step , 0x00, 0x00 , 0x40 );    // Nice and not-too-bright blue hue

            The numbers are red, green, and blue values so “0x00,0x00,0x40” is a light blue. “0x50,0x00,0x00” would be a slightly brighter red. You can find tables of RGB values on the web.

  30. eduardvanraalte

    whats the benefit of using #define instead of a typical variable declaration?
    Before compilation of the code the #define statement causes a kan nd of ‘Find&Replace’ for the defined ‘variables’ or rather ‘constants’. So actual values are replaced for the ‘variables’. This is more efficient, resulting in smaller and faster code compared to variable declarations. A variable must be able to change its value during execution of the code. This will use up more space and processing than a single value.
    Hope this answers 1/3 of your questions and leave others the chance to answer the rest ;-)

    • bigjosh2

      Agreed! In modern C you can also use a const variable instead of a #define and get better type checking, but it is traditional to use #defines at the top of a program to indicate values that the user might want to change later.

  31. Chris Eaton

    Do you think it would be possible to load the message from a webpage?
    If so, would it be necessary to have another device to create the webpage then “send” it to the Arduino to display?
    Have you seen anyone do this?

      • Chris Eaton

        Hi Josh,
        That is what I envisioned, but as I am a complete newbie on the Arduino and have very little experience on the Pi ( a bit of Python to light a few LEDs ), I don’t know where to start.
        I guess getting the Arduino display working first is a good idea.

  32. Angel Lopez

    Hey Josh, I was wondering if it is possible to connect 3 of this LED strips to an Arduino MEGA with every sign displaying something different. Our signs are 7 strips high and 1 meter long.

    • bigjosh2

      Maybe possible, but you would have to code very carefully to have enough time to get all 3 bit patterns out on time. Probably not worth the effort – just use 3 cheap Arduinos, they only cost a couple bucks!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s