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….

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





    • 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.

  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,

  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..


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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s