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

DSC_1381

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.

DSC_1404_052016_115931_AM

DSC_1403_052016_120359_PM

(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

ezgif-122169061

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

https://github.com/bigjosh/MacroMarquee/blob/master/Arduino/SimpleScroll/SimpleScroll.ino

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

DSC_1365

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

https://github.com/bigjosh/MacroMarquee

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

FAQ

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…

https://github.com/bigjosh/MacroMarquee/blob/slower/Arduino/SimpleScroll/SimpleScroll.ino#L395

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.

###

232 comments

  1. Giuseppe Cusmai

    Thanks! That’s a good idea. I’ll use the cheaper 60/meter and space the strips to get a square grid. I didn’t know of the 96/meter variant.

    • Tom Hammond

      Hi Giuseppe,

      I noticed in your Q&A section that it is possible to support taller displays (more than 7 rows). I would like to build a display 12 rows tall. I assume that requires 12 data pins on the Arduino. Can you provide a quick overview of how the code needs changed to support 12 rows?

      Thanks!
      Tom

      • bigjosh2

        To support more than 8 rows would significant software changes. Probably the easiest way would be to break the pins into two sets of less than 8 pins each, each on it own PORT. Then duplicate the existing code and modify the second copy to access the second PORT. Then update the two sets of pins in sequence for each new frame. This will obviously slow down frame rate, but not necessarily by 50% since you can update one set while the other is in the reset delay.

        • Tom Hammond

          Thanks for the advice about using more than 7 rows, either duplicating the code and using two PORTs or using two Arduinos. If I get around to trying this out, I will let you know how it turns out!

  2. abera

    Thanks for sharing,for me worked perfect at first try.i connected 2 ws2812b 60 rgb leds per meter to 1 Arduino pin,so it is 14 rows by 60 colomuns.And to slow down the speed of scolling i increased the #define pixels 964 to 1988 for i do not know how to set the speed in the program and it works perfect.my question is how to send data from serial monitor to the rgb pixels?can any one help me.Thanks a lot.

  3. Ali

    Hi Josh- just wanted to say thanks so much for posting this awesome guide and developing the code that makes it work. I used your guide to make an LED sign which I am putting inside a replica Mouse Droid from Star Wars, which I am designing and building. I am making a video series on this and can post the link if you want to see it in action.

    Thanks again!
    Ali

          • Ali

            Thanks! Adding the bluetooth wasn’t so bad. The two bumps in the road were: – Figuring out about using a common ground for the LED strips and the Arduino, which I found out about in these comments.
            – With an HC-05 bluetooth module, you can’t use serial output (e.g. for debugging) or Pin1 of the LEDs won’t work.

          • Chris Eaton

            Hi Ali/Josh,

            I would be very interested in seeing the code for the Bluetooth.
            I would also be very interested in finding out if anyone else has any code to allow me to upload a single line of message from a Webpage.

            I am very new to Arduino programming and I am finding it a bit of an uphill struggle.
            Perhaps deciding to create a message display as my first real project (apart from driving 3 ordinary LEDs to create a traffic light sequence!) was probably a step too far. However, I have created a 0.7 meter display using 60LEDs/m strip and i have found that i can drive my messages straight from the Arduino just powered from a small USB Phone power supply.

            The first issue I encountered was setting the length of my display (0.7) and the number of LED’s/m (60) and changing this in your MacroMarquee code caused the display to become a complete blur. Clearly it was too fast. I couldn’t work out from your code/comments where i should go to vary the speed of the text for a small display. At first i tried to increase the “length of display” setting to something ridiculous like 30m and this DID slow it down.

            Then I looked further down and put a Delay in the for Loop at the bottom after the sei() command. This works, but i wonder if this is the correct place to do it.
            Josh, i cannot find a variable anywhere in your comments that mentions Scroll speed. The only mention of a Delay seems to be here:

            delayMicroseconds( (RES / 1000UL) + 1);
            I played with it a little, but the display went a bit “funny” so i put it back again.

            Is there anywhere where i SHOULD set the scroll speed?

            I am also looking to be able to set the color of a line of text as a variable too.
            Perhaps i should do this in the bottom sendString command, replacing the three Hex numbers with variables?
            sendString( m , step , 0x00, 0x00 , 0x40 ); // Nice and not-too-bright blue hue

            Any help would be appreciated.

            Regards
            Chris Eaton

  4. Ralph Richardson

    Josh, I built a 1 meter version of your sign with a different scrolling text.
    I would like to change the color of the scrolling text while it is scrolling.
    How would I do that ?
    Thanks , Ralph

    • bigjosh2

      If you look at the code, the sendRowRGB() function sends a row of pixels out the LEDs with any pixel that is on in the font set to the specified RGB color. You can Send any color you want here, so you can change colors for the whole display or even just one row at any time. Do yuo want the whole display to change to different colors, or just parts of the scrolling message?

      • Ralph Richardson

        I would like a set of words to change color like( Merry Christmas) as a set then have that change to a different color the next time it scrolls by, doing that several times.
        Ralph

  5. I SADEK

    very nice work their i am trying to do something like this it work fine with 7 or 8 rows
    but i am tying to do 11 row
    i discovered their is group for the arduino pins B C D
    wold you please give me any hint how to use multi group in you code
    i would be very grateful

    • bigjosh2

      You could potentially use the 6 pins of PORTC or PORTB…

      (PORTB is nicer I think because the pins are right above the PORTD pins on an Arduino Uno).

      To do this, you’d need to copy all my code that uses PORTD and make a new copy that uses PORTB. Then you would have to make a font that uses all these rows but you would lay it out as two fonts – one for the bottom of the letters on PORTD and the other for the top on PORTB. Then for each time you send data to the LED strings, you’d actually send twice – one font to PORTB and one to PORTD. That’s it! Conceptually easy, but a bit of footwork to get it working (hardest part making the font, the rest is glorified copy/paste with search/replace).

        • bigjosh2

          Look at how the existing code does the single font of 7 rows. Now just imagine that you had two arduinos, each connected ti 7 strings of LEDs and those 14 strings are visually placed so the second 7 are placed above the first 7. Now imagine the font you’d make for the bottom arduino – it would be the bottom 7 rows of 14 row high letters. The top arduino’s font would similarly be the top 7 rows.

          Now imagine that instead of two ardunos, you only have one arduino, but the top strings are connected to one PORT and the bottom strings connected to the other PORT. See how that font might look?

  6. I SADEK

    good day to you sir i am very sorry but i have on question
    i finally managed to use all 11 row of my matrix but the i cant separate the top last 3 row from the first bottom rows
    it send exactly first 3 bit of first PORTD to PORTB
    can you tell me whats wrong with the code

  7. Nomis

    Noob question; if I wanted my sign to have a larger font (ie, be readable from farther away), I could simply use 60 pixel/meter strips instead of the 96, right? If I adjusted the vertical spacing accordingly, the result would still be a 7 row font, but it would just be a larger sign, correct?

  8. People's driver

    Hi Josh,
    I have build two displays for testing, one 1m long 8 rows nano pro mini board with 60/m ws2812b leds and one 5m long 7 rows with 30/m ws2811 leds.For the second one I had to modify the code to work, but everything works perfect.
    Now I’m trying to change the font for the first one to work with all 8 rows and for the second one to change the font to look better, because of the 3 leds per pixel of the stip.
    Please advice me on this as I’m new to Arduino programming and If you could give me an example of code for the Twitter Feed to be displayed would pe amazing.
    I can post some pics and videos of my testings.
    Thank you

  9. Dat-Data

    Greetings! I’m looking to build a sign myself with a different board:
    https://docs.particle.io/datasheets/wi-fi/photon-datasheet/

    Since this is my first project like this and I’m having a little difficulty wrapping my head around the pin/port setup and how it’s used in your SimpleScroll.ino. What is the best way to determine if the board I’m attempting to use has “Has at least 7 pins connected to a single port” and how adaptable is the SimpleScroll.ino to other boards?

    Thanks in advanced!

    • bigjosh2

      Sorry, the particle uses an ARM chip so it is totally different than the AVR chip I use here.

      You may be able to drive neopixel with this ARM chip, but not using anything like my code. You’d have to find something that works specifically for that chip (or at least that kind of chip).

      Note that the TEENSY boards use ARM chips and have very nice libraries for driving lots of neopixels!

      • Dat-Data

        Thanks for the reply, much appreciated!

        I went with the Ardunio Uno Wifi Rev2 as my project relies on communicating with an API. In attempting to compile the the SimpleScroll.ino it keeps failing due to an “impossible constraint in ‘asm'” error. Is there a library I’m missing or could this be due to the board itself?

        • bigjosh2

          Unfortunately despite the promising very similar sounding name, a Ardunio Uno Wifi Rev2 is a totally different beast than an Arduino Uno. They have different chips with different pins and different capabilities. While I bet you could get this code to work on the chip inside the Ardunio Uno Wifi Rev2, it wouuld take some work. If you want to use this code then I could get a real trusty normal boring Uno. If you need to communicate with things on the internet, probably the best strategy would be to plug the Uno into the USB power of somethign like a computer or a Raspberry pi and have that do the internetting for you.

          • Dat-Data

            Just wanted to provide an update, the Arduino ultimately did not fulfill my needs so I took a chance on a Particle Photon board and I’m happy with the results.

            The Particle photon is scrolling text across 8 strips @ 141 LEDs each using the Adafruit_NeoMatrix library, all running off of one pin. The LED board itself is about 7ft long and currently has three different messages scrolling across:

            Message of the day – This text can be updated via our team’s slack channel, I added a function on the Photon to handle new text entries
            Systems Check – There is a nodejs server I have running that performs a check on multiple systems to determine whether something is down and call the Photon with the “All good” if everything is running or a list of systems that are down if any
            Forecast – The Photon board will call a hourly weather api every 30 minutes to get the current temperature and forecast

            We already have request from other teams to be able to post messages to the board on a regular basis so I might need to add some more slack commands but that’s a good problem to have in my book. Thanks again for the article, without it my team would not have made what we have now!

  10. Dylan L Coiro

    Hi Josh,

    I’m also working on this for a school project, I’m trying to display information that would be displayed parallel to a moving conveyor belt. I’m fairly inexperienced with arduino and was wondering if you could provide and more detailed pictures/instructions on the wiring?

    Once I have it wired up, I also want to modify the speed…I saw that another commenter wanted to do the same thing and was simply changing the definePixels value. Is there a more direct way to change the speed to (through trial and error) have it match up with a constant known speed of a conveyor belt?

    Thank you

    Dylan Coiro

    • bigjosh2

      If the speed of the belt is constant, then you could an Arduino hardware timer to have the message advance one pixel forward each time the belt moves the equivalent distance. Is the belt speed constant and predicable?

      • Dylan Coiro

        Thank you for getting back to me. Yes the belt speed is constant (10 inches/second).

        Also we have it displaying the text of Jaberwocky, but the letters are mirrored, do you know why this might be?

        • bigjosh2

          the letters are mirrored, do you know why this might be?

          Something is both backwards and upside down. You can fix this by switching any two directions in hardware and/or software. For a hardware-only fix you could, say, reverse the order that strips are connected and then flip the sign upside down. Or you could turn the side upside down and reverse the order of the scrolling columns. Any combination of two flips will fix it! See why?

        • bigjosh2

          Yes the belt speed is constant (10 inches/second).

          If you want a quick and easy hack, you could just experiment with changing the delay() between steps in the loop() function (that is, after the sednString() until you get close enough (high numbers=slower scrolling). If you want to get fancy, you could put some kind of sensor to read the movement of the belt and connect that to the Arduino and have it automatically adjust to whatever the belt speed is.

  11. dave

    Hi Josh
    Awsome project, I have got simple scroll working and added sd card into void setup which compiled/uploaded and gave the output on the serial monitor of a sample.txt residing on the connected sd card, I could not get it to output onto the leds, I couldnt seem to get the void loop right possibly but I,m no expert on coding, any suggestions ? Thanks Dave

    • bigjosh2

      This project is specifically only for WS2813B/Neopixel LED strips. There is no way to individually control 5050 SMD LEDs on most strips. Sorry!

  12. Kirk M

    So, how did you get the audio coordinated with scrolling letters? This part is particularly of interest for my son…

    • bigjosh2

      You could use something like this microphone connected to unused pin on the Arduino to “hear” the sound. Depending on what the sound actually sounds like, it can be difficult to actually figure out where the beats are – but it it is something simple like a clapping hand with silence in between then should be no problem.

  13. Gijs

    Hi Josh,
    Was just testing the simpe setup (which I love btw) with GS8208 led strips. That does not really work very well. The jabberwocky text gets scrambled. Seems like a timing issue. GS8208 should be the same timing etc as WS2813.
    Also tested MacroMarquee, The big texts were holding up better/good but the scrolling text is garbled beyond recognition.
    Any ideas?
    Thanks,
    Gijs

    • bigjosh2

      Looking at the datasheets, I think the timing for the GS8208 might be different enough that you would need need to adjust this code. Maybe try increasing the reset time length or fiddling with the high and low bit times and report back if you get it working!

  14. Bart Vandersarren

    Hi,
    I love this setup!
    I’m new to arduino, but i will get me some electronics to get started on this project,

    Can you make this multiple lines as well? To make the kind of display you often see in cities, to display information.
    Like say, 5 lines, and 20 chars per line.

    Thanks!

    • bigjosh2

      The easiest way to make multiple lines is to make multiple signs! The additional cost is just an extra Arduino per sign, which can be <$5 if you use a full board or <$1 if you just use the chip directly. THis way you will be able to keep up high frame update rates no matter how many lines you have.

      • Bart Vandersarren

        still waiting on my hardware to arrive, getting impatient to start :-)

        but if i were to chop up the big line (120 pixels) , and put 5 segments on top of each other , I would get almost the same thing?
        or will the voltage drop be an issue over an extension cord?

        also in this setup, would I be able to have some basic animations spread over this new 35×120 “matrix”?

        another idea was to place “flipped” lines between the character lines, in order to avoid long connecting cables and create a better matrix (63×120), but then you would have the first 7 lines going left, the next 7 going right, and so on

        I hope I described this well, being not native english :-)

        • bigjosh2

          If you only need 120 pixels long than you could “fold” the display into 5 short 24 pixel lines. If you want to save wire you could “double back” where every other line is backwards, but then you would need to update the code to correctly generate the alternating forwards and backwards lines. Not hard, but you would have to do it.

  15. Robin

    Hi, I’m a teacher from The Netherlands and I’m using this project in my lessons where 1 team of students is making this board in a 1.2 meter version. But we want to also be able to print the Euro symbol: €. This is not possible in the code yet, but how can we create a euro symbol?

    Thanks!

  16. Jon Beverley

    Hi Josh. Great project! I’m wondering if you have any suggestions on how to update the text that the sign says over usb rather than having it hard coded. Does the fact that we are using pin 1 (Tx) make this impossible?

  17. abera

    Hi Josh,
    I tried displaying other signs with the 57 font and i succeeded .But the signs i want to display require more places so i changed the font to 77 and made minor changes in the code such as font_width to 7 and uint8_Font to 77 but did not work.What do i have to change in the code to make it work with 77 font?
    Best regards.

  18. Paul G

    Hi Josh,
    I was able to complete your project and even have two of them running in my lab. My next focus is trying to create “mini” versions of your boards that run vertically and have characters only 4 LEDs in width. You mentioned earlier that it was possible to run the LEDs using an Arduino pro micro but I was wondering what you would need to change for it to work. Port outputs? Font?

    Thank you and awesome project!
    -Paul

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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

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