//**********************************************************************// INFO BATTERY PACK//**********************************************************************// (c) OK1XGL 2008// verze 1.0 - uvodni verze// 1.1 - referencni teplota pro samovybijeni se uklada pri zadani doby mereni samovybijeni////#include "ibp2.h"// nastavi orientaci a klidovy stav portu//void init_ports (void) {set_tris_a (0b00101011);output_a (0b000000000);set_tris_b (0b11010000);output_b (0b00100000);port_b_pullups (FALSE);}////////////////////////////////////////////////////// iterrupty// cele preruseni zabere 33+xx+30 cyklu////////////////////////////////////////////////////// periodicky casovac//#INT_TIMER1void tmr1_int (void) {// natahovani casovaceset_timer1 (S_TICK_TIME);s_tick = 1;if (l_timer == 0) {l_timer = L_TICK_TIME;l_tick = 1;blink = ~blink;if (blink)slow_blink = ~slow_blink;}elsel_timer--;}/////////////////////////////////////////////////////// FUNKCE PRO PRACI S TEPLOMEREM////////////////////////////////////////////////////// testuje pritomnost teplomeru, pri pritomnosti vraci 1// zabere 1060 taktu//int8 TM_present() {int1 present;output_low (TM_PIN);output_fixed (TM_PIN);delay_us (500);disable_interrupts (GLOBAL);output_float (TM_PIN);if(!input (TM_PIN)) {enable_interrupts (GLOBAL);return (0);}delay_us (65);present = input(TM_PIN);enable_interrupts (GLOBAL);delay_us (440);if (present)return (0);elsereturn (1);}// precte bajt z teplomeru//int8 TM_read_byte() {int8 i,data;for(i = 0; i < 8; ++i) {disable_interrupts (GLOBAL);output_low (TM_PIN);output_fixed (TM_PIN);delay_us (2);output_float (TM_PIN);delay_us (8);shift_right (&data,1,input(TM_PIN));enable_interrupts (GLOBAL);delay_us (55);}return (data);}// zapise bajt do teplomeru//void TM_write_byte(int8 data) {int8 i;for (i = 0 ; i < 8; ++i) {disable_interrupts (GLOBAL);output_low (TM_PIN);output_fixed (TM_PIN);delay_us (5);if (shift_right (&data,1,0))output_float (TM_PIN);delay_us (60);output_float (TM_PIN);delay_us (2);enable_interrupts (GLOBAL);}}// vraci 0 pri ukonceni mereni// vraci 1 pri rozpracovanem mereni// zabere max 1100 taktu na 1 cyklus// potrebuje 10 volani pro zmereni teploty//int8 measure_temp () {static int8 phase;static int8 tmp;int8 tmp2;switch (phase) {case 0:if (! TM_present ()) { // over pritomnost teplomeruphase = 0;TB_val = TB_DEFAULT;return (0); // teplomer neni pritomen, dal nelze pokracovat}break;case 1:TM_write_byte (0xcc); // preskoc na dalsi sadu prikazubreak;case 2:TM_write_byte (0x44); // prikaz spust mereni teplotyoutput_high (TM_PIN); // zapni tvrdy pullupoutput_fixed (TM_PIN); //break;case 3:case 4:case 5: // cekej nejmene 750 msbreak;case 6:output_float (TM_PIN); // vyppni tvrdy pullupoutput_low (TM_PIN); //if (! TM_present ()) { // over pritomnost teplomeruphase = 0;TB_val = TB_DEFAULT;return (0); // teplomer neni pritomen, dal nelze pokracovat}break;case 7:TM_write_byte (0xcc); // preskoc na dalsi sadu prikazubreak;case 8:TM_write_byte (0xbe); // prikaz precti zmerenou teplotubreak;case 9:tmp = TM_read_byte () >> 4; // precti LSB bajt s teplotou a zahod destiny stupnebreak;case 10:tmp |= TM_read_byte () << 4; // precti MSB bajt s teplotou a sloz s LSBtmp2 = tmp & 0x7F; //if (tmp2 < 80) { // teplota je v moznem rozsahu (nahrada kontroly CRC - bylo by casove prilis dlouhe)if (tmp & 0x80)TB_val = 0; // zapornou teplotu povazujeme za nulovouelseTB_val = tmp2;}phase = 0;return (0);break;default:phase = 0;TB_val = TB_DEFAULT;return (0);}phase++;return (1);}////////////////////////////////////////////////////////// FUNNKCE PRO MERENI NAPETI A PROUDU////////////////////////////////////////////////////////// meri velikost proudu z/do baterie a prumeruje z 8 mereni// zabere max 1760 taktu (1760 us)//int16 measure_IB (void) {int16 out;set_adc_channel (IB_CAN);delay_us (100);out = read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);delay_us (100);out += read_adc (ADC_START_AND_READ);out = out >> 3;return (out);}// meri velikost napeti baterie a provadi klouzavy prumer z 8 mereni// zabere max 320 taktu (320 us)//int16 measure_VB (void) {static int16 smpl [8];static int8 i;int16 out;if (i >= 8-1)i = 0;elsei++;set_adc_channel (VB_CAN);delay_us (100);smpl [i] = read_adc (ADC_START_AND_READ);out = smpl [0] + smpl [1] + smpl [2] + smpl [3] +smpl [4] + smpl [5] + smpl [6] + smpl [7];out = out >> 3;return (out);}// meri velikost vstupniho napeti zdroje pro nabijeni// zabere max 200 taktu (200 us)//int16 measure_VS (void) {int16 out;set_adc_channel (VS_CAN);delay_us (100);out = read_adc (ADC_START_AND_READ);return (out);}// meri vystupni napeti OZ pro mereni proudu pri nulovem odberu - pro kompenzaci ofsetu OZ//int16 measure_offset (void) {int16 out;int8 i;// vypni vsechny spotrebiceinit_ports ();disable_interrupts (GLOBAL);ADIE = 1;PEIE = 1;delay_ms (500);// mer napeti OZ a vypocti prumer z 8 mereniset_adc_channel (IB_CAN);delay_us (100);out = 0;for (i = 0; i < 8; i++) {read_adc (ADC_START_ONLY);sleep ();out += read_adc (ADC_READ_ONLY);delay_us (100);restart_wdt ();}out = out >> 3;ADIE = 0;PEIE = 0;enable_interrupts (GLOBAL);return (out);}///////////////////////////////////////////////////// FUNKCE PRO PRACI S LED///////////////////////////////////////////////////// rozsviti vsechny led//void leds_all_on () {output_high (LED4_R);output_high (LED3_Y);output_high (LED2_Y);output_high (LED1_G);}// zhasne vsechny led//void leds_all_off () {output_low (LED4_R);output_low (LED3_Y);output_low (LED2_Y);output_low (LED1_G);}// signalizuje kapacitu baterie pri nabijeni// vraci cislo odpovidajici stavu nabiti// zabere max 40 cyklu//int8 leds_chrg (void) {if (B_cap >= B_cap_4_4) {leds_all_on ();return (4); // baterie plne nabita}if (B_cap > B_cap_3_4) {output_high (LED4_R);output_high (LED3_Y);output_high (LED2_Y);if (slow_blink)output_high (LED1_G);elseoutput_low (LED1_G);return (3);}if (B_cap > B_cap_2_4) {output_high (LED4_R);output_high (LED3_Y);if (slow_blink)output_high (LED2_Y);elseoutput_low (LED2_Y);output_low (LED1_G);return (2);}if (B_cap > B_cap_1_4) {output_high (LED4_R);if (slow_blink)output_high (LED3_Y);elseoutput_low (LED3_Y);output_low (LED2_Y);output_low (LED1_G);return (1);}if (slow_blink)output_high (LED4_R);elseoutput_low (LED4_R);output_low (LED3_Y);output_low (LED2_Y);output_low (LED1_G);return (0);}// signalizuje chybu//void leds_err () {output_low (LED1_G);output_low (LED4_R);if (blink) {output_high (LED2_Y);output_high (LED3_Y);}else {output_low (LED2_Y);output_low (LED3_Y);}}// signalizuje neznamou aktualni kapacitu baterie//void leds_invalid_cap () {output_low (LED2_Y);output_low (LED3_Y);if (blink) {output_high (LED1_G);output_high (LED4_R);}else {output_low (LED1_G);output_low (LED4_R);}}// signalizuje zbyvajici kapacitu baterie pri vybijeni//void leds_dis () {if (B_cap < B_cap_1_4) {output_low (LED1_G);output_low (LED2_Y);output_low (LED3_Y);output_high (LED4_R);return;}if (B_cap < B_cap_2_4) {output_low (LED1_G);output_low (LED2_Y);output_high (LED3_Y);output_low (LED4_R);return;}if (B_cap < B_cap_3_4) {output_low (LED1_G);output_high (LED2_Y);output_low (LED3_Y);output_low (LED4_R);return;}output_high (LED1_G);output_low (LED2_Y);output_low (LED3_Y);output_low (LED4_R);}// signalizuje temer vybitou baterii//void leds_VB_low () {output_low (LED1_G);output_low (LED2_Y);output_low (LED3_Y);if (slow_blink)output_high (LED4_R);elseoutput_low (LED4_R);}// zobrazi cislo v rozsahu 0 - 9 v binarnim kodu na ledkach//void num_to_leds (int8 num) {switch (num) {case 0:output_low (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_low (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 1:output_high (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_low (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 2:output_low (LED4_R); // nejnizsi bitoutput_high (LED3_Y);output_low (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 3:output_high (LED4_R); // nejnizsi bitoutput_high (LED3_Y);output_low (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 4:output_low (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_high (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 5:output_high (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_high (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 6:output_low (LED4_R); // nejnizsi bitoutput_high (LED3_Y);output_high (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 7:output_high (LED4_R); // nejnizsi bitoutput_high (LED3_Y);output_high (LED2_Y);output_low (LED1_G); // nejvyssi bitbreak;case 8:output_low (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_low (LED2_Y);output_high (LED1_G); // nejvyssi bitbreak;case 9:output_high (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_low (LED2_Y);output_high (LED1_G); // nejvyssi bitbreak;default:output_low (LED4_R); // nejnizsi bitoutput_low (LED3_Y);output_low (LED2_Y);output_low (LED1_G); // nejvyssi bit}}/////////////////////////////////////////////////////////// FUNKCE PRO CTENI TLACITEK A KONTAKTU/////////////////////////////////////////////////////////// je pripojena zatez?// vraci 1 pri pripojene zatezi//int1 is_load () {int1 load;port_b_pullups (TRUE);delay_us (100);load = input (LOAD_ON); // precti stav kontaktu pripojeni zatezeport_b_pullups (FALSE);return (load);}// cte stav nastavovacich tlacitek// vraci masky stisknutych tlacitek, 0 = klidovy stav//int8 read_keys () {static int1 up_key_old;static int1 set_key_old;static int8 keys;int1 key_state;key_state = input (UP);if (key_state != up_key_old)up_key_old = key_state;elseif (! key_state)keys |= UP_MASK;elsekeys &= ~UP_MASK;key_state = input (SET);if (key_state != set_key_old)set_key_old = key_state;elseif (! key_state)keys |= SET_MASK;elsekeys &= ~SET_MASK;return (keys);}/////////////////////////////////////////////////////// VYKONNE FUNKCE/////////////////////////////////////////////////////// vybijeni baterie//void do_discharge () {int16 IB_val;int16 I_zero;int16 VB_val;int16 dec_cap;int1 load, load_old;int1 err;#ifdef DEBUGint16 max,min;int16 cnt;#endif// signalizuj neduveryhodnost zbyvajici kapacity baterieif (invalid_cap) {blink = 1;leds_invalid_cap ();delay_ms (500);leds_all_off ();}// nastaveni AD prevodniku: reference je 2.5V posun mereni proudu o 2,51V => cim vetsi prout, tim nizzsi cislo z prevodnikusetup_adc_ports (sAN0 | sAN1 | sAN2 | sAN3 | sAN5 | VSS_VREF);setup_vref (VREF_HIGH | VREF_A2 | 8); // na A2 vystup reference 2.51Vdelay_ms (1);I_zero = measure_offset (); // precti klidovou hodnotu, tedy offset OZ - nulovy odebirany proudoutput_high (BATT_ON);leds_dis (); // signalizuj zbyvajici kapacitu bateieerr = 0;blink = 1;l_tick = 0;s_tick = 0;// jeden pruchod smycku zabere max 2000 taktufor(;;) {restart_wdt ();if (s_tick) {s_tick = 0;IB_val = measure_IB (); // mer proud odebirany z baterieif (IB_val == 0 ) {// proudove pretizenioutput_low (BATT_ON); // odpoj bateriierr = 1; // signalizuj chybu}dec_cap = I_zero - IB_val; // zbav se ofsetu OZif (B_cap > dec_cap)B_cap = B_cap - dec_cap; // uprav zbyvajici kapacitu baterieif (! err)VB_val = measure_VB (); // napeti baterie je mozne merit jen pokud neni odpojena#ifdef DEBUGif (IB_val > max)max = IB_val;if (IB_val < min)min = IB_val;cnt++;#endif}if (l_tick) {l_tick = 0;if (! is_load ()) {return; // koncime, zatez odpojena}if (VB_val < VB_MIN) {// baterie zcela vybitaB_cap = 0; // nastav prazdnou kapacituinvalid_cap = 0; // aktualni kapacita baterie je nyni znamareturn;}if (err) {leds_err (); // signalizuj chybu}else {if (VB_val < VB_LOW) {leds_VB_low (); // signalizuj temer vybitou baterii}else {leds_dis (); // signalizuj zbyvajici kapacitu bateie}}#ifdef DEBUGprintf ("cnt:%lu z:%lu max:%ld delta:%u dec:%lu\n\r",cnt,I_zero,max,(int8)(max-min),dec_cap);max = 0;min = 1024;cnt = 0;#endif}}}// proces nabijeni baterie//void do_charge () {int1 chrg;int1 err;int16 I_zero;int16 IB_val;int16 inc_cap;int32 fast_chrg;int8 pwm;int16 duty;#ifdef DEBUGint16 max,min;int16 vs_val;#endif// vypocti mez do ktere budeme nabijet vyssim proudem// fast_chrg = (B_cap_4_4 - B_cap) / 64;fast_chrg = (B_cap_4_4 - B_cap) / 72;fast_chrg *= chrg_eff;fast_chrg += B_cap;#ifdef DEBUG// printf ("%lu %u %lu %lu\n\r\n\r",B_cap_4_4, chrg_eff,B_cap, fast_chrg);#endiferr = 0;s_tick = 0;l_tick = 0;pwm = 0;chrg = 0;// nastaveni AD prevodniku, reference je VDD = 5V , zadny posun napeti pri mereni proudu => cim vyssi proud, tim vyssi cislo z prevodnikusetup_adc_ports (sAN0 | sAN1 | sAN2 | sAN3 | sAN5 | VSS_VDD);setup_vref (VREF_LOW | VREF_A2 | 2); // na A2 vystup reference 0.416Vdelay_ms (1);I_zero = measure_offset (); // precti klidovou hodnotu, tedy ofset OZ - nulovy nabijeci proudif (invalid_cap == 0 &&TB_val < TB_MAX &&TB_VAL > TB_MIN) {// kapacita baterie je znama a teplota baterie je v mezichoutput_high (BATT_ON); // pripoj bateriioutput_high (CHRG_ON); // pripoj zdroj nabijenidelay_ms (500); // cekej na ustaleni menicechrg = 1;}if (measure_VS () < VS_MIN) { // kontrola napeti zatizeneho menice// napajeci zdroj je prilis mekkyerr = 1; // signalizuj chybuchrg = 0; // ukonci nabijenioutput_low (CHRG_ON); // odpoj zdroj nabijenioutput_low (BATT_ON); // odpoj bateriidelay_ms (300); // cekej na ustaleni menice}// jeden pruchod smyckou zabere max 3000 taktufor (;;) {restart_wdt ();if (s_tick) {s_tick = 0;IB_val = measure_IB (); // mer proud dodavany do baterie 1760 taktuif (IB_val > I_zero) // zbav se ofsetu OZIB_val -= I_zero;elseIB_val = 0;// nasledujici sekvence zabere max 300 taktuif (chrg) {if (IB_val == 0) { // tece vubec nejaky nabijeci proud ?// NE neteceerr = 1; // signalizuj chybuchrg = 0; // ukonci nabijenioutput_low (CHRG_ON);output_low (BATT_ON);}else {// ANO teceinc_cap = IB_val * chrg_eff; // uprav koeficientem ucinnosti nabijeniinc_cap = inc_cap >> (6-1); // zbav se vynasobeni 64x a vynasob dvema, protoze krok proudu pri nabijeni je dvojnasobny proti vybijeniB_cap = B_cap + inc_cap; // uprav kapacitu baterie}}#ifdef DEBUGif (IB_val > max)max = IB_val;if (IB_val < min)min = IB_val;#endif}if (l_tick) {l_tick = 0;measure_temp (); // mer teplotu baterie - 1100 taktuif (measure_VS () < VS_MIN)return; // koncime, napajeci zdroj byl odpojenif (is_load ())return; // koncime, je pripojena zatezif (invalid_cap)leds_invalid_cap (); // signalizace nezname aktualni kapacity baterie - nutno nejdive baterii vybitelseif (err)leds_err (); // signalizace chybyelse {// signalizace nabiti baterieif ( leds_chrg () == 4 || TB_val > TB_MAX) {// baterie je plne nabitaoutput_low (CHRG_ON);output_low (BATT_ON);chrg = 0;B_cap = B_cap_4_4;}else {if (B_cap > fast_chrg)duty = chrg_01C; // temer nabito dale nabijime 0.1Celseduty = chrg_02C; // nabijeni proudem max. 0.2Cif (pwm == 0) {output_high (CHRG_ON);chrg = 1;}else {if (pwm >= duty / IB_val) { // 400 taktuoutput_low (CHRG_ON);chrg = 0;}}pwm++;}}#ifdef DEBUGrestart_wdt ();// printf ("z:%lu h:%ld add:%lu cap:%lu T:%u\n\r",I_zero,max,inc_cap,B_cap,TB_val);// printf ("pwm:%u z:%lu max:%lu d:%lu\n\r",pwm,I_zero,max,max-min);// printf ("%lu %lu\n\r",B_cap, fast_chrg);printf ("z:%lu max:%lu delta:%u inc:%lu\n\r",I_zero,max,(int8)(max-min),inc_cap);max = 0;min = 1024;#endif}}}// upravi kapacitu baterie dle samovybijeni// zabere max. 2000 cyklu//void selfdischarge (int8 day_cnt) {int8 k2;int16 temp;int32 dec_cap;// realizuje upravu koeficientu samovybijeni podle teploty k2 = k * Z * delta_TB// zmena Z je 1.05 na stupenif (TB_avr24 > TB_ref)temp = (3 * (TB_avr24 - TB_ref)) + 64;else {temp = 3 * (TB_ref - TB_avr24);if (temp > 64)temp = 0;elsetemp = 64 - temp;}temp = (temp * k) / 64;k2 = (int8)temp;// v prvnich 5 dnech je samovybijeni strmejsiif (day_cnt < 5)k2 = k2 * 2;dec_cap = k2 * CAP_BATT;if (B_cap > dec_cap)B_cap -=dec_cap;#ifdef DEBUG// printf ("k:%u k2:%u dec_cap:%lu cap:%lu ",k,k2,dec_cap,B_cap);#endif}////////////////////////////////////////////////////////// PRIPRAVNE A NASTAVOVACI FUNKCE////////////////////////////////////////////////////////// pripravi promenne pro beh programu//void prepare_var () {int16 B_cap;int8 tmp8;int16 tmp16;int32 tmp32;float tmpf;// priprav meze pro signalizaci stavu vybiti baterieB_cap = read_eeprom (B_CAP_L_ADDR);B_cap *= 100;tmp16 = read_eeprom (B_CAP_H_ADDR);tmp16 *= 1000;B_cap += tmp16; // kapacita baterie v mAhB_cap_4_4 = B_cap * CAP_BATT;// B_cap_4_4 = 100 * CAP_BATT;B_cap_2_4 = B_cap_4_4 / 2;B_cap_1_4 = B_cap_2_4 / 2;B_cap_3_4 = B_cap_2_4 + B_cap_1_4;// priprav omezeni nabijecich proudutmpf = B_cap / 10;tmpf *= 256;tmpf /= 4.88;chrg_01C = (int16)tmpf;chrg_02C = chrg_01C * 2;// priprav koeficient ucinnosti nabijeni// eff = 1+(( read_eeprom (EFF_ADDR) * 5) / 100.0); // koeficient s jednickou// eff -= 0.1;// eff = 64 / eff; // ucinnost nabijeni (0-1) nasovena 64// chrg_eff = (int8)(eff); // ucinnost nabijeni vhodna pro celociselnou aritmetikuchrg_eff = CHRG_EFF_TAB [read_eeprom (EFF_ADDR)]; // toto je vyhodnejsi varianta// priprav koeficient samovybijenitmp8 = read_eeprom (LOSS_CAP_H_ADDR) * 10 + read_eeprom (LOSS_CAP_L_ADDR); // ztracena kapacita v procentechtmp32 = B_cap;tmp32 *= tmp8;tmp16 = tmp32 / 100; // ztracena kapacita v mAhtmp8 = read_eeprom (LOSS_DAY_H_ADDR) * 10 + read_eeprom (LOSS_DAY_L_ADDR); // pocet dni, za kterou se kapacita ztratilak = tmp16 / tmp8; // strmost poklesu samovybijeni v mAh / denTB_ref = read_eeprom (TB_REF_ADDR); // teplota, pri ktere k samovybijeni dochazelo#ifdef DEBUG// printf ("chrg_eff:%lu ",B_cap);// printf ("chrg_eff:%u ",chrg_eff);// printf ("k:%u ",k);#endif}// pripravi konstantu pro odmereni 1 hod pomoci wdt//prepare_hour_time () {int32 hour_time_cor;// vypocti potrebny pocet tiku wdt pro odmereni jedne hodinyhour_time_cor = 400 - hour_time;hour_time_cor *= HOUR_TIME_WDT;hour_time_cor /= hour_time;hour_time = HOUR_TIME_WDT + (int16)hour_time_cor;}// priprav vse pro minimalizaci spotreby ve spanku//void prepare_sleep () {leds_all_off ();output_low (BATT_ON);output_low (CHRG_ON);setup_vref (FALSE);}// nastavi parametry programu//void do_set_par () {int8 par_num; // cislo parametruint8 par_val; // hodnota parametruint8 key_timer; // pro osetreni zakmitu nastavovacich tlacitekint8 keys; // stav nastavovacich tlacitekint1 set_par; // jsme v rezimu nastavovani hodnoty parametruint1 wait_release; // cekame na uvolneni tlacitkaleds_all_on (); // oznam, ze jsme v nastavovacim rezimudelay_ms (1000);par_num = 0;s_tick = 0;l_tick = 0;key_timer = 0;wait_release = 0;set_par = 0;num_to_leds (par_num); // zobraz zvoleny parametrfor (;;) {restart_wdt ();if (s_tick) {s_tick = 0;if (key_timer != 0)key_timer--;else {key_timer = 5;keys = read_keys (); // precti stav tlacitekif (keys & SET_MASK) {// tlacitko SET je stisknuto - rezim vyberu parametruif (set_par) {if (par_val != read_eeprom (par_num)) { // prechazime z rezimu nastaveni parametru, uloz zvoleny parametrwrite_eeprom (par_num, par_val); // uloz jen pokud byl zmenenif (par_num == LOSS_DAY_H_ADDR ||par_num == LOSS_DAY_L_ADDR)write_eeprom (TB_REF_ADDR,TB_avr24); // pokud byla zmenena hodnota ztracene kapacity samovybijenim, uloz TB_avr24 jako refrerencni}num_to_leds (par_num); // zobraz zpatky zvoleny parametrset_par = 0;}else {// vybirame parametrif (keys & UP_MASK) {if (! wait_release) {if (par_num < 6)par_num++;elsepar_num = 0;num_to_leds (par_num); // zobrazeni vybraneho parametruwait_release = 1; // cekame na uvolneni tlacitka UP}}elsewait_release = 0; // tlacitko UP bylo uvolneno}}else {// tlacitko SET je uvolneno - rezim nastaveni parametruif (! set_par) {par_val = read_eeprom (par_num); // prechazime z rezimu vyberu parametru, vyzvedni zvoleny parametrnum_to_leds (par_val); // zobraz hodotu parametruset_par = 1;}else {// nastavujeme parametrif (keys & UP_MASK) {if (! wait_release) {if (par_val < PAR_MAX_TAB [par_num])par_val++;elsepar_val = 0;num_to_leds (par_val); // zobraz hodnotu parametruwait_release = 1; // cekame na uvolneni tlacitka UP}}elsewait_release = 0;}}}}if (l_tick) {l_tick = 0;if (measure_VS () < VS_MIN)break; // koncime, napajeci zdroj odpojen}}prepare_var (); // konec nastavovani, aktualizuj promenne programu}///////////////////////////////////////////////////// HLAVNI FUNKCE///////////////////////////////////////////////////main () {int1 load_old;int1 load;int1 no_load;int1 start_TB; // spust mrereni teploty baterieint16 wdt_timer; // pro odmereni hodiny pomoci wdtint8 hour_timer; // pro odmerovani hodinint8 day_timer; // pro odmerovani dni od nabitiint16 TB_avr_tmp; // pro vypocet prumerne teploty#ifdef DEBUGint16 c;int16 inc_cap,IB_val,I_zero;int8 val;#endifinit_ports ();if (restart_cause () != WDT_TIMEOUT) {// mereni skutecne doby behu wdt proved pro vseshny resety krome wdtsetup_oscillator (OSC_4MHZ | OSC_NORMAL);delay_ms (100);setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);setup_wdt (WDT_288MS);hour_time = 0;set_timer1 (~1000);restart_wdt ();for (;;) {if (TMR1IF) {hour_time++;TMR1IF = 0;set_timer1 (~1000);}}}setup_oscillator (OSC_4MHZ | OSC_NORMAL);setup_timer_0 (RTCC_INTERNAL| RTCC_DIV_1);setup_wdt (WDT_288MS);setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);set_timer1 (S_TICK_TIME);setup_spi (FALSE);setup_comparator (NC_NC_NC_NC);setup_vref (FALSE);setup_ccp1 (CCP_OFF);setup_adc (ADC_CLOCK_INTERNAL); // doba prevodu cca 48 uSsetup_adc_ports (sAN0 | sAN1 | sAN2 | sAN3 | sAN5 | VSS_VDD);enable_interrupts (INT_TIMER1);enable_interrupts (GLOBAL);prepare_var (); // priprav promenne pro beh programu z udaju o vlastnostech baterieprepare_hour_time ();//////////////////////////////////////////////////// uvodni bliknuti ledkououtput_high (LED1_G);delay_ms (250);output_low (LED1_G);/*#ifdef DEBUGoutput_high (BATT_ON);printf ("Ahoj %lu\n\r",hour_time);for (;;) {restart_wdt ();if (is_load ())break; // napajeci zdroj byl pripojendelay_ms (100);}B_cap = B_cap_2_4;invalid_cap = 0;set_timer1 (0);// zde se meri doba trvani funkci nebo vybraneho kodu// selfdischarge (0); //OKdo_discharge ();c = get_timer1 ();// printf ("T:%lu %lu %u \n\r",c,B_cap,chrg_eff);printf ("T:%lu\n\r",c);output_low (BATT_ON);delay_ms (250);for (;;)restart_wdt ();#endif*/#ifdef DEBUGinvalid_cap = 0;// B_cap = B_cap_3_4;B_cap = B_cap_2_4;#elseinvalid_cap = 1; // nezname zbyvajici kapacitu baterieB_cap = 0; // povazujeme ji za vybitou#endifTB_avr24 = TB_DEFAULT;TB_avr_tmp = 0;wdt_timer = 0;hour_timer = 0;day_timer = 0;start_TB = 1;no_load = 0;// hlavni programova smyckafor (;;) {restart_wdt ();prepare_sleep ();sleep ();setup_adc_ports (sAN0 | sAN1 | sAN2 | sAN3 | sAN5 | VSS_VDD);load = is_load (); // precti stav kontaktu pripojeni zatezeif (load != load_old)load_old = load; // stav kontaktu neni platnyelse {if (load) {if (! no_load) {do_discharge (); // zatez pripojena, vybijime - ma vyssi priorituno_load = 1; // dalsi vybijeni je mozne az po odpojeni zatezewdt_timer = 0;}}else {no_load = 0; // zatez byl odpojenaif (measure_VS () > VS_MIN) { // ma zdroj pro nabijeni dostatecne napeti?if (input (SET))do_charge (); // zatez odpojena a pripojen zdroj pro nabijeni, nabijime - ma nizsi piorituelsedo_set_par (); // prechazime do rezimu pro nastavovani parametru programuTB_avr_tmp = 0;wdt_timer = 0;hour_timer = 0;day_timer = 0;}}}// reseni samovybijeniif (wdt_timer < hour_time)wdt_timer++;else {// uplynula hodinastart_TB = 1; // odstartuj mereni teplotywdt_timer = 0; // natahni odmerovani hodinyif (hour_timer < 23)hour_timer++;else {// uplynul denTB_avr24 = TB_avr_tmp / 24; // vypocti prumernou teplotu za denif (day_timer < 90)day_timer++;elseinvalid_cap = 1; // po 90 dnech uz neverime kapacite baterieselfdischarge (day_timer); // uprav kapacitu baterie s ohledem na samovybijeni#ifdef DEBUG// printf ("TB:%u\n\r",TB_avr24);#endifTB_avr_tmp = 0;hour_timer = 0;}}// realizace mereni teploty - je v mnoha krocichif (start_TB) {if (measure_temp () == 0) {#ifdef DEBUG// printf("T:%u ",TB_val);#endifTB_avr_tmp += TB_val; // pocitame prumer teplotystart_TB = 0;}}}}