Arduino + WS2812B LED Clock

by BA_WE in Circuits > Clocks

4027 Views, 14 Favorites, 0 Comments

Arduino + WS2812B LED Clock

IMG_20211116_183107189.jpg

I previously made an animated LED clock with WS2812B's stuck to some triplex, and Arduino driving everything, and a cloth diffuser: https://www.instructables.com/Animated-LED-Clock/

However I wasn't super happy with the result, it's clunky and low-res. When I saw some of Parallize's designs on Thingiverse - in particular the 'Lazy Grid Clock' at https://www.thingiverse.com/thing:4263318 I figured this was a better way to make a 3D printed holder.

I've adapted the original design and used this to program a 24x12 pixel LED clock using an Arduino, WS2812B's and a 3D printed holder for the LED's which can be found at https://www.thingiverse.com/thing:5138944

Supplies

Arduino nano + 2 micro breadboards

Generic 5v power supply

WS2812B strips (aliexpress, 90LED/meter)

DS3232 RTC module + battery

Wires & soldering iron :)

The Diffuser & Holder

IMG_20210507_113846.jpg
IMG_20210507_114034.jpg
IMG_20210508_104046.jpg
IMG_20210508_104017.jpg
12x12holder_picture.png

Inspired by https://www.thingiverse.com/parallyze/designs but designed completely anew to fit the particular LED strip I had lying around. The key to this is that the LEDs aren't facing frontward but shine through a little gap off to the side. They will light up the little square pixel they are projecting into so with the right diffuser it looks quite nice as if the whole square is lighting up evenly. Pixels are about 16mm x 16mm in this design.

I had a couple of tries at various models, including circular and filled in (just printing a single layer of white PLA for the LED to shine though) but at the end I settled on a simple design where the LED strip is held in place and projects light into squares of light. It works both sides - if you want a soft effect you can use a paper sheet as a diffuser, but in the end I opted to leave everything open because the colours pop a little more. Even then I still have the paper glued to it, it helps keep everything together, but just let the back side face away from the wall.

White PLA works the best. I also tried black but this gives a dimmer display. In both cases there is some light bleed from one pixel to the next, its less when using white PLA. If you really wanted to stop light bleed then probably need to double the wall thickness which doubles the print - this took about 5 hours for a single 12x12 pixel panel.

The LED strip folds back at the top (scary at first but works fine), and then at bottom I bridge the gap to the next column with some soldered wires. You could just loop the LED strip across to the next column (Parallyze does this) which would save a lot of soldering and make it somewhat more reliable in the process, but there are a couple of LEDs which never do anything in that case and I like the open wires in this design.

LEDs are wedged in place and are pretty stable. I did end up printing a couple of clips which you can wedge into and across the rows which help keep the strip from falling out but this is strictly optional.

Connect Panels Together

IMG_20211102_224011237_HDR.jpg

I just printed two 12x12 panels which I wired up and glued to a sheet of white paper, looping the LED strip through each column. First attempt was two separate sheets but I ended up gluing both to a single sheet of A3, connects them together quite well. In hindsight if I had oriented each panel 90 degrees it would have saved me about half the soldering, (looping the LED strip across the columns instead) but it was too late for that by then.

You could quite easily extend the panel further both horizontally and vertically by just repeating everything, but this is more soldering than I like to think about, and you'll rapidly run out of memory on a standard Arduino uno or nano platform

Wire Everything Up

IMG_20211102_204323811.jpg
IMG_20211102_224008384.jpg
IMG_20211102_204312389.jpg
20211008_094507.jpg

I went through a couple of iterations, one using a large breadboard, but ended up using the two smallest I have, joined together, with an Arduino nano. The wiring is as follows:

+5v and ground from a power supply (generic 5V, 2A, soldered some Dupont wire onto the positive and ground leads) to respective pins on the nano.

The LED strip also joined to +5V and ground, I use pin 6 for data

Three buttons connected to pins 11,9, and 7 used to cycle the various fonts, backgrounds.

The DS3232 RTC is wired up to the respective +3.3V and GND, and to the SDA and SCL pins on the nano.

I quite like the wires sticking around - gives it the home made feel - but if you dont want it it would be quite reasy to 3D print a little box to hold everything. I did print out a holder for the breadboards and is stuck to the matrix panel to keep everything to the side. Tried a couple of things but just off to the side seems to be nicest to me.

Software

I wont go into complete detail here - any questions how it all works please feel free to ask, I've tried to keep the code as legible and obvious as I can (I'd just confuse myself otherwise!!). I'm no expert and have self taught programming, so there's a good chance the code is inefficient or I've done something silly somewhere. I'd love to hear it if so!

Some highlights:

  • To light up a particular x,y position (column, row) I call the calcLEDposition subroutine which takes in the row & column and then returns which pixel along the LED strip this corresponds to (from 0 to 287). The code made sense to me at the time but I tried to strip out all of the unnecessary additions and subtractions so it's now not very readable anymore. Important is that it works. I believe FastLED actually has a built in routine for this kind of thing but I figured I might as well write it myself.
  • So if you want to light up pixel [2,2] then you call the calcLEDposition subroutine, this returns the pixel number (r) to light up (in this case number 13). Then call FastLED to light up LED no. 13 in the desired colour: for example {leds[r] = CRGB(255,0,0)}
  • The backgrounds were adapted from the Perlin noise + palette demo that comes with FastLED, doesn't say who wrote this but I can't thank them enough, it looks great! They are largely unchanged but I ripped out some of the superfluous stuff in my case.
  • The clock is set (separately, not in this sketch) and read using the standard DS3232RTC library
  • I have a number of different fonts which I store in flash using PROGMEM (otherwise I'd be well out of memory) and they are cycled by just offsetting a counter with each button press.
  • The fonts were designed in excel. Instructables wont let me upload an excel file, but basically I just draw out the font I want to have and then use excel to calculate some pixel offsets. Could write a proper macro but that's more hassle than its worth in this case (I'd need to learn how, first!)
  • The fonts tend to be very difficult to read. Partially because I tried to go for style over substance in the font design, but also because you just need a little distance from the LEDs to see them properly. The code allows moving them around a little vertically, so I've staggered them by one pixel which helps slightly in readability.
  • I have two variants, the standard and a 'backwards' (this one) depending on which way I want to hang the clock paper side to the wall or away from the wall.

Enjoy!

20211008_093759.jpg
IMG_20211116_180709263.jpg
LED clock with WS2812B and Arduino
LED Clock Backgrounds

I think the end result is quite nice! See the Youtube videos for a quick demo. Any questions or comments, please let me know!