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.

###

322 comments

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

      • rvbcrs

        Sorry forgot to mention I am running the arduino platform on the ESP8266: https://github.com/esp8266/Arduino it makes the ESP8266 run arduino programs, normally with a bit of changing to the code, but not much! Therefore I was hoping you maybe also tried it to see if you could make it work

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

        • bigjosh2

          Yes, I left pin 0 (Rx) free for just such an application! I’d probably use serial feed from an ESP8266 to send internet data into the display.

          • undy

            Hi, this might be a dumb question but how did you intend to use pin 0? Wouldn’t using Serial mean that you could not use pin 1 for digital output anymore? Afaik pin 1 won’t be usable for the 7th LED strip anymore, right?

            • bigjosh2

              Great question! Is it actually possible to enable only the RX pin on the serial port and leave the TX pin still connected as digital IO…

              TX pin control

              So you could just start up the Serial class as normal and then clear that TX enable bit.

              Or, even better, you could talk directly to the USART though the registers. Since the USART on this chip effectively has almost 2 bytes of buffer, as long as you check it for a newly received char at least as fast as the buad rate, you can avoid all interrupts and get the serial almost for free.

              data ready

  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

    Hello,
    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…

    thanks

    Niko

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

        Thanks

        Alan

  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!
    Tom

    • 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!
        Tom

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

    Thanks!
    Tom

      • 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,
        Tom

      • 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

      Hello,
      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

      cli();

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

      sei();

      delay (100);

      }

      m++;

      }

      }

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

        m--;

        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?

    Thanks,
    Bobby

    • bigjosh2

      You can find them for as cheap as $3 per meter (about 3 feet) on AliExpress.com 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,
          Tom

  13. Chris

    Hi,
    great project!

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

    Best regrads,
    Chris

  14. Chris

    Hi,
    great project!

    Is it possible to run it with WS2811 stripes?
    If not any suggestions how to adapt?

    Best regards,
    Chris

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

  15. 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
      
               cli();
        
               sendString( m , step , 0x00, 0x00 , 0x40 );    // Nice and not-too-bright blue hue
              
               sei();
               
        
            }
      
          m++;
      
        }
      
      
      }
      

      …which scrolls, you’d just write…

      void loop() {
        
               cli();
        
               sendString( jabberText , 0 , 0x00, 0x00 , 0x40 );    // Nice and not-too-bright blue hue
              
               sei();
      
               while (1);
               
        
      
      }
      
  16. 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() {
            sei();
            PIXEL_DDR |= onBits; // Set used pins to output mode
            Serial.begin(9600);
            cli();
            }

            char messageChar[] = “123456”;

            void loop() {

            // CMD SMS

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

            }

            }


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

            Thanks!

  17. yuliana

    Hey,

    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.

    Thanks!

    • 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

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

  19. 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.
    Cheers!!
    Stefan

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

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

    Cheers,
    Heiko

    • 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: http://www.haitronic.cn/index.php?route=product%2Fproduct&product_id=660&search=led%20strip

        My test code main loop:

        void loop()
        {
        clear();

        cli();
        sendString( “Twas brillig, and the slithy toves ” , 0 , 0x1f, 0x1f, 0x1f );
        sei();
        show();
        delay(500);
        clear();

        cli();
        sendString( “The jaws that bite, the claws that catch!” , 0 , 0x1f, 0x1f, 0x1f );
        sei();
        show();
        delay(500);
        }

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

          Thanks!

  21. Steven Palomino

    Question. How would I power this on just USB. I’m wanting to have a dim red led scrolling sign that’s using the 1m strips or so but still 7 strips high. How would I wire this?

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

        Thanks!

        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!

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

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

        • bigjosh2

          The included font is 5×7 – so it is only 7 pixels high. If you want a font that uses all 8 pixels of height then you will have to make (or find) one!

  24. 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,
    Lampenschakelen

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

  25. Pierre

    Josh,

    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!

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

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

      https://electronics.stackexchange.com/questions/102050/what-is-the-purpose-of-adding-a-300-ohm-to-500-ohm-resistor-on-the-neopixel-data

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

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

  30. 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:
        https://www.arduino.cc/en/Reference/PortManipulation

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

          https://www.arduino.cc/en/Reference/SoftwareSerial

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

  31. 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: https://github.com/blkhwks19/LED-Marquee

        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.

          https://github.com/blkhwks19/LED-Marquee/pull/1/files

          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?

          • undy

            Hi again (is it possible there’s a limit on the reply depth in the comment section?). I’m the guy from yesterday who asked about how to use pin 0 for serial and still use pin 1 for digital io. Thanks for the help on that, it works quite well, however I’ve run into issues with receiving serial data in general, the first time I send serial data to the arduino after a reset it displays the text perfectly, but the next time I send data there’s always some letters that seem to have gone missing, would you happen to know why this could be? I tested this with your serial code (I’m aware it’s softwareserial, I adapted it for normal serial) and code from other sources but the problem occurs with all solutions I’ve tried.

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

          Thanks

          AL

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

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

        • undy

          I am working on exactly this with pretty good results right now, I’m running a node server on my raspi and sending post data from it to the arduino over serial (connected pin 8 from the pi with pin 0 on the arduino via jumper cable, you’d probably wanna use a resistor or level converter between the two since the pi uses 3.3v on its pins but the arduino uses 5v to be safe, but it’s working fine for me right now).

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

  35. Aphex

    Hey Josh! First off, thank you, thank you, thank you for the insanely detailed posts you’ve written on this project, as well as the huge depth of comments above – they’ve helped me immensely as I worked to implement a smaller, 1-meter, double sided, mobile version of this work of art. I’m going to be carrying it on a flagpole to festivals and the like, and am powering it with 2x 12V 11,000maH batteries! (I’ll make a big post about it after I take it to EDC this week).

    Yesterday, after working on the physical construction and the software for two weeks, and wiring the power (I really liked your pluggable perfboard trick so I fashioned one myself), I ceremoniously turned it on, and LO: the jabberwock text began to scroll:

    However, note the pixel corruption. I think there’s some sort of timing/interrupt issue. My current code is here and it’s what the arduino is running in that video:
    https://github.com/aphexcx/arduino-led-marquee/blob/ccff7d67be99e34d4095d26c143e23c0ba01a1a5/LED_Marquee.ino

    I’m trying to figure out the cause of the corruption/flickering. Do you have any ideas?

    • bigjosh2

      Do you get the corruption with running the stock code from the article? Probably not.
      I’m pretty sure the corruption is coming from the SoftwareSerial() stuff. This uses interrupts and, as you guessed, with the very precise timing constraints of these pixels there is really no way to service an interrupt while pixels are being generated without trashing the datastream.

      There are a couple ways around this…

      Firstly, you can (carefully) use the hardware serial port with some custom code that checks the RX buffer only between pixels (or, better, between frames). Since the hardware serial reads the bits autonomously you don’t need any interrupts.

      If you can’t use the hardware serial pin or you need more than one serial input, then you can set up the protocol so that you are only use the softwareserial when the pixels are not updating – between frames, for example. So you could send a frame, turn on the softwareserial, send a char the connected host saying “I am Ready if you want to send something, but send it quick!”, read anything that comes in, close the software serial, repeat.

      • Aphex

        Haha yes, take a look at my getCustomData() function, which as it happens implements that EXACT idea of sending a ‘~’, and then calling readBytesUntil(). This function gets called in loop(), before scroll() – which I believe means it would run between frames.

        I successfully tested this call/response protocol with my other board, which is an Pico-i IMX7d board running Android Things 1.0. The IMX connects via serial to my Uno’s SoftwareSerial pins (currently set to pins 10 and 11). (Fun factoid: the IMX also runs a custom Bluetooth Low Energy GATT server that my phone can connect to and send strings for the sign to display.)

        However, the above SoftwareSerial stuff isn’t being used at all at the moment; the call to getCustomData() is currently commented out and the only thing in loop() is scroll(). Are you saying that even just having virtualSerial.begin(19200) in setup() is enough to start gumming up the works with interrupts? And if that’s the case, would that mean I need to move the .begin() call into getCustomData() – and probably also .end() it before I start the scroll()?

        • bigjosh2

          Are you saying that even just having virtualSerial.begin(19200) in setup() is enough to start gumming up the works with interrupts? And if that’s the case, would that mean I need to move the .begin() call into getCustomData() – and probably also .end() it before I start the scroll()?

          Yes, likely.

          • Aphex

            Ack, that made so much sense in theory, but no — the corruption/flicker still occurs with my code with virtualSerial.begin() disabled. It also still happens with the stock SimpleScroll code from the article. Hmmmmmm. I’m racking my brains as to what could be the cause. Random thoughts:

            1) Maybe I have a bad ground for the data pins or something?

          • Aphex

            Or 2) Maybe the arduino needs to run from the same 5v source as the LEDs? (Currently, the LEDs run off a buck converter from the 12v side of the battery, whereas the arduino is connected directly to the battery’s little 5v output. Seeing as these are ‘different’ 5v sources, perhaps it’s screwing up the data voltages…?

        • bigjosh2

          I can’t find the source for SoftSerialbut my guess is that the way the implemented is to set a timer to generate a periodic ISR and then they check the state of the input pin inside that ISR. This means that the ISR runs all the time while you are able to receive.

        • undy

          Just chiming in, I had a similar flicker issue as you and traced it down to the Arduino not being connected to the same ground and power source as the LEDs (was running the Arduino via USB). Hooked it up to the same power source and it worked perfectly.

          • Jim Elder

            HI, I just wanted to mention my experience with making the portable sign had the same flicker issue due to three reasons that I eventually figured out, first is the need for a common ground like Undy pointed out, second was poor digital signal connections and third seems to be static related. On the second issue, I wanted an easy way to unhook the LED panel from the power and arduino for transport, and thought a Cat 5 cable would be perfect for the digital signals and the ground. When I tried it though I found that the LEDs would flicker like in your video, but the flicker would go away if I made direct connections. I figure there must be enough resistance in the extra junctions to cause problems. The third issue with static I discovered by accident when I had direct digital connections and a common ground but was still getting a flicker. I’m using a 9v battery to power the arduino and a USB power pack to run the LEDs, and while I was seeing the flicker I happened to touch both supplies and the flicker went away. Then I discovered if I made sure the power sources were in contact, the flicker was avoided. Mind you, the grounds were tied together, so my guess was there is still some potential for static to create problems. Hope this helps.

      • Afik Cohen

        I just realized I never replied to this! Haha it was indeed a grounding issue – once they all shared a common ground the flickering went away.

  36. Ryan Bailis

    Hi Josh,

    Great project. I enjoyed putting it together and following your guide. However, I am running into problems getting the program to run on my UNO. When I run either one of your programs (MarcoMarquee or SimpleScroll) I just get random gibberish and flashing LEDs all over the place. However, I am confident that the build is correct because I can run “strandTest.ino” that comes with the neopixel library on each one of the rows individually. But of course, I can only test one row at a time.

    The problems I am describing only occur when I use your code. Do I have to change any of the predefined variables to fit my situation? I’m am a beginner with Arduino so any guidance and suggestions would be greatly appreciated. Really awesome project, and I hope to attempt some of your other projects in the future.

    Thanks so so so much!!

    Ryan

  37. Jonathan Hrenko

    Hey Josh, this site helped a lot in making and awesome FRC Robotics cart. Everyone loves our cart. We used your setup plus some changes to make it battery powered. And we combined your single strip code with this one to make it do more than just text.
    Here is a video of it. https://youtu.be/BcKHHP-qvI0

  38. Brad Haynes

    Thanks a bunch feeling hopeful. This method fixed most of my flickering by connecting the uno to the same power as the leds
    I get flickering on the blue font Just as the jabber starts
    It look like the letters are trying to be 3D I see green outline then blue with lots of flickering when the color changes from green the yellow and last red it work amazing
    I’ve also noticed just at the end of the jabber wording script
    The flicker starts again

    At this point I’m not sure what to do
    Checked grounds check external power supply

    Ada fruit strand test works good wondering if there is to much data

    I’m new to Arduino but have completed many projects
    However the coding isn’t my strong suit also can’t seem to see the count down timer on the leds with running the coat for it

    Would like to try just the count down on its own to see if it shows up on the leds

    • bigjosh2

      Hmmm… are you sure you have enough power for the whole sign? Blue uses the most power so if you start to have problems when there are lots of blue pixels on, hints at not enough power. Red uses the least, and that seems to work ok?

      Maybe as a test try changing the number of pixels to like half as many and see if that resolves the issues. If so, then you probably either need a bigger power supply, or fewer pixels, or not so much blue, or adding power on both ends of the LED strings, or all of the above until it work. Report back what you find!

  39. Brad H

    Hey again I hope all is good
    I have tried a few more things, but Still getting lots of flickering with power
    Injected at opposite end using the link on your website script from github

    Using the script link from your help section comments it works good only seeing one color for the entire script
    Would be nice to have multiple colors or be able to maybe change the color

    Grounds are good

    I notice something a little unusual when the uno has have its own power and ground and plugged into the computer the color would change on the led light to blue then unplug the usb and the lights changed to red very Bizzarre

    Power is good 5 volt 30 amps

    I can’t seem to see the count down timer
    Witch looks awesome on your video I have ran all codes wondering if I could have just the code for the timer by it self to see if it will show up

    I noticed when running the code with the multiple aliens they were once red or orange and they are now white is that a random thing
    Or is there something more going on

    Also when I get a lot of flickering it looks like there are 3 colors at once exp the letter m would have 3 legs blue red green

    I have a 6ft sign with the ws2812
    120 led light per row times 7 rows 840 led light total

    5 volt power supply 30amps
    Using uno board
    5 volts from power supply to uno vin and ground to gnd on uno

    I have row 7 connected to tx1
    Led Row 6 to pin 2
    Led Row 5 to pin3
    Led Row 4 to pin 4
    Led Row 3 to pin 5
    Led Row 2 to pin 6
    Led Row 1 to pin 7

    At this point would really just like to see the count Down and the effects

    Wondering if I should use a arduino mega for more memory could the uno possibly be having stability issues with memory

    If I need to use the mega witch ports would I need to use

    Thanks a bunch great project just wished I could get it working right off the bat
    I really appreciate you and the time to read all this

    • bigjosh2

      Arduino mega will not make any difference, this is not a matter of not having enough memory or pins.

      My first guess would be this a power problem. To narrow this down, try sending a lower power display. Red uses the least power, so maybe try sending a string of text in all red.

      If that works, then almost certainly a power problem. If not, then report back and we will figure out next things to test.

  40. Brad

    Hey josh I have injected power on both side with no change
    I can run your code in the link you last posted it scrolls blue and seems a little bumpie but no random RGB flickering like when I run your other codes on your video I am not able to see the count down timer at all . Would you mind sending me me just the code form the count down. The flickering is the same as Aphex may 14 is experiencing
    I am able to run full color and many on my led board with now power issues or flickering. Any ideas thanks

    • Brad H

      Hey josh I’ve found a large Rv 6 volt battery plenty of power for this project :) any ideas why the rest of the code is not showing up like the count down
      The random RGB flickering is still there and the colors seem off sometime on the letters
      I’ve notice when running the code it’s really affected by static but only seem to be when I run your code
      It’s got me beat for now any idea please let my know or name your price $
      Thanks

      • bigjosh2

        Big battery is great, but without the right connections pixels can still be under voltage and cause problems. Did you try running with, say, only 20 pixels in the #define linked to above? Does that work perfectly? Or is there still some problem? If so, a video of the test code running only 20 pixels would be helpful!

  41. Sagar Jansari

    I’m making a 16 feet long display of WS2812B LED strips. It is approximately 3600 pixels which are to be driven by single arduino.
    I’m not able to calculate the power supply requirement of the whole led structure.
    Please help me with this thing.

    • bigjosh2

      It depends most of all on what you are going to be displaying on those pixels. If all are displaying 100% bright white then it will be a heck of a lot more power than if you have a single dim red dot bouncing around on the display.

  42. Giuseppe Cusmai

    Hey Josh!
    Your sign looks great and I’m about to make one with my 14yr old niece to teach her some coding.

    In your price calculation you mentioned 60 LED/Meter strip, but from the pictures it looks like you got the “premium” 144 LED/Meter. Can you confirm?
    Here are the 3 variants (30,60,144 led per meter):
    https://a.pololu-files.com/picture/0J5801.1200.jpg?7e89d6512a2ba534004078af7e9b210c

    Your pixel grid looks square (similar X and Y distance) which is nice. Do you think it will look ok with only 60 LED/Meter (to save some money) and non-square pixel grid?

    Thanks!
    Giuseppe

    • bigjosh2

      The ones on this sign do look like denser than 60/m, but probably not 144/m (those a really close together). Maybe 90/m?
      You can use any density and aspect ratio you like. If you have 60/m strips and want square pixel boxes, then you can just space the strips out more and end up with a taller sign. Similarly you could put 60/m right on top of each other and have a longer looking font. If you don’t need the serial pin, then bumping up to 8 rows would help unsquish things.

Leave a Reply to lampenschakelenCancel reply