// podprogramy pro praci s SD kartou //================================================ char jmeno_souboru[] = "20190125.csv"; // retezec pro konstrukci jmena souboru char jmeno_slozky[] = "2019"; // retezec pro konstrukci nazvu slozky char cesta[] = "2019/20190125.csv"; // retezec pro konstrukci cele cesty k souboru //---------------------------------------------- // zapis dat na kartu do souboru (\rok\yyyymmdd.csv) // vcetne nastaveni datumu a casu posledniho zapisu souboru do FAT void SD_save(void) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { // nejdriv zjistit, jestli je dneska pred polednem, nebo po poledni. Podle toho se urci jmeno souboru. // Kdyz je dnesek jeste pred polednem, uklada se do souboru s predchozim dnem unsigned long tt = rtc_korekce(); // aktualni cas v RTC v sekundach od 1.1.1970 sek1970_datcas(tt,false); // mtt_file se pouziva k vytvoreni jmena souboru a slozky, a proto tam muze byt nekdy i vcerejsek if (mtt.hour < 12) // od pulnoci se cele dopoledne dnesniho dne ulkada jeste do vcerejsiho souboru { tt_file = tt - 43200UL; // datum je o 12 hodin starsi (vcerejsi) breakTimeFCE(tt_file,mtt_file); } else // od poledne az do nasledujici pulnoci se uz vytvari normalni dnesni soubor { breakTimeFCE(tt,mtt_file); } // den, mesic a rok pro jmeno souboru a slozky LOC_den_file = mtt_file.day; LOC_mes_file = mtt_file.month; LOC_rok_file = mtt_file.year+1970; rokmesden = LOC_rok_file * 10000 + LOC_mes_file*100 + LOC_den_file; // zacatek obdobi, pro ktere plati zaznamenane hodnoty (napriklad pri aktualnim case "23.5.2019 16:48" se zaznamena 20190523) jmeno_slozky[0] = 48 + ((LOC_rok_file % 10000) / 1000 ); // tisice let jmeno_slozky[1] = 48 + ((LOC_rok_file % 1000) / 100 ); // stovky let jmeno_slozky[2] = 48 + ((LOC_rok_file % 100) / 10 ); // desitky let jmeno_slozky[3] = 48 + ((LOC_rok_file % 10)) ; // jednotky roku jmeno_souboru[0] = 48 + ((rokmesden % 100000000L) / 10000000L ); // rad tisicu roku jmeno_souboru[1] = 48 + ((rokmesden % 10000000L) / 1000000L ); // rad stovek roku jmeno_souboru[2] = 48 + ((rokmesden % 1000000L) / 100000L ); // rad desitek roku jmeno_souboru[3] = 48 + ((rokmesden % 100000L) / 10000L ); // rad jednotek roku jmeno_souboru[4] = 48 + ((rokmesden % 10000L) / 1000L ); // rad desitek mesicu jmeno_souboru[5] = 48 + ((rokmesden % 1000L) / 100L ); // rad jednotek mesicu jmeno_souboru[6] = 48 + ((rokmesden % 100L) / 10L ); // rad desitek dni jmeno_souboru[7] = 48 + ((rokmesden % 10L) ); // rad jednotek dni // jmeno_souboru[8] = '.'; // tyhle znaky se nemeni // jmeno_souboru[9] = 'c'; // jmeno_souboru[10] = 's'; // jmeno_souboru[11] = 'v'; // jmeno_souboru[12] = '\0'; for ( i = 0; i< 4 ; i++) { cesta[i] = jmeno_slozky[i]; } cesta[4] = '/'; for ( i = 5; i< 18 ; i++) { cesta[i] = jmeno_souboru[i-5]; } if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena if (!sd.exists(jmeno_slozky)) sd.mkdir(jmeno_slozky); bool novy_soubor; if (!sd.exists(cesta)) novy_soubor = true; // Soubor neexistuje - bude se zapisovat hlavicka else novy_soubor = false; // Soubor uz existuje - hlavicka se zapisovat nebude if (novy_soubor == true) // pri zalozeni noveho souboru se jeho jmeno (yyyymmdd) zaznamena do EEPROM { // pak se muze pouzit pro funkci "vypis POSLEDNIHO souboru se zaznamy" EEPROM_write_long(eeaddr_posledni_den,rokmesden); } SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(cesta, O_WRITE | O_APPEND | O_CREAT); if (open_OK) { if (vytvaret_hlavicku == true and novy_soubor == true) { // soubor.println(hlavicka); print_co_kam(false, true); } // soubor.println(vystupni_retezec); print_co_kam(true, true); delay(20); soubor.close(); } else { chyba(2); // SD-Err } } else // karta je vysunuta, nic se nezapisuje { bitSet(err_bit,2); // SD karta je vysunuta, nastavuje se bit v promenne 'err_bit' if (bitRead(signal_LED,2) == true) // pokud je povoleno bliknuti LED pri chybach { blik_B(); // pri vysunute karte blikne modrou LED } } } // kdyz neni nastaveno pouzivani SD karty, tak se ukladaci podprogram preskakuje } //---------------------------------------------- //---------------------------------------------- // podprogram pro nastavovani datumu a casu u souboru na SD karte: // zdroj: https://forum.arduino.cc/index.php?topic=348562.0 void dateTime(uint16_t* date, uint16_t* time) { if (pouzivat_SD_kartu == true) { *date = FAT_DATE(LOC_rok, LOC_mes, LOC_den); *time = FAT_TIME(LOC_hod, LOC_min, LOC_sek); } } //---------------------------------------------- //---------------------------------------------- // prevede cast pole prijato[] na integer // (reseni s podprogramem je hlavne kvuli uspore mista v PROGMEM - prevzal jsem to z jineho sveho programu a uz se mi to nechtelo predelavat) // priklad: prijato = { 50, 48, 49, 56} // v ASCII znacich to je prijato = {'2', '0', '1', '8'} // tak zavolani funkce "prijato_int(0,4)" vrati cislo 2018 unsigned int prijato_int( byte znak_start, byte znak_stop) { unsigned int soucet = 0; unsigned int mocnina = 0; for (i = znak_start; i < znak_stop; i++) { switch (znak_stop - i) { case 1: mocnina = 1; break; case 2: mocnina = 10; break; case 3: mocnina = 100; break; case 4: mocnina = 1000; break; } soucet = soucet + (prijato[i] - '0') * mocnina ; } return soucet; } //---------------------------------------------- //---------------------------------------------- // Pri nastaveni casu pres GPS se zaznamenaji na SD kartu udaje o aktualnim case v RTC aby bylo mozne zjistovat presnost vnitrniho RTC void RTC_SD(unsigned long novy, unsigned long v_rtc, long odchylka, unsigned long interval, unsigned long log_korekce , unsigned int logznacka) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { char dbg_cesta[] = "LOGS/RTC_set.csv"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena bool RTC_hlavicka = false; if (!sd.exists(dbg_cesta)) RTC_hlavicka = true; // Soubor neexistuje - bude se zapisovat hlavicka SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(dbg_cesta, O_WRITE | O_APPEND | O_CREAT); if (open_OK) { if (RTC_hlavicka == true) { soubor.println("YYYY/MM/DD;hh:nn:ss; GPS [s] ; RTC [s] ; RTC-GPS ; int[D]; kor[h] ;9 Info 0;"); // soubor.println("===================================================================================;"); for (byte i = 0 ; i < 83 ; i++) { soubor.print('='); } soubor.println(';'); } soubor.print(DATCAS_retezec); soubor.print(';'); soubor.print(novy); soubor.print(';'); if (v_rtc < 1000000000UL) soubor.print(" "); else soubor.print(v_rtc); soubor.print(';'); if (odchylka < 0) soubor.print('-'); else soubor.print('+'); odchylka = abs(odchylka); if (odchylka < 1000000000L) soubor.print('0'); if (odchylka < 100000000L) soubor.print('0'); if (odchylka < 10000000L) soubor.print('0'); if (odchylka < 1000000L) soubor.print('0'); if (odchylka < 100000L) soubor.print('0'); if (odchylka < 10000L) soubor.print('0'); if (odchylka < 1000L) soubor.print('0'); if (odchylka < 100L) soubor.print('0'); if (odchylka < 10L) soubor.print('0'); soubor.print(odchylka); soubor.print(';'); if (interval > 63115200) { soubor.print(" "); } else { if ((interval / 86400) < 100) soubor.print('0'); if ((interval / 86400) < 10) soubor.print('0'); soubor.print(interval / 86400.0,3); } soubor.print(';'); if (log_korekce == 0x7FFFFFFFUL) { soubor.print(" "); } else { if (log_korekce >= 0x80000000UL) soubor.print('-'); else soubor.print('+'); log_korekce = (0x7FFFFFFF & log_korekce); // odstraneni nejjvyssiho bitu jako znamenka if ((log_korekce / 3600) < 100000UL) soubor.print('0'); if ((log_korekce / 3600) < 10000UL) soubor.print('0'); if ((log_korekce / 3600) < 1000UL) soubor.print('0'); if ((log_korekce / 3600) < 100UL) soubor.print('0'); if ((log_korekce / 3600) < 10UL) soubor.print('0'); soubor.print((log_korekce/3600.0),2); } soubor.print(';'); if (logznacka < 512) soubor.print('0'); if (logznacka < 256) soubor.print('0'); if (logznacka < 128) soubor.print('0'); if (logznacka < 64) soubor.print('0'); if (logznacka < 32) soubor.print('0'); if (logznacka < 16) soubor.print('0'); if (logznacka < 8) soubor.print('0'); if (logznacka < 4) soubor.print('0'); if (logznacka < 2) soubor.print('0'); soubor.print(logznacka,BIN); soubor.println(';'); delay(20); soubor.close(); } } else // karta neni zasunuta { bitSet(err_bit,2); // SD karta je vysunuta, nastavuje se bit v promenne 'err_bit' } } // kdyz neni povolene pouzivani SD karty, nic se nestane } //---------------------------------------------- //---------------------------------------------- // Zapis parametru ze systemove oblasti EEPROM na SD kartu jako textovy soubor // (zaloha systemoveho nastaveni) void SD_sysMEM_WRITE(void) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { char cesta[] = "LOGS/SYS_MEM.TXT"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(cesta, O_WRITE | O_CREAT); // pripadny stary soubor se prepisuje if (open_OK) { soubor.print(EEPROM_verze); // na prvni radku v souboru se ulozi verze rozlozeni EEPROM, se kterou je zaloha vytvorena // "ver:001\r\n" bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' for (unsigned int adr_mem = 0; adr_mem < eeaddr_MIN_EEPROM; adr_mem ++) // zapisuje se cela oblast adres 0 az 699 { if (adr_mem < 10 ) soubor.print('0'); if (adr_mem < 100) soubor.print('0'); soubor.print(adr_mem); soubor.print(';'); byte data_mem = EEPROM_read(adr_mem); if (data_mem < 10 ) soubor.print('0'); if (data_mem < 100) soubor.print('0'); soubor.println(data_mem); Serial.print(adr_mem); Serial.print(';'); Serial.println(data_mem); } soubor.close(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } } // kdyz neni SD karta povolena, podprogram se nevykona } //---------------------------------------------- // Obnoveni parametru z SD karty do systemove casti pameti (adresy 8 az 699) s vyjimkou // casove kalibrace a zachytneho bodu pro hledani prazdneho mista void SD_sysMEM_READ(void) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se z ni muze cist { char cesta[] = "LOGS/SYS_MEM.TXT"; char buff[15]; // buffer pro ukladani ctenych dat ze souboru unsigned int adr_dat; // prectena data pro kazdou adresu bool shoda; bool vynechat; // nektere udaje se nenahrazuji starymi hodnotami ze souboru a ponechavaji se v EEPROM beze zmeny if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(cesta, O_READ); // soubor pro cteni if (open_OK) { soubor.fgets(buff, 9); // prvni radka je pro zjisteni rozlozeni dat v EEPROM (verze) shoda = true; for (byte i = 0; i < 7 ; i++) { if (buff[i] != EEPROM_verze[i]) shoda = false; // kdyz se verze neshoduji, neni mozne obnoveni } if (shoda == false) { Serial.println(lng321); // "Verze zalohovaneho souboru se neshoduje s verzi pozadovanou v tomto programu." Serial.print(buff); Serial.print(EEPROM_verze); return; // obnovovaci podprogram se ukonci } bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' for (unsigned int adr_mem = 0; adr_mem < eeaddr_MIN_EEPROM; adr_mem ++)// cte se cela oblast adres 0 az do prvniho bajtu prvniho zaznamu (adresa 700) { soubor.fgets(buff, 9); // prvni 3 znaky jsou adresa, dalsi znak je strednik, pak 3 znaky pro data, nakonec ukonceni radky CRLF vynechat = false; // nektere udaje se nenahrazuji starymi hodnotami ze souboru a ponechavaji se v EEPROM beze zmeny if ((adr_mem >= eeaddr_RTC_set) and (adr_mem <= (eeaddr_RTC_set + 3))) vynechat = true; // cas posledni kalibrace if ((adr_mem >= eeaddr_RTC_korekce) and (adr_mem <= (eeaddr_RTC_korekce + 3))) vynechat = true; // autokorekce if (adr_mem == eeaddr_10kB_znacka) vynechat = true; // zachytny bod pro hledani prazdneho mista if (vynechat == false) // vsechno ostatni se prepisuje hodnotami ze souboru { adr_dat = (buff[4] - 48) * 100; adr_dat = adr_dat + (buff[5] - 48) * 10; adr_dat = adr_dat + (buff[6] - 48); Serial.print(adr_mem); Serial.print(';'); Serial.println(adr_dat); EEPROM_write(adr_mem,adr_dat); } } soubor.close(); EEPROM_write(eeaddr_10kB_znacka,0); // zachytny bod pro hledani volne pameti se nastavi na 0 SOFT_RESET(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } } // kdyz neni SD karta povolena, podprogram se nevykona } //---------------------------------------------- //---------------------------------------------- // Pokud je povolene detailni logovani, uklada se do souboru "SYS_LOG.TXT" na SD kartu kazda zmena obsahu EEPROM na adresach 0 az 699 // Specialni kody pro dalsi typy logu (999 = bezne zapnuti napajeni) void SD_log(unsigned long adresa , unsigned int logdata) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { char log_cesta[] = "LOGS/SYS_LOG.TXT"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); sd.begin(SD_CONFIG); // inicializace SD karty pro pripad, ze by byla predtim vytazena if (!sd.exists("LOGS")) sd.mkdir("LOGS"); // kdyz slozka "\LOGS\" neexistuje, tak se vytvori SdFile::dateTimeCallback(dateTime); open_OK = log_soubor.open(log_cesta, O_WRITE | O_APPEND | O_CREAT); // dalsi logy se pridavaji na konec logovaciho souboru if (open_OK) { bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' if (LOC_rok < 2000) // jen ochrana pro spatne nastavene RTC { DATCAS_retezec[0] = '1'; DATCAS_retezec[1] = '9'; DATCAS_retezec[2] = 48 + ((LOC_rok-1900) / 10); DATCAS_retezec[3] = 48 + ((LOC_rok-1900) % 10); } else { DATCAS_retezec[0] = '2'; DATCAS_retezec[1] = '0'; DATCAS_retezec[2] = 48 + ((LOC_rok - 2000) / 10); DATCAS_retezec[3] = 48 + ((LOC_rok - 2000) % 10); } DATCAS_retezec[5] = 48 + (LOC_mes / 10); DATCAS_retezec[6] = 48 + (LOC_mes % 10); DATCAS_retezec[8] = 48 + (LOC_den / 10); DATCAS_retezec[9] = 48 + (LOC_den % 10); DATCAS_retezec[11] = 48 + (LOC_hod / 10); DATCAS_retezec[12] = 48 + (LOC_hod % 10); DATCAS_retezec[14] = 48 + (LOC_min / 10); DATCAS_retezec[15] = 48 + (LOC_min % 10); DATCAS_retezec[17] = 48 + (LOC_sek / 10); DATCAS_retezec[18] = 48 + (LOC_sek % 10); log_soubor.print(DATCAS_retezec); log_soubor.print(';'); if (adresa < 10 ) log_soubor.print('0'); if (adresa < 100) log_soubor.print('0'); log_soubor.print(adresa); log_soubor.print(';'); if (logdata > 999) // omezeni cisla na sirku 3 znaky { log_soubor.println("^^^"); } else { if (logdata < 10 ) log_soubor.print('0'); if (logdata < 100) log_soubor.print('0'); log_soubor.println(logdata); } log_soubor.close(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } } // kdyz neni SD karta povolena, nic se neloguje } //---------------------------------------------- // v rezimu prubezneho mereni jasu BEZ KOREKCE se merene hodnoty ukladaji do souboru "logjas.txt" void logjas(unsigned int logovane_cislo) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { char cesta[] = "LOGS/logjas.txt"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena if (!sd.exists("LOGS")) sd.mkdir("LOGS"); // kdyz slozka "\LOGS\" neexistuje, tak se vytvori SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(cesta, O_WRITE | O_APPEND | O_CREAT); // dalsi logy se pridavaji na konec logovaciho souboru if (open_OK) { bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' if (LOC_rok < 2000) // jen ochrana pro spatne nastavene RTC { DATCAS_retezec[0] = '1'; DATCAS_retezec[1] = '9'; DATCAS_retezec[2] = 48 + ((LOC_rok-1900) / 10); DATCAS_retezec[3] = 48 + ((LOC_rok-1900) % 10); } else { DATCAS_retezec[0] = '2'; DATCAS_retezec[1] = '0'; DATCAS_retezec[2] = 48 + ((LOC_rok - 2000) / 10); DATCAS_retezec[3] = 48 + ((LOC_rok - 2000) % 10); } DATCAS_retezec[5] = 48 + (LOC_mes / 10); DATCAS_retezec[6] = 48 + (LOC_mes % 10); DATCAS_retezec[8] = 48 + (LOC_den / 10); DATCAS_retezec[9] = 48 + (LOC_den % 10); DATCAS_retezec[11] = 48 + (LOC_hod / 10); DATCAS_retezec[12] = 48 + (LOC_hod % 10); DATCAS_retezec[14] = 48 + (LOC_min / 10); DATCAS_retezec[15] = 48 + (LOC_min % 10); DATCAS_retezec[17] = 48 + (LOC_sek / 10); DATCAS_retezec[18] = 48 + (LOC_sek % 10); soubor.print(DATCAS_retezec); soubor.print(';'); if (logovane_cislo < 10000) soubor.print('0'); if (logovane_cislo < 1000) soubor.print('0'); if (logovane_cislo < 100) soubor.print('0'); if (logovane_cislo < 10) soubor.print('0'); soubor.println(logovane_cislo); soubor.close(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } } // kdyz neni SD karta povolena, nic se neloguje } //---------------------------------------------- //---------------------------------------------- // docasne ukladani merene hodnoty do souboru "logafd.txt" void logafd(uint32_t logovane_cislo) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { char cesta[] = "LOGS/logafd.txt"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena if (!sd.exists("LOGS")) sd.mkdir("LOGS"); // kdyz slozka "\LOGS\" neexistuje, tak se vytvori SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(cesta, O_WRITE | O_APPEND | O_CREAT); // dalsi logy se pridavaji na konec logovaciho souboru if (open_OK) { bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' if (LOC_rok < 2000) // jen ochrana pro spatne nastavene RTC { DATCAS_retezec[0] = '1'; DATCAS_retezec[1] = '9'; DATCAS_retezec[2] = 48 + ((LOC_rok-1900) / 10); DATCAS_retezec[3] = 48 + ((LOC_rok-1900) % 10); } else { DATCAS_retezec[0] = '2'; DATCAS_retezec[1] = '0'; DATCAS_retezec[2] = 48 + ((LOC_rok - 2000) / 10); DATCAS_retezec[3] = 48 + ((LOC_rok - 2000) % 10); } DATCAS_retezec[5] = 48 + (LOC_mes / 10); DATCAS_retezec[6] = 48 + (LOC_mes % 10); DATCAS_retezec[8] = 48 + (LOC_den / 10); DATCAS_retezec[9] = 48 + (LOC_den % 10); DATCAS_retezec[11] = 48 + (LOC_hod / 10); DATCAS_retezec[12] = 48 + (LOC_hod % 10); DATCAS_retezec[14] = 48 + (LOC_min / 10); DATCAS_retezec[15] = 48 + (LOC_min % 10); DATCAS_retezec[17] = 48 + (LOC_sek / 10); DATCAS_retezec[18] = 48 + (LOC_sek % 10); soubor.print(DATCAS_retezec); soubor.print(';'); if (logovane_cislo < 10000) soubor.print('0'); if (logovane_cislo < 1000) soubor.print('0'); if (logovane_cislo < 100) soubor.print('0'); if (logovane_cislo < 10) soubor.print('0'); soubor.println(logovane_cislo); soubor.close(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } } // kdyz neni SD karta povolena, nic se neloguje } //---------------------------------------------- //---------------------------------------------- // Obsah vybraneho souboru vypise do seriove linky. // Podle parametru 2 muze vypsat jen cast souboru (poslednich nekolik radek). // Parametr 3 u nekterych typu souboru vybira konkretni jmeno souboru (typy 'B' a 'C'), nebo umoznuje filtraci vypisovanych adres (typ 'A'). // Funkce ma nasledujici parametry // @> [t][,par2][,par3] // // t ... typ souboru // A "/LOGS/SYS_LOG.TXT" // B "/yyyy/########.csv" // C "/R30S/r_30s_##.csv" // D "/LOGS/RTC_set.csv" // E "/LOGS/SYS_MEM.TXT" // F "/LOGS/logafd.txt" // G "/LOGS/logjas.txt" // H "/TRCK/trck####.gpx" // ? "/HELP/2_[.txt" (napoveda - bez zadani typu je to default) // // param2 ... maximalni pocet zaznamu (radek) pro vypis // (minimum je 1; bez parametru = 50) radky se pocitaji od konce souboru // Pri typu '?' se vypisuje cela napoveda, nezavisle na zadanem poctu radek. // Pri typu 'H' se vypisuje cely GPX soubor, nezavisle na zadanem poctu radek. // // param3 ... pro typ A volba vypisovane adresy // (bez parametru = vsechno) // pro typ B datum v CSV souboru // (bez parametru = datum posledniho zaznamu) // pro typ C poradove cislo ## ve jmene "r_30s_##.csv" // (bez parametru = posledni pouzite cislo) // pro typ H poradove cislo #### ve jmene "trck####.gpx" // (bez parametru = posledni pouzite cislo) // pro ostatni typy souboru je parametr 3 vypusten. void file_to_serkom(char typ, unsigned int param2, unsigned int param3) { unsigned int read_adresa; // adresa, ktera se precte z radky sys_logu unsigned int pocet_radek = 0; // pocet zjistenych radek v souboru unsigned int delka_radky; // kazdy typ souboru ma jiny pocet znaku char cesta[] = "XXXX/12345678.XYZ"; // retezec pro konstrukci cele cesty k souboru pro pripad, ze je soubor v nejake slozce char f_name_A[] = "LOGS/SYS_LOG.TXT "; // definice konkretnich jmen souboru char f_name_B[] = "2024/20240825.csv"; // misto cisel bude rok jako slozka a datum ve formatu YYYYMMDD jako jmeno souboru char f_name_C[] = "R30S/r_30s_##.csv"; // cislo ## se bude jeste upravovat podle 3. parametru char f_name_D[] = "LOGS/RTC_set.csv "; char f_name_E[] = "LOGS/SYS_MEM.TXT "; char f_name_F[] = "LOGS/logafd.txt "; char f_name_G[] = "LOGS/logjas.txt "; char f_name_H[] = "TRCK/trck####.gpx"; // cislo #### se bude upravovat podle 3. parametru char f_name_I[] = "HELP/2_[.txt "; // pozustatek z doby, kdy se napoveda pro tuto funkci vypisovala jako default prikazu '@>' nebo "@>?" if (pouzivat_SD_kartu == true) { if (typ == 'A') // priklad souboru: "LOGS/SYS_LOG.TXT " { for (byte fn_znak = 0; fn_znak < 16 ; fn_znak ++) { cesta[fn_znak] = f_name_A[fn_znak]; } cesta[16] = '\0'; delka_radky = 29; } if (typ == 'B') // priklad souboru: "2024/20240420.csv" { f_name_B[0] = 48 + ((param3 % 100000000UL) / 10000000UL ); // rad tisicu roku ve jmenu slozky f_name_B[1] = 48 + ((param3 % 10000000UL) / 1000000UL ); // rad stovek roku ve jmenu slozky f_name_B[2] = 48 + ((param3 % 1000000UL) / 100000UL ); // rad desitek roku ve jmenu slozky f_name_B[3] = 48 + ((param3 % 100000UL) / 10000UL ); // rad jednotek roku ve jmenu slozky f_name_B[4] = '/'; f_name_B[5] = f_name_B[0]; // rad tisicu roku ve jmenu souboru f_name_B[6] = f_name_B[1]; // rad stovek roku ve jmenu souboru f_name_B[7] = f_name_B[2]; // rad desitek roku ve jmenu souboru f_name_B[8] = f_name_B[3]; // rad jednotek roku ve jmenu souboru f_name_B[9] = 48 + ((param3 % 10000UL) / 1000UL ); // rad desitek mesicu ve jmenu souboru f_name_B[10] = 48 + ((param3 % 1000UL) / 100UL ); // rad jednotek mesicu ve jmenu souboru f_name_B[11] = 48 + ((param3 % 100UL) / 10UL ); // rad desitek dni ve jmenu souboru f_name_B[12] = 48 + ((param3 % 10UL) ); // rad jednotek dni ve jmenu souboru f_name_B[13] = '.'; f_name_B[14] = 'c'; f_name_B[15] = 's'; f_name_B[16] = 'v'; for (byte fn_znak = 0; fn_znak < 17 ; fn_znak ++) { cesta[fn_znak] = f_name_B[fn_znak]; } cesta[17] = '\0'; delka_radky = velikost_hlavicky + 2; // delka radky je zavisla na poctu pouzitych rezervnich cidel } if (typ == 'C') // priklad souboru: "R30S/r_30s_25.csv" { for (byte fn_znak = 0; fn_znak < 17 ; fn_znak ++) { cesta[fn_znak] = f_name_C[fn_znak]; } if (param3 < 100) { cesta[11] = 48 + ((param3 % 100UL) / 10UL ); // rad desitek v poradovem cisle cesta[12] = 48 + ((param3 % 10UL) ); // rad jednotek v poradovem cisle } else // pri parametru 100 a vice je ve jmene souboru misto cisla dvojite 'x' ("r_30s_xx.csv") { cesta[11] = 'x'; cesta[12] = 'x'; } cesta[17] = '\0'; delka_radky = 100; } if (typ == 'D') // priklad souboru: "LOGS/RTC_set.csv "; { for (byte fn_znak = 0; fn_znak < 16 ; fn_znak ++) { cesta[fn_znak] = f_name_D[fn_znak]; } cesta[16] = '\0'; delka_radky = 86; } if (typ == 'E') // priklad souboru: "LOGS/SYS_MEM.TXT " { for (byte fn_znak = 0; fn_znak < 16 ; fn_znak ++) { cesta[fn_znak] = f_name_E[fn_znak]; } cesta[16] = '\0'; delka_radky = 9; } if (typ == 'F') // priklad souboru: "LOGS/logafd.txt " { for (byte fn_znak = 0; fn_znak < 15 ; fn_znak ++) { cesta[fn_znak] = f_name_F[fn_znak]; } cesta[15] = '\0'; cesta[16] = '\0'; delka_radky = 27; } if (typ == 'G') // priklad souboru: "LOGS/logjas.txt " { for (byte fn_znak = 0; fn_znak < 15 ; fn_znak ++) { cesta[fn_znak] = f_name_G[fn_znak]; } cesta[15] = '\0'; cesta[16] = '\0'; delka_radky = 27; } if (typ == 'H') // priklad souboru "TRCK/trck1234.gpx"; { f_name_H[9] = 48 + ((param3 % 10000) / 1000 ); // rad tisicu f_name_H[10] = 48 + ((param3 % 1000) / 100 ); // rad stovek f_name_H[11] = 48 + ((param3 % 100) / 10 ); // rad desitek f_name_H[12] = 48 + ((param3 % 10) ); // rad jednotek for (byte fn_znak = 0; fn_znak < 17 ; fn_znak ++) { cesta[fn_znak] = f_name_H[fn_znak]; } cesta[17] = '\0'; delka_radky = 109; } if (typ == '?') // priklad souboru "HELP/2_[.txt"; { for (byte fn_znak = 0; fn_znak < 12 ; fn_znak ++) { cesta[fn_znak] = f_name_I[fn_znak]; } cesta[12] = '\0'; cesta[13] = '\0'; cesta[14] = '\0'; cesta[15] = '\0'; cesta[16] = '\0'; delka_radky = 100; // pri vypisu obycejneho textoveho souboru, ktery se dal nezpracovava, na delce radky nezalezi } if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o cteni { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' Serial.print(cesta); //---------------------------------------------------------------------------------------------- // prvni otevreni souboru je jen pro zjisteni poctu radek - je to rychle, nic se nevypisuje sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(cesta, O_READ); // otevreni souboru vcetne slozky if (open_OK) { pocet_radek = 0; while ((soubor.fgets(read_buffer, delka_radky)) > 0) // cist znak po znaku, dokud soubor neco obsahuje { if (typ == 'A') // pri vypisu syslogu se nepocitaji vsechny radky, ale jen ty, ktere odpovidaji zadane adrese { read_adresa = ((read_buffer[20] - 48) * 100) + ((read_buffer[21] - 48) * 10) + (read_buffer[22] - 48); if (param3 == read_adresa or param3 == 1000) { pocet_radek ++; } } else // pri ostatnich typech souboru se pocitaji vsechny radky { pocet_radek ++; } } soubor.close(); if (typ == 'H' or typ == '?' ) // u trasovaciho souboru a u napovedy se vypisuje vzdycky vsechno { param2 = pocet_radek; // proto se parametr 2 nastavi na celkove zjisteny pocet radek } if (typ == 'H') // u trasovaciho souboru a u napovedy se misto poctu radek vypisuje pocet zaznamenanych bodu { param2 = pocet_radek; // u trasovaciho souboru, se vypisuje vzdycky vsechno proto se parametr 2 nastavi na celkove zjisteny pocet radek Serial.print(" ("); Serial.print(lng360); // "pocet GPS bodu: " if (trackuj == true and param3 == (EEPROM_read_int(eeaddr_GPS_track_id) & 0x3FFF)) // kdyz se vypisuje prave bezici soubor ... { pocet_radek = pocet_radek - 5; // ... z celkoveho poctu se odecita 6 radek ze zacatku souboru } else { pocet_radek = pocet_radek - 11; // ve vsech ostatnich pripadech se odecita 9 radek (5 na zacatku souboru, 6 na konci) } Serial.print(pocet_radek); Serial.println(')'); } if (typ == '?' ) // u napovedy se vypisuje vzdycky vsechno { param2 = pocet_radek; // proto se parametr 2 nastavi na celkove zjisteny pocet radek Serial.println(' '); // a pred vypisem se zadny pocet radek nezobrazuje (jen se odradkuje za jmenem souboru) } if (typ >= 'A' and typ <= 'G' ) // u ostatnich souboru se vypisuje pocet vsech radek v souboru { Serial.print(lng342); //" (pocet radek: " Serial.print(pocet_radek); Serial.println(')'); } Serial.println("-------------"); // oznaceni zacatku souboru //---------------------------------------------------------------------------------------------- // druhe otevreni souboru uz zobrazuje radky v seriove lince, ale nejdriv si spocita, kolik radek se ma ignorovat sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(cesta, O_READ); // otevreni souboru vcetne slozky if (open_OK) { while ((soubor.fgets(read_buffer, delka_radky)) > 0) // cist znak po znaku, dokud soubor neco obsahuje { if (digitalRead(pin_tl_ok) == false) // predcasne ukonceni dlouheho vypisu stiskem tlacitka [OK], { break; } if (typ == 'A') // pri vypisu logovaciho souboru se porovnava adresa v bufferu [20] az [22] s pozadovanou adresou { read_adresa = ((read_buffer[20] - 48) * 100) + ((read_buffer[21] - 48) * 10) + (read_buffer[22] - 48); if (param3 == read_adresa or param3 == 1000) // vypisuji se jen shodne adresy, nebo pri adrese 1000 se vypise vsechno { pocet_radek --; // celkovy pocet radek se v tomto cyklu zase odecita if (pocet_radek < param2) // logy se tisknou jen v pripade, ze jich od konce souboru zbyva mene, nez pozadovany pocet logu { Serial.print(read_buffer); delay(1); // pri vypisech se mezi radky dela kratka pauza } } } if (typ == 'H') // pri vypisu trackovaciho souboru se vypisuji vsechny radky, a muze se provadet i matematicka analyza souradnic { Serial.print(read_buffer); delay(2); } if (typ > 'A' and typ < 'H') // u vsech ostatnich typu souboru ('B' az 'G') se jen vypisuji posledni radky { pocet_radek --; // celkovy pocet radek se v tomto cyklu zase odecita if (pocet_radek < param2) // logy se tisknou jen v pripade, ze jich od konce souboru zbyva mene, nez pozadovany pocet logu { Serial.print(read_buffer); delay(1 + (delka_radky / 100)); // pri vypisech se mezi radky dela kratka pauza } } } soubor.close(); } else { Serial.println(lng320); // "chyba pri otevirani souboru / soubor neexistuje" } } else { Serial.println(lng320); // "chyba pri otevirani souboru / soubor neexistuje" } Serial.println("-------------"); // oznaceni konce vypisu } } } //---------------------------------------------- //---------------------------------------------- // Obsah vybraneho HELP souboru vypise do seriove linky. // jmeno souboru vcetne cesty je v globalnim znakovem poli 'helpfile_name[]' ("HELP/#_#.txt") void helpfile(void) { char read_buffer[300]; // sem se bude nacitat obsah souboru a prubezne zpracovavat if (pouzivat_SD_kartu == true) { if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o cteni { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' Serial.println(helpfile_name); Serial.println("-------------"); // oznaceni zacatku souboru sd.begin(SD_CONFIG); // inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(helpfile_name, O_READ); // otevreni souboru vcetne slozky if (open_OK) { while ((soubor.fgets(read_buffer, 100)) > 0) // cist znak po znaku, dokud soubor neco obsahuje { if (digitalRead(pin_tl_ok) == false) // predcasne ukonceni dlouheho vypisu stiskem tlacitka [OK], { break; } else { Serial.print(read_buffer); delay(2); // pri vypisech se mezi radky dela kratka pauza } } soubor.close(); } else { if (helpfile_name[5] == 'm') // na prikaz ?? se nejdriv pokusi vypsat soubor "/HELP/mmm.txt" { // kdyz neexistuje, nebo nejde otevrit vypisou se vsechny bezene napovedy najednou ser_napoveda0(); ser_napoveda1(); ser_napoveda2(); ser_napoveda3(); ser_napoveda4(); ser_napoveda5(); } else { Serial.println(lng320); // "chyba pri otevirani souboru / soubor neexistuje" } } Serial.println("-------------"); // oznaceni konce vypisu } else { if (helpfile_name[5] == 'm') // na prikaz ?? se nejdriv pokusi vypsat soubor "/HELP/mmm.txt" { // kdyz ale neni karta zasunuta, vypisou se vsechny bezene napovedy najednou ser_napoveda0(); ser_napoveda1(); ser_napoveda2(); ser_napoveda3(); ser_napoveda4(); ser_napoveda5(); } else { Serial.print(lng136); // " SD karta: " Serial.println(lng138); // "vysunuta" } } } } //---------------------------------------------- //---------------------------------------------- // do globalni promenne "GPS_track_cesta[]" se pripravi nazev souboru pro ukladani trasy void zaloz_GPX_soubor(void) { if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { zobraz_RTC(false); unsigned int track_cislo = EEPROM_read_int(eeaddr_GPS_track_id) & 0x7FFF; // precte posledni pouzity index GPX souboru track_cislo ++; // zvetsi ho o jednicku if (track_cislo > 9999) track_cislo = 1; // pri prekroceni povoleneho rozsahu se priste bude zacinat od 1 EEPROM_write_int(eeaddr_GPS_track_id , track_cislo); // a zapise ho zpatky (trasovani je i v EEPROM porad zastavene) nastav_cestu_tracku(); // pripravi jmeno GPX souboru s novym indexem if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena if (!sd.exists("TRCK")) sd.mkdir("TRCK"); // kdyz slozka "\TRCK\" neexistuje, tak se vytvori SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(GPS_track_cesta, O_WRITE | O_APPEND | O_CREAT); if (open_OK) { bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' // zapsat GPX hlavicku na zacatek souboru soubor.println(" "); soubor.println(" "); soubor.println(" "); soubor.print("SQM - "); for (byte zn = 5 ; zn <= 16 ; zn++) { soubor.print(GPS_track_cesta[zn]); } soubor.print(" - Local DateTime: "); soubor.print(LOC_rok); soubor.print('-'); if(LOC_mes < 10) soubor.print('0'); soubor.print(LOC_mes); soubor.print('-'); if(LOC_den < 10) soubor.print('0'); soubor.print(LOC_den); soubor.print(' '); if(LOC_hod < 10) soubor.print('0'); soubor.print(LOC_hod); soubor.print(':'); if(LOC_min < 10) soubor.print('0'); soubor.print(LOC_min); soubor.print(':'); if(LOC_sek < 10) soubor.print('0'); soubor.print(LOC_sek); soubor.println(" "); soubor.println(" "); soubor.close(); unsigned int cislo_tracku = EEPROM_read_int(eeaddr_GPS_track_id) | 0x8000; // nastavi nejvyssi bit (trasovani na spusteno) EEPROM_write_int(eeaddr_GPS_track_id , cislo_tracku); trackuj = true; posledni_zaznam_tracku = millis(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } } } //---------------------------------------------- //---------------------------------------------- // do posledniho vytvoreneho trasovaciho GPX souboru prida jeden zaznam souradnic void track_GPS(void) { float sourad_print; if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); gps(0); if (GPS_alt < 9500 ) // k zapisu bodu dojde jen v pripade, ze jsou vyskova data v normalnich mezich. Kdyz jeste neni zafixovano, odesila se ve vysce 65535m n.m. { sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(GPS_track_cesta, O_WRITE | O_APPEND | O_CREAT); // dalsi souradnice se pridavaji na konec souboru if (open_OK) { bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' // zapsat bod do GPX souboru ve spravnem formatu (cas je v UTC formatu). Priklad: // +0495.000000 if (pole_GPS_I2C[9] < 99) // jen test spravneho roku (test funkcni komunikace I2C) { // pri nejake necekane chybe komunikace se mi stalo, ze se vratil triznakovy rok soubor.print(" 90000000UL) // severni sirka { sourad_print = (GPS_lat-90000000UL) / 1000000.0; soubor.print('+'); } else // jizni sirka { sourad_print = GPS_lat / 1000000.0; soubor.print('-'); } if (sourad_print < 10) soubor.print('0'); // uvodni nula pro sirku soubor.print( sourad_print, 6); soubor.print("\" lon=\""); if (GPS_lon > 180000000UL) // vychodni delka { sourad_print = (GPS_lon - 180000000UL) / 1000000.0; soubor.print('+'); } else // zapadni delka { sourad_print = GPS_lon / 1000000.0; soubor.print('-'); } if (sourad_print < 100) soubor.print('0'); // uvodni nula pro delku if (sourad_print < 10) soubor.print('0'); // uvodni nula pro delku soubor.print(sourad_print , 6); soubor.print("\">"); sourad_print = GPS_alt - 500; if (sourad_print > 0) soubor.print('+'); else soubor.print('-'); sourad_print = abs(sourad_print); if (sourad_print < 1000) soubor.print('0'); // uvodni nula pro vysku if (sourad_print < 100) soubor.print('0'); // uvodni nula pro vysku if (sourad_print < 10) soubor.print('0'); // uvodni nula pro vysku soubor.print(sourad_print , 6); soubor.print(""); } soubor.close(); if (bitRead(signal_LED,5) == true) // kdyz je blikani pri trasovani povolene { blik_G_fast(); // 1x se kratce blikne zelene } posledni_zaznam_tracku = millis(); } else { chyba(2); } // SD-Err } else // souradnice nejsou k dispozici { posledni_zaznam_tracku = millis() - (track_interval * 500); // dalsi pokus o zapis prijde za polovicni dobu, nez je nastaven interval } } else { chyba(3); // No-SD } } // kdyz neni SD karta povolena, nic se neloguje } //---------------------------------------------- //---------------------------------------------- //provede ukonceni GPX souboru void ukonci_GPX_soubor(void) { long read_akt = 0; // pro moznost prumerovani souradnic v GPX souboru se v prvnim pruchodu hledaji minima a maxima vsech tri souradnic long track_off_lon = 0; // z minima a maxima se spocte offset pro prumerovani long track_off_lat = 0; long track_off_alt = 0; long track_suma_lat = 0; // soucty upravenych souradnic long track_suma_lon = 0; long track_suma_alt = 0; long track_min_lon = 180000000; long track_max_lon = 0; long track_min_lat = 90000000; long track_max_lat = 0; long track_min_alt = 9999; long track_max_alt = -500; float prum_lat; // finalni hodnoty prumeru, ktere se budou zapisovat do prumerovaciho waypoint float prum_lon; float prum_alt; unsigned int delka_radky = 0; long pocet_bodu = 0; if (pouzivat_SD_kartu == true) // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat { if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { bitClear(err_bit,2); // SD karta je zasunuta, maze se pripadny bit v promenne 'err_bit' sd_out_err = true; // pri vytazeni karty a pokusu o pristi zapis se 1x zahlasi "no-Sd" zobraz_RTC(false); // ------- pred ukoncenim GPS souboru se provede analyza GPS souradnic ------------------ // --- prvni otevreni souboru je jen pro zjisteni poctu radek a minimalnich a maximalnich hodnot v souradnicich --- sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena delka_radky = 109; open_OK = soubor.open(GPS_track_cesta, O_READ); // otevreni souboru vcetne slozky if (open_OK) { pocet_bodu = 0; while ((soubor.fgets(read_buffer, delka_radky)) > 0) // cist znak po znaku, dokud soubor neco obsahuje { if (read_buffer[12] == '+' or read_buffer[12] == '-') // pracuje se jen s radky, ktere obsahuji souradnice { pocet_bodu ++; read_akt = buf_to_long(12,15); // hodnota zemepisne sirky if (read_akt > track_max_lat) track_max_lat = read_akt; if (read_akt < track_min_lat) track_min_lat = read_akt; read_akt = buf_to_long(29,33); // hodnota zemepisne delky if (read_akt > track_max_lon) track_max_lon = read_akt; if (read_akt < track_min_lon) track_min_lon = read_akt; read_akt = buf_to_long(47,52)/1000000; // hodnota nadmorske vysky (tam se pocita v celych metrech bez desetinne casti) if (read_akt > track_max_alt) track_max_alt = read_akt; if (read_akt < track_min_alt) track_min_alt = read_akt; } } soubor.close(); track_off_lat = (track_max_lat + track_min_lat) / 2; // tyhle hodnoty se budou v druhem pruchodu odecitat od kazde souradnice prd jejim scitanim do prumeru track_off_lon = (track_max_lon + track_min_lon) / 2; track_off_alt = (track_max_alt + track_min_alt) / 2; } else // chyba otevreni souboru ... { chyba(2); // SD-Err return; // predcasny navrat z podprogramu bez ukonceni souboru a zastaveni trasovani } // --- druhe otevreni souboru projde znova vsechny souradnice a pomoci odectu vypoctenych offsetu spocte prumery souradnic --- sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(GPS_track_cesta, O_READ); // otevreni souboru vcetne slozky if (open_OK) { while ((soubor.fgets(read_buffer, delka_radky)) > 0) // cist znak po znaku, dokud soubor neco obsahuje { if (read_buffer[12] == '+' or read_buffer[12] == '-') // pracuje se jen s radky, ktere obsahuji souradnice { read_akt = buf_to_long(12,15) - track_off_lat; // hodnota zemepisne sirky posunuta o offset track_suma_lat = track_suma_lat + read_akt; read_akt = buf_to_long(29,33) - track_off_lon; // hodnota zemepisne delky posunuta o offset track_suma_lon = track_suma_lon + read_akt; read_akt = (buf_to_long(47,52)/1000000) - track_off_alt; // hodnota nadmorske vysky posunuta o offset (tady se pocita s celymi metry bez desetinne casti) track_suma_alt = track_suma_alt + read_akt; } } if (pocet_bodu > 0) { prum_lat = (track_off_lat + (track_suma_lat / (float)pocet_bodu)) / 1000000.0; prum_lon = (track_off_lon + (track_suma_lon / (float)pocet_bodu)) / 1000000.0; prum_alt = (track_off_alt + (track_suma_alt / (float)pocet_bodu)); } else // kdyz neni ani jeden zapsany bod, neda se prumerovat (deleni nulou) { prum_lat = 0; prum_lon = 0; prum_alt = 0; } soubor.close(); } else // chyba otevreni souboru ... { chyba(2); // SD-Err return; // predcasny navrat z podprogramu bez ukonceni souboru a zastaveni trasovani } // ----------- treti otevreni GPX souboru uz jen zapise statistiky a zaverecne znacky sd.begin(SD_CONFIG); //inicializace SD karty pro pripad, ze by byla predtim vytazena SdFile::dateTimeCallback(dateTime); open_OK = soubor.open(GPS_track_cesta, O_WRITE | O_APPEND | O_CREAT); // pridani dat na konec souboru if (open_OK) { bitClear(err_bit,1); // SD karta je v poradku, maze se pripadny bit v promenne 'err_bit' soubor.println(" "); soubor.println(" "); // zapis prumernych souradnic do GPX souboru jako waypoint (zapisuje az za blok ....) // "+0372.000000 AvgPoint " soubor.print(""); if (prum_alt < 0) soubor.print('-'); else soubor.print('+'); prum_alt = abs(prum_alt); if (prum_alt < 1000) soubor.print('0'); if (prum_alt < 100) soubor.print('0'); if (prum_alt < 10) soubor.print('0'); soubor.print(prum_alt,6); soubor.print(""); soubor.print(" AvgPoint "); soubor.println(" "); // zapis strednich souradnic do GPX souboru jako waypoint (zapisuje az za blok ....) // "+0372.000000 MidPoint " prum_lat = track_off_lat / 1000000.0; // jen vypujceny nazev promenne soubor.print(""); prum_alt = track_off_alt / 1000000.0; // jen vypujceny nazev promenne if (prum_alt < 0) soubor.print('-'); else soubor.print('+'); prum_alt = abs(track_off_alt); if (prum_alt < 1000) soubor.print('0'); if (prum_alt < 100) soubor.print('0'); if (prum_alt < 10) soubor.print('0'); soubor.print(prum_alt,6); soubor.print(""); soubor.print(" MidPoint "); soubor.println(" "); //zapis znacky s minimalnimi a maximalnimi souradnicemi // " " soubor.print(" "); soubor.println(" "); // zapis poznamky s poctem bodu // " " soubor.print(" "); soubor.print(" "); soubor.close(); } else { chyba(2); // SD-Err } } else { chyba(3); // No-SD } } unsigned int track_cislo = EEPROM_read_int(eeaddr_GPS_track_id) & 0x7FFF; // smaze nejvyssi bit (trasovani zastaveno) EEPROM_write_int(eeaddr_GPS_track_id , track_cislo); // a ulozi nezmenene cislo ulozi zpatky do EEPROM trackuj = false; } //---------------------------------------------- //---------------------------------------------- // podle cisla tracku v EEPROM pripravi jmeno GPX souboru void nastav_cestu_tracku(void) { unsigned int cislo_tracku = EEPROM_read_int(eeaddr_GPS_track_id) & 0x7FFF; // nejvyssi bit udava stav trasovani // GPS_track_cesta[] = "TRCK/trck1234.gpx"; GPS_track_cesta[9] = 48 + ((cislo_tracku % 10000) / 1000); // tisice GPS_track_cesta[10] = 48 + ((cislo_tracku % 1000) / 100); // stovky GPS_track_cesta[11] = 48 + ((cislo_tracku % 100) / 10); // desitky GPS_track_cesta[12] = 48 + ((cislo_tracku % 10) ); // jednotky } //---------------------------------------------- //---------------------------------------------- // prevede textovou hodnotu ze zadane pozice v "read_buffer[]" na long hodnotu bez desetinne tecky // priklad "+49.444332" prevede na 49444332 long buf_to_long(byte zacatek_cisla,byte tecka) { char temp_buf[13]; byte cil_ukazatel = 0; for (byte pozice = zacatek_cisla; pozice < zacatek_cisla + 12 ; pozice++) { if (pozice != tecka) { temp_buf[cil_ukazatel] = read_buffer[pozice]; cil_ukazatel ++; } } temp_buf[12] = 'X'; return atol(temp_buf); }