eDOT: Präzise Arduino-Uhr & Wetterstation mit IR-Fernbedienung
Komponenten und Zubehör
| ATmega328P-PU (Mikrocontroller) | × | 1 |
| MAX7219 LED-Matrix-Treiber | × | 6 |
| BME280 (GY-BMEP Breakout) – Temp, Feuchte, Druck | × | 1 |
| 8×8 LED-Dot-Matrix (Luckylight M1603095, weiß) | × | 6 |
| DS3231 RTC (Echtzeituhr, hochpräzise) | × | 1 |
| Arduino Nano R3 (für Programmierung/Tests) | × | 1 |
| Arduino UNO (Alternative) | × | 1 |
| eDOTcore PCB (eigene Steuerplatine) | × | 1 |
Benötigte Werkzeuge & Maschinen
- 3D-Drucker (Flashforge Dreamer) für Gehäuseteile
Apps und Online-Dienste
- Arduino IDE
Projektbeschreibung
eDOT
eDOT ist eine Arduino-basierte Präzisionsuhr und Wetterstation mit integriertem IR-Empfänger und automatischer Helligkeitsanpassung. Sechs 8×8 LED-Matrix-Displays (insgesamt 48×8 Pixel) zeigen Uhrzeit, Datum, Wochentag, Temperatur, Luftfeuchte und Luftdruck an – wahlweise auch Scrolltexte oder zukünftig Daten per WLAN (RSS, API).
Merkmale:
- Sehr niedriger Stromverbrauch
- Elegantes Design: Glasfront + 3D-gedruckter Korpus
- Modular erweiterbar (WLAN-Modul, weitere Sensoren)
- Automatische Display-Helligkeit per LDR
- IR-Fernbedienung für Bedienung
3D-Druckdateien auf Thingiverse | YouTube-Kanal: UCbIomyFKzBiLHqEb2xv9GHQ
Stückliste (B.O.M.)
- 1× 3D-gedrucktes linkes Gehäusehälfte
- 1× 3D-gedrucktes rechtes Gehäusehälfte
- 1× 3D-gedruckter linker Deckel
- 1× 3D-gedruckter rechter Deckel
- 2× 3D-gedruckte Füße
- 12× 3D-gedruckte Display-Halterungen
- 1× Poliertes Glas 240×75×5 mm
- 1× Orangefarbener Filter (für LED-Display)
- 6× Adafruit 8×8 Dot-Matrix (Luckylight M1603095, weiß)
- 6× MAX7219 Treiberplatine
- 1× USB-Breakout-Board (Stromversorgung)
- 1× BME280 Breakout
- 1× DS3231 Chip
- 1× IR-Empfänger (IRM-56384)
- 1× Fotowiderstand (LDR-07)
- 1× ATmega328P-PU (auf eDOTcore PCB)
- 6× Omron 12 mm Taster
eDOTcore PCB
Die erste Prototypen-Platine der Steuerung ist eingetroffen. Sie bündelt alle Anschlüsse (Matrix-Treiber, Sensoren, IR, Buttons, Strom) auf einer kompakten Platine.
Projektseite: eDOTcore
Quellcode (Arduino)
// eDOT: Versatile precision weather station and clock
// HISTORY
// 11/12/2015 Added measurement calibration coefficients
// 09/06/2016 Added automatic display brightness
// 09/06/2016 Added task scheduler
// 07/08/2016 Added eDOT splashscreen
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <Average.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "RTClib.h"
#include <EasyScheduler.h>
Adafruit_BME280 bme; // I2C
RTC_DS3231 rtc;
int pinCS = 10; // CS an Pin 10, DIN an MOSI, CLK an SCK (SPI)
int numberOfHorizontalDisplays = 7; // 6 Matrix + 1 Reserve?
int numberOfVerticalDisplays = 1;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
#define TEMPERATURE 0
#define HUMIDITY 1
#define PRESSURE 2
#define TIME 3
#define DAY 4
#define DATE 5
float temp, tempavg; char tempf[8];
float hum, humavg; char humf[8];
float press, pressavg; char pressf[8];
int screen = 0;
long previousLEDMillis = 0;
long LEDInterval = 5000; // 5 s pro Anzeige
int screenMax = 5;
bool screenChanged = true;
float lightsens, screenBrt = 0, lightsensavg;
Average<float> avetemp(60);
Average<float> avehum(60);
Average<float> avepress(60);
Average<float> avelightsens(40);
// Kalibrierungskoeffizienten
float temp_o = -1.70, temp_s = 1.0, temp_lin;
float hum_o = 2.45, hum_s = 1.0, hum_lin;
float press_o = 0.0, press_s = 1.0, press_lin;
float brt_o = -4, brt_s = 1.35;
Schedular Task1;
Schedular Task2;
void setup() {
Task1.start(); Task2.start();
Wire.begin();
bme.begin(0x76);
matrix.setIntensity(screenBrt); // 0-15
// Display-Orientierung justieren (je nach Einbau)
for (int i = 0; i < 8; i++) matrix.setRotation(i, 1);
rtc.begin();
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Einmalig Zeit setzen
// eDOT Splashscreen mit Fade-in/out
matrix.fillScreen(0); matrix.write();
matrix.setCursor(12,0); matrix.print("eDOT");
for(screenBrt=0; screenBrt<=15; screenBrt++){ delay(25); matrix.setIntensity(screenBrt); matrix.write(); }
delay(250);
for(screenBrt=15; screenBrt>=0; screenBrt--){ delay(50); matrix.setIntensity(screenBrt); matrix.write(); }
delay(500);
matrix.fillScreen(0); matrix.write();
delay(1000);
}
void loop() {
Task1.check(acq1, 500); // Sensoren alle 500 ms
Task2.check(acq2, 20); // Helligkeit alle 20 ms
}
void acq1() {
// Sensoren lesen & mitteln
temp = bme.readTemperature(); avetemp.push(temp); tempavg = avetemp.mean();
hum = bme.readHumidity(); avehum.push(hum); humavg = avehum.mean();
press = bme.readPressure(); avepress.push(press); pressavg = avepress.mean();
DateTime now = rtc.now();
outSec = now.second(); outMin = now.minute(); outHour = now.hour();
outday = now.day(); outmonth = now.month(); outyear = now.year() - 2000;
dow = now.dayOfTheWeek();
}
void acq2() {
// Helligkeitssensor glätten & Display-Helligkeit setzen
lightsens = analogRead(A3);
avelightsens.push(lightsens);
lightsensavg = avelightsens.mean();
screenBrt = constrain(((lightsensavg / 1023.0 * 15) * brt_s + brt_o), 0, 15);
matrix.setIntensity(screenBrt);
// Linearisierung mit Kalibrierung
temp_lin = tempavg * temp_s + temp_o;
hum_lin = humavg * hum_s + hum_o;
press_lin = pressavg * press_s + press_o;
// Bildschirmwechsel alle 5 s
unsigned long currentLEDMillis = millis();
if (currentLEDMillis - previousLEDMillis > LEDInterval) {
previousLEDMillis = currentLEDMillis;
screen++; if (screen > screenMax) screen = 0;
screenChanged = true;
}
if (screenChanged) {
screenChanged = false;
matrix.fillScreen(0);
switch(screen) {
case TEMPERATURE:
dtostrf(temp_lin, 4, 2, tempf);
matrix.setCursor(6,0); matrix.setTextSize(1); matrix.setTextColor(255);
matrix.print(tempf); matrix.drawRect(37,0,2,2,255); matrix.print("C");
break;
case HUMIDITY:
dtostrf(hum_lin, 4, 2, humf);
matrix.setCursor(6,0); matrix.setTextSize(1); matrix.setTextColor(255);
matrix.print(humf); matrix.print("%");
break;
case PRESSURE:
dtostrf(press_lin, 6, 0, pressf);
matrix.setCursor(0,0); matrix.setTextSize(1); matrix.setTextColor(255);
matrix.print(pressf); matrix.print("Pa");
break;
case TIME:
matrix.setCursor(0,0); matrix.setTextSize(1); matrix.setTextColor(255);
if (outHour < 10) matrix.print("0");
matrix.print(outHour); matrix.print(":");
if (outMin < 10) matrix.print("0");
matrix.print(outMin); matrix.print(":");
if (outSec < 10) matrix.print("0");
matrix.print(outSec);
break;
case DATE:
matrix.setCursor(0,0); matrix.setTextSize(1); matrix.setTextColor(255);
if (outday < 10) matrix.print("0");
matrix.print(outday); matrix.print("/");
if (outmonth < 10) matrix.print("0");
matrix.print(outmonth); matrix.print("/");
matrix.print(outyear);
break;
case DAY:
matrix.setCursor(15,0); matrix.setTextSize(1); matrix.setTextColor(255);
matrix.print(daysOfTheWeek[dow]);
break;
}
matrix.write();
}
}
Hinweis: Der Code nutzt Bibliotheken Max72xxPanel, Average, EasyScheduler, Adafruit_BME280, RTClib. Diese vorab über Bibliotheksverwalter installieren.
Herstellungsprozess
- DIY Solar-betriebene Wetterstation mit Raspberry Pi
- Outdoor-Wetterstation mit Raspberry Pi 2 & ADS-WS1 bauen
- Fortgeschrittene Wetterstation v2.0: Echtzeit Temperatur, Druck, Feuchte & Höhe Monitoring
- Arduino POV-Uhr: Persistence-of-Vision LED-Display selbst bauen
- Einen eigenen LED-Master-Clock mit Alarm bauen – aus 12 Metern Entfernung ablesbar
- Arduino Temperaturoverwachung & Echtzeituhr mit 3,2″ TFT-Display
- Tragbare Arduino-Wetterstation für 10$ bauen (Nano, DHT22, BMP180 & LCD)
- Echtzeit-Zelluläre Automaten auf Arduino mit 128x64 OLED-Display
- Wetterstation mit Arduino & ThingSpeak IoT (DHT11 + ESP8266)
- Echtzeit-RFID-Anwesenheitssystem mit Arduino & Google Tabellen