Hallo
Ik ben Noé.
Ik ben nu al een tijdje beig met een project zodat de kippen automatish eten krijgen.
Ik heb heel wat geprogrameerd en dingen gebouwd en opzoekwerk gedaan.
Ik heb een probleem met mijn code maar ik weet niet hoe dat het komt.
Alles is verbonden zoals in de code.
Het probleem is dat het werkt 2-3 keer.
Maar dan blijft de tijd steken voor ewig tot dat ik het weer reset.
Zouden jullie weten hoe en waarom dat dit komt?
Dit is de code:
#include <ThreeWire.h>
#include <RtcDS1302.h>
// Pinnen voor buzzer en relais
const int buzzPin = 13; // Pin buzzer
const int relPin = 9; // Pin relais
// Pinnen voor RTC (DS1302)
const int clk = 11; // Klok
const int dat = 12; // Data
const int rst = 10; // Reset
// Initialiseer ThreeWire interface voor RTC
ThreeWire myWire(dat, clk, rst);
RtcDS1302<ThreeWire> Rtc(myWire);
// Instellen van alarmtijden (3 verschillende tijden)
// Pas deze tijden aan naar wens
int Hour[] = {14, 14, 14}; // Uren
int Minute[] = {25, 27, 3}; // Minuten
int Second[] = {30, 10, 0}; // Seconden
// Instellingen voor alarm
const int Count = 15; // Tijd dat relais actief blijft (in seconden)
const int toneDuration = 1000; // Duur van elke toon in milliseconden
const int totalTones = 6; // Aantal tonen dat buzzer afspeelt
// Statusvariabelen voor alarm
bool alarmActive = false; // Geeft aan of het alarm aan staat
bool buzzerDone = false; // Geeft aan of buzzer klaar is met afspelen
// Tijdregistratie voor het afspelen van tonen en relais activeren
unsigned long toneStart = 0; // Starttijd voor tonen
int toneStep = 0; // Huidige toonstap
unsigned long relayStart = 0; // Starttijd voor relais
void setup() {
Serial.begin(115200); // Start seriële communicatie (baudrate 115200)
pinMode(buzzPin, OUTPUT); // Zet buzzerpin als uitgang
pinMode(relPin, OUTPUT); // Zet relaispin als uitgang
digitalWrite(relPin, LOW); // Zet relais initieel uit
// Initialiseer RTC
Rtc.Begin();
Rtc.SetIsWriteProtected(false);
Rtc.SetIsRunning(true);
// Controleer of RTC tijd geldig is
if (!Rtc.IsDateTimeValid()) {
Serial.println("⚠️ RTC tijd ongeldig. Stel in op compileertijd...");
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
Rtc.SetDateTime(compiled); // Stel RTC tijd in op moment van compileren
}
}
void loop() {
// Variabelen die persistent blijven tussen loop-calls
static unsigned long lastUpdate = 0; // Tijdstip van laatste tijdupdate
static RtcDateTime now; // Huidige RTC tijd
// Vernieuw RTC tijd maximaal 1x per seconde
if (millis() - lastUpdate >= 1000) {
lastUpdate = millis(); // Update tijd van laatste check
now = Rtc.GetDateTime(); // Lees huidige tijd van RTC
// Debug: controleer of RTC tijd "vastzit" (bevroren seconden)
static uint8_t lastSecond = 255; // Vorige seconde, initieel onwaarschijnlijk getal
static int freezeCounter = 0; // Tel hoe vaak dezelfde seconde wordt gezien
if (now.Second() == lastSecond) {
freezeCounter++; // Seconde is gelijk aan vorige, verhoog teller
if (freezeCounter > 3) {
Serial.println("⛔ RTC tijd lijkt vast te zitten!"); // Waarschuwing
}
} else {
freezeCounter = 0; // Seconde is veranderd, reset teller
lastSecond = now.Second(); // Sla nieuwe seconde op
}
// Print de huidige tijd op seriële monitor
char buffer[16];
sprintf(buffer, "%02u:%02u:%02u", now.Hour(), now.Minute(), now.Second());
Serial.println(buffer);
}
// Alarm check: start alarm als huidige tijd overeenkomt met een ingestelde alarmtijd
if (!alarmActive) {
for (int i = 0; i < 3; i++) {
// Controleer uur, minuut en seconde (binnen 1 seconde marge)
if (now.Hour() == Hour[i] && now.Minute() == Minute[i] &&
abs(now.Second() - Second[i]) <= 1) {
Serial.println("🔔 Buzzer gestart");
alarmActive = true; // Zet alarm actief
buzzerDone = false; // Buzzer is nog niet klaar
toneStart = millis(); // Starttijd tonen instellen
toneStep = 0; // Begin bij eerste toon
break; // Stop met zoeken, alarm gestart
}
}
}
// Fase 1: Buzzer afspelen
if (alarmActive && !buzzerDone) {
// Als er nog tonen over zijn en de tijd voor de volgende toon is bereikt
if (toneStep < totalTones && millis() - toneStart >= toneStep * toneDuration) {
// Speel afwisselend twee tonen (523 Hz en 587 Hz)
tone(buzzPin, (toneStep % 2 == 0) ? 523 : 587);
toneStep++; // Volgende toon
}
// Als alle tonen zijn gespeeld
else if (toneStep >= totalTones) {
noTone(buzzPin); // Stop buzzer
buzzerDone = true; // Buzzer klaar
relayStart = millis(); // Start tijd voor relais aan
digitalWrite(relPin, HIGH); // Zet relais aan
Serial.println("➡️ Relay gestart");
}
}
// Fase 2: Relay aanhouden en daarna uitschakelen
if (buzzerDone && millis() - relayStart >= Count * 1000UL) {
digitalWrite(relPin, LOW); // Zet relais uit
alarmActive = false; // Zet alarm uit
buzzerDone = false; // Reset buzzer status
Serial.println("🛑 Alarm volledig beëindigd");
}
delay(50); // Kleine pauze om CPU te ontlasten
}
// Comments en debug systeem gemaakt door ChatGPT
De comments en het debug systeem zijn gemaakt door chatGPT.
Alvast bedankt voor jullie hulp
Noé
PS: Ik zal er de volgende twee weken niet zijn dus ik zal niet kunnen antwoorden sorry.
De RTC-tijd wordt maar één keer per seconde bijgewerkt. Als die verversing net gebeurt vlak vóór het alarmmoment, wordt de voorwaarde gecontroleerd met de oude waarde en faalt. De volgende update komt te laat, één seconde na het alarm, waardoor de controle niet meer klopt. Gevolg: het alarm wordt gemist en pas de volgende minuut opnieuw geprobeerd.
Bedankt voor je antwoord
Maar dat is niet het probleem het probleem is dat het volledig werkt maar dat het soms (dus niet altijd) na dat het alarm is afgegaan de tijd ineens blijft steken voor ewig. Hoe zou ik dit kunnen oplossen?
Je hebt een RTC, dus het is nutteloos om de tijd slechts één keer per seconde uit te lezen. Laat de loop() de tijd voortdurend lezen en reageer op basis van het verloop van de tijd zonder kunstmatige frequentiebeperking
Waar precies ? wat is de laatste 'debug message' die wordt geprint ?
Ik blijf het lastig lezen vinden als de '&&' voorwaarden niet door haakjes gescheiden zijn, maar in principe test je hier voor een exacte overeenkomst, terwijl je moet testen of de tijd verstreken is.
Als je een externe tijd gebruikt om de tijd binnen je programma op te meten, kan het zijn dat door een tijd update de tijd verspringt. Je moet voor alle tussenliggende tijdsmomenten ook alle condities testen. Als de RTC voor ligt op de CPU tijd, dan moet je ook het verspringende deel uitvoeren voor de te testen condities.
Hmm ik zie dat je helemaal geen CPU tijd mee laat lopen. De klok van de CPU zal over de periode vna een dag hoogstens enkele (tientallen) seconden afwijken van de werkelijke tijd, dus of je kan gebruik maken van de interne klok en deze slechts heel weinig vergelijken met de RTC (zoals je dat met een NTP tijd zou doen) of je kan de RTC continue lezen zonder het 1 seconde interval.
Dat is wel een relevante vraag ! Ook omdat het schakelen van het relais het moment lijkt te zijn dat er iets fout gaat.
Je moet kijken of de tijd verstreken is, maar je kijkt nu of het precies op tijd is.
Daardoor is de kans dat niet aan die voorwaarde wordt voldaan, ontelbaar groter dan dat er wel aan wordt voldaan.
Zo loopt je sketch dus wel vast.
Denk dat er bedoeld wordt dat == in de vergelijking vervangen zou kunnen worden door >= Verspringt de tijd exact voor het moment van vergelijken, dan is altijd nog aan de voorwaarde voldaan......
Dat is dus een volledig 'kaal' relais op een PCB met wat pinnen om 'm aan te sluiten. Je kan zo'n relais niet rechtstreeks van een arduino pin aansturen. Je moet een transistor gebruiken en er hoort een fly-back diode op, en een externe 5v voeding is waarschijnlijk ook geen overbodige luxe (hoewel je van de USB poort nog wel voldoende 5v kan krijgen, maar bv niet voldoende als je de Arduino met 12v voedt en dan het relais op de 5v pin aansluit.
Oh ja aan de zijkant daar, was niet zichtbaar op de foto die ik bekeek, Q1 is aan transistor en D1 een diode, waarschijnlijk een fly-back, gelukkig maar, toch is hoe het wordt aangesloten wel degelijk van belang.
Er is maar 1 arduino 5V pin en het verloopt als volgt:
5V ---| Drie touwtjes aan elkaar gesoldeerd
Eentje in de arduino 5V pin, eentje in de relais positief pin en eentje in de RTC positief pin.
Dit is nog is mijn code:
#include <ThreeWire.h>
#include <RtcDS1302.h>
// Pinnen voor buzzer en relais
const int buzzPin = 13; // Pin buzzer
const int relPin = 9; // Pin relais
// Pinnen voor RTC (DS1302)
const int clk = 11; // Klok
const int dat = 12; // Data
const int rst = 10; // Reset
// Initialiseer ThreeWire interface voor RTC
ThreeWire myWire(dat, clk, rst);
RtcDS1302<ThreeWire> Rtc(myWire);
// Instellen van alarmtijden (3 verschillende tijden)
// Pas deze tijden aan naar wens
int Hour[] = {14, 14, 14}; // Uren
int Minute[] = {25, 27, 3}; // Minuten
int Second[] = {30, 10, 0}; // Seconden
// Instellingen voor alarm
const int Count = 15; // Tijd dat relais actief blijft (in seconden)
const int toneDuration = 1000; // Duur van elke toon in milliseconden
const int totalTones = 6; // Aantal tonen dat buzzer afspeelt
// Statusvariabelen voor alarm
bool alarmActive = false; // Geeft aan of het alarm aan staat
bool buzzerDone = false; // Geeft aan of buzzer klaar is met afspelen
// Tijdregistratie voor het afspelen van tonen en relais activeren
unsigned long toneStart = 0; // Starttijd voor tonen
int toneStep = 0; // Huidige toonstap
unsigned long relayStart = 0; // Starttijd voor relais
void setup() {
Serial.begin(115200); // Start seriële communicatie (baudrate 115200)
pinMode(buzzPin, OUTPUT); // Zet buzzerpin als uitgang
pinMode(relPin, OUTPUT); // Zet relaispin als uitgang
digitalWrite(relPin, LOW); // Zet relais initieel uit
// Initialiseer RTC
Rtc.Begin();
Rtc.SetIsWriteProtected(false);
Rtc.SetIsRunning(true);
// Controleer of RTC tijd geldig is
if (!Rtc.IsDateTimeValid()) {
Serial.println("⚠️ RTC tijd ongeldig. Stel in op compileertijd...");
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
Rtc.SetDateTime(compiled); // Stel RTC tijd in op moment van compileren
}
}
void loop() {
// Variabelen die persistent blijven tussen loop-calls
static unsigned long lastUpdate = 0; // Tijdstip van laatste tijdupdate
static RtcDateTime now; // Huidige RTC tijd
// Vernieuw RTC tijd maximaal 1x per seconde
if (millis() - lastUpdate >= 1000) {
lastUpdate = millis(); // Update tijd van laatste check
now = Rtc.GetDateTime(); // Lees huidige tijd van RTC
// Debug: controleer of RTC tijd "vastzit" (bevroren seconden)
static uint8_t lastSecond = 255; // Vorige seconde, initieel onwaarschijnlijk getal
static int freezeCounter = 0; // Tel hoe vaak dezelfde seconde wordt gezien
if (now.Second() == lastSecond) {
freezeCounter++; // Seconde is gelijk aan vorige, verhoog teller
if (freezeCounter > 3) {
Serial.println("⛔ RTC tijd lijkt vast te zitten!"); // Waarschuwing
}
} else {
freezeCounter = 0; // Seconde is veranderd, reset teller
lastSecond = now.Second(); // Sla nieuwe seconde op
}
// Print de huidige tijd op seriële monitor
char buffer[16];
sprintf(buffer, "%02u:%02u:%02u", now.Hour(), now.Minute(), now.Second());
Serial.println(buffer);
}
// Alarm check: start alarm als huidige tijd overeenkomt met een ingestelde alarmtijd
if (!alarmActive) {
for (int i = 0; i < 3; i++) {
// Controleer uur, minuut en seconde (binnen 1 seconde marge)
if (now.Hour() == Hour[i] && now.Minute() == Minute[i] &&
abs(now.Second() - Second[i]) <= 1) {
Serial.println("🔔 Buzzer gestart");
alarmActive = true; // Zet alarm actief
buzzerDone = false; // Buzzer is nog niet klaar
toneStart = millis(); // Starttijd tonen instellen
toneStep = 0; // Begin bij eerste toon
break; // Stop met zoeken, alarm gestart
}
}
}
// Fase 1: Buzzer afspelen
if (alarmActive && !buzzerDone) {
// Als er nog tonen over zijn en de tijd voor de volgende toon is bereikt
if (toneStep < totalTones && millis() - toneStart >= toneStep * toneDuration) {
// Speel afwisselend twee tonen (523 Hz en 587 Hz)
tone(buzzPin, (toneStep % 2 == 0) ? 523 : 587);
toneStep++; // Volgende toon
}
// Als alle tonen zijn gespeeld
else if (toneStep >= totalTones) {
noTone(buzzPin); // Stop buzzer
buzzerDone = true; // Buzzer klaar
relayStart = millis(); // Start tijd voor relais aan
digitalWrite(relPin, HIGH); // Zet relais aan
Serial.println("➡️ Relay gestart");
}
}
// Fase 2: Relay aanhouden en daarna uitschakelen
if (buzzerDone && millis() - relayStart >= Count * 1000UL) {
digitalWrite(relPin, LOW); // Zet relais uit
alarmActive = false; // Zet alarm uit
buzzerDone = false; // Reset buzzer status
Serial.println("🛑 Alarm volledig beëindigd");
}
delay(50); // Kleine pauze om CPU te ontlasten
}
// Comments en debug systeem gemaakt door ChatGPT