Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: ne duben 28 2024, 14:43 Předmět: Arduino, přepínání zímní / letní čas
Lámu si tady palici s problémem, jak UTC čas z GPS modulu přehazovat zimní a letní čas. Časový pásmo pro střední Evropu je jen jednoduchý přičtení +1 hodina. To je pak zimní čas, s tím problém nemám.
Jenže co to přepínání brzo ráno poslední neděli března na letní a poslední neděli října na zimní? Kdyby to byly hodiny, co jdou furt, tak stačí tenhle řádek na detekci přechodu na léto:
if ((dayOfWeek == 7)&&(dayOfMonth >= 25)&&(month == 3)&&(hour == 2)) {pricti = true}
Jenže tady to bude v zařízení, který bude 99% času vypnutý a po zapnutí je potřeba aby zjistilo, že ta přechodová podmínka už byla a provedla se opožděně. Jenže ty údaje o datu a čase už v GPS signálu nejsou. Prostě stejný chování jako když se pustí po změně Wokna a zeptaj se, jestli posunout čas.
Nemáte prosím někdo tip jak na to? Open Ai na tom vybouchl, když jsem testoval kód od něho v reálu, tak to pro každej rok hlásilo jiný kraviny. Možná že byl problém s číslováním prvního dne v týdnu, u nás je 1. den PO. na západě NE.
Zásady jsou celkem jednoduchý, měsíc 11. až 2. je zima a 4. až 9. je léto . Ale ten 3. a 10. nevím jak, přepnutí na letní dochází mezi 25.3. až 31.3 a na zimní mezi 25.10. až 31.10. a datumy se každých 6 let opakují. _________________ Jirka
Založen: Oct 30, 2010 Příspěvky: 6766 Bydliště: Praha
Zaslal: ne duben 28 2024, 15:03 Předmět:
Vygoogli si vzorec, který z data spočítá den v týdnu. Potom můžš uplatnit test, zda máš zimní nebo letní čas na každý časový údaj vyčtený z GPS a podle toho s ním pak pracovat. _________________ Krátce před tím, než se to rozbilo, tak to ještě fungovalo...
Založen: Jan 01, 2023 Příspěvky: 2090 Bydliště: Česká Lípa
Zaslal: ne duben 28 2024, 16:05 Předmět:
Pokud slouží GPS jako jediný zdroj času v daném zařízení pak platí níže uvedené.
Od zapnutí zařízení do prvního načtení UTC času z GPS by měl být čas v zařízení považován za neznámý a po prvním a každém dalším načtení UTC času z GPS už bude zřejmé zda je to v rámci letního času či nikoli a dle níže zhruba popsané postupu tak vždy z načteného času GPS získáte aktuální lokální čas ČR.
Z tohoto pohledu tedy vůbec nebude nutné mít informaci o tom zda se to už dělalo před posledním vypnutím napájení, protože se to bude dělat vždy po každém načtení času z GPS.
Letní čas SELČ v Česku platí od 1:00 UTC (2:00 SEČ, resp. 3:00 SELČ) poslední neděle v březnu do 1:00 UTC (3:00 SELČ, resp. 2:00 SEČ) poslední neděle v říjnu.
Mělo by stačit použít tuto knihovnu TimeLib a pomocí jejich funkcí po každém načtení UTC času včetně datumu z GPS vypočítat zda je to uvnitř výše zmíněného UTC intervalu pro letní čas či nikoli.
Pokud bude načtený UTC čas z GPS uvnitř UTC intervalu pro letní čas pak víte, že máte ten UTC načtený čas převést na letní čas a pokud to v tom intervalu nebude tak na zimní čas. Pomocí funkcí zmíněné knihovny pak hodnotu UTC času načtenou z GPS posunete příslušným způsobem a s výslednou hodnotou dále pak už budete v zařízení zacházet jako s aktuálním lokálním časem v ČR.
Naposledy upravil Valdano dne ne duben 28 2024, 16:20, celkově upraveno 1 krát.
Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: ne duben 28 2024, 16:19 Předmět:
Valdano napsal(a):
Mělo by stačit použít tuto knihovnu TimeLib a pomocí jejich funkcí po každém načtení UTC času včetně datumu z GPS vypočítat zda je to uvnitř výše zmíněného UTC intervalu pro letní čas či nikoli.
Jo, tak právě s touhle knihovnou to OpenAi zkoušel a lezly z toho nesmysly.
Taky mě mate, kde ta knihovna je, ve výpisu knihoven v IDE není a stejně to prochází kompilací.
edit: jo, už jsem ji našel, je schovaná v TimeMaster. _________________ Jirka
Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: ne duben 28 2024, 16:50 Předmět:
Tak tohle je třeba příklad z knihovny. Jen jsem upravil ruční zadání času místo GPS:
kód:
/*
* TimeGPS.pde
* example code illustrating time synced from a GPS
*
*/
#include <TimeLib.h>
#include <TinyGPS.h> // http://arduiniana.org/libraries/TinyGPS/
#include <SoftwareSerial.h>
// TinyGPS and SoftwareSerial libraries are the work of Mikal Hart
// To use a hardware serial port, which is far more efficient than
// SoftwareSerial, uncomment this line and remove SoftwareSerial
//#define SerialGPS Serial1
// Offset hours from gps time (UTC)
const int offset = 1; // Central European Time
//const int offset = -5; // Eastern Standard Time (USA)
//const int offset = -4; // Eastern Daylight Time (USA)
//const int offset = -8; // Pacific Standard Time (USA)
//const int offset = -7; // Pacific Daylight Time (USA)
// Ideally, it should be possible to learn the time zone
// based on the GPS position data. However, that would
// require a complex library, probably incorporating some
// sort of database using Eric Muller's time zone shape
// maps, at http://efele.net/maps/tz/
time_t prevDisplay = 0; // when the digital clock was displayed
void setup()
{
Serial.begin(9600);
while (!Serial) ; // Needed for Leonardo only
SerialGPS.begin(4800);
Serial.println("Waiting for GPS time ... ");
}
void loop()
{
/* while (SerialGPS.available()) {
if (gps.encode(SerialGPS.read())) { // process gps messages
// when TinyGPS reports new data...
unsigned long age;
int Year;
byte Month, Day, Hour, Minute, Second;
gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, NULL, &age);
if (age < 500) {
// set the Time to the latest GPS reading
setTime(Hour, Minute, Second, Day, Month, Year);
*/
int Year;
byte Month, Day, Hour, Minute, Second;
setTime(0, 0, 0, 1, 3, 25);
adjustTime(offset * SECS_PER_HOUR);
// }
// }
// }
if (timeStatus()!= timeNotSet) {
if (now() != prevDisplay) { //update the display only if the time has changed
prevDisplay = now();
digitalClockDisplay();
}
}
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits) {
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
funkce adjustTime(offset * SECS_PER_HOUR); to nedělá, po celej rok se jen přičítá 1 hodina pro SEČ.
V popisu knihovny ani v jejich příkladech jsem nic k přepínání zimní/letní nenašel. _________________ Jirka
Založen: Jan 01, 2023 Příspěvky: 2090 Bydliště: Česká Lípa
Zaslal: ne duben 28 2024, 19:05 Předmět:
Celeron napsal(a):
Tak že to v tý knihovně TimeLib Valdano není?
Je tam na to jen částečná podpora a zbytek je potřeba dopsat jak už jsem zmínil. Jen se musí vědět jak správně na to. Níže jsem upravil příklad dle mé specifické varianty řešení. Upravte si to podle toho.
// do techto promennych je potreba nacitat UTC cas a datum z GPS
// nacitani casu z GPS neni soucast tohoto prikladu
uint8_t gps_sec_utc; // 0 az 59
uint8_t gps_min_utc; // 0 az 59
uint8_t gps_hod_utc; // 0 az 23
uint8_t gps_den_utc; // 1 az 31
uint8_t gps_mes_utc; // 1 az 12
int gps_rok_utc; // napr. 2024
int gps_rok_last = -1; // posledni z GPS nactene cislo roku
unsigned long casovasNacitaniGps;
// pomocne promenne pro zacatek a konec letniho rozmezi casu v UTC
// dle definovanych pravidel ve funkci Nastav_utc_rozsah_letni()
time_t utc_letni_zac;
time_t utc_letni_end;
// do techto promennych se prevadi UTC cas z GPS na lokalni cas CR viz nize
time_t tt_loc_cr;
tmElements_t tm_loc_cr;
void Nastav_utc_rozsah_letni (int rok)
{
int i;
time_t tt;
tmElements_t cs;
// UTC zacatek pro letni casove rozmezi v CR
// od 01:00 posledni nedeli v breznu
cs.Second = 0;
cs.Minute = 0;
cs.Hour = 1;
cs.Day = 1;
cs.Month = 4;
cs.Year = (uint8_t)(rok - 1970);
tt = makeTime(cs) - SECS_PER_DAY;
// najdeme posledni nedeli v breznu
for (i=1; i<8; i++) {
cs.Wday = 0;
breakTime(tt, cs);
if (cs.Wday == 1) {
// nedele
utc_letni_zac = tt;
break;
} else {
tt -= SECS_PER_DAY;
};
};
// UTC konec pro letni casove rozmezi v CR
// do 01:00 posledni nedeli v rijnu
cs.Second = 0;
cs.Minute = 0;
cs.Hour = 1;
cs.Day = 1;
cs.Month = 11;
cs.Year = (uint8_t)(rok - 1970);
tt = makeTime(cs) - SECS_PER_DAY;
// najdeme posledni nedeli v rijnu
for (i=1; i<8; i++) {
cs.Wday = 0;
breakTime(tt, cs);
if (cs.Wday == 1) {
// nedele
utc_letni_end = tt;
break;
} else {
tt -= SECS_PER_DAY;
};
};
}
void Preved_utc_na_lokal()
{
time_t tt;
tmElements_t cs;
cs.Second = gps_sec_utc;
cs.Minute = gps_min_utc;
cs.Hour = gps_hod_utc;
cs.Day = gps_den_utc;
cs.Month = gps_mes_utc;
cs.Year = (uint8_t)(gps_rok_utc - 1970);
tt = makeTime(cs);
if (tt >= utc_letni_zac && tt <= utc_letni_end) {
// UTC cas je v letnim rozmezi pro CR
// takze provedeme prepocet na letni cas UTC + 2h
tt_loc_cr = tt + (SECS_PER_HOUR * 2);
} else {
// UTC cas neni v letnim rozmezi
// takze provedeme prepocet na bezny cas v CR tj. UTC + 1h
tt_loc_cr = tt + SECS_PER_HOUR;
};
breakTime(tt_loc_cr, tm_loc_cr);
}
void loop()
{
// nenacitat cas z GPS zbytecne casto v kazdem cyklu
// ale treba jen jednou za sekundu
// v programu muzete pouzit promennou gps_rok_last pro detekci nacteni casu
if (gps_rok_last < 0 || (millis() - casovasNacitaniGps) > 1000) {
// od startu programu cas z GPS jeste nebyl nacten nebo uplynula sekunda
if (gps.encode(SerialGPS.read())) {
gps.crack_datetime(&gps_rok_utc, &gps_mes_utc , &gps_den_utc,
&gps_hod_utc, &gps_min_utc, &gps_sec_utc, NULL, NULL);
if (gps_rok_last != gps_rok_utc) {
// nastaveni letniho UTC rozsahu jen pokud se rok lisi od predchoziho volani
gps_rok_last = gps_rok_utc;
Nastav_utc_rozsah_letni(gps_rok_utc);
};
// nyni se zavola prevedeni casu
// napriklad
// UTC cas 17:50:00 28.4.2024 prevede na lokalni letni cas 19:50:00 28.4.2024
Preved_utc_na_lokal();
// a nyni bude v
// tt_loc_cr lokalni cas CR jako cislo (pocet sekund o zacatku roku 1970)
// tm_loc_cr lokalni cas CR jako struktura tmElements_t
// POZOR: tm_loc_cr.Year je hodnota 0 az 255 kde 0=1970
// takze souctem 1970 + tm_loc_cr.Year ziskate spravnou hodnotu roku
digitalClockDisplay();
};
casovasNacitaniGps = millis();
};
}
Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: ne duben 28 2024, 23:19 Předmět:
Teda jestli jsi to celý psal, tak to ses docela nadřel, velké díky.
Opravil jsem dvě chyby v syntaxi, co vyhodil kompiler IDE. Zrušil jsem načítání z GPS a v definicích na začátku jsem ručně doplňoval datum a čas. Zkoušel jsem zatím jen rok 2028 a vypadá to, že maká jak má. Tedy nejsem si jistej, jestli se správně přepíná podle hodin, posuď sám:
23.3. 2028 pokud je UTC 0:0:0, tak výpis času je 1:0:0. Pokud je UTC 1:0:0 tak je výpis 3:0:0.
29.10.2028 pokud je UTC 1:0:0, tak výpis času je 3:0:0. Pokud je UTC 2:0:0 tak je výpis 3:0:0.
Problém je, že to zabírá v 328P pětinu flešky a čtvrtinu RAMky a když k tomu přidám hlavní část projektu, pro kterou je tenhle doplněk, tak se to nevejde, musel bych použít Every.
Zkouším tady něco svýho přes tabulku, kde je 6 začátků a 6 konců letního času ve formátu DD:MM:RRRR pro rok 2024 až 2029. Když se to stále opakuje po šesti letech, tak stačí jen od roku většího než 2029 odečístat 6 aby se rok dostal do rozsahu 2024 až 2029. Hodiny neřeším, jen dny. Rozsahy měsíc 11.-2. a 4.-9. jsou jasný hned, takže zbývá jen 3. a 10. měsíc. Ten 3. měsíc mi chodí jak má, ale 10. ne a nevím proč. Je to zatím asi 4 x menší na obou pamětech, než co jsi napsal Ty. Když se mi to nepovede zprovoznit, tak budu muset sáhnout na to Tvý řešení. Možná bys to měl dát na Github, aby z toho měli užitek i ostatní.
Ještě jednou díky! _________________ Jirka
Založen: Jan 01, 2023 Příspěvky: 2090 Bydliště: Česká Lípa
Zaslal: po duben 29 2024, 1:41 Předmět:
Celeron napsal(a):
Problém je, že to zabírá v 328P pětinu flešky a čtvrtinu RAMky a když k tomu přidám hlavní část projektu, pro kterou je tenhle doplněk, tak se to nevejde, musel bych použít Every.
A co použít třeba WeMos D1 Mini? Tam je 4MB Flash a 64 KB SRAM což je mnohem víc místa než v 328P i Every. Nemluvě o mnohem výkonnějším procesoru.
Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: po duben 29 2024, 9:54 Předmět:
Nelze, potřebuju víc analogů. Včera jsem nakonec rozchodil toto:
kód:
#include <TimeLib.h> // Knihovna pro práci s časem
#include <avr/pgmspace.h>
const int letniCasOdDo[][4] PROGMEM = {
{31, 3, 2024}, // Datum začátku letního času v roce 2024
{27, 10, 2024}, // Datum konce letního času v roce 2024
{30, 3, 2025}, // Datum začátku letního času v roce 2025
{26, 10, 2025}, // Datum konce letního času v roce 2025
{29, 3, 2026}, // Datum začátku letního času v roce 2026
{25, 10, 2026}, // Datum konce letního času v roce 2026
{28, 3, 2027}, // Datum začátku letního času v roce 2027
{31, 10, 2027}, // Datum konce letního času v roce 2027
{26, 3, 2028}, // Datum začátku letního času v roce 2028
{29, 10, 2028}, // Datum konce letního času v roce 2028
{25, 3, 2029}, // Datum začátku letního času v roce 2029
{28, 10, 2029}, // Datum konce letního času v roce 2029
};
const int pocetZmenCasu = sizeof(letniCasOdDo) / sizeof(letniCasOdDo[0]);
//***********************************************
void setup() {
Serial.begin(9600);
// Nastavení aktuálního času
setTime(0, 0, 0, 26, 3, 2028); // Nastavte počáteční datum
// Kontrola, zda je aktuální čas v letním čase nebo ne
bool letniCas = jeLetniCas(year(), month(), day(), hour());
if (letniCas) {
Serial.println("Aktuálně je letní čas.");
} else {
Serial.println("Aktuálně je zimní čas.");
}
}
//************************************************
bool jeLetniCas(int year, int month, int day, int hour) {
// Odečíst 6 let, dokud není rok nižší nebo roven 2029
while (year > 2029) {
year -= 6;
}
// Pokud je měsíc mezi dubnem a zářím, je jednoznačně letní čas
if (month > 3 && month < 10) {
return true;
}
// Pokud je měsíc mezi listopadem a únorem, je jednoznačně zimní čas
if (month < 3 || month > 10) {
return false;
}
// Pokud je měsíc březen nebo říjen, zkontrolujeme, zda je datum změny na letní čas
for (int i = 0; i < pocetZmenCasu; i++) {
if (month == 3) {
if (pgm_read_byte(&(letniCasOdDo[i][0])) <= day && pgm_read_byte(&(letniCasOdDo[i][1])) == month && pgm_read_word(&(letniCasOdDo[i][2])) == year) {
return true; // začíná letní čas
}
}
if (month == 10) {
if (pgm_read_byte(&(letniCasOdDo[i+1][0])) > day && pgm_read_byte(&(letniCasOdDo[i+1][1])) == month && pgm_read_word(&(letniCasOdDo[i+1][2])) == year) {
return true; //ještě je letní čas
}
}
}
return false;
}
//***************************************
void loop() {
}
//***************************************
Když byla tabulka změn v RAM, tak 9% flash a 18% RAM. Po použití PROGMEM tedy přesunu tabulky do flash je kupodivu stále 9%flash ale jen 13% RAM.
Program je zjednodušený, dny kdy se mění čas jsou změněný už od půlnoci. Pro moji potřebu to vůbec nevadí.
Tak teď ten odzkoušený příklad zapracovat do zobrazení času v GPS. _________________ Jirka
Založen: Jan 01, 2023 Příspěvky: 2090 Bydliště: Česká Lípa
Zaslal: po duben 29 2024, 19:15 Předmět:
Celeron napsal(a):
Nelze, potřebuju víc analogů.
V tom případě zvažte ESP32-DevKitC. Tam je víc analogů i binárů a jsou tam myslím dokonce 2 mega RAM.
Celeron napsal(a):
Když byla tabulka změn v RAM, tak 9% flash a 18% RAM. Po použití PROGMEM tedy přesunu tabulky do flash je kupodivu stále 9%flash ale jen 13% RAM.
ATmega328P má 1024 bajtů EEPROM. Můžete tedy zvážit uložení té tabulky do EEPROM, ale i tak si moc nepomůžete, protože jste se zbytkem RAM a FLASH už docela nízko. Takže v případě nějakého rozšiřování v budoucnu zřejmě znovu narazíte. ESP32 by tedy bylo řešením na hodně dlouho do budoucna bez nutnosti se obávat, že vám dojde FLASH či RAM.
Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: po duben 29 2024, 21:15 Předmět:
Nerozumím, ty procenta jsou obsazenost, ne volný místo. Když jsem to zapracoval do hlavního programu GPS normálu, tak je ještě přes 30% flash a 42% RAM volno. _________________ Jirka
Založen: Jan 01, 2023 Příspěvky: 2090 Bydliště: Česká Lípa
Zaslal: út duben 30 2024, 0:28 Předmět:
Myslel jsem to ve vztahu k tomu původnímu příkladu bez tabulky. Psal jste, že když tam přidáte hlavní část projektu tak se to tam už nevejde.
Celeron napsal(a):
Problém je, že to zabírá v 328P pětinu flešky a čtvrtinu RAMky a když k tomu přidám hlavní část projektu, pro kterou je tenhle doplněk, tak se to nevejde, musel bych použít Every.
Navíc i když jste to teď tou tabulkou obešel tak to pořád není žádná sláva, protože 328P má celkově jenom 2KB RAM, a to opravdu není nic moc. Takže do budoucna stačí zas nějaká další trochu na paměť náročnější úprava a zas budete bojovat s pamětí. Použití ESP32 by bylo řešením na dlouho do budoucna bez jakýchkoli obav o nedostatek místa v RAM nebo FLASH a analogových i binárních IO tam rozhodně je dostatek.
Založen: Apr 02, 2011 Příspěvky: 18547 Bydliště: Nový Bydžov
Zaslal: út duben 30 2024, 6:57 Předmět:
A proč a nač nějaká budoucí úprava, když už to dělá vše, co je potřeba a nic víc od toho potřeba není? A plošák je na 328P v DIL28. _________________ Jirka
Časy uváděny v GMT + 1 hodina Jdi na stránku 1, 2Další
Strana 1 z 2
Nemůžete odesílat nové téma do tohoto fóra. Nemůžete odpovídat na témata v tomto fóru. Nemůžete upravovat své příspěvky v tomto fóru. Nemůžete mazat své příspěvky v tomto fóru. Nemůžete hlasovat v tomto fóru. Nemůžete připojovat soubory k příspěvkům Můžete stahovat a prohlížet přiložené soubory
Informace na portálu Elektro bastlírny jsou prezentovány za účelem vzdělání čtenářů a rozšíření zájmu o elektroniku. Autoři článků na serveru neberou žádnou zodpovědnost za škody vzniklé těmito zapojeními. Rovněž neberou žádnou odpovědnost za případnou újmu na zdraví vzniklou úrazem elektrickým proudem. Autoři a správci těchto stránek nepřejímají záruku za správnost zveřejněných materiálů. Předkládané informace a zapojení jsou zveřejněny bez ohledu na případné patenty třetích osob. Nároky na odškodnění na základě změn, chyb nebo vynechání jsou zásadně vyloučeny. Všechny registrované nebo jiné obchodní známky zde použité jsou majetkem jejich vlastníků. Uvedením nejsou zpochybněna z toho vyplývající vlastnická práva. Použití konstrukcí v rozporu se zákonem je přísně zakázáno. Vzhledem k tomu, že původ předkládaných materiálů nelze žádným způsobem dohledat, nelze je použít pro komerční účely! Tento nekomerční server nemá z uvedených zapojení či konstrukcí žádný zisk. Nezodpovídáme za pravost předkládaných materiálů třetími osobami a jejich původ. V případě, že zjistíte porušení autorského práva či jiné nesrovnalosti, kontaktujte administrátory na diskuzním fóru EB.