Arduino och sommartid (Europa)
Bara den gångna helgen Europa har startat i sommartid. Ni alla var tvungen att återställa dina klockor, men hur är din microcontroller? Många program på arduino och andra microcontrollers håller tid och gör att med en av de populära RTC chips som DS1307 eller DS3231. De håller tiden mycket bra (men jag föredrar DS3231) och det finns en hissa bibliotek tillgängliga för dem. En sak de inte gör är att automatiskt växla mellan normaltid och sommartid (DST). Självklart som skulle vara ganska svårt eftersom det finns olika DST förhållanden över hela världen
Men man kunde ju återställa RTC chip manuellt två gånger om året men det är tråkigt, speciellt när det kan enkelt lösas med några rader kod.
Olika delar av världen har olika regler för när i sommartid äger rum och många länder har naturligtvis ingen sommartid: meningsfullt blir det först (om alls) att göra det mellan tropikerna och arktiska cirklar, så i själva verket mellan Kräftans vändkrets och polcirkeln och Stenbockens vändkrets och Antarktis circle.
I Australien sommartid är en fråga om stater och territorier men i allmänhet sommartid mellan den första söndagen i oktober och första söndagen i April (kom ihåg, det är enligt)
I Kanada till stor del beror på var du bor, följer vissa stater Förenta staterna. Newfoundland sv Nunavut har sin egen regel och många av de norra territorierna har inte sommartid
USA har sommartid från den 2: a söndagen i mars till första söndagen i November.
EU har naturligtvis en riktlinje på det som bestämmer i sommartid att börja den sista söndagen i mars och till slut den sista söndagen i oktober. I EU är timmen att byta 01:00 UTC. UTC är i praktiken lika med GMT (Greenwich Mean Time). UTC sig är inte en förkortning men en kompromiss mellan den franska förkortningen "TUC" och engelsmännen "CUT" (Temps Universel Coordonné resp Koordinerad universell tid).
Catering för din lokala dagsljus besparingar programmerar är oftast ganska lätt: Låt din program kontrollera rätt månad och sedan räkna antalet söndagar (ändringen är vanligtvis på en söndag). När du kommer till önskad söndag kontrollera tiden och om det är säger 2 am, avancera klockan en timme (= ställa in den till 3) om DST har att starta, eller vänta till 3 am och återställa klockan timmar till 2. Naturligtvis måste du också ange en flagga att göra klockan korrigeringen endast en gång.
Enkel nog... Om du inte bor i EU (eller Nunavut). I EU är inte växeln gjorde på första, andra, tredje eller fjärde söndagen i mars resp. oktober, men på den sista söndagen i månaden.
Tja, en månad har fyra söndagar rätt? Fel. Om till exempel oktober börjar på en fredag, lördag eller söndag, har den 5 söndagar. Så vad göra? Du kan väl naturligtvis bestämma om den första dagen startar på fredag, lördag eller söndag och om det, räkna till 5 och annars räkna till 4. Men det finns ett enklare sätt, där du inte ens behöver räkna.
Kan sätta det i ett program för Västeuropa, vilket innebär att växla tiderna är 2 och 3 på (det är 1:00 UTC)
Låt oss håller med om att du har en RTC som kommer att hålla "dagen av veckan" (liksom DS1307 och DS3231). Som du ställer in dessa kan själv håller med om att du har angett dagen i veckan så att måndag är dag 1 och söndag dag 7. Vissa människor gillar att börja veckan på söndag, men det är bara en fråga om smak. Hur som helst, vi har följande variabler läsa från vår RTC
Dow = veckodag (som i 1-7)
Mo = månad
d = dag (som i 1-31)
h = timme
DST är en flagga som vi satt när DST startar och att vi i slutet av DST att undvika att programmet börjar korrigera tiden för en hel timme och även att få i en oändlig loop när vi in klockan tillbaka som oktober har 31 dagar, vi vet att den sista söndagen kommer alltid att falla från den 25: e till den 31: a så våra kolla i slutet av dagsljus spara följande :
if (dow == 7 && mo == 10 && d >= 25 && h == 3 && DST==1)
{
setclockto 2 am;
DST=0;//store this in your NVRAM
}
Som du kan använda olika bibliotek kommandot ' setclockto 2 på "är bara en plats innehavare för din specifika rutin att ställa in din RTC till 2 am. Jag skulle råda för att lagra flaggan DST någonstans i icke flyktigt minne, om du behöver koppla bort din arduino. DS1307 har några på chip icke flyktiga RAM där du kan lagra det, DS3231 inte. Båda kommer emellertid vanligt som en modul med en EEPROM på det också, annars EEPROM av Arduino kan användas.
Hur som helst kan göra en kontroll om vi har rätt rutin: Antag att den 1 oktober är en söndag. Det betyder att 25 är en onsdag och den 29: e söndag (den sista och 5: e söndagen), så rutinen kommer faktiskt att aktiveras 29 alla villkor är uppfyllda. Anta att oktober startar på en måndag. Det betyder det finns bara 4 söndagar och den sista söndagen kommer att falla på den 28: e. Återigen, det är mellan 25 och 31 så att villkoret är uppfyllt. Antar att första oktober faller på en torsdag, då den 25: e kommer att vara en söndag (den fjärde söndagen) och den 31: a kommer att vara en lördag, kommer så återigen villkoret att uppfyllas för sist (och i detta fall 4: e söndag).
För att starta sommaren/daylightsaving tid sista är söndagen i mars i tillämpliga delar detsamma:
if (dow == 7 && mo == 3 && d >= 25 && h ==2 && DST==0)
{
setclockto 3 am;
DST=1; //store this in your NVRAM
}
Mars har 31 dagar så beräkningarna är samma. Denna gång om vi kolla på 2 am och reset DST flagga och sedan ange att klockan 3 är och DST flaggan att indikera det görs redan.
Nu om du inte använder en RTC som håller dagen i veckan eller om du hålla reda på tid och datum på något annat sätt än med en RTC, finns så det en enkel formel för att fastställa dag i veckan från och med Sakamotos algoritm
//gives day of week for a given date Sunday=0, Saturday=6
int dow(int y, int m, int d)
{ static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; static int t[] = y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7; }0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4;
y -= m < 3; return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
sinne du dock att denna rutin räknar från 0 (söndag) till 6 (lördag)
Jag har fått veta att Avr-libc har time.h med DST stöd men inte bara har du att berätta biblioteket du vill använda DST men du måste också innehålla en ganska omfattande verktyg fil, beroende på om du är i Europa eller USA. Jag vågar säga min kod är betydligt kortare.