Mit einem Arduino und einem Real Time Clock Modul DS3231, eine kleine Uhr erstellen. Als Anzeige wird ein LCD1602-Modul verwendet. Die Helligkeitsregelung wird ein 10KΩ Potentiometer übernehmen.
Das Modul ist mit Speicher und einer Batterie ausgestattet. So verliert es, auch bei Stromausfall, nicht die eingestellte Uhrzeit. Besonders präzise ist diese Uhr aber nicht. Es kann pro Jahr zu mehrere Minuten Abweichungen kommen.
Angeschlossen wird es über den I2C-Bus und benötigt 5 Volt Spannung.
Es gibt weiter unten, bereits zwei weitere überarbeitete Versionen.
Hardware:
Elegoo Mega 2560
DS3231 RTC AT24C32 Echtzeit-Uhrenmodul für Arduino und Raspberry Pi
LCD1602-Modul Display 2×16 Zeichen
Quellcode:
#include <LiquidCrystal.h>
#include <Wire.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
void setup()
{
Wire.begin();
Serial.begin(9600);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Datum:");
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
// sets time and date data to DS3231
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(second)); // set seconds
Wire.write(decToBcd(minute)); // set minutes
Wire.write(decToBcd(hour)); // set hours
Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
Wire.write(decToBcd(month)); // set month
Wire.write(decToBcd(year)); // set year (0 to 99)
Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void displayTime()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// retrieve data from DS3231
readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
&year);
// send it to the serial monitor
Serial.print(hour, DEC);
// convert the byte variable to a decimal number when displayed
Serial.print(":");
if (minute<10)
{
Serial.print("0");
}
Serial.print(minute, DEC);
Serial.print(":");
if (second<10)
{
Serial.print("0");
}
Serial.print(second, DEC);
Serial.print(" ");
Serial.print(dayOfMonth, DEC);
Serial.print("/");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(year, DEC);
Serial.print(" Day of week: ");
switch(dayOfWeek){
case 1:
Serial.println("Sunday");
break;
case 2:
Serial.println("Monday");
break;
case 3:
Serial.println("Tuesday");
break;
case 4:
Serial.println("Wednesday");
break;
case 5:
Serial.println("Thursday");
break;
case 6:
Serial.println("Friday");
break;
case 7:
Serial.println("Saturday");
break;
}
{
lcd.setCursor(7, 0);
lcd.print(dayOfMonth);
lcd.print(":");
lcd.print(month);
lcd.print(":");
lcd.print(year);
lcd.setCursor(0, 1);
lcd.print("Uhr: ");
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)
{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
// set up the LCD's number of columns and rows:
//lcd.begin(0, 1);
// Print a message to the LCD.
}
}
void loop()
{
displayTime(); // display the real-time clock data on the Serial Monitor,
delay(1000); // every second
}
Datenblatt:
DS3231.pdf (maximintegrated.com)
Überarbeitete vereinfachte Version:
Damit die Verdrahtung deutlich einfacher wird, werden die LCD-Displayˋs zukünftig mit einem I2C-Adapter verlötet. Somit braucht man nur noch zwei Stromversorgungsanschlüsse und zwei für die Seriellen Datenübertragung an A4 + A5. Die Helligkeit kann mit einem Potentiometer auf der Rückseite des I2C-Adapter eingestellt werden.
Hardware zusätzlich:
LCM 1602 IIC für LCD Display 1602 und 2004
oder
LCD incl i2c Adapter
Library:
Dieser Code verwendet die Bibliotheken RTClib.h und LiquidCrystal_I2C.h, um die RTC und das LCD-Display über I2C zu initialisieren und zu steuern. In der Setup-Funktion wird die RTC initialisiert und die aktuelle Zeit und das Datum auf die RTC gesetzt. In der Loop-Funktion wird die aktuelle Zeit und das Datum von der RTC gelesen und auf dem LCD-Display angezeigt.
RTClib
LiquidCrystal_I2C
Quellcode:
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
//Initialisiere RTC
RTC_DS3231 rtc;
// Initialisiere das LCD-Display
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
// Initialisiere das LCD-Display
lcd.init();
// Aktiviere das Backlight des LCD-Displays
lcd.backlight();
// Überprüfe, ob die RTC korrekt funktioniert
if (! rtc.begin()) {
lcd.print("RTC konnte nicht gefunden werden!");
while (1);
}
// Setze die Zeit der RTC
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
void loop() {
// Lese die aktuelle Zeit von der RTC aus
DateTime now = rtc.now();
// Formatiere Datum und Uhrzeit
char buffer[20];
sprintf(buffer, "%02d.%02d.%04d", now.day(), now.month(), now.year());
String dateStr = String(buffer);
sprintf(buffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
String timeStr = String(buffer);
// Schreibe Datum und Uhrzeit auf das LCD-Display
lcd.setCursor(0, 0);
lcd.print(dateStr);
lcd.setCursor(0, 1);
lcd.print(timeStr);
// Warte eine Sekunde und aktualisiere das Display
delay(1000);
lcd.clear();
}
Weitere Version mit 4 Zeilen LCD und Temperaturanzeige:
Da der RTC DS3231 auch einen Temperatursensor mitbringt, liegt es nahe, diese Information in einer Weiteren Zeile anzuzeigen. Somit wird das 2 Zeilen LCD durch einen 4 Zeilen ersetzt. Verdrahtung bleibt unverändert zur vorherigen Version.
Temperaturanzeige von 0 bis +70 ℃
Neue Hardware:
LCD2004 incl I2C
Quellcode:
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 4);
void setup() {
Wire.begin();
rtc.begin();
lcd.init();
lcd.backlight();
rtc.adjust(DateTime(__DATE__, __TIME__));
}
void loop() {
DateTime now = rtc.now();
float temperature = rtc.getTemperature();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Date: ");
lcd.print(now.day(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.year(), DEC);
lcd.setCursor(0,1);
lcd.print("Time: ");
lcd.print(now.hour(), DEC);
lcd.print(':');
lcd.print(now.minute(), DEC);
lcd.print(':');
lcd.print(now.second(), DEC);
lcd.setCursor(0,2);
lcd.print("Temp: ");
lcd.print(temperature, 2);
lcd.print("C");
delay(1000);
}