Eine einfache Binary-Clock

By Vincent 3 comments

Die Idee für eine BinaryClock habe ich im Internet gefunden: https://www.instructables.com/id/The-Ultimate-Binary-Watch/. Die Armbanduhr hier ist super schick, aber gerade habe ich nicht die Möglichkeiten diese selber zu basteln. Deshalb sollte meine eigene BinaryClock für den Schreibtisch sein. Glücklicherweise hatte ich noch alle Bauteile dafür da.

Durch das Anordnen von LEDs in solch einem Raster kann man die Uhrzeit sehr einfach und schick anzeigen lassen.

Bauteile:

  • Einen WeMos-D1 mini (oder ein Arduino-Board (z.B. Arduino pro Micro/Leonardo) mit einer RealTimeClock)
  • 16 RGB-LEDs WS2812 im Streifen
  • Litze, Headerpins, Lötkram
  • Ein bisschen Holz und Papier für den Rahmen

Ich verwende für meine Uhr ein WeMos-D1 mini, da sich dieser mit dem Internet/WLAN verbinden kann. Somit kann ich mir eine RealTimeClock sparen. Nachteil ist hierbei, dass meine Uhr eine kleine Api braucht um die Uhrzeit zu laden, da die Zeitmessung des WeMos-D1 nicht sehr genau ist und die Uhr ständig falsch gehen würde. Diese Api liegt daher lokalen Netzwerk. Wer dies nicht hat, bzw. nicht verwirklichen kann empfehle ich eine RealTimeClock mit einem anderen Arduino.

Also der Plan:

Die Uhr soll eigentlich nur in einem kleine und flache Holzkiste passen. Also diese erstmal gebaut. Zwei Platten für die Vorder- und Rückwand und dann noch kleine Leisten für den Rahmen rundrum. Die Kiste ist knapp 12x12cm groß. In eine der Platten habe ich kleine Löcher gebohrt, die LEDs können dann später dahinter angebracht werden, damit wir das Raster bekommen.

Die Elektronik ist sehr einfach. Dabei muss nur der LED streifen passend geschnitten und gelötet werden (schlangenlinienförmig). Der Anfang kommt dann an den WeMos (GDN -> G, 5V -> VCC, Di -> D2). Für die Stromversorgung kann man entweder direkt ein USB-Kabel an den WeMos stecken, oder man hat noch ein altes Kabel mit Netzteil (5V, ca. 500mA), welches man direkt an dem WeMos lötet. Der Einfachkeit halber, habe ich dem WeMos auf keine Platine gesetzt, sondern kleine Kabel an den Pins angebracht.

Als die Elektronik fertig war, konnte alles montiert und getestet werden. Hierbei habe ich die LEDs mit Klebeband an der vorderen Platte gesichert und noch eine kleine Kabeldurchführung in eine Seite für das Stomkabel eingesägt. Jetzt kann programmiert werden. Danach habe ich die Uhr noch mit einer Schicht weißem Papier beklebt: einfach damit sie noch etwas schlichter ist.

Hier der Code für dem WeMos mit Api im lokalen Netzwerk:

Der Code ist sehr einfach. Tatsächlich besteht die Binär-Codierung nur aus Abfragen/Verzeigungen

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Adafruit_NeoPixel.h>

#define DISPLAY_PIN D2
#define NUM_PIXELS 16
#define DELAY_VALUE_IDLE 2000
#define DELAY_VALUE_CONNECTING 100

Adafruit_NeoPixel pixels(NUM_PIXELS, DISPLAY_PIN, NEO_GRB + NEO_KHZ800);
ESP8266WiFiMulti WiFiMulti;

int backgroundRed = 7;
int backgroundGreen = 1;
int backgroundBlue = 25;
int displayRed = 255;
int displayGreen = 150;
int displayBlue = 12;

void setup() {
  Serial.begin(115200);
  pixels.begin();
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("SSID", "PASSWORD");
}

void loop() {
  if ((WiFiMulti.run() == WL_CONNECTED)) { //Display time
    displayTime(getHours(), getMinutes());
    delay(DELAY_VALUE_IDLE);
  } else { //Waiting connect to WiFi
    Serial.print("."); 
    for (int i = 0; i < NUM_PIXELS; i++) {
      int r = random(0, 255);
      pixels.setPixelColor(i, pixels.Color(r, 10, 40));
    }
    pixels.show();
    delay(DELAY_VALUE_CONNECTING);
  }
}

void displayTime(int hours, int minutes) {
  setBackgroundColor();

  int h1 = hours / 10;
  int h2 = hours - h1 * 10;
  int m1 = minutes / 10;
  int m2 = minutes - m1 * 10;

  if (h1 == 1) {
    updatePixels(0, 0);
  } else if (h1 == 2) {
    updatePixels(1, 1);
  }

  if (h2 == 1) {
    updatePixels(7, 7);
  } else if (h2 == 2) {
    updatePixels(6, 6);
  } else if (h2 == 3) {
    updatePixels(6, 7);
  } else if (h2 == 4) {
    updatePixels(5, 5);
  } else if (h2 == 5) {
    updatePixels(5, 5);
    updatePixels(7, 7);
  } else if (h2 == 6) {
    updatePixels(5, 6);
  } else if (h2 == 7) {
    updatePixels(5, 7);
  } else if (h2 == 8) {
    updatePixels(4, 4);
  } else if (h2 == 9) {
    updatePixels(4, 4);
    updatePixels(7, 7);
  }

  if (m1 == 1) {
    updatePixels(8, 8);
  } else if (m1 == 2) {
    updatePixels(9, 9);
  } else if (m1 == 3) {
    updatePixels(8, 9);
  } else if (m1 == 4) {
    updatePixels(10, 10);
  } else if (m1 == 5) {
    updatePixels(10, 10);
    updatePixels(8, 8);
  }

  if (m2 == 1) {
    updatePixels(15, 15);
  } else if (m2 == 2) {
    updatePixels(14, 14);
  } else if (m2 == 3) {
    updatePixels(14, 15);
  } else if (m2 == 4) {
    updatePixels(13, 13);
  } else if (m2 == 5) {
    updatePixels(13, 13);
    updatePixels(15, 15);
  } else if (m2 == 6) {
    updatePixels(13, 14);
  } else if (m2 == 7) {
    updatePixels(13, 15);
  } else if (m2 == 8) {
    updatePixels(12, 12);
  } else if (m2 == 9) {
    updatePixels(12, 12);
    updatePixels(15, 15);
  }

  pixels.show();
}

void updatePixels(int min, int max) {
  for (int i = min; i <= max; i++) {
    Pixels.setPixelColor(i, displayRed, displayGreen, displayBlue);
  }
}

void setBackgroundColor() {
  Pixels.clear();
  for (int i = 0; i < NUM_LEDS; i++) {
    Pixels.setPixelColor(i, backgroundRed, backgroundGreen, backgroundBlue);
  }
}

int getHours() {
  WiFiClient client;
  HTTPClient http;
  if (http.begin(client, "http://192.168.0.1/stunden.php")) {
    int httpCode = http.GET();
    if (httpCode > 0) {
      if (httpCode == HTTP_CODE_OK) {
        String payload = http.getString();
        Serial.println("[HTTP][getHours()] GET successfull");
        http.end();
        return payload.toInt();
      }
    } else {
      Serial.printf("[HTTP][getHours()] GET failed, error: %s\n", http.errorToString(httpCode).c_str());
      http.end();
      return -1;
    }
  } else {
    Serial.println("[HTTP][getHours()] Unable to connect");
    return -1;
  }
}

int getMinutes() {
  WiFiClient client;
  HTTPClient http;
  if (http.begin(client, http://192.168.0.1/minuten.php")) {
    int httpCode = http.GET();
    if (httpCode > 0) {
      if (httpCode == HTTP_CODE_OK) {
        String payload = http.getString();
        Serial.println("[HTTP][getMinutes()] GET successfull");
        http.end();
        return payload.toInt();
      }
    } else {
      Serial.printf("[HTTP][getMinutes()] GET failed, error: %s\n",  http.errorToString(httpCode).c_str());
      http.end();
      return -1;
    }
  } else {
    Serial.println("[HTTP][getMinutes()] Unable to connect");
    return -1;
  }
}

Die Api:

<?php
  //stunden.php
  $timestamp = time();
  $datum = date("H", $timestamp);
  echo $datum;
?>

<?php
  //minuten.php
  $timestamp = time();
  $datum = date("i", $timestamp);
  echo $datum;
?>

Oder hier der Code/Schaltung für einen Arduino mit RealTimeClock (I2C-Verbindung):

In diesem Fall wurde in ein einer weiteren Version ein Arduino Pro Micro / Leonardo und die DS3231-RTC verwendet.

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

#define LED_PIN 10
#define NUM_LEDS 16

Adafruit_NeoPixel Pixels(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
DS3231 Clock;

int backgroundRed = 7;
int backgroundGreen = 1;
int backgroundBlue = 25;
int displayRed = 255;
int displayGreen = 150;
int displayBlue = 12;

bool h12;
bool PM;

void setup() {
  Wire.begin();
  Pixels.begin();
}

void loop() {

  int hours = Clock.getHour(h12, PM);
  int minutes = Clock.getMinute();
  int seconds = Clock.getSecond();
  displayTime(hours, minutes);
  int secondsToNextMinute = 60 - seconds; 
  delay(secondsToNextMinute * 1000L);
}

void displayTime(int hours, int minutes) {
  setBackgroundColor();

  int h1 = hours / 10;
  int h2 = hours - h1 * 10;
  int m1 = minutes / 10;
  int m2 = minutes - m1 * 10;
  
 if (h1 == 1) {
    updatePixels(0, 0);
  } else if (h1 == 2) {
    updatePixels(1, 1);
  }

  if (h2 == 1) {
    updatePixels(7, 7);
  } else if (h2 == 2) {
    updatePixels(6, 6);
  } else if (h2 == 3) {
    updatePixels(6, 7);
  } else if (h2 == 4) {
    updatePixels(5, 5);
  } else if (h2 == 5) {
    updatePixels(5, 5);
    updatePixels(7, 7);
  } else if (h2 == 6) {
    updatePixels(5, 6);
  } else if (h2 == 7) {
    updatePixels(5, 7);
  } else if (h2 == 8) {
    updatePixels(4, 4);
  } else if (h2 == 9) {
    updatePixels(4, 4);
    updatePixels(7, 7);
  }

  if (m1 == 1) {
    updatePixels(8, 8);
  } else if (m1 == 2) {
    updatePixels(9, 9);
  } else if (m1 == 3) {
    updatePixels(8, 9);
  } else if (m1 == 4) {
    updatePixels(10, 10);
  } else if (m1 == 5) {
    updatePixels(10, 10);
    updatePixels(8, 8);
  }

  if (m2 == 1) {
    updatePixels(15, 15);
  } else if (m2 == 2) {
    updatePixels(14, 14);
  } else if (m2 == 3) {
    updatePixels(14, 15);
  } else if (m2 == 4) {
    updatePixels(13, 13);
  } else if (m2 == 5) {
    updatePixels(13, 13);
    updatePixels(15, 15);
  } else if (m2 == 6) {
    updatePixels(13, 14);
  } else if (m2 == 7) {
    updatePixels(13, 15);
  } else if (m2 == 8) {
    updatePixels(12, 12);
  } else if (m2 == 9) {
    updatePixels(12, 12);
    updatePixels(15, 15);
  }
  
  Pixels.show();
}

void updatePixels(int min, int max) {
  for (int i = min; i <= max; i++) {
    Pixels.setPixelColor(i, displayRed, displayGreen, displayBlue);
  }
}

void setBackgroundColor() {
  Pixels.clear();
  for (int i = 0; i < NUM_LEDS; i++) {
    Pixels.setPixelColor(i, backgroundRed, backgroundGreen, backgroundBlue);
  }
}

3 Comments

Julius

Mai 5, 2020, 11:32 pm Antworten

Kann ich den kompletten Code copy-pasten xD

Vincent

Mai 5, 2020, 6:03 am Antworten

Na klar

Theo

Mai 5, 2020, 7:45 pm Antworten

Das sieht ja super aus, vielen Dank. Ich sitze gerade leider noch selbst an meinem ersten großen Projekt aber danach kann ich das ja mal vllt ausprobieren. Danke 🙂

Schreibe einen Kommentar