#include <Arduino.h>
#include <TM1637Display.h>
#include <RTClib.h>
#include <SimpleRotary.h>
#include <Wire.h>
// Module connection pins (Digital Pins)
#define CLK 13
#define DIO 12
// Interval for blinking the colon (in milliseconds)
#define BLINK_INTERVAL 1000
#define ROTARY_TIMEOUT 3000 // Timeout duration in milliseconds (3 seconds)
TM1637Display display(CLK, DIO);
RTC_DS1307 rtc;
SimpleRotary rotary(3, 4, 5);
unsigned long lastColonMillis = 0; // Stores the last time the colon was updated
unsigned long lastRotaryMillis = 0; // Stores the last time the rotary encoder was used
bool colonState = true; // Tracks the colon's state (on/off)
// Alarm vars
int alarmMM = 0;
int alarmHH = 8;
bool showingAlarm = false; // Tracks whether we are showing the alarm
void setup() {
Serial.begin(57600);
display.setBrightness(0x01);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
while (1) delay(10);
}
if (!rtc.isrunning()) {
Serial.println("RTC is NOT running, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
} else {
Serial.println("RTC already running");
}
}
void loop() {
// Get the current time
DateTime now = rtc.now();
int hour = now.hour();
int minute = now.minute();
int displayTime = (hour * 100) + minute;
// Get the current time in milliseconds
unsigned long currentMillis = millis();
// Handle rotary encoder input
handleRotation(currentMillis);
// Check if we should still display alarm (last rotary interaction within 3 seconds)
if (currentMillis - lastRotaryMillis <= ROTARY_TIMEOUT) {
int displayAlarm = (alarmHH * 100) + alarmMM; // Combine hours and minutes into HHMM
display.showNumberDecEx(displayAlarm, 0b01000000 , true); // Show alarm with or without colon
showingAlarm = true;
} else {
showingAlarm = false;
}
// If we are not showing the alarm time, show the current time with blinking colon
if (!showingAlarm) {
// Check if BLINK_INTERVAL has passed since the last colon update
if (currentMillis - lastColonMillis >= BLINK_INTERVAL) {
lastColonMillis = currentMillis; // Save the current time
colonState = !colonState; // Toggle the colon state
// Update the display with or without the colon
if (colonState) {
display.showNumberDecEx(displayTime, 0b01000000, true); // Colon on
} else {
display.showNumberDecEx(displayTime, 0b00000000, true); // Colon off
}
}
}
}
void handleRotation(unsigned long currentMillis) {
// Handle rotary encoder input
byte button = rotary.push();
byte rotation = rotary.rotate();
if (button == 1) {
handleRotaryBtn(currentMillis);
}
// Increase alarmMM by 5 and reset to 0 if it goes above 60
if (rotation == 1) {
alarmMM = alarmMM + 5;
if (alarmMM >= 60) {
alarmMM = 0; // Reset to 0 if it goes beyond 60
}
Serial.print("CW - Alarm minute: ");
Serial.println(alarmMM);
lastRotaryMillis = currentMillis; // Update last rotary interaction time
}
// Increase by one and repeat at 23
if (rotation == 2) {
alarmHH++;
if (alarmHH > 23) {
alarmHH = 0; // Reset to 23 if it goes below 0
}
Serial.print("CCW - Alarm hour: ");
Serial.println(alarmHH);
lastRotaryMillis = currentMillis; // Update last rotary interaction time
}
}
void handleRotaryBtn(unsigned long currentMillis){
Serial.println("rotary btn push");
lastRotaryMillis = currentMillis;
}