# statefunc.c File Reference

## Detailed Description

State functions.

Contains the functions related to the states defined in menu.h.
Also contains related functions, i.e. for checking jumpers, setting error flags and "dozing".

Note:
  The state function Charge() is in a separate file since it should easily be changed with regard to battery type.

Application note:
  AVR458: Charging Li-Ion Batteries with BC100
  AVR463: Charging NiMH Batteries with BC100

Documentation
  For comprehensive code documentation, supported compilers, compiler settings and supported devices see readme.html

Author:
  Atmel Corporation: http://www.atmel.com
  Support email: avr@atmel.com

$Name$

Revision
  2299

$RCSfile$

URL
  http://revisor.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/trunk/code/IAR/statefunc.c

Date
  2007-08-23 12:55:51 +0200 (to, 23 aug 2007)

Definition in file statefunc.c.

`#include <ioavr.h>`
`#include <inavr.h>`
`#include <stdlib.h>`
`#include "structs.h"`
`#include "enums.h"`
`#include "ADC.h"`
`#include "statefunc.h"`
`#include "battery.h"`
`#include "charge.h"`
`#include "main.h"`
`#include "menu.h"`
`#include "OWI.h"`
`#include "PWM.h"`
`#include "time.h"`
`#include "USI.h"`

Include dependency graph for statefunc.c:

Go to the source code of this file.

## Functions
unsigned char | BatteryControl (unsigned char inp)
| Tests jumper settings and batteries, starts charging if necessary.
unsigned char | Discharge (unsigned char inp)
| Start running on batteries.
void | Doze (void)
| Doze off for approx. 8 seconds (Vcc = 5 V).
unsigned char | Error (unsigned char inp)
| Handles errors.
unsigned char | Initialize (unsigned char inp)
| Initialization.
unsigned char | JumperCheck (void)
| Checks on-board jumpers.
void | SetErrorFlag (unsigned char Flag)
| Sets the specified error-flag and saves the current state.
unsigned char | Sleep (unsigned char inp)
| Sleeps until either battery needs charging.
## Variables
unsigned char | ErrorFlags
| Holds error flags.
unsigned char | ErrorState
| Holds the state in which latest error flag was set.

## Function Documentation

unsigned char BatteryControl | ( | unsigned char | inp | ) |

Tests jumper settings and batteries, starts charging if necessary.

First, JumperCheck() is called. If successful, the function checks if any valid batteries are connected and attempts to charge these, if necessary.
If no charging is necessary, the charger goes to ST_SLEEP next.
ST_ERROR is next if either JumperCheck() fails or there are no valid batteries. In this last case, the error is also flagged.

Parameters:

  | inp | Not used.

Return values:

  | ST_ERROR | Next state if either the jumper check failed, or there are no valid batteries.
  | ST_PREQUAL | Next state if a battery is found to enabled and not fully charged.
  | ST_SLEEP | Next state if battery/batteries are enabled and fully charged.

Definition at line 145 of file statefunc.c.

References ADC_Wait(), BattControl, BattData, BatteryDataRefresh(), BatteryStatusRefresh(), Batteries_struct::Charged, DisableBatteries(), EnableBattery(), ERR_NO_BATTERIES_ENABLED, JumperCheck(), SetErrorFlag(), ST_ERROR, ST_PREQUAL, and ST_SLEEP.

    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 }

Here is the call graph for this function:

unsigned char Discharge | ( | unsigned char | inp | ) |

Start running on batteries.

Todo:
  Run on batteries, if battery voltage high enough.

Todo:
  Jump here when mains voltage drops below threshold

Definition at line 192 of file statefunc.c.

References ST_BATCON.

    00193 {
    00194         return(ST_BATCON);  // Supply voltage restored, start charging
    00195 }

void Doze | ( | void |  | ) |

Doze off for approx. 8 seconds (Vcc = 5 V).

Waits for ADC-cycles to complete, disables the ADC, then sleeps for approx. 8 seconds (Vcc = 5 V) using the watchdog timer. On wakeup, ADC is re-enabled.

Definition at line 236 of file statefunc.c.

References ADC_Wait(), ADCS, FALSE, ADC_Status_struct::Flag, ADC_Status_struct::Halt, and TRUE.

Referenced by Error(), and Sleep().

    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 }

Here is the call graph for this function:

unsigned char Error | ( | unsigned char | inp | ) |

Handles errors.

Stops PWM output and disables batteries. The function then goes into a loop that starts with a call to Doze(), then attempts to handle each error. The loop will reiterate until all flags are cleared.
The charger will reinitialize after this.

Jumper errors are handled by clearing the flag, then calling JumperCheck(). If unsuccessful, the error flag will now have been set again.

If there are no valid batteries, the loop will simply reiterate until a valid battery is found. The error flag will then be cleared.

In the case of PWM controller or battery temperature errors, the error flag is simply cleared. This is because the problem may have gone away during Doze(), or after reinitializing.

If a battery is exhausted, we clear its exhausted-flag in BattData, and change batteries before clearing the error flag.

Parameters:

  | inp | Not used.

Definition at line 286 of file statefunc.c.

References BattActive, BattControl, BattData, DisableBatteries(), Doze(), ERR_BATTERY_EXHAUSTED, ERR_BATTERY_TEMPERATURE, ERR_JUMPER_MISMATCH, ERR_NO_BATTERIES_ENABLED, ERR_PWM_CONTROL, ErrorFlags, Batteries_struct::Exhausted, FALSE, JumperCheck(), PWM_Stop(), and ST_INIT.

    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 }

Here is the call graph for this function:

unsigned char Initialize | ( | unsigned char | inp | ) |

Initialization.

- Sets the system clock prescaler to 1 (run at 8 MHz)
- Initializes the one-wire interface
- Clears on-chip EEPROM
- Sets battery enable pins as outputs, then disables batteries
- Initializes SPI according to SPIMODE
- Initializes ADC
- Initializes timers
- Reads battery data from both battery inputs (via ADC)
- Disables batteries again
- Sets battery A as the current one (BattActive = 0)
- Clears ErrorFlags

Parameters:

  | inp | Not used.

Return values:

  | ST_BATCON | Next state in the sequence.

Definition at line 85 of file statefunc.c.

References ADC_Init(), ADC_Wait(), BattActive, BattEEPROM, BatteryStatusRefresh(), DisableBatteries(), EnableBattery(), ErrorFlags, OWI_Init(), OWIBUS, SPI_Init(), SPIMODE, ST_BATCON, and Time_Init().

    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 }

Here is the call graph for this function:

unsigned char JumperCheck | ( | void |  | ) |

Checks on-board jumpers.

Checks on-board jumpers by disconnecting all loads, engaging the PWM and increasing the duty cycle until conditioned output voltage equals conditioned input voltage. At low PWM duty and no load buck output should be zero and, when increasing PWM duty, should quickly jump to steady state output roughly equal to input voltage. Will disable and leave disabled all batteries.

Return values:

  | FALSE | If jumper or load mismatch.
  | TRUE | If everything OK.

Definition at line 374 of file statefunc.c.

References ADC_Wait(), ADCS, DisableBatteries(), FALSE, ADC_Status_struct::IBAT, PWM_IncrementDutyCycle(), PWM_Start(), PWM_Stop(), ADC_Status_struct::rawVBAT, Time_Left(), Time_Set(), TIMER_GEN, TRUE, ADC_Status_struct::VBAT, ADC_Status_struct::VIN, VIN_VBAT_DIFF_MAX, and VIN_VBAT_DIFF_TYP.

Referenced by BatteryControl(), and Error().

    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 }

Here is the call graph for this function:

void SetErrorFlag | ( | unsigned char | Flag | ) |

Sets the specified error-flag and saves the current state.

Updates ErrorFlags and ErrorState.

Note:
  Error flags are specified in statefunc.h.

Parameters:

  | Flag | Specifies what error to flag.

Definition at line 356 of file statefunc.c.

References CurrentState, ErrorFlags, and ErrorState.

Referenced by BatteryControl(), ConstantCurrent(), ConstantVoltage(), HaltNow(), and MaxVoltageAndCurrent().

    00357 {
    00358         ErrorFlags |= Flag;
    00359         ErrorState = CurrentState;
    00360 }

unsigned char Sleep | ( | unsigned char | inp | ) |

Sleeps until either battery needs charging.

Calls Doze(), then refreshes the status for both batteries on wakeup. If connected batteries are both charged, the function will loop. If not, it's back to ST_BATCON.

Parameters:

  | inp | Not used.

Return values:

  | ST_BATCON | Next state if a connected battery isn't fully charged.

Definition at line 208 of file statefunc.c.

References ADC_Wait(), BattData, BatteryStatusRefresh(), Batteries_struct::Charged, DisableBatteries(), Doze(), EnableBattery(), ST_BATCON, and TRUE.

    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 }

Here is the call graph for this function:

## Variable Documentation

unsigned char ErrorFlags

Holds error flags.

Note:
  See statefunc.h for definitions of flags.

Definition at line 56 of file statefunc.c.

Referenced by Error(), Initialize(), and SetErrorFlag().

unsigned char ErrorState

Holds the state in which latest error flag was set.

Note:
  See menu.h for definitions of states.

Definition at line 61 of file statefunc.c.

Referenced by SetErrorFlag().