/*
Tix Clock
Deze code implementeert een Tix-klok op een Arduino-bord met behulp van een RTC-module
(Real-Time Clock) en NeoPixel LED-strips. Een Tix-klok is een klok die de tijd weergeeft
met behulp van LED's gerangschikt in de vorm van de cijfers 0 tot 9. Deze klok toont de
uren en minuten op afzonderlijke LED-strips, waarbij elk cijfer wordt weergegeven met
zijn respectievelijke aantal LED's.
De circuit:
- RTC-module (bijv. DS3231) voor het bijhouden van de tijd
- NeoPixel LED-strips voor het weergeven van de tijd
- Knoppen voor het handmatig aanpassen van de tijd
*/
//=========================================================================================================================
#include <RTClib.h>
#include <Adafruit_NeoPixel.h>
RTC_DS3231 rtc; // Initialisatie van de Real-Time Clock (RTC) module
// Definities voor de pinnen die de LED-strips aansturen
#define LED_PIN_HOUR_TENS 13 // Pin voor het eerste cijfer van het uur
#define LED_PIN_HOUR_ONES 12 // Pin voor het tweede cijfer van het uur
#define LED_PIN_MINUTES_TENS 8 // Pin voor het eerste cijfer van de minuten
#define LED_PIN_MINUTES_ONES 7 // Pin voor het tweede cijfer van de minuten
// Aantal LED's op elke LED-strip
#define LED_COUNT_HOUR_TENS 3 // Aantal LED's voor het eerste cijfer van het uur
#define LED_COUNT_HOUR_ONES 9 // Aantal LED's voor het tweede cijfer van het uur
#define LED_COUNT_MINUTES_TENS 6 // Aantal LED's voor het eerste cijfer van de minuten
#define LED_COUNT_MINUTES_ONES 9 // Aantal LED's voor het tweede cijfer van de minuten
// Pinnen voor de knoppen om de tijd aan te passen
#define HOUR_INC_BUTTON_PIN 2 // Pin voor de knop om het uur te verhogen
#define HOUR_DEC_BUTTON_PIN 3 // Pin voor de knop om het uur te verlagen
#define MIN_INC_BUTTON_PIN 4 // Pin voor de knop om de minuten te verhogen
#define MIN_DEC_BUTTON_PIN 5 // Pin voor de knop om de minuten te verlagen
#define BUZZER_PIN 6
// Initialisatie van de NeoPixel LED-strips
Adafruit_NeoPixel stripHourTens(LED_COUNT_HOUR_TENS, LED_PIN_HOUR_TENS, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripHourOnes(LED_COUNT_HOUR_ONES, LED_PIN_HOUR_ONES, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripMinutesTens(LED_COUNT_MINUTES_TENS, LED_PIN_MINUTES_TENS, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripMinutesOnes(LED_COUNT_MINUTES_ONES, LED_PIN_MINUTES_ONES, NEO_GRB + NEO_KHZ800);
bool klok = true;
bool alarm = false;
bool adjust_time = false;
bool adjust_alarm = false;
bool modus = true;
int hour;
int minute;
int alarmtime;
int alarmhourTens = 0;
int alarmhourOnes = 0;
int alarmminTens = 0;
int alarmminOnes = 0;
int alarmActivate;
bool eersteCyclus = false;
// Setup functie=========================================================================================================
void setup() {
Serial.begin(9600); // Start de seriële communicatie voor debugging
if (!rtc.begin()) { // Controleer of de RTC-module correct is geïnitialiseerd
Serial.println("Kon de RTC niet vinden!"); // Foutmelding als de RTC niet gevonden kan worden
while (1); // Blijf hier hangen als de RTC niet gevonden kan worden
}
if (rtc.lostPower()) { // Controleer of de RTC de stroom is kwijtgeraakt
Serial.println("RTC is gestopt met werken, laten we de tijd instellen!"); // Melding als de RTC is gestopt met werken
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Stel de tijd opnieuw in op het moment van compileren
}
// Configureer de pinnen van de knoppen als input met pull-up weerstand
pinMode(HOUR_INC_BUTTON_PIN, INPUT_PULLUP);
pinMode(HOUR_DEC_BUTTON_PIN, INPUT_PULLUP);
pinMode(MIN_INC_BUTTON_PIN, INPUT_PULLUP);
pinMode(MIN_DEC_BUTTON_PIN, INPUT_PULLUP);
// Start de NeoPixel LED-strips
stripHourTens.begin();
stripHourOnes.begin();
stripMinutesTens.begin();
stripMinutesOnes.begin();
// Initialiseer alle pixels op de LED-strips als 'uit'
stripHourTens.show();
stripHourOnes.show();
stripMinutesTens.show();
stripMinutesOnes.show();
}
//FUNCTIES:=============================================================================================================
// Functie om alle LED's op een strip uit te zetten
void clearLEDs(Adafruit_NeoPixel &strip) {
for (int i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, 0); // Zet de LED uit
}
strip.show();
}
// Functie om een aantal willekeurige LED's op een strip te laten oplichten
void randomLights(Adafruit_NeoPixel &strip, int count, uint32_t color) {
clearLEDs(strip); // Schakel eerst alle LED's uit op de strip
int ledPositions[strip.numPixels()]; // Array om gebruikte posities bij te houden
int usedPositions = 0;
while (usedPositions < count) {
int randomPos = random(strip.numPixels()); // Kies een willekeurige positie op de strip
bool alreadyUsed = false;
// Controleer of de positie al eerder is gebruikt
for (int i = 0; i < usedPositions; i++) {
if (ledPositions[i] == randomPos) {
alreadyUsed = true;
break;
}
}
if (!alreadyUsed) {
ledPositions[usedPositions] = randomPos; // Sla de gebruikte positie op
usedPositions++;
strip.setPixelColor(randomPos, color); // Stel de kleur in voor de verlichte LED's
}
}
strip.show(); // Laat de veranderingen zien op de LED-strip
}
// Functie om de tijd aan te passen
void adjustTime(int &timeValue, int minValue, int maxValue, int increment) {
timeValue += increment;
if (timeValue < minValue) {
timeValue = maxValue; // Terug naar het maximum als de waarde kleiner is dan het minimum
} else if (timeValue > maxValue) {
timeValue = minValue; // Terug naar het minimum als de waarde groter is dan het maximum
}
}
// Functie om de tijd te laten zien
void KLOK() {
DateTime now = rtc.now(); // Haal de huidige tijd op van de RTC-module
hour = now.hour(); // Haal het uur op
int minute = now.minute(); // Haal de minuten op
// Verdeel de tijd in uren en minuten
int hourTens = hour / 10; // Tientallen van uren
int hourOnes = hour % 10; // Eenheden van uren
int minTens = minute / 10; // Tientallen van minuten
int minOnes = minute % 10; // Eenheden van minuten
// Toon de minuten op de LED-strips als de minuten zijn veranderd
static int prevMinOnes = -1;
static int prevMinTens = -1;
if (minOnes != prevMinOnes || minTens != prevMinTens||eersteCyclus) {
randomLights(stripMinutesTens, minTens, stripMinutesTens.Color(0, 255, 0)); // Groene LED's voor tientallen van minuten
randomLights(stripMinutesOnes, minOnes, stripMinutesOnes.Color(170, 0, 255)); // Paarse LED's voor eenheden van minuten
prevMinOnes = minOnes;
prevMinTens = minTens;
}
// Toon de uren op de LED-strips als de uren zijn veranderd
static int prevHourOnes = -1;
static int prevHourTens = -1;
if (hourOnes != prevHourOnes || hourTens != prevHourTens||eersteCyclus) {
randomLights(stripHourTens, hourTens, stripHourTens.Color(0, 0, 255)); // Blauwe LED's voor tientallen van uren
randomLights(stripHourOnes, hourOnes, stripHourOnes.Color(255, 0, 0)); // Rode LED's voor eenheden van uren
prevHourOnes = hourOnes;
prevHourTens = hourTens;
}
eersteCyclus=0;
}
// Controleer of de knoppen zijn ingedrukt om de tijd aan te passen
void ADJUST_TIME(){
DateTime now = rtc.now();
static int counterSetTime = 0;
if (digitalRead(HOUR_INC_BUTTON_PIN) == LOW) {
adjustTime(hour, 0, 23, 1); // Verhoog het uur met 1
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hour, minute, 0)); // Pas de tijd aan op de RTC-module
counterSetTime = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
if (digitalRead(HOUR_DEC_BUTTON_PIN) == LOW) {
adjustTime(hour, 0, 23, -1); // Verlaag het uur met 1
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hour, minute, 0)); // Pas de tijd aan op de RTC-module
counterSetTime = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
if (digitalRead(MIN_INC_BUTTON_PIN) == LOW) {
adjustTime(minute, 0, 59, 1); // Verhoog de minuten met 1
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hour, minute, 0)); // Pas de tijd aan op de RTC-module
counterSetTime = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
if (digitalRead(MIN_DEC_BUTTON_PIN) == LOW) {
adjustTime(minute, 0, 59, -1); // Verlaag de minuten met 1
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hour, minute, 0)); // Pas de tijd aan op de RTC-module
counterSetTime = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
counterSetTime++;
if (counterSetTime > 2000) {
adjust_time = false;
modus = true;
counterSetTime = 0;
}
}
//Functie alarm
void ALARM(){
clearLEDs(stripHourTens);
clearLEDs(stripHourOnes);
clearLEDs(stripMinutesTens);
clearLEDs(stripMinutesOnes);
delay(2000);
alarm = false;
klok = true;
modus = true;
eersteCyclus = true;
}
void ADJUST_ALARM(){
static int counterSetAlarm = 0;
if (digitalRead(HOUR_INC_BUTTON_PIN) == LOW) {
adjustTime(alarmhourTens, 0, 2, 1);
randomLights(stripHourTens, alarmhourTens, stripHourTens.Color(255, 255, 255));
counterSetAlarm = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
if (digitalRead(HOUR_DEC_BUTTON_PIN) == LOW) {
adjustTime(alarmhourOnes, 0, 4, 1);
randomLights(stripHourOnes, alarmhourOnes, stripHourOnes.Color(255, 255, 255));
counterSetAlarm = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
if (digitalRead(MIN_INC_BUTTON_PIN) == LOW) {
adjustTime(alarmminTens, 0, 5, 1);
randomLights(stripMinutesTens, alarmminTens, stripMinutesTens.Color(255, 255, 255));
counterSetAlarm = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
if (digitalRead(MIN_DEC_BUTTON_PIN) == LOW) {
adjustTime(alarmminOnes, 0, 9, 1);
randomLights(stripMinutesOnes, alarmminOnes, stripMinutesOnes.Color(255, 255, 255));
counterSetAlarm = 0;
delay(150); // Debouncing vertraging om meerdere knopdrukken te voorkomen
}
counterSetAlarm++;
delay(10);
if (counterSetAlarm > 2000) {
adjust_alarm = false;
klok = true;
modus = true;
counterSetAlarm = 0;
eersteCyclus=true;
}
}
//Functie Klok modus bepalen
void MODUS(){
static int counterToSetAlarm = 0;
static int counterToSetTime = 0;
if (digitalRead(HOUR_INC_BUTTON_PIN) == LOW && digitalRead(HOUR_DEC_BUTTON_PIN) == LOW) {
counterToSetAlarm++; //count the amount of loops that the 2 buttons are pressed.
if (counterToSetAlarm > 3000) {
klok = false;
modus = false;
adjust_alarm = true;
clearLEDs(stripHourTens);
clearLEDs(stripHourOnes);
clearLEDs(stripMinutesTens);
clearLEDs(stripMinutesOnes);
counterToSetAlarm = 0;
}
}
else{ // The two buttons are not pressed
counterToSetAlarm = 0;
}
if (digitalRead(MIN_INC_BUTTON_PIN) == LOW && digitalRead(MIN_DEC_BUTTON_PIN) == LOW) {
counterToSetTime++; //count the amount of loops that the 2 buttons are pressed.
if (counterToSetTime > 3000) {
modus = false;
adjust_time = true;
counterToSetTime = 0;
}
}
else{ // The two buttons are not pressed
counterToSetTime = 0;
}
}
void checkAlarm() {
DateTime now = rtc.now();
int currentHour = now.hour();
int currentMinute = now.minute();
int alarmHour = alarmhourTens * 10 + alarmhourOnes;
int alarmMinute = alarmminTens * 10 + alarmminOnes;
if (currentHour == alarmHour && currentMinute == alarmMinute) {
digitalWrite(BUZZER_PIN, HIGH);
delay(3000);
digitalWrite(BUZZER_PIN, LOW);
}
}
// Hoofdprogramma========================================================================================================
void loop() {
//functies oproepen:
if (adjust_time) {
ADJUST_TIME();
}
if (adjust_alarm) {
ADJUST_ALARM();
}
if (klok){
KLOK();
}
if (modus){
MODUS();
}
if (alarm){
ALARM();
}
checkAlarm();
}