// 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) { #ifdef pouzivat_SD_kartu // 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) rtclock.breakTime(tt_file,mtt_file); } else // od poledne az do nasledujici pulnoci se uz vytvari normalni dnesni soubor { rtclock.breakTime(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 { sd.begin(pin_SD_CS,SD_SCK_HZ(F_CPU/4)); //inicializace SD karty pro pripad, ze by byla predtim vytazena if (!sd.exists(jmeno_slozky)) { sd.mkdir(jmeno_slozky); } boolean 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 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); } soubor.println(vystupni_retezec); delay(20); soubor.close(); } else { #ifdef displej_TM1637_5 zobraz_text(37); // na displeji napis 5d-Er = chyba karty #endif #ifdef signal_LED analogWrite(pin_LED_B, 200); // rozsvitit modrou LED #endif tone_X(pin_bzuk,500, 100); // chybove pipnuti delay(2000); } } else // karta je vysunuta, nic se nezapisuje { #ifdef signal_LED blik_B(); // pri vysunute karte blikne modrou LED #endif } #endif // kdyz neni nastaveno pouzivani SD karty, tak se ukladaci podprogram preskakuje } //---------------------------------------------- #ifdef pouzivat_SD_kartu // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat //---------------------------------------------- // 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) { *date = FAT_DATE(LOC_rok, LOC_mes, LOC_den); *time = FAT_TIME(LOC_hod, LOC_min, LOC_sek); } //---------------------------------------------- #endif //---------------------------------------------- // 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; } //---------------------------------------------- #ifndef omezeni_funkci_2 // tuto funkci je mozne kvuli uspore prostoru v PROGMEM uplne vypnout //---------------------------------------------- // 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) { #ifdef pouzivat_SD_kartu // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat char dbg_cesta[] = "RTC_set.csv"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { sd.begin(pin_SD_CS,SD_SCK_HZ(F_CPU/4)); //inicializace SD karty pro pripad, ze by byla predtim vytazena boolean 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(); } } #endif // kdyz neni povolene pouzivani SD karty, nic se nestane } //---------------------------------------------- #endif #ifndef omezeni_funkci_2 // tuto funkci je mozne kvuli uspore prostoru v PROGMEM uplne vypnout //---------------------------------------------- // vypis zaznamenanych dat z SD karty do seriove linky void RTC_SD_READ(void) { #ifdef pouzivat_SD_kartu // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat char buff[10]; // buffer pro ukladani ctenych dat ze souboru char dbg_cesta[] = "RTC_set.csv"; // jmeno souboru, ktery se ma vypisovat Serial.println(dbg_cesta); Serial.println("-------------"); if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o cteni { sd.begin(pin_SD_CS,SD_SCK_HZ(F_CPU/4)); //inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(dbg_cesta, O_READ); if (open_OK) { while ((soubor.fgets(buff, sizeof(buff))) > 0) // cist znak po znaku, dokud neco obsahuje { Serial.print(buff); } delay(20); soubor.close(); } } Serial.println("-------------"); #endif // kdyz neni SD karta povolena, podprogram se nevykona } //---------------------------------------------- #endif //---------------------------------------------- // Zapis parametru ze systemove oblasti EEPROM na SD kartu jako textovy soubor // (zaloha systemoveho nastaveni) void SD_sysMEM_WRITE(void) { #ifdef pouzivat_SD_kartu // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat char cesta[] = "SYS_MEM.TXT"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { zobraz_RTC(false); sd.begin(pin_SD_CS,SD_SCK_HZ(F_CPU/4)); //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) { for (unsigned int adr_mem = 0; adr_mem < 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 } #endif // kdyz neni SD karta povolena, podprogram se nevykona } //---------------------------------------------- // Obnoveni parametru z SD karty do systemove casti pameti (adresy 8 az 699) s vyjimkou // identifikace, casove kalibrace a zachytneho bodu pro hledani prazdneho mista void SD_sysMEM_READ(void) { #ifdef pouzivat_SD_kartu // kdyz je nastaveno pouzivani SD karty, tak se z ni muze cist char cesta[] = "SYS_MEM.TXT"; char buff[15]; // buffer pro ukladani ctenych dat ze souboru if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { zobraz_RTC(false); sd.begin(pin_SD_CS,SD_SCK_HZ(F_CPU/4)); //inicializace SD karty pro pripad, ze by byla predtim vytazena open_OK = soubor.open(cesta, O_READ); // soubor pro cteni if (open_OK) { for (unsigned int adr_mem = 0; adr_mem < 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 if (adr_mem > 7 and adr_mem != 18) // nekolik parametru se preskakuje (kalibrace casu, zachytny bod) { unsigned int adr_dat = (buff[4] - 48) * 100; // vsechno ostatni se prepisuje 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(18,0); // zachytny bod pro hledani volne pameti se nastavi na 0 } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } #endif // 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) { #ifdef pouzivat_SD_kartu // kdyz je nastaveno pouzivani SD karty, tak se muze ukladat char cesta[] = "SYS_LOG.TXT"; if (digitalRead(pin_karta_IN) == LOW) // LOW = karta zasunuta, muze se provest pokus o zapis { zobraz_RTC(false); sd.begin(pin_SD_CS,SD_SCK_HZ(F_CPU/4)); //inicializace SD karty pro pripad, ze by byla predtim vytazena 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) { 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 (adresa < 10 ) soubor.print('0'); if (adresa < 100) soubor.print('0'); soubor.print(adresa); soubor.print(';'); if (logdata > 999) // omezeni cisla na sirku 3 znaky { soubor.println("^^^"); } else { if (logdata < 10 ) soubor.print('0'); if (logdata < 100) soubor.print('0'); soubor.println(logdata); } soubor.close(); } else { chyba(2); } // SD-Err } else { chyba(3); // No-SD } #endif // kdyz neni SD karta povolena, nic se neloguje }