// menu ovladane 3 tlacitky se zobrazovanim na displeji //====================================================== unsigned long trvani_stisku; // doba drzeni tlacitka OK v milisekundach v hlavnim menu unsigned long trvani_stisku2; // doba drzeni tlacitka OK v milisekundach v podmenu unsigned long start_UD; // promenne pro automaticke listovani pri dlouhem stisku tlacitek nahoru a dolu unsigned int cas_UD; boolean auto_UD; byte pocet_polozek_menu; int pozice_menu1; // nalistovana pozice v hlavnim menu // 0 = LIST (listovani v poslednich namerenych hodnotach) // 1 = Auto: (nastaveni automatickeho zaznamu) // 2 = ZonA: (prepinani LETO/ZIMA - SEC/SELC) // 3 = CALIb: (zobrazeni a ulozeni jasu bez prepoctu) // 4 = dAtuM: (zobrazeni a moznost nastaveni datumu) // 5 = CAS: (zobrazeni a moznost nastaveni casu) // 6 = tEPL: (prubezne zobrazovani aktualni teploty) // 7 = VLH: (prubezne zobrazovani aktualni vlhkosti) // 8 = JAS: (prubezne zobrazovani aktualniho jasu) // 9 = Ho-Mi: (prubezne zobrazovani aktualniho casu) //10 = PruM: (nastaveni prumerovani) //11 = LEd: (regulovatelna cervena svitilna) //12 = StoP: (Stopky) //13 = GPS: (zobrazeni zemepisnych souradnic) - jen kdyz je pripojeny GPS modul a jsou k dispozici data //14 = Stan (prednastavene pozorovaci stanoviste misto GPS) //15 = Spec (specialni funkce) //16 = int (specialni funkce) //21 = CoPy (specialni funkce) //22 = uHEL (naklonomer) //23 = 5L-ME Aktualni poloha Slunce a Mesice //24 = OdPOc Odpocet (budik, casovac) //25 = COMPA Kompas //26 = rA-dE prepocet Rektascenze a Deklinace na Azimut a Elevaci //27 = VoLtY Mereni napeti zdroje //---------------------------------------------- // listovani v hlavnim menu a volba polozky void menu_1(void) { blokuj_znacku30 = true; // blokovani blikani prvni segmentovky v rezimu R30s pocet_polozek_menu = pocet_polozek_v_menu + 1; // maximalni pocet pocet polozek (+1) pres ktere se listuje (nezalezi na tom, jestli jsou pouzite) // moznost rucne omezit nektere polozky v menu pole_zobr_menu[ 0] = true; // LIST pole_zobr_menu[ 1] = true; // Auto pole_zobr_menu[ 2] = true; // ZonA pole_zobr_menu[ 3] = true; // CALIb pole_zobr_menu[ 4] = true; // dAtuM pole_zobr_menu[ 5] = true; // CAS pole_zobr_menu[ 6] = true; // tEPL pole_zobr_menu[ 7] = true; // VLH pole_zobr_menu[ 8] = true; // JAS pole_zobr_menu[ 9] = true; // Ho-Mi pole_zobr_menu[10] = true; // PruM pole_zobr_menu[11] = true; // LEd pole_zobr_menu[12] = true; // StoP pole_zobr_menu[13] = false; // GPS polozka se povoluje automaticky podle toho, jestli je GPS zasunute a povolene pole_zobr_menu[14] = true; // 5tAn (Stan) Prednastavene pozorovaci stanoviste kdyz neni zasunuty GPS modul pole_zobr_menu[15] = false; // #SPEC polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[16] = false; // # int polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[17] = false; // #PAr2 polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[18] = false; // #PAr3 polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[19] = false; // #FCE1 polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[20] = false; // #FCE2 polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[21] = false; // #CoPy polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[22] = false; // uHEL polozka se povoluje automaticky podle typu zasunuteho specialniho HW pole_zobr_menu[23] = true; // 5L-ME pole_zobr_menu[24] = true; // odPoc pole_zobr_menu[25] = false; // COMPA Kompas polozka se povoluje automaticky pokud je pouzito cidlo LSM303DLHC pole_zobr_menu[26] = false; // rA-dE Ra-Dec na Az-El polozka se povoluje automaticky pokud je pouzito cidlo LSM303DLHC pole_zobr_menu[27] = true; // VoLtY mereni napeti zdroje // ---- zacatek bloku R30s -- // ---- konec bloku R30s -- #ifdef modul_LSM303DLHC pole_zobr_menu[22] = true; // uHEL pole_zobr_menu[25] = true; // CoMPA pole_zobr_menu[26] = true; // rA-dE #endif #ifdef ukladat_GPS if (digitalRead(pin_EXT_ZAP) == internal_GPS) // kdyz je GPS povolene a zasunute, tak se polozka bude zobrazovat { pole_zobr_menu[13] = true; // polozku GPS zobrazit pole_zobr_menu[14] = false; // polozku Stan nezobrazit } else { pole_zobr_menu[13] = false; // polozku GPS nezobrazit pole_zobr_menu[14] = true; // polozku Stan zobrazit } #endif auto_exit_casovani = millis(); // vstup do menu spousti casovac automatickeho vypadnuti z menu if (prvni_vstup_do_menu == true) // pri prvnim vstupu do menu po zapnuti napajeni najde prvni zobrazitelnou polozku { for (byte po = 0; po < pocet_polozek_menu ; po++) // pri vypnuti nejake polozky menu v uvodnich definicich programu se tady tato polozka skutecne zakaze { if (menu_enable[po] == false) pole_zobr_menu[po] = false; } // pro pripad, ze by nekdo zakazal vsechny polozky krome tech, ktere se stejne nezobrazuji bylo nutne porovnat dve pole boolean menu_dostupne = false; for (byte po = 0; po <= pocet_polozek_v_menu ; po ++) { if (menu_enable[po] == true and pole_zobr_menu[po] == true) // byla nalezena alespon jedna polozka k zobrazeni { menu_dostupne = true; pozice_menu1 = po; break; // vypadnuti ze smycky for } } if (menu_dostupne == false) // zadna polozka se nema zobrazovat { while (digitalRead(pin_tl_ok) == LOW) delay(100); // cekani na uvolneni tlacitka OK s odrusenim zakmitu delay(100); return; // zadne menu se nezobrazi a po uvolneni tlacitka OK se vrati program zpatky do hlavni smycky } } prvni_vstup_do_menu = false; zobraz_text(pozice_menu1); while (digitalRead(pin_tl_ok) == LOW) // do hlavniho menu se vstoupilo dlouhym stiskem tlacitka OK { // ted je nutne pockat na jeho uvolneni delay(20); if (digitalRead(pin_tl_ok) == HIGH) delay(50); // kdyz se behem drzeni tlacitka ok objevi kratky vypadek kontaktu, tak se odignoruje } delay(50); bude_save = true; // prvni vstup do menu musi umoznit pruchod while smyckou alespon 1x while (bude_save == true) { pozice_menu1 = plusminus('#', pozice_menu1, 0, pocet_polozek_menu); // tady na teto radce se spousti listovani v hlavnim menu a dal se program dostane az po stisku OK if (bude_save == true) // ukonceni listovani v polozkach bylo provedeno dlouhym stiskem OK { podmenu(pozice_menu1); // skoci se do podmenu (kratk stisk OK v podmenu by ale zpuspobil i ukonceni menu) bude_save = true; // aby se pri navratu z podmenu kratkym stiskem OK z menu nevyskocilo, prepise se vzdycky znacka 'bude_save' na true } else // kratky stisk OK v hlavnim menu zpusobi vypadnuti z podprogramu 'menu_1' { break; } } blokuj_znacku30 = false; // povoleni blikani prvni segmentovky v rezimu R30s zobraz_text(28); // pri opusteni menu se zhasne displej } //------------------------------------------ //------------------------------------------ void podmenu(byte polozka) { int zadano; if (polozka == 14) // polozka 14 ("Stan") je trochu specialni - tam se misto pomlcek zhasne displej { // pomlcky znamenaji nenastavene pozorovaci stanoviste, proto se tady nezobrazuji zobraz_text(28); // " " } else // pro vsechny ostatni polozky se dlouhym stiskem zobrazi pomlcky { zobraz_text(29); // vsechny jednotky zobrazi "-----" a ceka se na uvolneni tlacitka (v podprogramu plusminus) } while (digitalRead(pin_tl_ok) == LOW) // do podmenu se vstoupilo dlouhym stiskem tlacitka OK { // ted je nutne pockat na jeho uvolneni delay(20); if (digitalRead(pin_tl_ok) == HIGH) delay(50); // kdyz se behem drzeni tlacitka ok objevi kratky vypadek kontaktu, tak se odignoruje } delay(50); if (polozka == 0) // LIST { zadano = plusminus('L', list,0,99); if (bude_save == true) // kdyz se z podprogramu 'plusminus()' vyskocilo dlouhym stiskem [OK], zobrazi se jedna polozka v EEPROM { list = zadano & 255; vypis_EEPROM(65531,0); } // pri navratu z podporgramu 'plusminus()' kratkym stiskem [OK], se EEPROM nevypise a vrati se na polozku 'LIST' } if (polozka == 1) // pocet minut mezi automatickym merenim { zadano = plusminus('A', automat,0,255); EEPROM_update(10,zadano & 255); automat = zadano & 255; MODdata[45] = automat; // interval automatickeho spousteni if (automat > 0) // pokud byl zadany nejaky casovy interval, { posledni_autospusteni = millis(); // spusti se prvni mereni okamzite mereni(6); } } if (polozka == 2) // SEC/SELC { zadano = plusminus('S', leto,0,1); EEPROM_update(8,zadano & 255); if ((zadano & 255) == 0) leto = false; else leto = true; } if (polozka == 3) // svetlo bez korekce pro kalibraci { delay(1000); mereni(7); // prumeruje 10 vzorku, ale vystup vraci bez korekce. Na zaver vystledek zobrazi na displeji while (digitalRead(pin_tl_ok) == HIGH) // dokud je tlacitko OK uvolnene, je videt hodnota svetla bez korekce { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni delay(20); if (digitalRead(pin_tl_up) == LOW) // prepnuti na zobrazeni posledni nezkorigovane teploty { pozice_tecky = 2; // teplota na 2 destinna mista zobraz_cislo((int_teplota - 5000 ), 1); D_pamet[4] = znak_stupen; } if (digitalRead(pin_tl_dn) == LOW) // prepnuti na zobrazeni posledniho nezkorigovaneho jasu { pozice_tecky = 3; // svetlo na 3 desetinna mista zobraz_cislo(int_svetlo , 0); } } delay(20); } if (polozka == 4) // datum { boolean pomprom_save = false; zobraz_RTC(false); // cas z RTC rozlozi do promennych "LOC_xxx" (vcetne korekci) // uprava promennych pomoci tlacitek byte zadany_den = plusminus('d', LOC_den,1,31); if (bude_save == true) pomprom_save = true; byte zadany_mesic = plusminus('M', LOC_mes,1,12); if (bude_save == true) pomprom_save = true; if (LOC_rok < 2000) LOC_rok = 2000; // kdyz jeste neni nastaveny cas v RTC, tak je rok nesmyslny, proto se upravi na '2000' byte zadany_rok = plusminus('r', LOC_rok - 2000,0,99); if (bude_save == true) pomprom_save = true; // v promennych 'zadany_den' (/ mesic / rok) jsou upravene hodnoty if (pomprom_save == true) { mtt.year = zadany_rok + 2000 - 1970; // knihovna je napsana tak, ze se cas pocita od 1.1.1970 mtt.month = zadany_mesic; mtt.day = zadany_den; mtt.hour = LOC_hod; mtt.minute = LOC_min; mtt.second = LOC_sek; if (leto == false) tt = rtclock.makeTime(mtt) - (60*60*zimni_posun); // v zime se pri ukladani casu uklada do RTC o hodinu mene (prevod SEC na UTC) else tt = rtclock.makeTime(mtt) - (60*60*letni_posun); // kdyz se nastavuje cas v lete (SELC), do RTC se uklada o dalsi hodinu mene (prevod SELC na SEC) rtclock.setTime(tt); cas_minuleho_nastaveni = 0; // zruseni automatickych korekci casu korekce = 0x7FFFFFFFUL; EEPROM_write_long(0,cas_minuleho_nastaveni); // do EEPROM se ulozi cas posledniho nastaveni (aktualni cas) a vypoctena korekce EEPROM_write_long(4,korekce); } } if (polozka == 5) // cas { boolean pomprom_save = false; zobraz_RTC(false); // cas z RTC rozlozi do promennych "LOC_xxx" (vcetne korekci) byte zadane_hodiny = plusminus('H', LOC_hod,0,23); if (bude_save == true) pomprom_save = true; byte zadane_minuty = plusminus('M', LOC_min,0,59); if (bude_save == true) pomprom_save = true; if (pomprom_save == true) { mtt.year = LOC_rok - 1970; // knihovna je napsana tak, ze se cas pocita od 1.1.1970 mtt.month = LOC_mes; mtt.day = LOC_den; mtt.hour = zadane_hodiny; mtt.minute = zadane_minuty; mtt.second = 0; if (leto == false) tt = rtclock.makeTime(mtt) - (60*60*zimni_posun); // v zime se pri ukladani casu uklada do RTC o hodinu mene (prevod SEC na UTC) else tt = rtclock.makeTime(mtt) - (60*60*letni_posun); // kdyz se nastavuje cas v lete (SELC), do RTC se uklada o dalsi hodinu mene (prevod SELC na SEC) rtclock.setTime(tt); cas_minuleho_nastaveni = 0; // zruseni automatickych korekci casu korekce = 0x7FFFFFFFUL; EEPROM_write_long(0,cas_minuleho_nastaveni); // do EEPROM se ulozi cas posledniho nastaveni (aktualni cas) a vypoctena korekce EEPROM_write_long(4,korekce); } } if (polozka == 6) // teplota { delay(500); byte pauza = 0; boolean s_korekci = true; // pri vstupu do polozky se vzdycky nejdriv zobrazuje teplota s korekci podle kalibracni tabulky while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni pauza ++; if (pauza == 200) // teplota se testuje kazde 2 sekundy (200 x 0.01s) { int pomprom = teplota(s_korekci); pauza = 0; D_pamet[4] = znak_stupen; // znacka "stupen" pro mereni teploty na prvni zobrazovaci jednotce (rad desetitisicu) pozice_tecky = 2; zobraz_cislo((pomprom - 5000 ), 1); } delay(10); if (digitalRead(pin_tl_up) == LOW and digitalRead(pin_tl_dn) == LOW) // funkce pro prepinani zobrazeni s korekci, nebo bez korekce { if (s_korekci == true) { s_korekci = false; zobraz_text(32); // "noCor" (zobrazeni prubezne teploty bez korekce ) } else { s_korekci = true; zobraz_text(33); // " Corr" (zobrazeni prubezne teploty s korekci ) } delay(50); while (digitalRead(pin_tl_up) == LOW or digitalRead(pin_tl_dn) == LOW) ; // ceka na uvolneni obou tlacitek delay(50); } } } if (polozka == 7) // vlhkost { byte pauza = 0; while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni pauza ++; if (pauza == 200) // vlhkost se testuje kazde 2 sekundy (200 x 0.01s) { unsigned int pomprom = vlhkost(); pauza = 0; D_pamet[4] = znak_V; // znacka "V" pro mereni vlhkosti na prvni zobrazovaci jednotce pozice_tecky = 2; zobraz_cislo(pomprom , 1); } delay(10); } } if (polozka == 8) // svetlo { byte pauza = 75; boolean luxmetr = false; // pri vstupu do teto polozky se zacina vzdycky rezimem SQM boolean s_korekci = true; // pri vstupu do polozky se vzdycky nejdriv zobrazuje jas s korekci podle kalibracni tabulky while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto OK { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni if (luxmetr == false) // je prepnuto na mereni mag/arcsec2 { if (pauza == 75) // svetlo se meri po 0,75 sekunde zobrazeni predchoziho mereni (75 x 0.01s) { pauza = 0; unsigned int pomprom = svetlo_1x(true,false); // meri jen 1 vzorek - bez bargrafu, je mozne prerusit stiskem tlacitka OK if (pomprom == 65535) break; // mereni bylo predcasne ukonceno tlacitkem, proto se ukonci nadrazena smycka while if (s_korekci == true) // pokud je zapnuty korekcni prepocet ... { pomprom = korekce_svetla(pomprom); // ... proved pred zobrazenim korekci podle kalibracni tabulky } pozice_tecky = 3; zobraz_cislo(pomprom , 0); } pauza ++; delay(10); } else // je prepnuto na luxmetr { zmer_lux(s_korekci); // zmeri a zobrazi aktualni hodnotu osvetleni v luxech. V pripade potreby si upravi citlivost. A podle parametru vrati cislo s korekci nebo bez korekce } if (digitalRead(pin_tl_up) == LOW) // tlacitko "nahoru" prepina na luxmetr { luxmetr = true; zobraz_text(50); // "LuXM " ("LuHM") delay(50); while (digitalRead(pin_tl_up) == LOW) // ceka na uvolneni tlacitka "Nahoru" { delay(50); if (digitalRead(pin_tl_dn) == LOW) // kdyz se pri napisu "LUXM" jeste stiskne tlacitko dolu, { s_korekci = ! s_korekci; // zinvertuje se stav korekce zobraz_text(32 + s_korekci); // a stav se zobrazi na dispeji ("Corr" / "noCor") while (digitalRead(pin_tl_dn) == LOW) delay(50); // a ceka se na uvolneni tlacitka } } delay(50); } if (digitalRead(pin_tl_dn) == LOW) // tlacitko "dolu" prepina na mereni v rezimu SQM { luxmetr = false; zobraz_text(51); // "SQM " ("5qM ") delay(50); while (digitalRead(pin_tl_dn) == LOW) // ceka na uvolneni tlacitka "dolu" { delay(50); if (digitalRead(pin_tl_up) == LOW) // kdyz se pri napisu "SQM" jeste stiskne tlacitko nahoru, { s_korekci = ! s_korekci; // zinvertuje se stav korekce zobraz_text(32 + s_korekci); // a stav se zobrazi na dispeji ("Corr" / "noCor") while (digitalRead(pin_tl_up) == LOW) delay(50); // a ceka se na uvolneni tlacitka } } delay(50); } } } if (polozka == 9) // Ho-Mi { boolean oddelovac_hodin = false; // pomocna promenna pro zjistovani stavu blikajici tecky mezi hodinama a minutama boolean ho_mi_styl = true; // zacina se vzdycky stylem Ho-Mi while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { if (digitalRead(pin_tl_up) == LOW ) // funkce pro prepinani zobrazeni Ho-Mi { ho_mi_styl = true; zobraz_text(9); // "Ho-Mi" delay(50); } if (digitalRead(pin_tl_dn) == LOW ) // funkce pro prepinani zobrazeni Mi-Se { ho_mi_styl = false; zobraz_text(56); // "Mi-Se" delay(50); } while (digitalRead(pin_tl_up) == LOW or digitalRead(pin_tl_dn) == LOW) ; // ceka na uvolneni obou tlacitek delay(50); interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni if (millis() % 1000 > 500 and oddelovac_hodin == true) { oddelovac_hodin = false; D_pamet[2] = 0; // pro prostredni displej se zrusi pomlcka mezi hodinami a minutami aktualizuj_displej(); } if (millis() % 1000 < 500 and oddelovac_hodin == false) { oddelovac_hodin = true; if (ho_mi_styl == true) ho_mi(); // zobrazeni udaje "HH-MM" na displeji (hodiny nezobrazuji uvodni nuly) else mi_se(); // zobrazeni udaje "MM-SS" na displeji (minuty zobrazuji uvodni nuly) } } } if (polozka == 10) // pocet vzorku svetla pro prumerovani svetla { zadano = plusminus('P', prumery,1,20); EEPROM_update(11,zadano & 255); prumery = zadano & 255; MODdata[40] = prumery; // pocet prumerovani } if (polozka == 11) // funkce LED svitilna { svitilna(); } if (polozka == 12) // funkce STOPKY { stopky(); } if (polozka == 13) // GPS { bool ExitFlag = false; delay(1000); gps(0); // pres I2C si stahne posledni souradnice (zprumerovane), s casem se nic nedeje - RTC se nenastavuje int lat_alt_lon = 0; // znacka, ze se zobrazuje LAT disp_GPS(GPS_lat, 0 , true); // na displeji se odscrolluje aktualni zemepisna sirka (LAT) byte pocitadlo_smycek = 0; while (digitalRead(pin_tl_ok) == HIGH and ExitFlag == false) // dokud je tlacitko OK uvolnene, jsou zobrazeny souradnice. Ze smycky se da vypadnout i nastavenim ExitFlagu na true { pocitadlo_smycek ++; if (pocitadlo_smycek == 40) // kazde 2 sekundy (40*50ms)) se aktualizuji souradnice a potom se zobrazi poslednich 5 mist na displeji { pocitadlo_smycek = 0; gps(0); // pres I2C si stahne posledni souradnice (zprumerovane), s casem se nic nedeje - RTC se nenastavuje if (lat_alt_lon == 0) disp_GPS(GPS_lat, 0, false); // na displeji se zobrazi jen poslednich 5 mist z aktualni zemepisne sirky (LAT) - bez scrollovani if (lat_alt_lon == 1) disp_GPS(GPS_alt, 1, false); // na displeji se zobrazi jen nadmorska vyska (ALT) - bez scrollovani if (lat_alt_lon == 2) disp_GPS(GPS_lon, 2, false); // na displeji se zobrazi jen poslednich 5 mist z aktualni zemepisne delky (LON) - bez scrollovani } interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni if (digitalRead(pin_tl_up) == LOW) // prepnuti na nasledujici polozku LAT -> ALT -> LON { lat_alt_lon = lat_alt_lon + 1; if (lat_alt_lon == 3) lat_alt_lon = 2; if (lat_alt_lon == 1) disp_GPS(GPS_alt, 1, false); // na displeji se zobrazi aktualni nadmorska vyska (ALT) - bez scrolovani if (lat_alt_lon == 2) disp_GPS(GPS_lon, 2, true); // na displeji se odscrolluje aktualni zemepisna sirka (LON) pocitadlo_smycek = 0; } if (digitalRead(pin_tl_dn) == LOW) // prepnuti na predchozi polozku LON -> ALT -> LAT { lat_alt_lon = lat_alt_lon - 1; if (lat_alt_lon < 0) lat_alt_lon = 0; if (lat_alt_lon == 0) disp_GPS(GPS_lat, 0, true); // na displeji se odscrolluje aktualni zemepisna sirka (LAT) - bez scrolovani if (lat_alt_lon == 1) disp_GPS(GPS_alt, 1, false); // na displeji se zobrazi aktualni nadmorska vyska (ALT) - bez scrolovani pocitadlo_smycek = 0; } while (digitalRead(pin_tl_up) == LOW or digitalRead(pin_tl_dn) == LOW) // cekani na uvolneni tlacitka UP/DOWN { delay(50); #ifndef omezeni_funkci_7 if (digitalRead(pin_tl_dn) == LOW and digitalRead(pin_tl_up) == LOW) // dlouhym soucasnym stiskem tlacitek nahoru a dolu se aktualizuji domaci souradnice { zobraz_text(66); // zhasnuti displeje delay(100); unsigned long zacatek_stisku_DN = millis(); delay(50); while (digitalRead(pin_tl_dn) == LOW and digitalRead(pin_tl_up) == LOW) { pocitadlo_smycek = 38; // aby se pri preruseni pokusu o ulozeni HC temer okamzite aktualizoval displej if (millis() - zacatek_stisku_DN > 2000) // po dvou sekundach drzeni tlacitka se domaci souradnice prepisou { zobraz_text(38); // napis "SAVE" na displeji nastav_HC(); // z globalnich promennych 'GPS_lat' a 'GPS_lon' nastavi domaci souradnice zobraz_text(68); // napis "-----" na displeji ExitFlag = true; // po ulozeni novych HC souradnic se vyskoci ze smycky do hlavniho menu do polozky s napisem "GPS" } else { graf_natazeni(millis() - zacatek_stisku_DN , 133); // dvousekundovy natahovaci graf (133ms na jeden z 15 segmentu = 1995ms na zaplneni displeje ) } } } #endif } delay(100); } delay(100); } if (polozka == 14) // prednastavene pozorovaci stanoviste { menu_stanoviste(); } // ---- zacatek bloku R30s -- // ---- konec bloku R30s -- #ifdef modul_LSM303DLHC if (polozka == 22) // naklonomer { float akt_naklon; styl_vodovahy = 0; while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni if (digitalRead(pin_tl_up) == LOW) // tlacitkem nahoru se meni styl zobrazeni vodovahy { styl_vodovahy ++; zobraz_text(29); // pri stisku tlacitka nahoru se zobrazi "-----" if (styl_vodovahy == 2) styl_vodovahy = 0; delay(100); while (digitalRead(pin_tl_up) == LOW and digitalRead(pin_tl_dn) == HIGH) delay(100); delay(100); } if (digitalRead(pin_tl_dn) == LOW and digitalRead(pin_tl_up) == LOW) // dlouhym soucasnym stiskem tlacitek nahoru a dolu se vstupuje do kalibrace vodovahy { zobraz_text(28); // zhasnuti displeje delay(100); unsigned long zacatek_stisku_DN = millis(); delay(50); while (digitalRead(pin_tl_dn) == LOW and digitalRead(pin_tl_up) == LOW) { if (millis() - zacatek_stisku_DN > 2000) // po dvou sekundach drzeni tlacitka se spousti kalibrace { kalibrace_naklon(); } else { graf_natazeni(millis() - zacatek_stisku_DN , 133); // dvousekundovy natahovaci graf (133ms na jeden z 15 segmentu = 1995ms na zaplneni displeje ) } } } akt_naklon = (uhel() - 10000); // zjisteni aktualniho uhlu zvetseneho o 1000 stupnu v desetinach stupne a prevod na desetinne cislo switch (styl_vodovahy) { case 0: // jednoduche zobrazeni elevace if (digitalRead(pin_tl_dn) == HIGH) // zobrazovani probiha jen kdyz je spodni tlacitko uvolnene. Jeho drzeni funguje jako "Data-Hold" a displej se neprekreluje { zobraz_cislo(akt_naklon, 9); // zobrazi na displeji uhel na 1 desetinne misto s pripadnym znamenkem na prvni segmentovce a znackou uhlu } break; default: if (akt_naklon < 450) vodovaha_hor(); // pod 45 stupnu se zobrazi horizontalni dvouosa vodovaha else vodovaha_zen(); // nad 45 stupnu se zobrazi vertikalni dvouosa vodovaha } } } #endif if (polozka == 23) // elevace Slunce a Mesice { while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { if (digitalRead(pin_tl_up) == LOW) // tlacitkem nahoru se meni parametr k zobrazeni (elevace Slunce / elevace Mesice / osvetleni Mesice / Azimut Slunce / Azimut Mesice) { astro_parametr ++; if (astro_parametr == 5) astro_parametr = 0; delay(100); while (digitalRead(pin_tl_up) == LOW) delay(100); delay(100); } if (digitalRead(pin_tl_dn) == LOW) // tlacitkem nahoru se meni parametr k zobrazeni (elevace Slunce / elevace Mesice / osvetleni Mesice / Azimut Slunce / Azimut Mesice) { astro_parametr --; if (astro_parametr == -1) astro_parametr = 4; delay(100); while (digitalRead(pin_tl_dn) == LOW) delay(100); delay(100); } interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni zobraz_RTC(false); // aktualizace casovych promennych (LOC_hod, .....) astro_vypocty(); // vypocet vsech elevaci a osvit switch (astro_parametr) { case 0: // zobrazeni jen elevace Slunce zobraz_cislo(Slu_elevace-90, 10); break; case 1: // zobrazeni jen elevace Mesice zobraz_cislo(Mes_elevace-90, 11); break; case 2: // zobrazeni jen osvetleni Mesice zobraz_cislo(Mes_osvit, 12); break; case 3: // zobrazeni jen azimutu Slunce zobraz_cislo(Slu_azimut, 13); break; case 4: // zobrazeni jen azimutu Mesice zobraz_cislo(Mes_azimut, 14); break; } delay(50); } } if (polozka == 24) // odpocet { int odpocet_H; int odpocet_M; boolean pomprom_save = false; unsigned long pomprom_ctdwn = rtc_korekce(); if (ctdwn_end > pomprom_ctdwn) // nejaky odpocet uz bezi z minula { odpocet_H = (ctdwn_end - pomprom_ctdwn) / 3600; // prepocet rozdilu na cele hodiny odpocet_M = ((ctdwn_end - pomprom_ctdwn) - (odpocet_H * 3600UL)) /60; // a minuty } else // zadny odpocet nebezi, zobrazi se 0 { odpocet_H = 0; odpocet_M = 0; } odpocet_H = plusminus('H', odpocet_H,0,99); // rozsah zadani: 0:00 az 99:59 (neco pres 4 dny) if (bude_save == true) pomprom_save = true; odpocet_M = plusminus('M', odpocet_M,0,59); if (bude_save == true) pomprom_save = true; if (pomprom_save == true) { if (odpocet_H == 0 and odpocet_M == 0) // zadanim 0 hodin a 0 minut se odpocet rusi { ctdwn_end = 0; } else // pri zadani nenulovych hodnot se prepocita za jak dlouho se ma alarm spustit { ctdwn_end = rtc_korekce() + (odpocet_H * 3600UL) + (odpocet_M * 60); // znacka spusteni odpoctu v sekundach od 1.1.1970 } EEPROM_write_long( 495 ,ctdwn_end); // ulozeni nove hodnoty ciloveho casu do EEPROM } } #ifdef modul_LSM303DLHC if (polozka == 25) // azimut { int akt_azimut; byte kompas_fce = 0; while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni if (digitalRead(pin_tl_up) == LOW) // tlacitkem nahoru se prepne na kalibraci { zobraz_text(28); // zhasnuti displeje delay(100); unsigned long zacatek_stisku_UP = millis(); while (digitalRead(pin_tl_up) == LOW) // pred kalibraci kompasu se musi tlacitko [nahoru] drzet alespon 2 sekundy { delay(50); if (millis() - zacatek_stisku_UP > 2000) // po dvou sekundach drzeni tlacitka se spousti kalibrace { kompas_fce = 1; zobraz_text(59); // "C-CAL" } else { graf_natazeni(millis() - zacatek_stisku_UP , 133); // dvousekundovy natahovaci graf (133ms na jeden z 15 segmentu = 1995ms na zaplneni displeje ) } } delay(100); } if (kompas_fce == 0) { uhel(); // uhel nakloneni se pouziva pro urceni, ktere osy magnetometru zvyhodnit ve vypoctech akt_azimut = zjisti_azimut(); if (digitalRead(pin_tl_dn) == HIGH) // displej se aktualizuje jen v pripade, ze je tlacitko [dolu] uvolnene { // (pokud je stisknute, meri se normalne dal, ale displej zustava beze zmeny - DataHold) zobraz_cislo(akt_azimut, 15); } } if (kompas_fce == 1) { kalibrace_magnet(false); kompas_fce = 0; } delay(100); } } if (polozka == 26) // Prepocet Ra-Dec na azimut a elevaci { boolean pomprom_save = false; zadana_rektascenze = plusminus('R', zadana_rektascenze,0,239); if (bude_save == true) pomprom_save = true; zadana_deklinace = plusminus('D', zadana_deklinace,-90,90); if (bude_save == true) pomprom_save = true; if (pomprom_save == true) { if (leto == true) casova_zona = letni_posun; else casova_zona = zimni_posun; z_LOC_na_Astro_UTC(casova_zona); // z globalnich promennych pro casove udaje v mistni casove zone (LOC_xxx) vypocte UTC datum a cas RaToAzim ( 3 , zadana_rektascenze / 10.0 , zadana_deklinace , LOC_rok , LOC_mes , LOC_den , LOC_hod , LOC_min , casova_zona , GeoLon , GeoLat ); // obecne teleso float angle_dist; // vysledek funkce pro mereni uhlove vzdalenosti uint16_t azimut_test; zobraz_text(62); // "HLEdA" while (digitalRead(pin_tl_ok) == HIGH) // hledani trva, nez se stiskne tlacitko OK { uhel(); azimut_test = zjisti_azimut(); angle_dist = uhlova_vzdalenost(obecny_azimut, obecna_elevace, azimut_test, posledni_uhel); if (digitalRead(pin_tl_dn) == HIGH and digitalRead(pin_tl_up) == HIGH) { D_pamet[4] = znak_u; // prvni sve segmentovky zobrazuji jen male "u" a mezeru D_pamet[3] = 0; zobraz_cislo(angle_dist , 8); } if (digitalRead(pin_tl_dn) == LOW) zobraz_cislo(obecny_azimut , 15); if (digitalRead(pin_tl_up) == LOW) zobraz_cislo((int)(obecna_elevace * 10.0) + 0.5 , 9); if (angle_dist > 1.5) // akusticky vystup je aktivni v okruhu pod 1,5 stupne, pri vetsim rozdilu je piskak uplne vypnuty { noTone(pin_bzuk); } else { tone_X(pin_bzuk, 600 , 20); // piska se jen v pripade, ze je piskani povolene (prikaz "@P") } } while (digitalRead(pin_tl_ok) == LOW) // cekani na uvolneni OK { zobraz_text(29); // "-----" delay(100); } delay(100); } } #endif if (polozka == 27) // Mereni napeti zdroje { unsigned int ref_in, bat_in; while (digitalRead(pin_tl_ok) == HIGH) // Dokud neni stisknuto tlacitko OK { interrupty(); // odskoceni na test, jestli neni nejaky pozadavek o komunikaci, nebo jestli neni cas spustit automaticke mereni ADC_CR2 = ADC_CR2 | 0b1; // zapnuti A/D prevodniku ref_in = analogRead(pin_refu); bat_in = analogRead(pin_AD_BAT); // DZ1=1.8V R8 / R7+R8 korekce float napeti_test = ((((1.8 / ref_in) * bat_in) / (8.2 / 108.2)) * 10.0 * 1.05) + 0.5; // zobrazeni na 1 des. misto se zaokroulenim pozice_tecky = 1; // tecka na druhe sedmisegmentovce zprava zobraz_cislo((long)napeti_test, 0); delay(300); } } zobraz_text(pozice_menu1); // po navratu z podmenu se zobrazi aktualne vybrana polozka auto_exit_casovani = millis(); delay(50); while (digitalRead(pin_tl_ok) == LOW) // ze zmeny hodnoty polozky se vraci dlouhym stiskem tlacitka OK { // ted je nutne pockat na jeho uvolneni delay(20); } delay(100); } //------------------------------------------ //------------------------------------------ // listovani v parametrech zvolene polozky o +/- 1 pomoci tlacitek nahoru adolu int plusminus(char znak1, int start_hodnota, int minimalni_hodnota, int maximalni_hodnota) { int vystup = start_hodnota; int nova_hodnota = start_hodnota; byte stav_casovani = 0; // casovani zmeny hodnot se meni v zavislosti na delce drzeni tlacitka unsigned long casova_znacka = millis(); unsigned long casova_znacka2 = 0; //-------------------------- zobrazeni puvodni hodnoty na displeji ------------------- switch (znak1) { case 'A': // (automat) D_pamet[4] = znak_A; // velke A D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,1); break; case 'P': // (prumerovani) D_pamet[4] = znak_P; // velke P D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,1); break; case 'd': // (den) D_pamet[4] = znak_d; // male d D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,1); break; case 'M': // (mesic nebo minuta) D_pamet[4] = znak_M; // velke M D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,1); break; case 'r': // (rok) D_pamet[4] = znak_r; // male r D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,1); break; case 'H': // (hodina) D_pamet[4] = znak_H; // velke H D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,1); break; case 'L': // (list) D_pamet[4] = znak_L; // velke L D_pamet[3] = 0b00000000; // druha sedmisegmentovka zleva (rad tisicu) je prazdna pozice_tecky = 0; zobraz_cislo(vystup,2); // speciani typ vypisu cisla break; case 'S': // (zona) zobraz_text(vystup + 57); // "2iMA" / "LEto" break; case 'R': // (rektascenze) D_pamet[4] = znak_R1; // male r (v napisu 'rA.') D_pamet[3] = znak_R2; // velke A. (v napisu 'rA.') pozice_tecky = 1; // jedno desetinne misto (0.0 az 23.9) zobraz_cislo(vystup,17); break; case 'D': // (deklinace) D_pamet[4] = znak_D1; // male d (v napisu 'dE.') D_pamet[3] = znak_D2; // velke E. (v napisu 'dE.') pozice_tecky = 0; // bez desetinnych mist (-90 az +90) zobraz_cislo(vystup,18); break; case 'X': // (interval pro režim R30s) D_pamet[4] = 134; // "I." D_pamet[3] = 72; // "=" pozice_tecky = 0; // bez desetinnych mist (10 az 250, 5M, 7M, 10M, 20M, 30M) zobraz_cislo(vystup,19); break; case '#': // (hlavni menu) if (digitalRead(pin_EXT_ZAP) == internal_GPS) // pri zasunuti GPS (nebo jine externi desky) se zrusi prednastavene pozorovaci stanoviste { if ((EEPROM_read(48) & 0b11100000) > 0) // zrusi se ale jen v pripade, ze je nejake nastavene (aby se porad dokola neprepisovala jedna bunka EEPROM) { EEPROM_update(48,(EEPROM_read(48) & 0b00011111)); // smazat nejvyssi 3 bity z adresy 48 } } if (vystup == 13 and pole_zobr_menu[13] == false ) vystup = 14; // okamzita aktualizace napisu pro pripad, ze dojde k vytazeni nebo zasunuti GPS modulu if (vystup == 14 and pole_zobr_menu[14] == false ) vystup = 13; zobraz_text(vystup); // polozky menu jsou seskladany na indexech [0] az [27] break; case '@': // (editace viditelnych polozek v menu) break; } while (digitalRead(pin_tl_ok) == HIGH and auto_exit_menu == false) // z teto smycky se vypadne jen tlacitkem OK (kratkym, nebo dlouhym) nebo vyprsenim casovace automatickeho opusteni menu { if (znak1 != '@') // pri editaci viditelnych polozek menu se interrupty neprovadi { for (byte dpam = 0 ; dpam < 5 ; dpam ++) { D_pam_pred_int[dpam] = D_pamet[dpam]; } interrupty(); for (byte dpam = 0 ; dpam < 5 ; dpam ++) { D_pamet[dpam] = D_pam_pred_int[dpam]; } aktualizuj_displej(); } if (digitalRead(pin_tl_up) == LOW or digitalRead(pin_tl_dn) == LOW) auto_exit_casovani = millis(); // kazdy stisk tlacitka nahoru nebo dolu spousti casovac automatickeho vypadnuti z menu if (millis() - auto_exit_casovani > AUTOEXITMENU) auto_exit_menu = true; // cas bez stisku tlacitka vyprsel... provede se odchod z menu, jakoby bylo stisknuto kratce OK // -------------- pocitani po jednotkach na kratky klik --------------- if (digitalRead(pin_tl_up) == LOW and stav_casovani == 0 and millis() > (casova_znacka + 100)) // prvni stisk tlacitka nahoru s odrusenim zakmitu na 0,1sekundy { stav_casovani = 1; casova_znacka = millis(); nova_hodnota = plus_hodnota(znak1 , nova_hodnota, minimalni_hodnota , maximalni_hodnota); // okamzite pri stisku (po desetine sekundy) pricte jednicku casova_znacka2 = millis(); } if (digitalRead(pin_tl_dn) == LOW and stav_casovani == 0 and millis() > (casova_znacka + 100)) // prvni stisk tlacitka doluru s odrusenim zakmitu na 0,1sekundy { stav_casovani = 1; casova_znacka = millis(); nova_hodnota = minus_hodnota(znak1 , nova_hodnota, minimalni_hodnota, maximalni_hodnota); // okamzite pri stisku (po desetine sekundy) odecte jednicku casova_znacka2 = millis(); } // -------------- // -------------- prepnuti z klikani na pomaly automat po jedne sekunde drzeni tlacitka --------------- if ( (digitalRead(pin_tl_up) == LOW or digitalRead(pin_tl_dn) == LOW ) and stav_casovani == 1 and millis() > (casova_znacka2 + 1000)) // nektere tlacitko je drzeno alespon sekundu { stav_casovani = 2; casova_znacka2 = millis(); } // -------------- // -------------- pocitani po jednotkach automaticky po sekundovem drzeni tlacitka --------------- if (digitalRead(pin_tl_up) == LOW and stav_casovani == 2 and millis() > (casova_znacka + 200)) // je drzeno tlacitko nahoru, kazdou 0,2 sekundy se pricita jednicka { casova_znacka = millis(); nova_hodnota = plus_hodnota(znak1 , nova_hodnota, minimalni_hodnota, maximalni_hodnota); if (millis() > (casova_znacka2 + 5000)) stav_casovani = 3; // po trech sekundach drzeni se prechazi na vysokou rychlost pricitani } if (digitalRead(pin_tl_dn) == LOW and stav_casovani == 2 and millis() > (casova_znacka + 200)) // je drzeno tlacitko nahoru, kazdou 0,2 sekundy se odecita jednicka { casova_znacka = millis(); nova_hodnota = minus_hodnota(znak1 , nova_hodnota, minimalni_hodnota , maximalni_hodnota); if (millis() > (casova_znacka2 + 5000)) stav_casovani = 3; // po trech sekundach drzeni se prechazi na vysokou rychlost odecitani } // -------------- // -------------- rychle pocitani automaticky po 3-sekundovem drzeni --------------- if (digitalRead(pin_tl_up) == LOW and stav_casovani == 3 and millis() > (casova_znacka + 50)) // po trech sekundach drzeni tlacitka nahoru, se kazdych 50 ms pricita jednicka { casova_znacka = millis(); nova_hodnota = plus_hodnota(znak1 , nova_hodnota, minimalni_hodnota , maximalni_hodnota); } if (digitalRead(pin_tl_dn) == LOW and stav_casovani == 3 and millis() > (casova_znacka + 50)) // po trech sekundach drzeni tlacitka dolu, se kazdych 50 ms odecita jednicka { casova_znacka = millis(); nova_hodnota = minus_hodnota(znak1 , nova_hodnota, minimalni_hodnota , maximalni_hodnota); } // -------------- // -------------- uvolneni tlacitek --------------- if (digitalRead(pin_tl_up) == HIGH and digitalRead(pin_tl_dn) == HIGH and millis() > (casova_znacka + 100)) // obe tlacitka uvolnena alespon na desetinu sekundy { stav_casovani = 0; casova_znacka = millis(); casova_znacka2 = millis(); } // -------------- } // konec listovaci smycky, ze ktere se vypadne jen tlacitkem OK if (digitalRead(pin_tl_ok) == LOW) // potvrzovaci tlacitko v polozce { auto_exit_casovani = millis(); // kazdy stisk tlacitka ok spousti casovac automatickeho vypadnuti z menu delay(50); // odruseni zakmitu vystup = nova_hodnota; unsigned long startTime = millis(); while (digitalRead(pin_tl_ok) == LOW) // dokud je tlacitko stisknute, nic se nedeje { delay(50); trvani_stisku2 = millis() - startTime; if (trvani_stisku2 > 500) // stisk byl delsi nez 0,5 sekundy { bude_save = true; switch(znak1) { case 'L': zobraz_text(29); // dlouhy stisk OK pri prohlizeni starych zaznamu (funkce LIST) zpusobi napis "-----" break; case 'A': // (automat) case 'P': // (prumerovani) case 'd': // (den) case 'M': // (mesic nebo minuta) case 'r': // (rok) case 'H': // (hodina) case 'S': // (casova zona) case 'R': // (rektascenze) case 'D': // (deklinace) case '@': // (editace viditelnych polozek v menu) case 'X': // (editace viditelnych polozek v menu) zobraz_text(38); // dlouhy stisk OK pri zadavani nejakych parametru zpusobi napis "SAVE" break; case '#': // (menu) break; // dlouhy stisk OK pri listovani v menu tady nezobrazi nic, ale v nasledujicich prikazech zobrazi vybrane podmenu } delay(500); break; } if (digitalRead(pin_tl_ok) == HIGH) delay(50); // kdyz se behem drzeni tlacitka OK objevi kratky vypadek kontaktu, tak se odignoruje } if (trvani_stisku2 <= 500) // stisk byl kratsi nez 0,5 sekundy { switch(znak1) { case '#': // pri kratkem stisku OK pri listovani v hlavnim menu se NENASTAVI puvodni polozka, ale zustane ulozena aktualni break; case '@': // menu editace viditelnych a neviditelnych polozek je trochu specialni, protoze se kratkym stiskem OK meni jas if (menu_enable[vystup] == true) menu_enable[vystup] = false; // ... prepina stav mezi "viditelna" / "neviditelna" polozka else menu_enable[vystup] = true; if (menu_enable[vystup] == true) jas_displeje = 7; // a zaroven se jeste aktualizuje jas prave editovane polozky else jas_displeje = 1; zobraz_text(vystup); // polozky menu jsou seskladany na indexech [0] az [27] break; default: // u vsech ostatnich listovani a nastavovani se vrati puvodni vstupni hodnota vystup = start_hodnota; // nastavene cislo se rusi a zustava puvodni } delay(200); // pauza pred opustenim menu (nebo po prepnuti viditelnosti polozky) bude_save = false; } } if (auto_exit_menu == true) // nekde v predchozi smycce doslo k vyprseni casu pro autoexit { vystup = start_hodnota; // vypadne se jakoby bylo kratce stisknuto OK bude_save = false; } return vystup; } //------------------------------------------ //============================================================================================== // pricitani a odecitani jednicky s kontrolou minimalni a maximalni hodnoty int plus_hodnota(char typ_pricitani , int hodnota, int minimum , int maximum) { pozice_tecky = 0; switch (typ_pricitani) { case 'A': // (automat) case 'P': // (prumerovani) case 'd': // (den) case 'M': // (mesic nebo minuta) case 'r': // (rok) case 'H': // (hodina) if (hodnota + 1 <= maximum ) hodnota ++; // bezne pricteni hodnoty s kontrolou na maximum zobraz_cislo(hodnota,1); break; case 'L': // (list) if (hodnota - 1 >= minimum ) hodnota --; // list funguje opacne (misto pricitani se odecita) zobraz_cislo(hodnota,2); break; case 'S': // (zona) hodnota ++; if (hodnota > maximum) hodnota = maximum; // maximum nelze prekrocit zobraz_text(hodnota + 57); break; case 'R': // (rektascenze) hodnota ++; if (hodnota > maximum) hodnota = minimum; // pri prekroceni maxima se pokracuje od minima zobraz_cislo(hodnota,17); break; case 'D': // (deklinace) hodnota ++; if (hodnota > maximum) hodnota = minimum; // pri prekroceni maxima se pokracuje od minima zobraz_cislo(hodnota,18); break; case 'X': // (interval R30s) hodnota ++; if (hodnota > maximum) hodnota = maximum; // pri prekroceni maxima se na maximu zarazi zobraz_cislo(hodnota,19); break; case '#': // (hlavni menu) - pohyb k nizsim indexum polozek (tlacitko nahoru) hodnota --; if (hodnota < 0) hodnota = 0; while (pole_zobr_menu[hodnota] == false) // kdyz je zvolena polozka nezobrazitelna, prepne se na dalsi nizsi { hodnota --; if (hodnota < 0) { hodnota = 0; break; // pri podteceni pod nultou polozku se vypadne ze smycky while } } while (pole_zobr_menu[hodnota] == false) // pokud se z predchozi smycky vystoupi pres podteceni nulove polozky { hodnota ++; // postupnym zvysovanim indexu se hleda nejnizsi povolena polozka } zobraz_text(hodnota); // polozky menu jsou seskladany na indexech [0] az [27] break; // tenhle break ukoncuje case '#' case '@': // (editace viditelnychj polozek menu) - pohyb k nizsim indexum polozek (tlacitko nahoru) hodnota --; while (spec_rezim == 0 and hodnota > 14 and hodnota < 22) hodnota --; // polozky menu pro specialni funkce se bez zasunuteho HW vubec nezobrazuji if (hodnota < 0) hodnota = 0; // zastaveni na polozce "List" if (menu_enable[hodnota] == true) jas_displeje = 7; // povolene polozky menu se zobrazi vysokym jasem else jas_displeje = 1; // zakazane polozky menu se zobrazi nizkym jasem zobraz_text(hodnota); // polozky menu jsou seskladany na indexech [0] az [27] break; // tenhle break ukoncuje case '#' } return hodnota; } //---------------------------------------------- //---------------------------------------------- int minus_hodnota(char typ_odecitani , int hodnota, int minimum, int maximum) { pozice_tecky = 0; switch (typ_odecitani) { case 'A': // (automat) case 'P': // (prumerovani) case 'd': // (den) case 'M': // (mesic nebo minuta) case 'r': // (rok) case 'H': // (hodina) if (hodnota - 1 >= minimum ) // bezne odecteni hodnoty s kontrolou na minimum { hodnota --; } zobraz_cislo(hodnota,1); break; case 'L': // (list) if (hodnota + 1 <= maximum ) // list funguje opacne (misto odecitani se pricita) { hodnota ++; } zobraz_cislo(hodnota,2); break; case 'S': // (zona) hodnota --; if (hodnota < minimum) hodnota = minimum; // minimum nelze podlezt zobraz_text(hodnota + 57); break; case 'R': // (rektascenze) hodnota --; if (hodnota < minimum) hodnota = maximum; // pri podlezeni pod minimum se nastavi maximum zobraz_cislo(hodnota,17); break; case 'D': // (deklinace) hodnota --; if (hodnota < minimum) hodnota = maximum; // pri podlezeni pod minimum se nastavi maximum zobraz_cislo(hodnota,18); break; case 'X': // (interval R30s) hodnota --; if (hodnota < minimum) hodnota = minimum; // pri podlezeni pod minimum se nastavi maximum zobraz_cislo(hodnota,19); break; case '#': // (hlavni menu) - pohyb k vyssim indexum polozek (tlacitko dolu) hodnota ++; while (pole_zobr_menu[hodnota] == false) // kdyz je zvolena polozka neaktivni, prepne se na dalsi vyssi { hodnota ++; if (hodnota > maximum) { hodnota = maximum; break; // pri preteceni maximalniho poctu polozek se ze smycky while vypadne } } while (pole_zobr_menu[hodnota] == false) // pokud se z predchozi smycky vystoupi pres prekroceni horni hranice poctu polozek { hodnota --; // postupnym snizovanim indexu se hleda nejvyssi povolena polozka } zobraz_text(hodnota); // polozky menu jsou seskladany na indexech [0] az [27] break; // tenhle brak ukoncuje case '@' case '@': // (editace viditelnych polozek menu) - pohyb k nizsim indexum polozek (tlacitko nahoru) hodnota ++; while (spec_rezim == 0 and hodnota > 14 and hodnota < 22) hodnota ++; // polozky menu pro specialni funkce se bez zasunuteho HW vubec nezobrazuji if (hodnota >= maximum) hodnota = maximum; // zastaveni na posledni polozce ("VoLtY") if (menu_enable[hodnota] == true) jas_displeje = 7; // povolene polozky menu se zobrazi vysokym jasem else jas_displeje = 1; // zakazane polozky menu se zobrazi nizkym jasem zobraz_text(hodnota); // polozky menu jsou seskladany na indexech [0] az [27] break; // tenhle break ukoncuje case '#' } return hodnota; } //============================================================================================== //------------------------------------------ // podprogram pro postupne odrotovani zaznamu stopek na displeji // vraci true pri predcasnem ukonceni rolovani pomoci tlacitka OK // nebo false po dobehnuti rolovani do konce boolean disp_zaznam_scroll(byte pocet_znaku) { pom_disp_scroll[0] = 0; // prazdna sedmisegmentovka pom_disp_scroll[1] = 0; // prazdna sedmisegmentovka pom_disp_scroll[2] = 0; // prazdna sedmisegmentovka pom_disp_scroll[3] = 0; // prazdna sedmisegmentovka for (byte i = 0; i< pocet_znaku - 4 ; i++) { D_pamet[4] = pom_disp_scroll[i]; D_pamet[3] = pom_disp_scroll[i+1]; D_pamet[2] = pom_disp_scroll[i+2]; D_pamet[1] = pom_disp_scroll[i+3]; D_pamet[0] = pom_disp_scroll[i+4]; aktualizuj_displej(); for (byte pauza = 0 ; pauza < 50 ; pauza++) { delay(10); if (i > 2 and digitalRead(pin_tl_ok) == LOW) { return true; } if (i > 2 and (digitalRead(pin_tl_dn) == LOW or digitalRead(pin_tl_up) == LOW) ) { return false; } } } return false; } void menu_stanoviste(void) { unsigned long trvani_stisku_stan = 0; unsigned int timeout_stan = 600; // timeout se nastavi na 30 sekund (600 x 0,05 sek) while (digitalRead(pin_tl_ok) == LOW) // cekani na uvolneni tlacitka OK (displej je od minule zhasnuty) { delay(50); } delay(50); // odruseni zakmitu pri uvolnovani int index_pozst = ((EEPROM_read(48) & 0b11100000) >> 5); // osekat nejvyssich 5 bitu (aktualne nastavene preddefinovane pozorovaci stanoviste) byte pomprom = index_pozst; // do pomocne promenne se ulozi indek stanoviste pri vstupu do podmenu for (byte j = 0; j < 5 ; j++) // zobrazeni aktualne nastaveneho stanoviste { D_pamet[4-j] = EEPROM_read( j + 495 + (index_pozst * 15)); } aktualizuj_displej(); while (digitalRead(pin_tl_ok) == HIGH and timeout_stan > 0) // nez dojde k potvrzeni stanoviste tlacitkem OK nebo nez vyprsi timeout, visi program v teto smycce { timeout_stan --; interrupty(); // odskoceni na test zadosti o komunikaci, nebo automaticke mereni if (digitalRead(pin_tl_up) == LOW and index_pozst < 6 ) { timeout_stan = 600; // obcerstveni timeoutu index_pozst ++; } if (digitalRead(pin_tl_dn) == LOW and index_pozst >= 0 ) { timeout_stan = 600; // obcerstveni timeoutu index_pozst --; } if (index_pozst > 5) index_pozst = 5; // zarazka na krajnich indexech 0 az 5 if (index_pozst < 0) index_pozst = 0; if (index_pozst == 0) // index 0 znamena zrusene stanoviste a zobrazi se pomlcky { zobraz_text(29); // "-----" } else // pro vyssi indexy se na displeji zobrazi 5-znakove popisky aktualne zvoleneho stanoviste { for (byte j = 0; j < 5 ; j++) { D_pamet[4-j] = EEPROM_read( j + 495 + (index_pozst * 15)); } aktualizuj_displej(); } while (digitalRead(pin_tl_up) == LOW or digitalRead(pin_tl_dn) == LOW) // cekani na uvolneni obou listovacich tlacitek { delay(50); } delay(50); // hlavni casovani pro timeout (600 x 0,05 sek = 30 sekund) } if (digitalRead(pin_tl_ok) == LOW) // ukonceni podmenu bylo zpusobeno stiskem tlacitka OK { delay(50); // odruseni zakmitu unsigned long startTime = millis(); while (digitalRead(pin_tl_ok) == LOW) // dokud je tlacitko stisknute, nic se nedeje { delay(20); trvani_stisku_stan = millis() - startTime; if (trvani_stisku_stan > 500) // stisk trval dele nez 0,5 sekundy .... potvrzeni nastaveneho stanoviste { zobraz_text(38); // napis "Save" se zobrazi vzdycky if (index_pozst != pomprom) // ke skutecnemu zapisu ale dochazi jen v pripade, pokud se index pozorovaciho stanoviste zmenil { byte data48 = (EEPROM_read(48) & 0b00011111); data48 = (data48 | (index_pozst << 5) ); EEPROM_update(48,data48); delay(500); } } if (digitalRead(pin_tl_ok) == HIGH) delay(50); // kdyz se behem drzeni tlacitka OK objevi kratky vypadek kontaktu, tak se odignoruje } if (trvani_stisku_stan <= 500) // stisk tlacitka OK byl kratsi nez 0,5 sekundy { zobraz_text(28); // nic se neuklada, jen se smaze displej a vrati se do hlavniho menu delay(100); // pauza pred opustenim podmenu } } if (timeout_stan == 0) auto_exit_menu = true; // kdyz vyprsi timeout v tomto podmenu, zrusi se zaroven timeout i v hlavnim menu, takze se provede navrat do hlavni vyckavaci smycky } //---------------------------------------------- //------------------------------------------ // moznost volby viditelnych polozek v menu void editace_polozek_menu(void) { int polozka = 0; unsigned long menubity; zobraz_text(54); // na displeji se zobrazi napis "MEnu " spec_rezim = test_zasunuti(); // test zasunuti pridavneho HW //!! (r30s) while (digitalRead(pin_tl_up) == LOW or digitalRead(pin_TS) == LOW) // do teto funkce se vstoupilo stiskem tlacitka UP a bocniho tlacitka pri zapnuti napajeni { delay(100); // musi se pockat, dokud se obe tlacitka neuvolni (vcetne odruseni zakmitu) } delay(100); if (menu_enable[polozka] == true) jas_displeje = 7; // pokud je prvni polozka ("List") povolena, zobrazi se vysokym jasem else jas_displeje = 1; // pokud je prvni polozka ("List") zakazana, zobrazi se nizkym jasem zobraz_text(polozka); // na displeji se zobrazi prvni polozka "List " while (true) // z tohoto podprogramu se vypadne dlouhym stiskem OK { polozka = plusminus('@', polozka, 0, pocet_polozek_v_menu); // '@' = editace viditelnosti polozek v menu if (bude_save == true) // dlouhy stisk = ukonceni editace viditelnych polozek { jas_displeje = 3; // stredni jas displeje break; // vypadnuti ze smycky while(true) } if (auto_exit_menu == true) break; // v predchozich smyckach doslo k vyprseni casu pro autoexit } while (digitalRead(pin_tl_ok) == LOW) delay(100); // cekani na uvolneni tlacitka OK s odrusenim zakmitu delay(100); if (auto_exit_menu == false) // k zapisu upravenych polozek dojde jen pro korektnim odklepnuti dlouhym stiskem OK { menubity = 0; // ulozeni nastavenych hodnot do EEPROM (4 bajty po 8 bitech - kazdy bit jedna polozka) for (polozka = 0; polozka <= pocet_polozek_v_menu ; polozka ++) { if (menu_enable[polozka] == true) bitSet(menubity,polozka); // priprava 32-bitove promenne } EEPROM_write_long(491 , menubity); // zapis promenne do EEPROM } } //----------------------------------------------