//Definice bitu pro ovladani lcd sbit LCD_RS at LATB4_bit; sbit LCD_EN at LATB5_bit; sbit LCD_D4 at LATB0_bit; sbit LCD_D5 at LATB1_bit; sbit LCD_D6 at LATB2_bit; sbit LCD_D7 at LATB3_bit; // Pin direction sbit LCD_RS_Direction at TRISB4_bit; sbit LCD_EN_Direction at TRISB5_bit; sbit LCD_D7_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB1_bit; sbit LCD_D4_Direction at TRISB0_bit; // Definice tlačítek sbit button_ok at RB6_bit; sbit button_plus at RB7_bit; sbit button_minus at RA3_bit; sbit button_cancel at RA4_bit; unsigned int zakmit = 0; // definice pro sledování a ovládání CCSka sbit CCS_IO at TRISE0_bit; sbit CCS_Override_R at RE0_bit; sbit CCS_Override_W at LATE0_bit; //definice pro ovladani multiplexoru sbit Vmax1_M at LATC0_bit; sbit Vmax2_M at LATC1_bit; sbit Vmax3_M at LATC6_bit; sbit Vnom1_M at LATC7_bit; sbit Vnom2_M at LATD0_bit; sbit Vnom3_M at LATD1_bit; sbit Ich1_M at LATD2_bit; sbit Ich2_M at LATD3_bit; sbit Ich3_M at LATD4_bit; sbit Ich_AB_M at LATD5_bit; // MMC module connections sfr sbit Mmc_Chip_Select at LATC2_bit; // for writing to output pin always use latch (PIC18 family) sfr sbit Mmc_Chip_Select_Direction at TRISC2_bit; // proměnné pro zvoleni nabíjení unsigned int vyber=0; unsigned int vnom=0; unsigned int vmax=0; unsigned int zpet=0; unsigned int proud=0; float ich=0; int proudy = 0; char txt_ich[3]; int pocet = 0; float napeti=0; char txt_napeti[15]; char txt_pocet[15]; char txt_typ_baterie[15]; // char txt_baterie[]="nimh"; //pozor absolutní velikost int i=0; //definice proměných k běhu nabíjecího procesu sbit Power_Led at RE2_bit; sbit Charge_Led at RE1_bit; int start_nabijeni =0; int stop_nabijeni =0; unsigned int dvojty =0; char txt_hodiny[1]; char txt_minuty[60]; //definice proměných k TMR0 - cíl je 1HZ volatile unsigned int sekundy = 0; unsigned int minuty = 0; unsigned int hodiny = 0; unsigned int counter = 0; //proměné pro SD CARTU char filename[] = "Data.TXT"; unsigned char cardtxt[13]; unsigned char error; unsigned int povoleni_sd=1; //proměné pro AD převodník unsigned int ANA4 = 0; char txtAD[10]; //proměnné pro výčet energie float energie=0; char txt_energie[15]; //proměnné pro ukončení nabíjení unsigned int konec=0; void uvod_LCD() { Lcd_Init(); //inicializace LCD Lcd_Cmd(_LCD_CLEAR); // Vymazani displeje Lcd_Cmd(_LCD_CURSOR_OFF); // Vypnuti kurzoru Lcd_Out(1, 1, "CCS stanice"); Delay_ms(2000); Lcd_Cmd(_LCD_CLEAR); } ADC_prevod() { unsigned int a; GO_bit = 1; while (GO_bit); a = ADRESL | (ADRESH<<8); return a; } void ADC_start() { ANA4 = 3.22265*ADC_prevod(); // AD prevod 3.3/1024 max napětí/rozlišení ad převodníku IntToStr(ANA4, txtAD); // Prevod Integeru na String // Lcd_Out(2, 1, "Napeti:"); // Vypise text na LCD na pozici 1,1 Lcd_Out(2, 1,txtAD); // Vypis textu na LCD, ozor integer vypisuje až do radu desetitisícu Lcd_Out(1,8,"mV"); // vypisuji jednotku Delay_ms(100); //tady bych měl ještě ukládat průběžné napětí pro případný zápis na SD // zde udělám přibližný výpočet dodané energie energie=(ich*(minuty+(60*hodiny)))/0.06; //výsledek by měl být v mAh sprintf(txt_energie, "%.3f", energie); // prevedi float na retezec s 3 desetinym mistem Lcd_Out(2,12,txt_energie); Delay_ms(30); } void overeni_SD() { while(MMC_Init()&&povoleni_sd==1) { Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1," CARD NOT FOUND"); Lcd_Out(2,1," press OK"); if (button_ok == 0) { Delay_ms(50); povoleni_sd=0; Lcd_Cmd(_LCD_CLEAR); } } if (povoleni_sd != 0) { Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1," CARD DETECTED!"); Lcd_Out(2,1,"CARD INITIALIZED"); Delay_ms(1000); Lcd_Cmd(_LCD_CLEAR); } } void typ_baterie() { int zmena=0; Lcd_Out(1,1,"Typ baterie:"); Lcd_Out(2,1,"+ / -"); vnom=0; vyber=0; zpet=0; while(vyber==0) { Delay_ms(50); if (button_plus==0 && vnom<=3 && vnom>=0) { Delay_ms(50); vnom ++; zmena=1; } if (button_minus==0 && vnom<=4 && vnom>=2) { Delay_ms(50); vnom --; zmena=1; } if (zmena==1) { switch (vnom) { case 1: Lcd_Out(2,1,"Ni-Mh / Ni-Cd"); // strcpy(txt_baterie,"Ni-Mh\0"); Delay_ms(50); break; case 2: Lcd_Out(2,1,"PB "); Delay_ms(50); break; case 3: Lcd_Out(2,1,"Li-ion "); Delay_ms(50); break; case 4: Lcd_Out(2,1,"Li-Pol "); Delay_ms(50); break; } } if (button_ok == 0 && vnom!=0) { Delay_ms(50); vyber=1; Lcd_Cmd(_LCD_CLEAR); } } vyber=0; } void pocet_clanku() { Lcd_Out(1,1,"Pocet clanku:"); Lcd_Out(2,1,"+ / -"); vmax=0; vyber=0; zpet=0; while (vyber==0) { if(((button_plus ==0)||(button_minus==0))&&((vnom==3)||(vnom==4))) { Delay_ms(50); if (vnom==3) { vmax=5; //Li-ion Lcd_Out(1,1,"Baterie Li-ion"); Delay_ms(50); Lcd_Out(2,1,"Pouze 1 clanek"); Delay_ms(50); pocet=1; strncpy(txt_typ_baterie, "Li-ion", 15); napeti=3.6; Vnom1_M=0; Vnom2_M=0; Vnom3_M=1; Vmax1_M=0; Vmax2_M=0; Vmax3_M=1; } else { vmax=6; //Li-Pol Lcd_Out(1,1,"Baterie Li-Pol"); Delay_ms(50); Lcd_Out(2,1,"Pouze 1 clanek"); Delay_ms(50); pocet=1; strncpy(txt_typ_baterie, "Li-Pol", 15); napeti=3.7; Vnom1_M=1; Vnom2_M=0; Vnom3_M=1; Vmax1_M=1; Vmax2_M=0; Vmax3_M=1; } } if (button_plus==0 && vnom==1 && vmax<=1) { delay_ms(50); if (vmax==0) { vmax=1; //-----------nimh 2 clanky----- Lcd_Out(2,1,"2 clanky 2.4V"); Delay_ms(50); pocet=2; strncpy(txt_typ_baterie, "Ni-Mh", 15); napeti=2.4; Vnom1_M=0; Vnom2_M=0; Vnom3_M=0; Vmax1_M=0; Vmax2_M=0; Vmax3_M=0; } else { vmax=2; //------nimh 4 clanky------ Lcd_Out(2,1,"4 clanky 4,8 V"); Delay_ms(50); pocet=4; strncpy(txt_typ_baterie, "Ni-Mh", 15); napeti=4.8; Vnom1_M=1; Vnom2_M=0; Vnom3_M=0; Vmax1_M=1; Vmax2_M=0; Vmax3_M=0; } } if (button_minus==0 && vnom==1 && vmax==2) { Delay_ms(50); //----nimh 2 clanky---- vmax=1; Lcd_Out(2,1,"2 clanky 2,4V"); Delay_ms(50); strncpy(txt_typ_baterie, "Ni-Mh", 15); pocet=2; napeti=2.4; Vnom1_M=0; Vnom2_M=0; Vnom3_M=0; Vmax1_M=0; Vmax2_M=0; Vmax3_M=0; } if (button_plus==0 && vnom==2 && (vmax==0 || vmax==3)) { Delay_ms(50); if (vmax==0) { vmax=3; //------ PB 3 clanky------ Lcd_Out(2,1,"3 clanky 6V"); Delay_ms(50); pocet=3; strncpy(txt_typ_baterie, "PB", 15); napeti=6.0; Vnom1_M=0; Vnom2_M=1; Vnom3_M=0; Vmax1_M=0; Vmax2_M=1; Vmax3_M=0; } else { vmax=4; //------- PB 4 clanky------ Lcd_Out(2,1,"4 clanky 12V"); Delay_ms(50); pocet=4; strncpy(txt_typ_baterie, "PB", 15); napeti=12.0; // tady je problem do floatu se ukládaá číslo 11.99 Vnom1_M=1; Vnom2_M=1; Vnom3_M=0; Vmax1_M=1; Vmax2_M=1; Vmax3_M=0; } } if (button_minus==0 && vnom==2 && vmax==4) { { vmax=3; //------------ PB 3 clanky ------- Lcd_Out(2,1,"3 clanky 6V"); Delay_ms(50); pocet=3; strncpy(txt_typ_baterie, "PB", 15); napeti=6.0; Vnom1_M=0; Vnom2_M=1; Vnom3_M=0; Vmax1_M=0; Vmax2_M=1; Vmax3_M=0; } } if (button_ok == 0 && vmax!=0) { Delay_ms(50); vyber=1; Lcd_Cmd(_LCD_CLEAR); } if (button_cancel==0) { Lcd_Cmd(_LCD_CLEAR); Delay_ms(50); zpet=1; vyber=1; } } vyber=0; } void zapis_SD() { MMC_Fat_Init(); // reinitialize spi at higher speed SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); Mmc_Fat_Assign(filename, 0x80); // Find existing file or create a new one Mmc_Fat_Rewrite(); IntToStr(ANA4, cardtxt); // Prevod Integeru z ad na nový String cardtxt[8]='V'; cardtxt[9]='\r'; cardtxt[10]='\n'; Mmc_Fat_Append(); Mmc_Fat_Write(cardtxt,11); Lcd_Cmd(_LCD_CLEAR); Lcd_Out(1,1,"FILE SAVED!"); Delay_ms(1000); } void vyber_proud() { switch (proud) { case 1: Lcd_Out(2,1,"Proud = 50mAh"); Delay_ms(50); ich=0.0501; proudy=50; Ich1_M=0; Ich2_M=0; Ich3_M=0; Ich_AB_M=0; break; case 2: Lcd_Out(2,1,"Proud = 100mAh"); Delay_ms(50); ich=0.1017; proudy=100; Ich1_M=1; Ich2_M=0; Ich3_M=0; Ich_AB_M=0; break; case 3: Lcd_Out(2,1,"Proud = 150mAh"); Delay_ms(50); ich=0.1588; proudy=150; Ich1_M=0; Ich2_M=1; Ich3_M=0; Ich_AB_M=0; break; case 4: Lcd_Out(2,1,"Proud = 200mAh"); Delay_ms(50); ich=0.2048; proudy=200; Ich1_M=1; Ich2_M=1; Ich3_M=0; Ich_AB_M=0; break; case 5: Lcd_Out(2,1,"Proud = 250mAh"); Delay_ms(50); ich=0.2395; proudy=250; Ich1_M=0; Ich2_M=0; Ich3_M=1; Ich_AB_M=0; break; case 6: Lcd_Out(2,1,"Proud = 300mAh"); Delay_ms(50); ich=0.3095; proudy=300; Ich1_M=1; Ich2_M=0; Ich3_M=1; Ich_AB_M=0; break; case 7: Lcd_Out(2,1,"Proud = 350mAh"); Delay_ms(50); ich=0.3593; proudy=350; Ich1_M=0; Ich2_M=1; Ich3_M=1; Ich_AB_M=0; break; case 8: Lcd_Out(2,1,"Proud = 400mAh"); Delay_ms(50); ich=0.4038; proudy=400; Ich1_M=1; Ich2_M=1; Ich3_M=1; Ich_AB_M=0; break; case 9: Lcd_Out(2,1,"Proud = 500mAh"); Delay_ms(50); ich=0.5108; proudy=500; Ich1_M=0; Ich2_M=0; Ich3_M=0; Ich_AB_M=1; break; case 10: Lcd_Out(2,1,"Proud = 600mAh"); Delay_ms(50); ich=0.5729; proudy=600; Ich1_M=1; Ich2_M=0; Ich3_M=0; Ich_AB_M=1; break; case 11: Lcd_Out(2,1,"Proud = 700mAh"); Delay_ms(50); ich=0.7066; proudy=700; Ich1_M=0; Ich2_M=1; Ich3_M=0; Ich_AB_M=1; break; case 12: Lcd_Out(2,1,"Proud = 800mAh"); Delay_ms(50); ich=0.8153; proudy=800; Ich1_M=1; Ich2_M=1; Ich3_M=0; Ich_AB_M=1; break; case 13: Lcd_Out(2,1,"Proud = 900mAh"); Delay_ms(50); ich=0.9021; proudy=900; Ich1_M=0; Ich2_M=0; Ich3_M=1; Ich_AB_M=1; break; case 14: Lcd_Out(2,1,"Proud = 1000mAh"); Delay_ms(50); proudy=1000; Ich1_M=1; Ich2_M=0; Ich3_M=1; Ich_AB_M=1; ich=1.0095; break; case 15: Lcd_Out(2,1,"Proud = 1100mAh"); Delay_ms(50); ich=1.1157; proudy=1100; Ich1_M=0; Ich2_M=1; Ich3_M=1; Ich_AB_M=1; break; case 16: Lcd_Out(2,1,"Proud = 1200mAh"); Delay_ms(50); ich=1.2045; proudy=1200; Ich1_M=1; Ich2_M=1; Ich3_M=1; Ich_AB_M=1; break; } } void nabijeci_proud() { Lcd_Out(1,1,"Nabijeci proud:"); Lcd_Out(2,1,"+ / -"); proud=0; vyber=0; zpet=0; while (vyber==0) { if (button_plus==0 && proud<=15) { delay_ms(50); proud++; vyber_proud(); } if (button_minus==0 && proud>=2) { delay_ms(50); proud--; vyber_proud(); } if (button_ok == 0 && proud!=0) { Delay_ms(50); vyber=1; Lcd_Cmd(_LCD_CLEAR); } if (button_cancel==0) { Lcd_Cmd(_LCD_CLEAR); Delay_ms(50); zpet=1; vyber=1; } } vyber=0; } void rekapitulace() { IntToStr(proudy, txt_ich); Lcd_Out(2,1,txt_ich); Delay_ms(30); Lcd_Out(2,7,"mAh"); Delay_ms(30); //FloatToStr(napeti, txt_napeti); je to zkurvený a nefunguje tak jak má sprintf(txt_napeti, "%.1f", napeti); // prevedi float n aretezec s jednim desetinym mistem Lcd_Out(2,12,txt_napeti); Delay_ms(30); Lcd_Out(2,16,"V "); Delay_ms(30); //IntToStr(pocet, txt_pocet); je to zkurvený a nefunguje tak jak má sprintf(txt_pocet, "%dx", pocet); /// pevedu int na retezec Lcd_Out(1,13,txt_pocet); Lcd_Out(1,1,txt_typ_baterie); Delay_ms(50); vyber=0; zpet=0; while(vyber==0) { if (button_ok == 0) { Delay_ms(50); vyber=1; Lcd_Cmd(_LCD_CLEAR); } if (button_cancel==0) { Lcd_Cmd(_LCD_CLEAR); Delay_ms(50); zpet=1; vyber=1; } Delay_ms(50); } vyber=0; } //------------------preruseni ------------------------------------- void interrupt() { if (TMR0IF_bit) { TMR0IE_bit = 0; // Disenable Timer0 interrupt TMR0IF_bit = 0; // clear TMR0IF TMR0L = 0; // Timer0 initial value TMR0H = 12; // nevím proč ale přesně na můj PIC to vychází (změřeno osc = 1 sec) } sekundy ++; TMR0IE_bit = 0; //enable Timer0 interrupt } void main() { OSCCON =0b01100110; //interní osc 8MHZ ANSELB = 0; //Nastaveni portu B TRISB = 0b11000000; //Nastaveni portu B RBPU_bit=0; //zapnutí pull_UP na portu B intcon2 TRISC = 0b00010000; // in z karty ANSELC = 0; // Configure AN pins as digital SLRCON = 0; // Configure all PORTS at the standard Slew Rate //---- nastavení I/O--- pro ostaní porty TRISD = 0b00000000; // ovladaní multiplexu TRISE = 0b1110; //RE0 CCS_OVERRIDE //vystup a log 1 -> zastavím nabíjení; log 0 -> povolím nabíjení //vstup log 1 -> ccs nabíjí; log 0 -> ccs nenabijí CCS_IO=0; //priprava na zakázaní nabijeni CCS_Override_W=1; // nabíjení je zakazano //---nastavení AD převodníku----- ANSELA = 0b00100000; // AN4 jako analogovy vstup, RA1-3 TRISA = 0b00111000; // RA5 jako vstup ADCON0 = 0b00010001; //Kanal AN4, Zapnuti ADC -> nastavení AD převodníku na RA5 ADCON1 = 0b00000000; //Vref+ = Vdd, Vref- = Vss ADCON2 = 0b10010110; //Zarovnani vpravo, dostatecny cas nabijeni, Fosc/x podle tabulky // inicializace SPI SPI1_Init(); SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64,_SPI_DATA_SAMPLE_MIDDLE,_SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); while(1) { uvod_LCD(); overeni_SD(); // tedka dám na radu Stany a predělám to do while // Stana má jenom samé dobré rady :-) while(1) { typ_baterie(); pocet_clanku(); if (zpet==1) { zpet=0; continue; } nabijeci_proud(); if (zpet==1) { zpet=0; continue; } rekapitulace(); if (zpet==1) { zpet=0; continue; } else { break; } } Lcd_Out(1,1,"Inicializuji"); Delay_ms(50); Lcd_Out(2,1,"cekejte prosim"); Delay_ms(50); // CCS_IO=1; //input sledovani nabijeni a zároven povoleni CCSku nabijet //zkoušk navíc věcí CCS_Override_W=0; // nabíjení je povoleno TRISE = 0b1111; start_nabijeni=0; while (start_nabijeni==0) // cekaci smycka - CCS pozna akumulator až za 20sec { if(Charge_Led==1 && CCS_Override_R==1) //pozor ještě nevím jaké bude napětí na Charge_Led a power_led ------ CCS_Override_R==1 // if (RE0==1 && RE1==1) { Lcd_Cmd(_LCD_CLEAR); Delay_ms(50); Lcd_Out(1,1,"Nabijeni"); Delay_ms(30); start_nabijeni=1; //tady by měla být inicializace Timeru TMR0L = 0; // Timer0 initial value TMR0H = 12; // nevím proč ale přesně na můj PIC to vychází (změřeno osc = 1 sec) T0CON = 0b10000100; // Set TMR0 to 16bit mode and prescaler to 32 GIE_bit = 1; // Enable global interrupt TMR0IE_bit = 1; // Enable Timer0 interrupt } } start_nabijeni=0; konec=0; // zde už by mělo probíhat samotné nabíjení while (stop_nabijeni==0) { //počítaní času: if (sekundy==60) { sekundy=0; minuty++; dvojty=0; } if (minuty==60) { minuty=0; hodiny++; } //----- konec samotného počítání času if ((sekundy==30 || sekundy ==60)&&CCS_Override_R==0 && dvojty==0 && konec==0) // 2x za minutu budu kontrolvat napětí na baterii - musím se strefit když LT obvod zrovna nenabijí { ADC_start(); dvojty=1; } if (sekundy==0 && dvojty==0 && konec==0) { //IntToStr (minuty,txt_minuty); //tohle do pice nefunguje //IntToStr (hodiny,txt_hodiny); //tohle do pice nefunguje sprintf(txt_hodiny,"%d:", hodiny); Lcd_Out(1,11,txt_hodiny); delay_ms(30); sprintf(txt_minuty, "%d", minuty); Lcd_Out(1,14,txt_minuty); delay_ms(30); dvojty=1; } if((CCS_Override_R==0 && Charge_Led==0) || button_cancel==0 ) // to znamená že se ukončilo nabíjení je jedno jak jestli uživatelem nebo ... { //musím vypnout prerušení GIE_bit = 0; // disenable global interrupt delay_ms(30); Lcd_Out(1,1,"Ukonceno"); konec=1; stop_nabijeni=1; if (povoleni_sd=1) { // zapis_SD(); //musí se zapsat dodaný náboj, celkový čas a průběžné napětí } stop_nabijeni=1; } } while (1) { if (button_cancel==0) //kompletní ukončení nabíjení Lcd_Cmd(_LCD_CLEAR); delay_ms(30); break; // vrácení zpět do hlavního while } } while(1) { Delay_ms(1000); } }