In this post, I will build a super cool word clock with Arduino and Neopixel LEDs. Such word clocks cost several hundred euros in the trade, but with a little skill, they are also fast self-built. I show you how it works. The electronic base is similar to that of my LED-Matrix.

UPDATE 2022: I built version 2.0 of the Word clock. This time with WiFi and some games to play on it (Pong, Tetris, Snake). Find my blog post about it here.

Material for the word clock

You need the following material for the word clock. Overall they cost less than 100 EURO.

  • deep wooden picture frame 24x30cm (or similar size, amazon.de*)
  • black adhesive foil (amazon.de*)
  • NeoPixel LED Strip with 114x WS2812b LEDs (60LEDs/m) (amazon.de*)
  • Arduino Nano V3.0 (amazon.de*)
  • Real-Time-Clock Modul DS3231 (amazon.de*)
  • power supply 5V/3A (amazon.de*)
  • DC power jack 5.5×2.1 (amazon.de*)
  • two sheets of black cardboard
  • one sheet of white paper
  • some cables, one 470 Ohm resistor, one 1000uF capacitor, one small switch

Optionally you can upgrade the Word Clock with these components:

* The links are affiliate links. The offers do not come from me, however, I receive a commission through the reference, if then a purchase takes place, but without you incurring additional costs.


Step-by-Step instructions

  1. The first step is to stick the adhesive foils onto the glass pane of the picture frame. Tip: Here it helps to spray the glass pane with detergent water first so that the bubbles can be easily pushed out of the foil afterward.
  2. The most complex task is cutting out the individual letters from the black adhesive foil. The best way to do this is to print out a template with the letters and fix it on the glass pane with adhesive tape. Now the letters can be cut out with a sharp cutter knife.
Cut out letters from the adhesive foil
  1. To avoid reflections, it is recommended to paint the back panel with spray paint.
Painted backboard
  1. Now you divide the LED strip into 10 strips of 11 LEDs each and glue them in a zigzag pattern on the back of the picture frame. It helps to mark the desired position on the back panel.
LED strip on the backboard
  1. To reduce stray light from the individual LEDs, we now create a grid structure from the black cardboard. To do this, we cut 2 cm wide strips from the cardboard and cut them 11 or 12 times up to the middle. Afterward, the strips can be put together as grids as shown in the picture below.
The black cardboard grid structure
  1. Now it goes to the electronics. We solder the Arduino with the LED strips and the real-time clock (RTC) module. It doesn’t matter if you use a hole board or solder the cables directly. As an add-on, you can add the radio clock receiver module DCF77 and/or the light sensor module for automatic brightness control, but this is not absolutely necessary. The RTC module with its battery always keeps the current time. But without using the radio receiver you have to flash the Arduino again when changing the battery of the RTC module.
Schematic of the word clock
Back panel with electronics
techniccontroller / think_wordclock

Arduino source code for the Wordclock on GitHub

  1. The next step is to flash the software to the Arduino. The complete source code can be found here on GitHub. It also describes which additional libraries need to be installed in the Arduino IDE. While connecting to a computer via USB, the small switch must be turned off (to prevent damage to the Arduino due to the high current drawn by the LEDs).
  2. So that the letters shine as a whole and not the individual LEDs are visible, we now stick a simple sheet of white paper on the back of the glass plate. Then we fix the grid with hot glue on the glass plate.
Grid structure inside the picture frame
  1. The last step is to insert the glass plate and back panel into the picture frame. You can also add an on/off switch in the picture frame.
The word clock at day
The word clock at night

You can extend the project as desired: As some of you might have noticed in the pictures above, a built-in light sensor allows automatic adjustment of the brightness of the LEDs to the environment. I placed the light sensor inside the first “K” and connect it to an analogue input (A6) of the Arduino.

Have fun rebuilding it.

Share this post

96 Comments

Jonas · 20/12/2022 at 21:54

Hallo zusammen,

ich habe das Projekt nachgebaut und bin begeistert über den Blog.
Jedoch funktioniert der Sketch bei mir nicht.
Ich habe auch keine Ausgabe im seriellen Monitor. Ist das normal?

Folgende Teile habe ich verbaut:
– Arduino Nano V3 (erstes war von AZ, habe ich jedoch auf Rat eines Freundes getauscht)
– RTC DS3231
– Widerstand und Kondensator
– Netzteil
– LED Stripe

Nicht verbaut:
– DCF77 Empfänger (momentan nicht lieferbar, kommt aber in zwei Wochen)
– Helligkeitssensor

Wenn ich den Beispielsketch für die LED´s einspiele, funktioniert dieser Einwandfrei.

Frage:
Muss ich im Sketch etwas ändern, weil der DCF77 und der Helligkeitssensor nicht vorhanden ist ?
Mein Board lässt sich nur mit Processor ATmega 328P (Old Bootloader) schreiben, ist hier schon ein Fehler?
Als Programmer ist AVRISP mkII automatisch gewählt, abwählen kann ich diesen gar nicht. Ist hier eine falsche Einstellung?

Bin etwas am verzweifeln, vielleicht kann mir jemand weiterhelfen.

Vielen Dank

    Techniccontroller · 20/12/2022 at 22:49

    Hallo Jonas,
    danke für dein Kommentar.
    Der Code funktioniert auch ohne angeschlossenem DCF und Helligkeitssensor.
    Das keine Ausgaben auf dem Seriellen Monitor angezeigt werden ist nicht gut. Das bedeutet, dass der Code gar nicht erst ausgeführt wird (kann z.B. ein Speicherproblem sein). Nutzt du den exakten Code von GitHub, oder hast du Änderungen am Code vorgenommen?

    Was die Auswirkungen bzgl. des Bootloaders sind , kann ich nicht beurteilen, ich musste bei mir den Processor noch nie umstellen (nutze aber auch keine originalen Arduinos ;)). Dein ausgewählter Programmer sollte passen.

    Kannst du mir mal deinen Code (*.ino Datei) und die komplette Ausgabe der Arduino IDE vom Kompilieren und Upload an mail@techniccontroller.com schicken. Dann kann ich mir das man anschauen.
    Vielleicht fällt mir direkt was auf. Ansonsten müssten man den Code Stück für Stück zusammensetzen und immer wieder Uploaden&Testen bis man auf die Zeilen stößt, die Probleme verursachen.
    VG
    Edgar

      Jonas · 21/12/2022 at 10:25

      Hallo Edgar,

      vielen Dank für deine Nachricht!

      Ich verwende den kompletten Code von Github. Geändert habe ich daran auch nichts.
      Gestern habe ich nochmals versucht, die RTC in einem Testprogramm am seriellen Monitor anzeigen zu lassen,
      leider ohne Erfolg. Jetzt habe ich nochmals genau nachgelesen und festgestellt, das die RTC von AZ mit 3,3V läuft, diese bei mir aber am 5V Netzteil hängt. Das war mir lediglich beim DCF77 bewusste mit der Betriebsspannung. Dies könnte meiner Meinung nach die Ursache sein. Morgen sollen hierzu die Spannungswandler 5V->3,3V bei mir eintreffen. Diesen baue ich dann zusammen mit einer neuen RTC ein und probiere es nochmals. Ich hoffe das löst mein Problem, andernfalls würde ich mich gerne nochmal melden.

      Vielen Dank und guten Start in den Tag !

Markus · 08/12/2022 at 11:54

Guten Tag, folgendes Problem tut sich bei mir auf wenn ein ein OLED Display (SSD1306 Chip 128 x 64 Pixel) zur Temperaturanzeige der RTC Temperatur einbinden möchte. Folgendes habe ich im Programmcode umgesetzt:

#include
#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

Ergänzt in der:
void setup() {
Serial.begin(9600);
Wire.begin();
delay(3000);
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay();
display.display();
}
Ergänzt in der:
void loop(){
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(30,0);
display.print (“Temperature: “);
display.print(rtc.getTemperature());
display.println(” C”);
}

Kompilieren tut er und das Uploaden funktioniert auch, trotzdem Funktioniert das Programm nicht, da die Startsequenz nicht mal mehr startet und auch die Aktuelle Uhrzeit nichtmehr angezeigt wird.

Sobald ich aber folgendes auskommentiere :
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

funktioniert das Programm wieder wie es soll.
Liegt es an der Aktuellen Version der und der alten Version der , das es dadruch zu indeferenzen kommt?

Viele Grüße!

    Techniccontroller · 08/12/2022 at 16:41

    Hallo Markus,
    dieses Verhalten liegt sehr wahrscheinlich am begrenzten Speicher des Arduino Nano (2kB SRAM). Der Code für die Wortuhr benötigt bereits einen großen Teil des dynamischen Speichers des Arduinos. Auch das SSD1306 Display benötigt sehr viel Speicher (min. 1kB SRAM). Das führt dazu, dass das Programm zwar kompiliert aber nicht ausgeführt werden kann (dynamischer Speicher = SRAM, wird erst zur Laufzeit benötigt). Ich hatte solche Probleme bereits öfters bei mehr Pixeln oder der Kombination zwischen NeoPixel und Display.

    Hier kann man mehr zu dem Speicher-Problem lesen:
    https://learn.adafruit.com/memories-of-an-arduino/large-memory-consumers
    https://docs.arduino.cc/learn/programming/memory-guide

    Ich empfehle für das SSD1306 nicht die Standardbibliothek von Adafruit zu verwenden, sondern eine Lightweight-Bibliothek, welche Speicher spart indem direkt auf das Display geschrieben wird anstatt eine Abbild des 128×64 große Displays im Speicher zu halten. Nachteil ist, dass weniger Designmöglichkeiten existieren.
    Beispiel für eine solche Bibliothek ist folgende, es gibt aber sicher noch mehr:

    https://github.com/mgcastro/SSD1306_text

    Hoffe das hilft dir weiter.
    VG
    Edgar

      Markus · 02/03/2023 at 20:21

      Hallo Edgar,
      ich hätte noch ne Frage bezüglich der Farben. Ich würde gerne nur eine Farbe nutzen. Welchen Teil aus dem Code muss ich da genau weglassen und wo stelle ich dann die Farbe ein die ich möchte?

      VG
      Markus

        Techniccontroller · 03/03/2023 at 12:56

        Hallo Markus,

        Wenn du nur den Wechsel der Farben verhindern willst (also fest auf einer Farbe stehen bleiben willst) kannst du die Zeile 124 auskommentieren:

        activeColorID = (activeColorID+1)%numColors;
        

        und die gewünschte Farb-ID (aus dem Array colors) in Zeile 74 definieren:

        uint8_t activeColorID = 0;      // current active color mode
        

        Du kannst die Farben im colors Array bis auf ID 0 auch individuell anpassen.

        PS: Zeilenummern beziehen sich auf die aktuellste Version des Codes auf GitHub, ich habe den Code vor ein paar Tagen etwas geändert (siehe Kommentar von Yess), sodass die Zeilennummern eventuell etwas verrutscht sind.

        VG
        Edgar

          Markus · 13/03/2023 at 10:04

          Hallo Edgar,
          vielen dank für die Rückmeldung. Habe das soweit jetzt abgeändert, leider zeigt meine Uhr immer noch Grün an, obwohl ich die Farbe 1 ausgewählt habe und dies soll laut Farbmodus Rot sein. Ändere ich die Farbe Grün in der Matrix in weiß, ändert sich dann auch die Farbe. Er ist also ständig in 5, obwohl ich von vornherein die Farbe auf 1 definiert habe.
          VG
          Markus

          Techniccontroller · 13/03/2023 at 14:17

          Hallo Markus,

          ah okay, hab meinen Denkfehler gefunden :).
          Du musst neben Zeile 124 auch noch Zeile 114 auskommentieren um das Wechseln der Farben zu verhindern.

           EEPROM.get(EE_ADDRESS_COLOR, activeColorID); 

          Sonst holt sich das Programm die activeColorID immer wieder aus dem persistenten EEPROM Speicher und überschreibt deinen vorher gesetzten Wert.

          VG
          Edgar

Dennis · 09/11/2022 at 21:06

Hallo Edgar,
auf meinem Arduino Nano V3 leuchten die LEDs leider nicht… Im Serial Monitor scheint alles zu passen, da laufen die richtigen Werte durch. Schließe ich einen Arduino MEGA an, funktioniert die Uhr einwandfrei. Gibt es eventuell noch einen Trick mit dem Nano V3? Es ist kein Originaler von Arduino, sondern von joy-it, sollte aber laut Datenblatt 100% kompatibel sein. Oder könnte es einen anderen Grund geben?
Danke dir und viele Grüße
Dennis

    Techniccontroller · 10/11/2022 at 0:09

    Hallo Dennis,
    danke für deinen Kommentar.
    Ich würde persönlich noch folgenden zwei Tests ausprobieren um zu prüfen ob es an dem Board liegt:
    – Probiere einen anderen Pin um die LEDs anzusteuern,
    – Probiere ein einfaches Testprogramm (z. B. einen Beispielcode aus der Adafruit_NeoPixel Bibliothek)

    Wenn beides nicht klappt, würde ich sagen, dass etwas an dem Board nicht stimmt. Vielleicht beeinflussen irgendwelche Kapazitäten das Signal (könnten man mit einem Oszi prüfen). Mir sind ansonsten keine Probleme mit Arduino Nano bekannt.

    VG
    Edgar

      Dennis · 10/11/2022 at 20:06

      Hallo Edgar,

      danke dir für die Antwort. Es funktioniert mit dem Arduino Nano V3, sobald ich die Funktion checkDCFSignal auskommentiere. Sobald ich checkDCFSignal wieder einbinde, gehen die LEDs nicht an. Laut Serial Monitor ist die Signalqualität gut und auch die anderen Werte laufen durch; heißt, das Programm bricht nicht ab. Irgendwie scheint der Nano das nicht zu vertragen….

      Viele Grüße
      Dennis

        Techniccontroller · 11/11/2022 at 0:05

        Hallo Dennis,
        okay das ist interessant, ich hatte die Funktion checkDCFSignal() tatsächlich nur zu Debuggingzwecken drin und deshalb auch im Code auskommentiert. Ich hab nicht mehr in Erinnerung ob das bei mir auch die LEDs gestört hat.

        Es kann aber durchaus sein, dass delayMicroseconds() die Konfiguration der Timer und somit die Ansteuerung der LEDs beeinflusst. Müsste man mal genauer untersuchen, ich hatte ähnliche Konflikte schon vorher. Die NeoPixel-LEDs benötigen ein sehr genaues Timing, da können andere Codeteile leicht Störungen hervorrufen.
        Ich habe aktuell leider keine passende Hardware zur Verfügung um mir das im Detail anzuschauen.
        Für die Funktion der Wortuhr ist die Funktion checkDCFSignal() nicht notwendig, deshalb würde ich an deiner Stelle die Funktion einfach auskommentiert lassen.

        VG
        Edgar

          Dennis · 11/11/2022 at 7:56

          Hallo Edgar,
          genau, ich lasse sie einfach auskommentiert. Interessant, dass der Arduino Mega damit klarkommt. Falls ich noch rausfinde, an was es genau liegt, gebe ich dir Bescheid.
          Auf jeden Fall nochmal vielen Dank für den Code! 🙂
          Beste Grüße
          Dennis

          Techniccontroller · 13/01/2023 at 22:37

          UPDATE 13.01.2023:

          Ich habe den Fehler gefunden.
          Es gab ein Speicherproblem. Die langen Strings in Serial.println() haben zu viel Speicher benötigt. Ich habe den Code nun optimiert. Jetzt wird die Signalstärke zudem bei jedem Start mit den LEDs angezeigt. (erste LED blinkt blau, dann wird rot/grün die Signalqualität als Balken gezeigt).

          Aktualisierter Code ist auf GitHub zu finden: https://github.com/techniccontroller/think_wordclock

          VG
          Edgar

Nicklas · 13/10/2022 at 21:01

Hallo,
Ich bin jetzt fertig mit der Uhr und finde sie ein wenig zu hell, kann man die Helligkeit ändern? Und kann man den Nachtmodus an verschiedenen Tagen zu verschiedenen Uhrzeiten anmachen?

Ich bin selbst daran interessiert an der TUM zu studieren und habe ein paar Fragen, die gerne einem Schüler stellen will. Kann ich Sie per E-Mail erreichen?

    Techniccontroller · 13/10/2022 at 21:41

    Hallo Nicklas,

    freut mich, dass deine Uhr funktioniert.

    Die Helligkeit kann einfach über die Funktion
    matrix.setBrightness(…)
    auf einen Wert zwischen 0-255 gestellt werde. Je nachdem, ob du den Lichtsensor verwendest oder nicht wird im Code die Helligkeit dynamisch angepasst. Du kannst den Teil des Code (am Anfang der loop() ) aber einfach auskommentieren und einen festen Wert für die Helligkeit vergeben.

    Der Nachmodus ist aktuell nur anhand der Uhrzeit definiert. Aber mit ein paar mehr if()-Bedingungen können auch für verschiedene Tage individuelle Zeiten für den Nachtmodus definiert werden. Die Variable rtctime bietet neben hour() auch die Funktion day() um auf den aktuellen Wochentag zugreifen zu können.
    Ich denke das kannst du mal selbst probieren zu implementieren.

    Bzgl. TUM, kannst du mir gerne ne Mail schreiben (an mail(at)techniccontroller.com).

    VG
    Edgar

Matthias · 11/10/2022 at 21:30

Hallo Diddy – danke für deine Tolle Arbeit. Ich möchte die Uhr für meine Frau zum Geburtstag bauen. Leider bekomme ich trotz aller Bibliotheken von Github den Code nicht kompiliert.

Kannst du weiterhelfen?

Hier die Fehlermeldungen:
c:\Users\Schule\Documents\Arduino\libraries\DCF77\DCF77.cpp: In static member function ‘static void DCF77::finalizeBuffer()’:
c:\Users\Schule\Documents\Arduino\libraries\DCF77\DCF77.cpp:160:21: error: ‘now’ was not declared in this scope
filledTimestamp = now();
^~~
c:\Users\Schule\Documents\Arduino\libraries\DCF77\DCF77.cpp:160:21: note: suggested alternative: ‘pow’
filledTimestamp = now();
^~~
pow
(…)

c:\Users\Schule\Documents\Arduino\libraries\DCF77\DCF77.cpp:326:64: error: ‘now’ was not declared in this scope
time_t currentTime =latestupdatedTime – UTCTimeDifference + (now() – processingTimestamp);
^~~
c:\Users\Schule\Documents\Arduino\libraries\DCF77\DCF77.cpp:326:64: note: suggested alternative: ‘pow’
time_t currentTime =latestupdatedTime – UTCTimeDifference + (now() – processingTimestamp);
^~~
pow

exit status 1

Compilation error: exit status 1

(edited by techniccontroller: shorted the comment)

    Techniccontroller · 12/10/2022 at 20:15

    Hallo Matthias,

    danke für deinen Kommentar.
    Bitte kopiere alle Bibliotheken direkt aus dem GitHub repository:
    https://github.com/techniccontroller/think_wordclock/tree/main/libraries
    in deinen ‘libraries’-Ordner von der Arduino-IDE um Versionskompatibilitätsprobleme auszuschließen.
    Mit diesen Bibliotheken kompliert der Code bei mir fehlerfrei.

    Die Ordnerstruktur sollte dann in etwa so aussehen:

    [MySketchbookLocation]

    └───libraries
    │ └───Adafruit-GFX-Library
    │ └───Adafruit_NeoMatrix
    │ └───Adafruit_NeoPixel
    │ └───Adafruit_BusIO
    │ └───DCF77
    │ └───RTClib
    │ └───Time
    │ └─── (…)

    └───think_wordclock
    │ └───wordclock_german
    │ │ └───wordclock_german.ino
    │ └───README.md

    Bitte gerne nochmal melden falls es weitere Probleme gibt.

    Viele Grüße
    Edgar

Add a Comment

Your email address will not be published. Required fields are marked *