- Main Page
- Related Pages
- Data Structures
- Files

# battery.c

Go to the documentation of this file.

    00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
    00031 #include <ioavr.h>
    00032 #include <inavr.h>
    00033
    00034 #include "structs.h"
    00035 #include "enums.h"
    00036
    00037 #include "ADC.h"
    00038 #include "battery.h"
    00039 #include "main.h"
    00040 #include "OWI.h"
    00041 #include "time.h"
    00042
    00043 #ifdef NIMH
    00044 #include "NIMHspecs.h"
    00045 #endif // NIMH
    00046
    00047 #ifdef LIION
    00048 #include "LIIONspecs.h"
    00049 #endif // LIION
    00050
    00051
    00052
    00053 //******************************************************************************
    00054 // Variables
    00055 //******************************************************************************
    00056 /* Control-struct for batteries */
    00060 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},
    00061                                      {TRUE, TRUE, FALSE}};
    00062
    00063 /* Data-struct for battery */
    00064 Batteries_t BattData;
    00065
    00066
    00067 /* Storage for battery EPROM */
    00071 __eeprom unsigned char BattEEPROM[4][32];
    00072
    00073
    00075 unsigned char BattActive;
    00076
    00077
    00084 const __eeprom RID_Lookup_t RID[RID_TABLE_SIZE] = {
    00085   {558, 659, 3900, 550, 260, 300, 10},
    00086   {744, 843, 6800, 750, 360, 300, 14},
    00087   {869, 958, 10000, 1000, 475, 300, 19},
    00088   {1097, 1153, 24000, 2000, 475, 420, 38}
    00089 };
    00090
    00091
    00103 // FOR VARTA POLYFLEX NTC
    00104 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {
    00105         {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},
    00106         {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},
    00107         {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},
    00108         {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}
    00109 };
    00110
    00111
    00112 // FOR MITSUBISHI NTC
    00113 /*
    00114 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {
    00115   {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},
    00116   {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},
    00117   {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},
    00118   {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}
    00119 };
    00120 */
    00121
    00122
    00123 //******************************************************************************
    00124 // Functions
    00125 //******************************************************************************
    00134 unsigned char BatteryCheck(void)
    00135 {
    00136         unsigned char success = TRUE;
    00137         unsigned int  oldCapacity;
    00138
    00139         // Save to see if battery data has changed.
    00140         oldCapacity = BattData.Capacity;
    00141
    00142         if (!BatteryStatusRefresh()) {
    00143                 success = FALSE;              // Battery not present or RID was invalid.
    00144         }
    00145
    00146         if (oldCapacity != BattData.Capacity) {
    00147                 success = FALSE;              // Battery configuration has changed.
    00148         }
    00149
    00150         return(success);
    00151 }
    00152
    00153
    00167 unsigned char BatteryStatusRefresh(void)
    00168 {
    00169         // Assume the worst..
    00170         unsigned char success = FALSE;
    00171
    00172         BattData.Present = FALSE;
    00173         BattData.Charged = FALSE;
    00174         BattData.Low = TRUE;
    00175         BattData.Circuit = OW_NONE;
    00176         BattData.Temperature = 0;
    00177         BattData.Capacity = 0;
    00178         BattData.MaxCurrent = 0;
    00179         BattData.MaxTime = 0;
    00180         BattData.MinCurrent = 0;
    00181
    00182         NTCLookUp();
    00183         BattData.HasRID = RIDLookUp();
    00184
    00185         // Is the battery voltage above minimum safe cell voltage?
    00186         if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {
    00187                 BattData.Low = FALSE;
    00188         }
    00189
    00190         // Is the battery charged?
    00191         if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {
    00192                 BattData.Charged = TRUE;
    00193         }
    00194
    00195         // If we are not charging, yet VBAT is above safe limit, battery is present.
    00196         // If we are charging and there's a current flowing, the battery is present.
    00197
    00203         if (((OCR1B == 0) && (!BattData.Low)) ||
    00204             ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {
    00205                 BattData.Present = TRUE;
    00206                 success = TRUE;
    00207         } else {
    00208                 BattData.Low = FALSE;  // (This is just a technicality..)
    00209                 success = FALSE;
    00210         }
    00211
    00212 #ifndef ALLOW_NO_RID
    00213         // Return FALSE if no valid RID entry was found, to stop charging.
    00214         if(!BattData.HasRID) {
    00215                 success = FALSE;
    00216         }
    00217 #endif
    00218
    00219         return(success);
    00220 }
    00221
    00222
    00234 unsigned char BatteryDataRefresh(void)
    00235 {
    00236         unsigned char offset;
    00237         unsigned char i, crc, family, temp, page;
    00238         unsigned char success;
    00239
    00240         // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.
    00241         for (page = 0; page < 4; page++)        {
    00242                 success = FALSE;
    00243
    00244                 if (OWI_DetectPresence(OWIBUS) == OWIBUS) {
    00245
    00246                         // Presence detected, check type and CRC.
    00247                         OWI_SendByte(OWI_ROM_READ, OWIBUS);
    00248                         family = OWI_ReceiveByte(OWIBUS);
    00249                         crc = OWI_ComputeCRC8(family,0);
    00250
    00251                         for (i = 0; i < 6; i++) {
    00252                                 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);
    00253                         }
    00254
    00255                         // CRC ok, device found.
    00256                         if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
    00257                                 BattData.Circuit = family;
    00258
    00259                                 // For now, we only read data from DS2505 EPROMs.
    00260                                 if (BattData.Circuit == OW_DS2505) {
    00261                                         offset = page*32;
    00262                                         OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.
    00263                                         OWI_SendByte(offset, OWIBUS);            // Data: low address.
    00264                                         OWI_SendByte(0, OWIBUS);                 // Data: high address.
    00265
    00266                                         // Calculate checksums.
    00267                                         crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);
    00268                                         crc = OWI_ComputeCRC8(offset,crc);
    00269                                         crc = OWI_ComputeCRC8(0,crc);
    00270
    00271                                         // Command received succesfully, now start reading data
    00272                                         // and writing it to EEPROM.
    00273                                         if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
    00274                                                 crc = 0;
    00275
    00276                                                 // Fill page with data.
    00277                                                 for (i=0; i<32; i++) {
    00278                                                         temp = OWI_ReceiveByte(OWIBUS);
    00279                                                         crc = OWI_ComputeCRC8(temp, crc);
    00280                                                         BattEEPROM[page][i] = temp;
    00281                                                 }
    00282
    00283                                                 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
    00284                                                                 success = TRUE;  // Data read OK
    00285                                                 }
    00286                                         } else { // Not able to start reading data.
    00287                                         }
    00288                                 } else { // Wrong device type.
    00289                                 }
    00290                         } else { // No device found.
    00291                         }
    00292                 } else { // No presence detected on one-wire bus.
    00293                 }
    00294
    00295           // Erase local EEPROM page if there were any errors during transfer.
    00296                 if (!success) {
    00297                         for (i=0; i<32; i++) {
    00298                                 BattEEPROM[page][i] = 0;
    00299                         }
    00300                 }
    00301         }
    00302
    00303         return(success);
    00304 }
    00305
    00306
    00315 void EnableBattery(unsigned char bat)
    00316 {
    00317         // Use general timer, set timeout to 100ms.
    00318         Time_Set(TIMER_GEN,0,0,100);
    00319
    00320         // Set specified battery as the active one.
    00321         BattActive = bat;
    00322
    00323         // Enable current battery in hardware, light LED & connect battery.
    00324         PORTB |= (1 << (PB4+bat));
    00325
    00326         // Disconnect other battery.
    00327         PORTB &= ~(1<<(PB5-bat));
    00328
    00329         do { // Let port switch settle.
    00330         } while (Time_Left(TIMER_GEN));
    00331 }
    00332
    00333
    00338 void DisableBatteries(void)
    00339 {
    00340         // Turn off LEDs and disconnect batteries.
    00341         PORTB &= ~((1<<PB4)|(1<<PB5));
    00342 }
    00343
    00344
    00354 unsigned char RIDLookUp (void)
    00355 {
    00356         unsigned char i, found = FALSE;
    00357
    00358         // Lookup in the RID-table. If measured RID is within the limits
    00359         // of an entry, those data are used, and TRUE is returned.
    00360         for (i = 0 ; i < RID_TABLE_SIZE; i++) {
    00361                 if (ADCS.rawRID >= RID[i].Low) {
    00362                         if (ADCS.rawRID <= RID[i].High) {
    00363                                 BattData.Capacity = RID[i].Capacity;
    00364                                 BattData.MaxCurrent = RID[i].Icharge;
    00365                                 BattData.MaxTime = RID[i].tCutOff;
    00366                                 BattData.MinCurrent = RID[i].ICutOff;
    00367
    00368                                 found = TRUE;
    00369                         }
    00370                 }
    00371         }
    00372
    00373         // If no valid entry is found, use defaults and return FALSE.
    00374         if (!found) {
    00375                 BattData.Capacity = DEF_BAT_CAPACITY;
    00376                 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;
    00377                 BattData.MaxTime = DEF_BAT_TIME_MAX;
    00378                 BattData.MinCurrent = DEF_BAT_CURRENT_MIN;
    00379         }
    00380
    00381         return(found);
    00382 }
    00383
    00384
    00398 void NTCLookUp (void)
    00399 {
    00400         unsigned char i;
    00401         unsigned char found = FALSE;
    00402
    00403         // Lookup in the NTC-table. Use the first entry which is equal or below
    00404         // sampled NTC. Calculate temperature by using the index number, and the
    00405         // difference between the measured NTC value and the one in the entry.
    00406         for (i = 0 ; (i < NTC_TABLE_SIZE) && (!found); i++)     {
    00407                 if (ADCS.rawNTC >= NTC[i].ADC) {
    00408                         BattData.Temperature = (i<<2) ;
    00409                         BattData.ADCSteps = NTC[i].ADCsteps;
    00410
    00411          // BattData.Temperature is a signed int, while all the operands in this
    00412          // calculation are unsigned. Casting for compiler safety..
    00413                         BattData.Temperature -= ( ( (signed int)ADCS.rawNTC
    00414                                      - (signed int)NTC[i].ADC ) << 1
    00415                                  ) / (signed int)BattData.ADCSteps;
    00416
    00417                         found = TRUE;  // Could be done with a break, but that violates MISRA.
    00418                 }
    00419         }
    00420
    00421         // For safety, if the battery temperature is greater than the NTC
    00422    // lookup-table has entries for, set it to a defined maximum.
    00423         if (!found) {
    00424                 BattData.Temperature = NTC_MAX_TEMPERATURE;
    00425         }
    00426 }