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 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 
00105 // FOR VARTA POLYFLEX NTC
00106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {
00107         {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},
00108         {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},
00109         {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},
00110         {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}
00111 };
00112 
00113 
00114 // FOR MITSUBISHI NTC
00115 /*
00116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {
00117   {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},
00118   {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},
00119   {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},
00120   {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}
00121 };
00122 */
00123 
00124 
00125 //******************************************************************************
00126 // Functions
00127 //******************************************************************************
00136 unsigned char BatteryCheck(void)
00137 {
00138         unsigned char success = TRUE;
00139         unsigned int  oldCapacity;
00140         
00141         // Save to see if battery data has changed.
00142         oldCapacity = BattData.Capacity;  
00143         
00144         if (!BatteryStatusRefresh()) {
00145                 success = FALSE;              // Battery not present or RID was invalid.
00146         }
00147         
00148         if (oldCapacity != BattData.Capacity) {
00149                 success = FALSE;              // Battery configuration has changed.
00150         }
00151 
00152         return(success);
00153 }
00154 
00155 
00169 unsigned char BatteryStatusRefresh(void)
00170 {
00171         // Assume the worst..
00172         unsigned char success = FALSE;
00173         
00174         BattData.Present = FALSE;
00175         BattData.Charged = FALSE;
00176         BattData.Low = TRUE;
00177         BattData.Circuit = OW_NONE;
00178         BattData.Temperature = 0;
00179         BattData.Capacity = 0;
00180         BattData.MaxCurrent = 0;
00181         BattData.MaxTime = 0;
00182         BattData.MinCurrent = 0;
00183 
00184         NTCLookUp();
00185         BattData.HasRID = RIDLookUp();
00186 
00187         // Is the battery voltage above minimum safe cell voltage?
00188         if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {
00189                 BattData.Low = FALSE;
00190         }
00191 
00192         // Is the battery charged?
00193         if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {
00194                 BattData.Charged = TRUE;
00195         }
00196 
00197         // If we are not charging, yet VBAT is above safe limit, battery is present.
00198         // If we are charging and there's a current flowing, the battery is present.
00199         
00205         if (((OCR1B == 0) && (!BattData.Low)) ||
00206             ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {
00207                 BattData.Present = TRUE;
00208                 success = TRUE;
00209         } else {
00210                 BattData.Low = FALSE;  // (This is just a technicality..)
00211                 success = FALSE;
00212         }
00213 
00214 #ifndef ALLOW_NO_RID
00215         // Return FALSE if no valid RID entry was found, to stop charging.
00216         if(!BattData.HasRID) {
00217                 success = FALSE;
00218         }
00219 #endif
00220 
00221         return(success);
00222 }
00223 
00224 
00236 unsigned char BatteryDataRefresh(void)
00237 {
00238         unsigned char offset;
00239         unsigned char i, crc, family, temp, page;
00240         unsigned char success;
00241         
00242         // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.
00243         for (page = 0; page < 4; page++)        {
00244                 success = FALSE;
00245         
00246                 if (OWI_DetectPresence(OWIBUS) == OWIBUS) {
00247                         
00248                         // Presence detected, check type and CRC.
00249                         OWI_SendByte(OWI_ROM_READ, OWIBUS);
00250                         family = OWI_ReceiveByte(OWIBUS);
00251                         crc = OWI_ComputeCRC8(family,0);
00252 
00253                         for (i = 0; i < 6; i++) {
00254                                 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);
00255                         }
00256 
00257                         // CRC ok, device found.
00258                         if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
00259                                 BattData.Circuit = family;
00260 
00261                                 // For now, we only read data from DS2505 EPROMs.
00262                                 if (BattData.Circuit == OW_DS2505) {
00263                                         offset = page*32;
00264                                         OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.
00265                                         OWI_SendByte(offset, OWIBUS);            // Data: low address.
00266                                         OWI_SendByte(0, OWIBUS);                 // Data: high address.
00267 
00268                                         // Calculate checksums.
00269                                         crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);
00270                                         crc = OWI_ComputeCRC8(offset,crc);
00271                                         crc = OWI_ComputeCRC8(0,crc);
00272 
00273                                         // Command received succesfully, now start reading data
00274                                         // and writing it to EEPROM.
00275                                         if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
00276                                                 crc = 0;
00277                                                 
00278                                                 // Fill page with data.
00279                                                 for (i=0; i<32; i++) {
00280                                                         temp = OWI_ReceiveByte(OWIBUS);
00281                                                         crc = OWI_ComputeCRC8(temp, crc);
00282                                                         BattEEPROM[page][i] = temp;
00283                                                 }
00284                                                 
00285                                                 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
00286                                                                 success = TRUE;  // Data read OK
00287                                                 }
00288                                         } else { // Not able to start reading data.
00289                                         }
00290                                 } else { // Wrong device type.
00291                                 }
00292                         } else { // No device found.             
00293                         }
00294                 } else { // No presence detected on one-wire bus.
00295                 }
00296 
00297           // Erase local EEPROM page if there were any errors during transfer.
00298                 if (!success) {
00299                         for (i=0; i<32; i++) {
00300                                 BattEEPROM[page][i] = 0;
00301                         }
00302                 }
00303         }
00304 
00305         return(success);
00306 }
00307 
00308 
00317 void EnableBattery(unsigned char bat)
00318 {
00319         // Use general timer, set timeout to 100ms.
00320         Time_Set(TIMER_GEN,0,0,100);
00321 
00322         // Set specified battery as the active one.
00323         BattActive = bat;
00324 
00325         // Enable current battery in hardware, light LED & connect battery.
00326         PORTB |= (1 << (PB4+bat));
00327 
00328         // Disconnect other battery.
00329         PORTB &= ~(1<<(PB5-bat));     
00330 
00331         do { // Let port switch settle.
00332         } while (Time_Left(TIMER_GEN));  
00333 }
00334 
00335 
00340 void DisableBatteries(void)
00341 {
00342         // Turn off LEDs and disconnect batteries.
00343         PORTB &= ~((1<<PB4)|(1<<PB5));  
00344 }
00345 
00346 
00356 unsigned char RIDLookUp (void)
00357 {
00358         unsigned char i, found = FALSE;
00359                 
00360         // Lookup in the RID-table. If measured RID is within the limits
00361         // of an entry, those data are used, and TRUE is returned.
00362         for (i = 0 ; i < RID_TABLE_SIZE; i++) {
00363                 if (ADCS.rawRID >= RID[i].Low) {
00364                         if (ADCS.rawRID <= RID[i].High) {
00365                                 BattData.Capacity = RID[i].Capacity;
00366                                 BattData.MaxCurrent = RID[i].Icharge;
00367                                 BattData.MaxTime = RID[i].tCutOff;
00368                                 BattData.MinCurrent = RID[i].ICutOff;
00369                                 
00370                                 found = TRUE;
00371                         }
00372                 }
00373         }
00374         
00375         // If no valid entry is found, use defaults and return FALSE.
00376         if (!found) {
00377                 BattData.Capacity = DEF_BAT_CAPACITY;
00378                 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;
00379                 BattData.MaxTime = DEF_BAT_TIME_MAX;
00380                 BattData.MinCurrent = DEF_BAT_CURRENT_MIN;
00381         }
00382         
00383         return(found);
00384 }
00385 
00386 
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                         BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;
00411                         
00412                         found = TRUE;  // Could be done with a break, but that violates MISRA.
00413                 }
00414         }
00415         
00416         // For safety, is temperature is greater than the NTC 
00417         if (!found) {
00418                 BattData.Temperature = 80;
00419         }
00420 }

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