Uhr mit 12bit RGB-LED-Ring

Die Idee für dieses kleine Projekt kam aus der Situation heraus, dass ich mir einen 12bit RGB-LED-Ring (WS2812) bestellt hatte und nun dafür einen sinnvollen Einsatz suchte.
Die Uhr funktioniert quasi wie eine normale Analoguhr mit Zeigern, jedoch werden statt den Zeigern jeweils eine bunte LED angezeigt (grün für Stunden, blau für Minuten und rot für Sekunden). Die Besonderheit dieser Uhr ist jedoch, dass sie nur 12 verschiedene Anzeigemöglichkeiten bietet, damit sind zwar die Stunden korrekt (im 12-Stunden-Format), jedoch dürfen Minuten und Sekunden nicht direkt abgelesen werden, sondern nur die Position der jeweiligen LED. Daraus folgt, dass man an dieser Uhr Minuten und Sekunden nicht präzise ablesen kann.
Einen weiteren Unterschied zu einer analogen Uhr gibt es noch: Die Position der Stunden ist immer fix bei der aktuellen Stunde und schaltet erst nach Ablauf von 59 Minuten auf die nächste Stunde um.

Video: Live-Demonstration der Uhr

Verwendete Bauteile

Anschlüsse & Funktionsweise

Das hier verwendete DS1307 Real-Time-Clock-Modul (RTC) ermöglicht das Auslesen und Setzen von Datum und Uhrzeit. Dank der integrierten Batterie verliert es die Uhrzeit auch nicht bei einem Stromverlust. In diesem Projekt wird Datum/Uhrzeit nur initial gesetzt und muss dann wieder auskommentiert werden, damit bei einem Neustart/Reset des Arduinos diese Daten nicht wieder überschrieben werden! Für die Darstellung der Uhrzeit wird das Datum nicht benötigt und daher auch nicht ausgelesen.

Vorderansicht des DS1307
Abb.: Vorderansicht des DS1307
Rückansicht des DS1307
Abb.: Rückansicht des DS1307

Das DS1307-Module wird folgendermaßen an den Arduino angeschlossen (Anschluss DS wird hier nicht benutzt):

DS1307 Arduino
VCC 3V
GND GND
SCL Analog PIN 5
SDA Analog PIN 4
Pinout des DS1307
Abb.: Pinout des DS1307
Anschluss des DS1307 an den Arduino
Abb.: Anschluss des DS1307 an den Arduino

Vorsicht: Manche RTC-Module haben integrierte Ladeautomatiken, die bei Nutzung einer CR2032-Knopfzelle Schäden verursachen können. Daher sollte man in diesen Fällen eine wiederaufladbare Lithium-Ionen-Knopfzelle (LIR2032) verwenden.

Aufbau

Aufbau und Anschluss des RGB-LED-Ringes siehe hier

Sketch

#include <Wire.h>
#include <Adafruit_NeoPixel.h>

#define PIN_LED_RING   8
#define NUMPIXELS      12
#define LED_BRIGHTNESS 35

#define DS1307_ADDRESS 0x68 // I²C Address

Adafruit_NeoPixel ring = Adafruit_NeoPixel(NUMPIXELS, PIN_LED_RING, NEO_GRB + NEO_KHZ800);

byte ledMapping[NUMPIXELS] = {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5};
int hours=0, minutes=0, seconds=0;
byte h=0, m=0, s=0;
float divisor = 0.0166666;
uint32_t colorSeconds, colorMinutes, colorHours;


void setup()
{
    Wire.begin();
    Serial.begin(9600);

    /*
    * You have to set the date/time only once.
    * Comment the following line after setting the date/time because it
    * will be overwritten after every setup/restart of your circuit.
    */
    //setDate();

    ring.begin();

    byte b = min(255, LED_BRIGHTNESS);
    colorSeconds = ring.Color(max(3, b/10), max(2, b/15), 0);
    colorMinutes = ring.Color(0, b/4, b/3);
    colorHours   = ring.Color(0, b, 0);
}

void loop()
{
    readTime();
    showClock();
    delay(1000);
}

void readTime()
{
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(0x00);
    Wire.endTransmission();
    Wire.requestFrom(DS1307_ADDRESS, 7);

    seconds = bcdToDec(Wire.read());
    minutes = bcdToDec(Wire.read());
    hours   = bcdToDec(Wire.read() & 0b111111);

    Serial.println((String)hours + ":" + (String)minutes + ":" + (String)seconds);
}

void setDate()
{
    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(0x00);
    Wire.write(decToBcd(30));   // seconds
    Wire.write(decToBcd(04));   // minutes
    Wire.write(decToBcd(11));   // hours (24-hour format)
    Wire.write(decToBcd(7));    // weekday
    Wire.write(decToBcd(29));   // day
    Wire.write(decToBcd(10));   // month
    Wire.write(decToBcd(2017)); // year
    Wire.write(0x00);
    Wire.endTransmission();
}

void showClock()
{
    s = (byte)(divisor*seconds*NUMPIXELS);
    if (s>=NUMPIXELS) {
        s = 0;
    }

    m = (byte)(divisor*minutes*NUMPIXELS);
    if (m>=NUMPIXELS) {
        m = 0;
    }

    h = hours%12;

    for(byte i=0; i<NUMPIXELS; i++) {
        ring.setPixelColor(i, 0);
    }

    ring.setPixelColor(ledMapping[s], colorSeconds);
    ring.setPixelColor(ledMapping[m], colorMinutes);
    ring.setPixelColor(ledMapping[h], colorHours);
    ring.show();
}

int decToBcd(int value)
{
    return ((value/10*16) + (value%10));
}

int bcdToDec(int value)
{
    return ((value/16*10) + (value%16));
}
zurück