Concept

A WS2812B LED (’NeoPixel’) clock that indicates the hours on the inside ring of LEDs, and the minutes on the outside ring. This is similar to my first idea pitched in Week 3.

Fabrication

I bought a bamboo embroidery hoop from Blick to get an affordable ring structure for my LEDs to be mounted. Since LEDs are an interest of mine, I had a roll of WS2812B LED tape from Amazon. I measured and cut the length of tape needed for the inside and outside of the ring.

Untitled

Untitled

Next, I soldered the data, power, and ground lines from the end of the outside LED ring to the beginning of the inside ring, so that the Arduino could see it as one long continuous strip.

Untitled

Untitled

Next, I soldered another set of wires from the beginning of the outside ring to be connected to the Arduino. Then, I plugged it in and ran the NeoPixel strandtest example to test if the wiring was good. I oriented the hoop so that the direction of the LED data (and the numbering of LEDs) is clockwise. Here are the results of that in video:

VID20231028185949.mp4

RTC Module

Next, I set up my DS3231 RTC module by connecting the SCL, SDA, GND, and 3.3V pins to my Arduino Zero. I ran the DS3231 example code to make sure that works and I was able to read the time. Here’s a picture of my setup and the serial monitor showing the current time printing.

Untitled

Screen Recording 2023-10-30 at 1.41.53 AM.mov

Coding Animations

The difficult part was mapping which pixel to light up for the time. I started by writing out the index of each LED, and then marking off the minutes and hours on the paper, to be able to reference and visualize the time. I started by drawing perpendicular axes for 12, 3, 6, and 9 o’clock positions. Then, I didn’t have a protractor, but I tried my best to mark off every 30 degrees for each hour / 5 minute subdivision.

Untitled

The frustrating part was that the outer ring was 47 pixels and the inner ring was 45. Neither of these numbers are divisible by 12, so the mapping was not very straightforward.

//map minutes to outside LED index
      if (demoMins <= 30) {
        demoMinsPixel = map(demoMins, 0, 30, 23, 47);
        if (demoMinsPixel == 47) {
          demoMinsPixel = 0;
        }
      } else {
        demoMinsPixel = map(demoMins, 30, 60, 0, 23);
      }

Additionally, I wanted the wire to come out the bottom (to rest the electronics on a table when the clock is hung on a wall). However, this means that the starting index of the LED rings is at the bottom (6 o’clock or 30 minute mark), instead of the top of the clock (12 o’clock or 0 minute mark). Not a big deal, just needed to account for that when mapping, by doing half the circle at a time (00 to 30, and then 30-60). I mapped the minutes using the following code:

For the hours, I wanted to avoid the “jumping hours” hand problem, which Jeff demonstrated in class using this p5.js sketch. Essentially this issue is making sure the hour hand moves gradually between the hours, instead of “jumping” from hour to hour.