Hallo zusammen, ich würde gerne ein weiteres Projekt vorstellen.
Einer meiner Freunde hat nicht sonderlich viel Glück mit der Liebe, bei ihm muss ich deshalb immer an ein bestimmtes Bild denken.
Jetzt habe ich mich mal ans Werk gemacht und ihm eine solche Uhr als Einzugsgeschenk für seine neue Wohnung gebaut.
Diese Uhr ist ein toller Gag und Aufhänger für Gespräche, anbei findet ihr alles was ihr braucht um solch eine Uhr nachzubauen.
Materialliste:
Wemos D1 mini v3.0 (oder anderes ESP8266 / ESP32 Board)
TM1637 0,56" 7-Segment Anzeige (Grün)
DS3231 ZS-042 Modul
(Plexiglasscheibe)
(Autotönungsfolie)
Wenn ihr euch für eine andere Farbe beim 7-Segment Display entscheidet, dann solltet ihr eine Plexiglasscheibe mit Autotönungsfolie folieren, die Displays lassen sich sonst schon ab geringer Entfernung nicht mehr angenehm ablesen. Das sieht man auch wunderbar auf dem Foto, dieses habe ich mal bewusst ohne eine getönte Scheibe für euch aufgenommen.
Die Verkabelung:
TM1637:
CLK <-> GPIO 16 (Wemos D1 mini v3.0: D0)
DIO <-> GPIO 14 (Wemos D1 mini v3.0: D5)
GND <-> GND
5V <-> 5V
DS3231 (Unbedingt die Ladeschaltung deaktivieren, hierzu muss ein Widerstand entfernt werden!):
SCL <-> SCL Pin eures Boards (Wemos D1 mini v3.0: D1)
SDA <-> SDA Pin eures Boards (Wemos D1 mini v3.0: D2)
VCC <-> 3V3
GND <-> GND
Zum Sketch: Dieser ist sofort lauffähig auf ESP8266 Boards, bei ESP32 Boards muss allerdings die WiFi Bibliothek in #include <WiFi.h>
geändert werden. Zusätzlich muss die komplette Funktion bool getLocalTime
ausgeklammert werden.
/* Quellenangaben:
* DS3231 RTC - Zeit per NTP setzen und aus der RTC auslesen, 2019-07-21 Heiko (https://web.archive.org/web/20220804035404/https://unsinnsbasis.de/ds3231-rtc/)
* Funktion calculateoverhang: https://github.com/programminghoch10/HangoverClock/blob/master/app/src/main/java/com/JJ/hangoverclock/ClockGenerator.java
* Restlicher Sketch: https://forum.arduino.cc/t/projektvorstellung-die-hangover-clock/1211889
*/
#include <Wire.h>
#include "RTClib.h"
#include <ESP8266WiFi.h>
#include "time.h"
#include <sys/time.h>
#include <TM1637Display.h>
#define CLK_PIN 16
#define DIO_PIN 14
TM1637Display display(CLK_PIN, DIO_PIN); // Datenstruktur für Display
RTC_DS3231 rtc;
struct tm tdata; // lokale Zeit
const char* ssid = "Uhrzeit";
const char* password = "00000000";
const char* ntp_server = "de.pool.ntp.org"; // oder (de/at/ch).pool.ntp.org // fritz.box
// lokale Zeitzone definieren
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
#define TIMEZONE "CET-1CEST,M3.5.0/02,M10.5.0/03"
char days_of_week[7][11] = {"Sonntag", "Montag", "Dienstag", "Mittwoch",
"Donnerstag", "Freitag", "Samstag"};
int twelvehoursnumber = 24;
int minuteoverhang = 40;
int houroverhang = 0;
bool firstloop = true;
const uint8_t conn[] = {
SEG_D | SEG_E | SEG_G, // c
SEG_C | SEG_D | SEG_E | SEG_G, // o
SEG_C | SEG_E | SEG_G, // n
SEG_C | SEG_E | SEG_G // n
};
bool getLocalTime(struct tm * info, uint32_t ms = 5000)
{
uint32_t start = millis();
time_t now;
while((millis()-start) <= ms) {
time(&now);
localtime_r(&now, info);
if(info->tm_year > (2016 - 1900)){
return true;
}
delay(10);
}
return false;
}
void setup () {
DateTime now;
timeval tv;
int rc;
Serial.begin(115200);
display.setBrightness(3);
delay(500);
if (! rtc.begin()) {
Serial.println("Keine Echtzeituhr gefunden!");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC wird neu gestellt");
// mit dem WLAN verbinden; nach Ermitteln der Zeit kann die
// Verbindung wieder getrennt werden
Serial.printf("Verbindung herstellen mit %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
display.setSegments(conn);
delay(500);
Serial.print(".");
}
Serial.println(" Verbunden!");
delay(1000);
// Zeit vom NTP-Server holen
configTime(0, 0, ntp_server);
// vor Trennung des WLANs einmal getLocalTime() aufrufen
getLocalTime(&tdata);
setenv("TZ", TIMEZONE, 1); // Zeitzone einstellen
// WLAN trennen
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
// RTC anhand der Systemzeit stellen
rtc.adjust(time(NULL));
} else {
// (System-)Zeit aus der RTC übernehmen
now = rtc.now();
tv.tv_sec = now.unixtime();
tv.tv_usec = 0; // keine Mikrosekunden setzen
rc = settimeofday(&tv, NULL); // NULL = keine Zeitzoneninfo an dieser Stelle ...
setenv("TZ", TIMEZONE, 1); // ... sondern hier: Zeitzone einstellen
Serial.printf("Returncode beim Setzen der Systemzeit nach der RTC: %d\n\n", rc);
}
}
void loop () {
DateTime now = rtc.now();
if (firstloop == true) {
Serial.printf("RTC Unix-Zeit - Datum TT.MM.JJJJ und Zeit: %s %02d.%02d.%d %02d:%02d:%02d\n",
days_of_week[now.dayOfTheWeek()],
now.day(), now.month(), now.year(),
now.hour(), now.minute(), now.second());
Serial.printf("RTC Unix-Zeit seit 1.1.1970 - %d Sekunden bzw. %d Tage\n",
now.unixtime(), now.unixtime() / 86400L);
}
getLocalTime(&tdata);
if (firstloop == true) {
Serial.printf("Systemzeit: time() = %d\n", time(NULL));
Serial.printf("Lokale Uhrzeit (aus Systemzeit): %02d:%02d:%02d\n",
tdata.tm_hour, tdata.tm_min, tdata.tm_sec);
Serial.printf("RTC-Temperatur: %2.1f °C\n\n",
rtc.getTemperature());
//delay(10000);
}
calculateoverhang(tdata.tm_hour, tdata.tm_min);
delay(1000);
}
void calculateoverhang(int h, int m) {
if (minuteoverhang % 60 > m) m += 60;
m += (minuteoverhang / 60) * 60;
h -= (m / 60) % twelvehoursnumber;
if (houroverhang % twelvehoursnumber > h) h += twelvehoursnumber;
h += (houroverhang / twelvehoursnumber) * twelvehoursnumber;
if (firstloop == true) {
Serial.println();
Serial.print(h);
Serial.print(":");
Serial.println(m);
firstloop = false;
}
display.showNumberDecEx((h)*100 + m, 0b01000000, true);
}
Beim ersten Start solltet ihr "conn" auf dem Display sehen, das bedeutet, dass keine Uhrzeit auf dem DS3231 Modul gespeichert ist. Aktiviert also einen Hotspot mit eurem Handy mit der SSID "Uhrzeit" und acht nullen "00000000" als Passwort. Das Board zieht sich dann die Uhrzeit von einem Zeitserver.
Die Uhrzeit geht dann anschließend immer bis XX:99 und schlägt dann auf XX:40 um. Dabei kann man die Uhrzeit aber immer ablesen, 15:98 ist dementsprechend 16:38.
Wenn jemand die Uhr nachgebaut hat, poste doch gerne ein Foto in den Thread!
PS: Verpasst eure Termine nicht.