statefunc.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00034 #include <ioavr.h>
00035 #include <inavr.h>
00036 #include <stdlib.h>
00037 
00038 #include "structs.h"
00039 #include "enums.h"
00040 
00041 #include "ADC.h"
00042 #include "statefunc.h"
00043 #include "battery.h"
00044 #include "charge.h"
00045 #include "main.h"
00046 #include "menu.h"
00047 #include "OWI.h"
00048 #include "PWM.h"
00049 #include "time.h"
00050 #include "USI.h"
00051 
00052 
00053 //******************************************************************************
00054 // Variables
00055 //******************************************************************************
00056 unsigned char ErrorFlags;  
00057 
00058 
00061 unsigned char ErrorState;
00062 
00063 
00064 //******************************************************************************
00065 // Functions
00066 //******************************************************************************
00085 unsigned char Initialize(unsigned char inp)
00086 {
00087         unsigned char i, page;
00088 
00089         // Disable interrupts while setting prescaler.
00090         __disable_interrupt();
00091         
00092         CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.
00093         CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.
00094         
00095         // Init 1-Wire(R) interface.
00096         OWI_Init(OWIBUS);
00097         
00098         // Clear on-chip EEPROM.
00099         for (page = 0; page < 4; page++)        {
00100                 for (i = 0; i < 32; i++) {
00101                         BattEEPROM[page][i] = 0;
00102                 }
00103         }
00104 
00105         DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.
00106         DisableBatteries();
00107         SPI_Init(SPIMODE);
00108         ADC_Init();
00109         Time_Init();
00110 
00111         // Attempt to get ADC-readings (also gets RID-data) from both batteries.
00112         for (i = 0; i < 2; i++) {
00113                 EnableBattery(i);
00114                 ADC_Wait();
00115                 BatteryStatusRefresh();
00116         }
00117     
00118         DisableBatteries();
00119         
00120         BattActive = 0;               // We have to start somewhere..
00121         ErrorFlags = 0;
00122         
00123         // Init complete! Go to ST_BATCON next.
00124         return(ST_BATCON);
00125 }
00126 
00127 
00145 unsigned char BatteryControl(unsigned char inp)
00146 {
00147         unsigned char i;
00148         
00149         // Make sure ADC inputs are configured properly! (Will disables batteries.)
00150         if (!JumperCheck()) {
00151                 return(ST_ERROR);           // Error. Exit before damage is done!
00152         }
00153         
00154         // If neither battery is valid, flag error and go to error state
00155         if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {
00156                 SetErrorFlag(ERR_NO_BATTERIES_ENABLED);
00157                 
00158                 return(ST_ERROR);
00159         }
00160 
00161         // Get ADC-readings, try to read EPROM, and start prequalification
00162         // of any uncharged battery.
00163         for (i = 0; i < 2; i++) {
00164                 if (BattControl[i].Enabled) {      
00165                         EnableBattery(i);
00166                         ADC_Wait();
00167 
00168                         if (BatteryStatusRefresh()) {
00169                                 if (!BattData.Charged) {
00170                                         BatteryDataRefresh();
00171 
00172                                         return(ST_PREQUAL);       
00173                                 }
00174                         }
00175                 }
00176         }
00177 
00178         // If we end up here, one or two batteries are found and fully charged.
00179         // Disconnect, so we don't drain them, and go to sleep.
00180         DisableBatteries();
00181 
00182         return(ST_SLEEP);
00183 }
00184 
00185 
00192 unsigned char Discharge(unsigned char inp)
00193 {
00194         return(ST_BATCON);  // Supply voltage restored, start charging
00195 }
00196 
00197 
00208 unsigned char Sleep(unsigned char inp)
00209 {
00210         unsigned char i;
00211 
00212         do {
00213                 Doze();               // Take a nap (~8 seconds).
00214 
00215                 // If any batteries need charging, go to ST_BATCON.
00216                 // Otherwise, keep sleeping.
00217                 for (i = 0; i < 2; i++) {
00218                         EnableBattery(i);
00219                         ADC_Wait();
00220                         if ((BatteryStatusRefresh()) && (!BattData.Charged)) {
00221                                 return(ST_BATCON);
00222                         }
00223                 }
00224                 
00225                 DisableBatteries();  // Disable both batteries before Doze()!
00226         } while (TRUE);
00227 }
00228 
00229 
00236 void Doze(void)
00237 {
00238         // Wait for this ADC cycle to complete, then halt after the next one.
00239         ADC_Wait();
00240         ADCS.Halt = TRUE;
00241         ADCS.Flag = FALSE;
00242         
00243         do {
00244         } while (ADCS.Flag == FALSE);    
00245         
00246         WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.
00247         WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.
00248         MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.
00249         __sleep();                              // Go to sleep, wake up by WDT.
00250         
00251         __watchdog_reset();                     // Clear watchdog reset flag.
00252         MCUSR &= ~(1<<WDRF);          
00253         WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.
00254         WDTCR = 0;                              // Turn off watchdog.
00255         
00256         ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.
00257         ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.
00258         
00259         // Wait for this cycle to complete.
00260         ADC_Wait();                             
00261 }
00262 
00263 
00286 unsigned char Error(unsigned char inp)
00287         {
00288         unsigned char i;
00289         
00290         PWM_Stop();           // Stop charging.
00291         DisableBatteries();   // Disable all loads.
00292         
00293         do {
00294                 Doze();           // Take a nap.
00295 
00296                 // For each bit in ErrorFlags, starting with LSB, handle
00297                 // associated error, if the flag is set.
00298                 for (i = 0x01; i!=0; i<<=1) {
00299                         if(i & ErrorFlags) {
00300                                 switch (i) {
00301                                 
00302                                 case  ERR_JUMPER_MISMATCH:
00303                                         // Clear flag & recheck.
00304                                         ErrorFlags &= ~i;
00305                                         JumperCheck();
00306                                 break;
00307 
00308 
00309                                 case  ERR_NO_BATTERIES_ENABLED:
00310                                         // Clear if any battery gets enabled.
00311                                         if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {
00312                                                         ErrorFlags &= ~i;
00313                                         }
00314                                 break;
00315 
00316 
00317                                 case  ERR_PWM_CONTROL:
00318                                         // Clear flag.
00319                                         ErrorFlags &= ~i;
00320                                 break;
00321 
00322 
00323                                 case  ERR_BATTERY_TEMPERATURE:
00324                                         // Clear flag.
00325                                         ErrorFlags &= ~i;
00326                                 break;
00327 
00328 
00329                                 case  ERR_BATTERY_EXHAUSTED:
00330                                         // Try the other battery.
00331                                         BattData.Exhausted = FALSE;
00332                                         BattActive = (BattActive + 1) % 2;
00333                                         ErrorFlags &= ~i;
00334                                 break;
00335 
00336                                         
00337                                 default:
00338                                 break;
00339                                 }
00340                         }
00341                 }
00342         } while (ErrorFlags);
00343 
00344         return(ST_INIT);
00345 }
00346 
00347 
00356 void SetErrorFlag(unsigned char Flag)
00357 {
00358         ErrorFlags |= Flag;
00359         ErrorState = CurrentState;
00360 }
00361 
00362 
00374 unsigned char JumperCheck(void)
00375 {
00376          DisableBatteries();       // Disconnect, or loads may be destroyed!
00377          
00378          PWM_Start();              // Start PWM (controls the buck charger).
00379         
00380          // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.
00381          Time_Set(TIMER_GEN,0,1,0);
00382         
00383         do {
00384                 // If the PWM output voltage saturates the ADC, stop PWM output and
00385                 // report a failure.
00386                 if (ADCS.rawVBAT == 1023) {
00387                         PWM_Stop();
00388                         return(FALSE);
00389                 }
00390 
00391                 // If the absolute difference between measured (VIN - VBAT) and the
00392                 // typical value are below our set maximum, everything is OK.
00393                 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <
00394                                      VIN_VBAT_DIFF_MAX ) {
00395                                  
00396                         PWM_Stop();
00397                         return(TRUE);
00398                 }
00399 
00400                 // Charge current is too high -> check load and jumper J405 and J406.
00401                 if (abs(ADCS.IBAT) > 100) {
00402                         PWM_Stop();
00403                         return(FALSE);
00404                 }
00405 
00406                 // If the PWM output can't be increased high enough -> check jumpers
00407                 // J400-J404, J407 and J408.
00408                 if (!PWM_IncrementDutyCycle()) {
00409                         PWM_Stop();
00410                         return(FALSE);
00411                 }
00412                 
00413       // Wait for ADC conversions to complete
00414                 ADC_Wait();
00415         } while (Time_Left(TIMER_GEN));
00416         
00417 
00418         // If we end up here, the measurements took too long.
00419         PWM_Stop();
00420         return(FALSE);
00421 }

Generated on Tue Sep 4 19:17:55 2007 for AVR463 Charging NiMH Batteries with ATAVRBC100 by  doxygen 1.5.2