/***************************************************** This program was produced by the CodeWizardAVR V2.05.3 Standard Automatic Program Generator © Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Powerpack Version : 0.0 Date : 7/20/2011 Author : Jacques de Wit Company : Sjelab DS Comments: Lithium poly Powerpack. solar charger Chip type : ATmega32 Program type : Application AVR Core Clock frequency: 12.288000 MHz Memory model : Small External RAM size : 0 Data Stack size : 512 *****************************************************/ #include #include // Standard Input/Output functions #include #include #include #include #define FRAMING_ERROR (1<256) { printf("sla waarden op in EEprom\n\r"); EECharge=chargemode; EEcapaciteit=capaciteit; delay_ms(1000); printf("Power down! \n\r"); INTERN_SWITCH=0; delay_ms(5000); } } if (!PINB.4) // In het geval de drukschakelaar wordt ingedrukt worden de CurrentMAx en UnderVoltage bits gereset { printf ("RESET security bits"); if (EECurrentMax>0) EECurrentMax=0; CurrentMax=0; if (EEUnderVoltage>0) EEUnderVoltage=0; UnderVoltage=0; if (EEOvervoltage>0) EEOvervoltage=0; Overvoltage=0; } } } void AccuMeet (void) { unsigned int waarde; signed temp; unsigned char error; printf("C=%5.5f\n\r",c); printf("Chargemode: %02X\n\r",chargemode); // unsigned char cnt; waarde=read_adc(0x00); AccuSpanningLow=waarde; printf("UL:%u\t",waarde); waarde=read_adc(0x01); AccuSpanningTot=waarde; printf("Utot:%u\t",waarde); waarde=read_adc(0x03); Uuit=waarde; printf("Uuit:%u\t",waarde); waarde=read_adc(0x04); Uin=waarde; printf("Uin:%u\t",waarde); waarde=read_adc(0x05); Uref=c*waarde; printf("Uref:%04X\t",waarde); waarde=read_adc(0x06); StroomUit=waarde-1; printf("Iout:%04X\t",waarde); waarde=read_adc(0x07); StroomIn=waarde-1; // + offset correctie printf("Iin:%04X\n\r",waarde); // Berekenening accu spanning: // referentiespanning/1024 Aangezien er een 1 op 2 deling is toegepast, // moeten we dit vermenigvuldigen met 2 // Ua = 2,5/1024 x 2 => 5/1024 AccuSpanningLow+=5; // correctie waarde AccuSpanningTot+=3; // correctie waarde // Uin-=3; // correctie waarde Uin = // AccuSpanningLow*=c; AccuSpanningTot*=c*2; Uin*=c*6; Uuit*=c*6; // berekening accustroom over een weerstand van 0,1ohm // ((Waarde x 5/1024) - referentiespanning(ca 2,5V)) / (R0,1ohm x versterking(5x)) // Dit komt overeen met 10mA/digit // Door een lek in de opamp, wordt een stroom veroorzaakt door de aangelegde referentie spanning. dit veroorzaakt een offste fout, // door 0x10 bij de waarde op te tellen , doen we deze teniet. StroomIn+=0x10; StroomIn*=c; StroomIn-=Uref; StroomIn*=2000; // stroom in mA // StroomIn-=1; // Iout is de uitgaande stroom, de verbruikers stroom. Gemeten over een weerstand van 0,1ohm versterking 5x // ((Waarde x 5/1024) - referentiespanning(=2,5V)) / 5 x 1/R(=0.1) // Door een lek in de opamp, wordt een stroom veroorzaakt door de aangelegde referentie spanning. dit veroorzaakt een offste fout, // door 0x06 bij de waarde af te trekkken , doen we deze teniet. StroomUit-=0x06; StroomUit*=c; StroomUit-=Uref; // ref 1.233V + meetoffset 35mV StroomUit*=-2000; // 1/5 x 1/0.1 => 1/5 x 10 => 2 // Iout-=1; // interne temperatuur meting waarde=read_adc(0x02); Utherm=c*waarde; Rtherm=(((5-Utherm)*10000)/Utherm); NTCtemp = log(Rtherm/10000); // Ln (RT/RT25) NTCtemp /= 3988; // gedeeld door B NTCtemp += 0.003355705; // 1/25°C = 1/298K = 0.003355705 NTCtemp=(1/NTCtemp)-273; IntTemp=NTCtemp+0.5; // afronden op gehele graden celcius naar IntTemp printf("interne temperatuur %u°C %2.1f\n\r",IntTemp,NTCtemp); // Als een van de accu spanningen < 2,5V wordt de accu switch uitgeschakeld // om verdere ontlading van de accu te voorkomen. if ((AccuSpanningLow<2.5)||(AccuSpanningTot<2.5)) { EXTERN_SWITCH=0; INTERN_SWITCH=0; UnderVoltage=1; SystemCheck=0; printf("Accu(s) diepontladen \n\r"); } else { INTERN_SWITCH=1; if ((CON_DETECT==0)&&(SystemCheck==1)) EXTERN_SWITCH=1; else EXTERN_SWITCH=0; } printf("U Accu's %2.2fV\t",AccuSpanningTot); printf("U AccuLow %2.2fV\t",AccuSpanningLow); AccuSpanningHigh=AccuSpanningTot-AccuSpanningLow; printf("U Accu High %2.2fV\n\r",AccuSpanningHigh); sprintf(LCDText,"L:%4.2fV H:%4.2fV %u'C",AccuSpanningLow,AccuSpanningHigh,IntTemp); LCD_regel1; LCD_zend_text(LCDText); PowerIn=(StroomIn/1000)*Uin; PowerUit=(StroomUit/1000)*Uuit; if (fsign(PowerIn)==-1) PowerIn*=-1; if (fsign(PowerUit)==-1) PowerUit*=-1; if (fsign(StroomIn)==-1) StroomIn=0; if (fsign(StroomUit)==-1) StroomUit=0; printf("Uref %2.2fV\n\r",Uref); printf("In : U=%2.2fV I=%5.0fmA P=%4.2fW\n\r",Uin,StroomIn,PowerIn); printf("Uit: U=%2.2fV I=%5.0fmA P=%4.2fW\n\r",Uuit,StroomUit,PowerUit); sprintf(LCDText,"In :%4.2fA %4.1fV%4.1fW",StroomIn/1000,Uin,PowerIn); LCD_regel2; LCD_zend_text(LCDText); sprintf(LCDText,"Out:%4.2fA %4.1fV%4.1fW",StroomUit/1000,Uuit,PowerUit); LCD_regel3; LCD_zend_text(LCDText); capaciteit+=(StroomIn/3600); capaciteit-=(StroomUit/3600); if (capaciteit<0) capaciteit=0; if (capaciteit>10000) capaciteit=10000; // Maximale capaciteit 10000mAh sprintf(LCDText,"%4.0fmAh",capaciteit); LCD_Setloc(0x5F); LCD_zend_text(LCDText); error=0; // Als beide van de accu spanningen kleiner zijn dan 4,2V staat de lader aan. if (((AccuSpanningLow<4.0)||(AccuSpanningHigh<4.0))&&(chargemode==0xFF)) chargemode=1; if ((chargemode!=0xFF)&&(Overvoltage==0)) { if ((IntTemp>0) && (IntTemp<40)) { if (chargemode==1) CHARGER=1; else chargemode=1; if (Uin>(AccuSpanningTot+0.3)) // Als de ingangs spanning kleiner is dan de accuspanning + 0,7V wordt er niet geladen door te lage ingangs spanning { // Meten van de status van het laden aangegeven door de LTC1731. CHRG_CONTROL=1; DDRB.1=1; delay_ms(100); if (PINB&0x01) // PortB.0 Pin meet ingang is hoog (er wordt niet geladen ) { CHRG_CONTROL=0; DDRB.1=0; delay_ms(100); // PortB.1 wordt in tri-state gezet if (PINB&0x01) // PIN portB.0 is nog hoog, laden is gestopt door andere reden { error=4; printf("Accu's niet laden reden accu vol of out of timer\n\r"); } else // PIN portB.0 is nu laag, laden is gestopt door reden accu vol { if (AccuSpanningTot<8.3) { printf("Accu's laden C/10\n\r"); chargemode=0x80; } else { printf("Accu's laden C/10 Bijna vol \n\r"); chargemode=0xFF; } } } else { printf("Accu's laden \n\r"); } } else { chargemode=0; error=3; printf("Accu's niet laden Uin te laag \n\r"); } } else { CHARGER=0; chargemode=0; error=2; printf("Accu's niet laden temp niet OK \n\r"); } } else { CHARGER=0; error=1; if (chargemode==0xFF) printf("Accu(s) vol laden gestopt\n\r"); else { chargemode=0; printf("Accu(s) laden gestopt Accu>4.22V Overvoltage \n\r"); Overvoltage=1; } } LCD_regel4; if (CurrentMax==1) strcpyf(LCDText,"Max current"); else if (UnderVoltage==1) strcpyf(LCDText,"Under Volt."); else if (Overvoltage==1) strcpyf(LCDText,"Over Volt. "); else if (chargemode==0) { switch (error) { case 1: strcpyf(LCDText,"Stop U>4V ");break; case 2: strcpyf(LCDText,"Stop T>40'C");break; case 3: strcpyf(LCDText,"Stop U=Low ");break; case 4: strcpyf(LCDText,"Stop LTC ");break; default:break; } } else if (chargemode==1) strcpyf(LCDText,"Charging OK"); else if (chargemode==0x80) strcpyf(LCDText,"Charge 10%C"); else if (chargemode==0xFF) strcpyf(LCDText,"Chg10%C End"); LCD_zend_text(LCDText); // Als de stroom kleiner is dan 5A dan is het systeem OK en // kan later de 12V worden ingeschakeld if ((StroomUit<4000)&&(CurrentMax==0)) { SystemCheck=1; } else { SystemCheck=0; EXTERN_SWITCH=0; CurrentMax=1; if (EECurrentMax==0) EECurrentMax=1; } // Als de accu spanningen zijn groter dan 3V dan is het systeem OK en // kan later de 12V worden ingeschakeld if ((AccuSpanningLow>3)&&(AccuSpanningHigh>3)&&(UnderVoltage==0)) { SystemCheck=1; } else { SystemCheck=0; EXTERN_SWITCH=0; UnderVoltage=1; if (EEUnderVoltage==0) EEUnderVoltage=1; } if ((AccuSpanningLow<4.22)&&(AccuSpanningHigh<4.22)) { } else { Overvoltage=1; if (EEOvervoltage==0) EEOvervoltage=1; } // if (Iout>60) Zandloper=0; // Zandloper voor uitschakelen systeem wordt gereset als er meer dan 50mA output stroom is // if (Uin>3.5) Zandloper=0; // Zandloper voor uitschakelen systeem wordt gereset als de ingangstroom > 20mA if (PowerIn>0.2) Zandloper=0; if (PowerUit>0.3) Zandloper=0; temp=(Uin-16)*-15; // PWM regelaar (Timer 0 OCR0) voor de vrlichting if (temp<0) temp=0; OCR0=temp; if (SystemCheck==1) printf ("System OK\t"); if (CurrentMax==1) printf ("Current Max\t"); if (UnderVoltage==1) printf ("Under Voltage"); if (Overvoltage==1) printf ("Over Voltage"); printf("\n\r\n\r"); } // ############################################################################### //; Lezen van het commando register. Het MSB bit is de status van de busy flag. Is deze //; 1 dan is het LCD display bezig. bit0 t/m bit6 geeft het adres weer van de cursor plaats. //; Register B bevat de gelezen waarde char LCD_test_BF (void) { char result=0x80; //LCD_Getloc: // Hoogste 4 bits worden ingang, 3 laagste blijven uitgang DDRC=0x07; CNTR_RW=1; delay_ms(1); while (result>0x7F) { CNTR_ENABLE=1; // sbi PORTD,ENABLE ; Enable lijn hoog delay_ms(1); // rcall LCD_wait result=(PINC&0xF0); CNTR_ENABLE=0; // cbi PORTD,ENABLE ; Enable lijn laag delay_ms(1); // rcall LCD_wait CNTR_ENABLE=1; // sbi PORTD,ENABLE ; Enable lijn hoog delay_ms(1); // rcall LCD_wait result+=(PINC>>4); CNTR_ENABLE=0; // cbi PORTD,ENABLE ; Enable lijn laag } // alle 4 hoogste + 3 laagste bits worden uitgang DDRC=0xF7; CNTR_RW=0; // CNTR_RW=0; R/W bit gereset in write mode return result; } void LCD_enable (void) { delay_us(10); CNTR_ENABLE=1; // ; Enable lijn wordt hoog delay_us(10); CNTR_ENABLE=0; // ; Enable lijn wordt laag delay_us(10); } void LCD_put(char writebyte) { char static poort; LCD_test_BF(); // ; Test of LCD klaar is poort=writebyte&0xF0; poort|=(PINC&0x0F); // pin 0,1,2,3 worden overgenomen //poort|=0x08; // PortD.3 reset moet hoog blijven PORTC=poort; CNTR_RS = 1; //sbi portC,4 ; RS bit geset LCD_enable(); poort=(writebyte<<4); poort|=(PINC&0x0F); // pin 0,1,2,3 worden overgenomen //poort|=0x08; // reset moet hoog blijven PORTC=poort; CNTR_RS = 1; //; RS bit geset LCD_enable(); CNTR_RS = 0; //; RS bit gereset } //;_________________________________________________________________ //; //; LCD_zend_text zend een text string naar het LCD display. en eindigen met karrakter 0 //; void LCD_zend_text(char *text) { char cnt=0; while (text[cnt]) { LCD_put(text[cnt]); cnt++; } } void LCD_commando (char LCDcmd) { char poort; LCD_test_BF(); //rcall LCD_test_BF ; Test of LCD klaar is poort=LCDcmd&0xF0; poort|=(PINC&0x0F); // pin 0,1,2,3 worden overgenomen PORTC = poort; LCD_enable(); poort=LCDcmd<<4; poort|=(PINC&0x0F); // pin 0,1,2,3 worden overgenomen PORTC = poort; LCD_enable(); } void LCD_Setloc(char locatie) { LCD_commando(locatie|0x80); //ori A,0x80 ; bit 7 is altijd 1 (schrijf locatie in commando register) } // USART Receiver interrupt service routine interrupt [USART_RXC] void usart_rx_isr(void) { char status,data; status=UCSRA; data=UDR; if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) { rx_buffer[rx_wr_index++]=data; #if RX_BUFFER_SIZE == 256 // special case for receiver buffer size=256 if (++rx_counter == 0) rx_buffer_overflow=1; #else if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; if (++rx_counter == RX_BUFFER_SIZE) { rx_counter=0; rx_buffer_overflow=1; } #endif } } char getchar(void) { char data; while (rx_counter==0); data=rx_buffer[rx_rd_index]; if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0; #asm("cli") --rx_counter; #asm("sei") return data; } // Read the AD conversion result unsigned int read_adc(unsigned char adc_input) { ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); // Delay needed for the stabilization of the ADC input voltage delay_us(10); // Start the AD conversion ADCSRA|=0x40; // Wait for the AD conversion to complete while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCW; } // Timer1 input capture interrupt service routine interrupt [TIM1_CAPT] void timer1_capt_isr(void) { printf("## "); }