Einleitung
Schon einmal eine Echtzeituhr (RTC) zu deinem Projekt hinzufügen wollen, aber die Hardware nicht zur Hand gehabt? Mit Velxio kannst du einen kompletten I2C-RTC-Auslesevorgang mit einem Raspberry Pi Pico und einer virtuellen DS1307 simulieren – alles in deinem Browser. In diesem Tutorial gehen wir die Schaltung, den Code und die wichtigsten Konzepte durch, damit du I2C-Kommunikation sicher in deinen eigenen Projekten einsetzen kannst.
Schaltungsaufbau
Beginnen wir mit einem Blick auf die Schaltung. Öffne das Beispiel in Velxio und du siehst die folgenden Komponenten:

Die Schaltung ist einfach: Ein Raspberry Pi Pico (nano-rp2040) ist mit zwei LEDs und einer virtuellen DS1307 RTC verbunden (nicht als separates Bauteil dargestellt – die RTC ist in die Simulation integriert). Die LEDs dienen als visuelle Indikatoren für die I2C-Aktivität.
- LED (blau): Verbunden mit Pin D12 (SDA-Leitung) über ein blaues Kabel. Ihre Anode (A) ist mit D12 verbunden, die Kathode (C) geht über ein schwarzes Kabel zu GND.1.
- LED (gelb): Verbunden mit Pin D10 (SCL-Leitung) über ein orangefarbenes Kabel. Ihre Anode (A) ist mit D10 verbunden, die Kathode (C) geht über ein schwarzes Kabel zu GND.1.
Beide LEDs teilen sich die gleiche Masse (GND.1). Der I2C-Bus besteht aus den Leitungen SDA (Daten) und SCL (Takt). Die DS1307 RTC ist intern mit diesen Leitungen unter der Adresse 0x68 verbunden. Die LEDs sind für die I2C-Kommunikation nicht zwingend erforderlich, geben aber einen visuellen Hinweis darauf, dass die Leitungen umschalten.
Um diese Schaltung selbst aufzubauen, kannst du die Velxio-Komponentenauswahl verwenden:

Suche nach “Raspberry Pi Pico” und “LED” und verdrahte sie wie beschrieben. Die Leinwand-Symbolleiste hilft dir beim Zoomen und Anordnen der Komponenten:

Code-Erklärung
Jetzt tauchen wir in den Code ein. Der Sketch verwendet die Wire-Bibliothek (vorinstalliert), um mit der DS1307 über I2C zu kommunizieren. Hier ist der vollständige Code:
// Raspberry Pi Pico — I2C DS1307 RTC Read
// Reads time from virtual RTC at address 0x68
#include <Wire.h>
byte bcdToDec(byte val) {
return ((val >> 4) * 10) + (val & 0x0F);
}
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin();
Serial.println("=== Pico I2C RTC Read ===");
Serial.println("Reading DS1307 at 0x68 (system time)");
Serial.println();
}
void loop() {
// Set register pointer to 0
Wire.beginTransmission(0x68);
Wire.write(0x00);
Wire.endTransmission();
// Read 7 bytes: sec, min, hr, dow, date, month, year
Wire.requestFrom(0x68, 7);
if (Wire.available() >= 7) {
byte sec = bcdToDec(Wire.read() & 0x7F);
byte min = bcdToDec(Wire.read());
byte hr = bcdToDec(Wire.read() & 0x3F);
byte dow = bcdToDec(Wire.read());
byte date = bcdToDec(Wire.read());
byte month = bcdToDec(Wire.read());
byte year = bcdToDec(Wire.read());
const char* days[] = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
Serial.print("Time: ");
if (hr < 10) Serial.print('0'); Serial.print(hr); Serial.print(':');
if (min < 10) Serial.print('0'); Serial.print(min); Serial.print(':');
if (sec < 10) Serial.print('0'); Serial.print(sec);
Serial.print(" Date: ");
Serial.print(days[dow]); Serial.print(' ');
if (date < 10) Serial.print('0'); Serial.print(date); Serial.print('/');
if (month < 10) Serial.print('0'); Serial.print(month); Serial.print('/');
Serial.print("20"); if (year < 10) Serial.print('0'); Serial.println(year);
} else {
Serial.println("RTC not responding!");
}
delay(1000);
}
Wie es funktioniert
-
Setup: Wir starten die serielle Kommunikation mit 115200 Baud und initialisieren den I2C-Bus mit
Wire.begin(). Die DS1307 hat die Adresse 0x68. -
Loop: Jede Sekunde führen wir folgende Schritte aus:
- Sende einen
beginTransmissionan Adresse 0x68, schreibe 0x00 (den Registerzeiger auf das Sekundenregister) und führeendTransmissionaus. - Fordere 7 Bytes von der RTC an mit
Wire.requestFrom(0x68, 7). - Lese jedes Byte und konvertiere es mit der Hilfsfunktion
bcdToDecvon BCD (Binary-Coded Decimal) in Dezimal. - Formatiere und gib die Uhrzeit und das Datum im seriellen Monitor aus.
- Sende einen
-
BCD-Konvertierung: Die DS1307 speichert Zeitwerte im BCD-Format. Zum Beispiel repräsentiert das Byte
0x45die 45 in BCD (4*10 + 5 = 45). Die FunktionbcdToDecextrahiert die Zehnerstelle (hohes Nibble) und die Einerstelle (niedriges Nibble) und kombiniert sie. -
Maskierung: Wir wenden Masken auf bestimmte Register an:
- Sekunden:
& 0x7Flöscht das CH-Bit (Clock Halt). - Stunden:
& 0x3Flöscht das Bit für den 12/24-Stunden-Modus (unter Annahme des 24-Stunden-Modus).
- Sekunden:
Wichtige Konzepte
- I2C-Protokoll: Ein serieller Zweidraht-Bus (SDA, SCL) für die Kommunikation zwischen Mikrocontrollern und Peripheriegeräten. Jedes Gerät hat eine eindeutige Adresse.
- Wire-Bibliothek: Die in Arduino integrierte I2C-Bibliothek. Verwende
Wire.begin(), um dem Bus beizutreten,Wire.beginTransmission(addr), um mit einem Gerät zu sprechen,Wire.write(), um Daten zu senden,Wire.endTransmission(), um abzuschließen, undWire.requestFrom(addr, count), um Bytes zu lesen. - BCD-Format: Viele RTCs verwenden BCD, um die Anzeige zu vereinfachen. Du musst für die menschenlesbare Ausgabe in Dezimal umwandeln.
- Registerbelegung: Die DS1307 hat eine spezifische Registerkarte: Sekunden (0x00), Minuten (0x01), Stunden (0x02), Wochentag (0x03), Datum (0x04), Monat (0x05), Jahr (0x06).
Häufige Fehler & Debugging-Tipps
- Falsche I2C-Adresse: Überprüfe die Geräteadresse. Die DS1307 ist normalerweise 0x68 (7-Bit). Wenn “RTC not responding!” erscheint, überprüfe die Adresse.
- Fehlende Pull-up-Widerstände: In echter Hardware benötigen I2C-Leitungen Pull-up-Widerstände. In Velxio werden sie intern simuliert, du musst sie also nicht hinzufügen.
- Falsche Baudrate: Stelle sicher, dass die Baudrate des seriellen Monitors 115200 entspricht.
- Registerzeiger nicht gesetzt: Setze immer den Registerzeiger vor dem Lesen. Der Code schreibt 0x00, um auf das Sekundenregister zu zeigen.
- Maskierungsfehler: Das Vergessen, das CH-Bit (Sekunden) oder das 12/24-Stunden-Bit (Stunden) zu maskieren, kann falsche Werte liefern.
Vorschläge für Erweiterungen
- Zeit einstellen: Füge Code hinzu, um die aktuelle Zeit in die RTC zu schreiben. Verwende
Wire.write(), um jedes Register zu setzen. - Alarmfunktion: Implementiere einen Alarm, der eine LED auslöst, wenn eine bestimmte Zeit erreicht ist.
- Anzeige auf LCD: Verwende ein I2C-LCD, um die Zeit anstelle des seriellen Monitors anzuzeigen.
- Mehrere RTCs: Versuche, von zwei verschiedenen I2C-Geräten auf demselben Bus zu lesen.
Probier es selbst aus!
Bereit zum Experimentieren? Öffne das Live-Beispiel in Velxio und starte die Simulation. Du siehst die Zeit jede Sekunde im seriellen Monitor ausgegeben. Ändere den Code, um das Aktualisierungsintervall anzupassen oder neue Funktionen hinzuzufügen.
Starte das Pico I2C RTC Read Beispiel
Viel Spaß beim Simulieren!