Tag: Ds3231
-
Stabiel de tijd bijhouden tussen herstarten
Met baby steps, zo komen we er wel. Eerder had ik het erover dat de Arduino geen eigen RTC (Real Time Clock) heeft en daardoor ten eerste een vrij grote afwijking van enkele seconden per dag heeft en ten tweede de tijd-instelling steeds kwijtraakt bij herstarten.
Er zijn twee goed ondersteunde RTCs voor Arduino verkrijgbaar; de DS1307 en de DS3231. Qua prijs ontlopen ze elkaar niet veel, maar qua precisie is de DS3231 absoluut superieur met een afwijking van maar ±2 minuten per jaar. Aansluiten op de Arduino, het wordt langzaam een beetje voorspelbaar, is weer een fluitje van een cent.
VCC
enGND
naar de plus en min,SDA
direct op analoge poortA4
enSCL
direct naar analoge poortA5
.
DS3231 met batterijhouder en pinsVervolgens kan je met de DS3231 library de boel besturen:
#include <DS3231.h> #include <AceTime.h> BasicZoneProcessor zoneProcessor; TimeZone tz = TimeZone::forZoneInfo(&zonedb::kZoneEurope_Amsterdam, &zoneProcessor); void setup() { // Initialiseer de verbinding Wire.begin(); Serial.begin(9600); } void loop() { // Haal de huidige tijd op uit de RTC DateTime rtcNow = RTClib::now(); ZonedDateTime now = ZonedDateTime::forUnixSeconds64(rtcNow.unixtime(), tz); now.printTo(Serial); delay(100); }
De tijd instellen
De kans dat de RTC de juiste tijd geeft als je hem voor het eerst gebruikt is op zich vrij klein, dus moet je hem eerst instellen. Via de seriële poort van de Arduino kunnen we de module instellen:
void loop() { // Als er iets op de seriële poort klaar staat... if (Serial.available()) { // ... dan lees het als een integer long readLong = Serial.parseInt(); // ... en lees de rest van de buffer leeg, zoals een <enter> of spaties while (Serial.available()) { Serial.read(); } // stel de RTC in op de integer die van de seriële poort is ingelezen rtc.setEpoch(readLong); } ZonedDateTime now = ZonedDateTime::forUnixSeconds64(RTClib::now().unixtime(), tz); now.printTo(Serial); delay(100); }
Vervolgens kunnen we de tijd instellen door de Unix epoch timestamp over de seriële poort naar de Arduino te sturen. De huidige Unix epoch krijg je met het commando
date +%s
. Je kan de uitvoer daarvan in de Arduino IDE naar de seriële poort sturen (Tools | Serial monitor), maar het kan ook vanaf de command line met hetcu
commando. Eerst moet je weten welk device je seriële poort heeft; in de Arduino IDE zie je dat onderin het scherm als je Arduino verbonden is. Bij mij is dat/dev/cu.usbmodem101
, vervolgens start jecu
met het commando:$ sudo cu -l /dev/cu.usbmodem101
Nu zie je alles wat over de seriële poort binnenkomt, dus in dit geval elke 100 milliseconden de huidige tijd. Het
cu
commando kan echter ook berichten terugsturen (zieman cu
), en heeft zelfs nog functionaliteit om de invoer uit een ander programma te halen door middel van~$<command>
. We krijgen de huidige epoch metdate +%s
(zie ookman date
).Als je door de stroom aan timestamps heen het commando
<enter>~$date +%s
invoert, zul je zien dat de timestamps opeens de huidige tijd weergeven. Aangezien je dit maar af en toe hoeft te doen zou je kunnen overwegen dit in een apart programma te doen, want dat scheelt weer in het geheugengebruik. Je sluitcu
netjes af met het commando<enter>~.
.Andere tijdsignaal-bronnen
Een RTC is zeker niet de enige bron van tijdsignalen. Als je een WiFi module toevoegt aan de Arduino, kan de tijd opgehaald worden vanaf een NTP-server. Met een GPS-ontvanger kan je de tijd ophalen van satellieten. Een nog andere optie is om een tijdsignaal van de DCF77-zender in Mainflingen bij Frankfurt op te vangen. Ook de originele klok in de Rheinturm doet dit!
Ik wil daar in de toekomst nog wel eens naar kijken, maar op dit moment is de klok volledig zelfstandig operationeel! De volgende stap is eerst iets compleet anders: de lichtstrip moet worden ingebouwd in een meer permanente opstelling.