#include <Wire.h>
#include <RTClib.h>
RTC_DS1307 rtc;
// Shift Register Pins
const uint8_t dataPin = 8; // D1 (GPIO8)
const uint8_t clockPin = 9; // D2 (GPIO9)
const uint8_t latchPin = 10; // D3 (GPIO10)
static uint8_t digits[6];
// Segment patterns (Common Cathode: 1=ON, 0=OFF)
const byte digitPattern[10] = {
B11111100, // 0 (A-F on, G/DP off)
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B10111110, // 6
B11100000, // 7
B11111110, // 8
B11110110 // 9
};
void setup() {
Serial.begin(9600);
// Initialize Shift Register Pins
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
// Initialize RTC
Wire.begin();
if (!rtc.begin()) {
while (1); // Halt if RTC not found
}
if (!rtc.isrunning()) {
// Set to compile time if RTC not running
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
static uint32_t lastUpdate = 0;
static uint8_t currentDigit = 0;
// Update time every second
if (millis() - lastUpdate >= 1000) {
DateTime now = rtc.now();
digits[0] = now.hour() / 10; // Hour tens
digits[1] = now.hour() % 10; // Hour ones
digits[2] = now.minute() / 10; // Minute tens
digits[3] = now.minute() % 10; // Minute ones
digits[4] = now.second() / 10; // Second tens
digits[5] = now.second() % 10; // Second ones
lastUpdate = millis();
// Serial debug output
Serial.printf("Time: %02d:%02d:%02d\n",
now.hour(), now.minute(), now.second());
}
// Multiplex digits (100Hz refresh)
if (millis() % 2 == 0) { // Update every 2ms
updateDisplay(currentDigit, digits[currentDigit]);
delay(2);
currentDigit = (currentDigit + 1) % 6;
}
}
void updateDisplay(uint8_t digitPos, uint8_t value) {
// Active-LOW digit control (common cathode)
byte digitByte = ~(1 << digitPos); // Invert to make active digit LOW
// Get segment pattern
byte segByte = digitPattern[value];
digitalWrite(latchPin, HIGH);
shiftOut(dataPin, clockPin, MSBFIRST, digitByte); // Digits first
shiftOut(dataPin, clockPin, LSBFIRST, segByte); // Then segments
digitalWrite(latchPin, LOW);
}