38
+ − 1 /**
+ − 2 ******************************************************************************
+ − 3 * @file batteryCharger.c
+ − 4 * @author heinrichs weikamp gmbh
+ − 5 * @date 09-Dec-2014
+ − 6 * @version V0.0.1
+ − 7 * @since 09-Dec-2014
+ − 8 * @brief LTC4054 Battery Charger
+ − 9 *
+ − 10 @verbatim
+ − 11 ==============================================================================
+ − 12 ##### How to use #####
+ − 13 ==============================================================================
+ − 14
+ − 15 The bq5105x provides one status output, CHG. This output is an open-drain NMOS device that is rated to 20 V.
+ − 16 The open-drain FET connected to the CHG pin will be turned on whenever the output (BAT) of the charger is
+ − 17 enabled. As a note, the output of the charger supply will not be enabled if the VRECT-REG does not converge to the
+ − 18 no-load target voltage.
+ − 19
644
+ − 20 CHG F4 7 O Open-drain output � active when BAT is enabled. Float if not used.
38
+ − 21
+ − 22 @endverbatim
+ − 23 ******************************************************************************
+ − 24 * @attention
+ − 25 *
+ − 26 * <h2><center>© COPYRIGHT(c) 2015 heinrichs weikamp</center></h2>
+ − 27 *
+ − 28 ******************************************************************************
+ − 29 */
+ − 30 /* Includes ------------------------------------------------------------------*/
+ − 31 #include "batteryCharger.h"
+ − 32 #include "batteryGasGauge.h"
+ − 33 #include "stm32f4xx_hal.h"
+ − 34 #include "scheduler.h"
+ − 35
+ − 36
643
+ − 37 /* Use This compile switch to select the new charger status control implementation */
644
+ − 38 #define ENABLE_CHARGER_STATUS_V2
643
+ − 39
662
+ − 40 #define CHARGER_DEBOUNCE_SECONDS (6u) /* 6 seconds used to avoid problems with charger interrupts / disconnections */
38
+ − 41
668
+ − 42 static uint8_t battery_i_charge_status = 0;
+ − 43 static uint16_t battery_charger_counter = 0;
643
+ − 44
+ − 45 #ifdef ENABLE_CHARGER_STATUS_V2
+ − 46 static chargerState_t batteryChargerState = Charger_NotConnected;
+ − 47 #endif
38
+ − 48
+ − 49 /* can be 0, 1 or 255
+ − 50 * 0 is disconnected
+ − 51 * 1 is charging
+ − 52 * 255 is full
+ − 53 */
+ − 54 uint8_t get_charge_status(void)
+ − 55 {
+ − 56 return battery_i_charge_status;
+ − 57 }
+ − 58
662
+ − 59 void set_charge_state(uint8_t newState)
+ − 60 {
+ − 61 #ifdef ENABLE_CHARGER_STATUS_V2
+ − 62 if(newState < Charger_END)
+ − 63 {
+ − 64 batteryChargerState = newState;
+ − 65 }
+ − 66 #endif
+ − 67 }
+ − 68
+ − 69 uint8_t get_charge_state(void)
+ − 70 {
+ − 71 return batteryChargerState;
+ − 72 }
+ − 73
38
+ − 74 void init_battery_charger_status(void)
+ − 75 {
+ − 76 #ifdef OSTC_ON_DISCOVERY_HARDWARE
+ − 77 return;
+ − 78 #endif
+ − 79
+ − 80 CHARGE_IN_GPIO_ENABLE();
+ − 81 CHARGE_OUT_GPIO_ENABLE();
+ − 82
+ − 83 ReInit_battery_charger_status_pins();
+ − 84 }
+ − 85
+ − 86 void ReInit_battery_charger_status_pins(void)
+ − 87 {
+ − 88 #ifdef OSTC_ON_DISCOVERY_HARDWARE
+ − 89 return;
+ − 90 #endif
+ − 91
+ − 92 GPIO_InitTypeDef GPIO_InitStructure;
+ − 93
+ − 94 GPIO_InitStructure.Pin = CHARGE_IN_PIN;
+ − 95 GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
+ − 96 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 97 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 98 HAL_GPIO_Init(CHARGE_IN_GPIO_PORT, &GPIO_InitStructure);
+ − 99
+ − 100 GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+ − 101 GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ − 102 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 103 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 104 HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
+ − 105 }
+ − 106
+ − 107
+ − 108 void DeInit_battery_charger_status_pins(void)
+ − 109 {
+ − 110 #ifdef OSTC_ON_DISCOVERY_HARDWARE
+ − 111 return;
+ − 112 #endif
+ − 113 GPIO_InitTypeDef GPIO_InitStructure;
+ − 114
+ − 115
+ − 116 GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ − 117 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 118 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 119
+ − 120 GPIO_InitStructure.Pin = CHARGE_IN_PIN;
+ − 121 HAL_GPIO_Init(CHARGE_IN_GPIO_PORT, &GPIO_InitStructure);
+ − 122
+ − 123 GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+ − 124 HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
+ − 125 }
+ − 126
+ − 127 /* static counter is used to avoid multiple counts of charge startings
+ − 128 and after that it is used, starting at 127 to count for the charge full signal
+ − 129
+ − 130 there a short disconnections with the QI charger
+ − 131 therefore the battery_charger_counter has a countdown instead of = 0.
+ − 132
+ − 133 battery_gas_gauge_set_charge_full and scheduleUpdateDeviceDataChargerFull are
+ − 134 set after disconnection as the charging process continues as long as not disconnected
+ − 135 to prevent the short disconnections the battery_charger_counter is used too including
+ − 136 upcounting again while battery_i_charge_status == 255 and the connection is established
+ − 137
+ − 138 */
+ − 139
643
+ − 140 void battery_charger_get_status_and_contral_battery_gas_gauge(uint8_t cycleTimeBase)
38
+ − 141 {
643
+ − 142 #ifdef ENABLE_CHARGER_STATUS_V2
+ − 143 static uint8_t notifyChargeComplete = 0;
+ − 144 #endif
+ − 145
38
+ − 146 #ifdef OSTC_ON_DISCOVERY_HARDWARE
+ − 147 return;
+ − 148 #endif
+ − 149
643
+ − 150 #ifdef ENABLE_CHARGER_STATUS_V2
662
+ − 151
+ − 152 if(batteryChargerState == Charger_ColdStart) /* wait for the first valid voltage meassurement */
643
+ − 153 {
686
+ − 154 if((global.lifeData.battery_voltage != BATTERY_DEFAULT_VOLTAGE) && (global.lifeData.battery_voltage < BATTERY_CHARGER_CONNECTED_VOLTAGE))
643
+ − 155 {
662
+ − 156 if(global.lifeData.battery_voltage > BATTERY_ENDOF_CHARGE_VOLTAGE) /* Voltage close to full state => maybe new battery inserted */
+ − 157 {
+ − 158 battery_gas_gauge_set_charge_full();
+ − 159 }
+ − 160 batteryChargerState = Charger_NotConnected;
643
+ − 161 }
+ − 162 }
+ − 163 else
662
+ − 164 { /* on disconnection or while disconnected */
+ − 165 if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN))
643
+ − 166 {
662
+ − 167 switch(batteryChargerState)
+ − 168 {
686
+ − 169 case Charger_WarmUp:
662
+ − 170 case Charger_Active: global.dataSendToMaster.chargeStatus = CHARGER_lostConnection;
+ − 171 global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection;
+ − 172 batteryChargerState = Charger_LostConnection;
686
+ − 173 if(cycleTimeBase > CHARGER_DEBOUNCE_SECONDS) /* adapt connection lost detection to sleep mode */
+ − 174 {
+ − 175 battery_charger_counter = cycleTimeBase + 1;
+ − 176 }
+ − 177 else
+ − 178 {
+ − 179 battery_charger_counter = CHARGER_DEBOUNCE_SECONDS;
+ − 180 }
662
+ − 181 break;
686
+ − 182 case Charger_Finished: battery_charger_counter = 0;
+ − 183 batteryChargerState = Charger_LostConnection;
+ − 184 /* no break */
668
+ − 185 case Charger_LostConnection: /* the charger stops charging when charge current is 1/10 */
+ − 186 /* Basically it is OK to rate a charging as complete if a defined voltage is reached */
686
+ − 187 if(((battery_gas_gauge_isChargeValueValid() == 0) || (global.lifeData.battery_charge < 90)) && (get_voltage() >= BATTERY_ENDOF_CHARGE_VOLTAGE) && (get_voltage() < BATTERY_CHARGER_CONNECTED_VOLTAGE))
662
+ − 188 {
+ − 189 notifyChargeComplete = 1;
+ − 190 }
686
+ − 191 else
+ − 192 {
+ − 193 notifyChargeComplete = 0;
+ − 194 }
+ − 195 if(battery_charger_counter >= cycleTimeBase)
662
+ − 196 {
+ − 197 battery_charger_counter -= cycleTimeBase;
+ − 198 }
+ − 199 else
+ − 200 {
+ − 201 battery_charger_counter = 0;
+ − 202 battery_i_charge_status = 0;
+ − 203 global.dataSendToMaster.chargeStatus = CHARGER_off;
+ − 204 global.deviceDataSendToMaster.chargeStatus = CHARGER_off;
643
+ − 205
662
+ − 206 if(notifyChargeComplete)
+ − 207 {
+ − 208 battery_gas_gauge_set_charge_full();
+ − 209 scheduleUpdateDeviceDataChargerFull();
+ − 210 notifyChargeComplete = 0;
+ − 211 }
+ − 212 batteryChargerState = Charger_NotConnected;
+ − 213 }
+ − 214 break;
+ − 215 default: break;
+ − 216 }
+ − 217 }
+ − 218 else
+ − 219 {
+ − 220 /* connected */
+ − 221 /* wait for disconnection to write and reset */
+ − 222 switch(batteryChargerState)
+ − 223 {
+ − 224 case Charger_NotConnected: battery_i_charge_status = 1;
+ − 225 battery_charger_counter = 0;
+ − 226 batteryChargerState = Charger_WarmUp;
+ − 227 break;
+ − 228 case Charger_LostConnection: batteryChargerState = Charger_Active;
+ − 229 break;
+ − 230 case Charger_WarmUp: battery_charger_counter += cycleTimeBase;
+ − 231 if(battery_charger_counter >= CHARGER_DEBOUNCE_SECONDS )
+ − 232 {
+ − 233 battery_i_charge_status = 2;
+ − 234 scheduleUpdateDeviceDataChargerCharging();
+ − 235 batteryChargerState = Charger_Active;
+ − 236 }
+ − 237 /* no break */
+ − 238 case Charger_Finished:
+ − 239 case Charger_Active: global.dataSendToMaster.chargeStatus = CHARGER_running;
+ − 240 global.deviceDataSendToMaster.chargeStatus = CHARGER_running;
643
+ − 241
662
+ − 242 /* drive the output pin high to determine the state of the charger */
+ − 243 GPIO_InitTypeDef GPIO_InitStructure;
+ − 244 GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+ − 245 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ − 246 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 247 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 248 HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
+ − 249 HAL_GPIO_WritePin(CHARGE_OUT_GPIO_PORT, CHARGE_OUT_PIN,GPIO_PIN_SET);
+ − 250 HAL_Delay(1);
+ − 251
+ − 252 if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN)) /* high => charger stopped charging */
+ − 253 {
+ − 254 batteryChargerState = Charger_Finished;
+ − 255 global.dataSendToMaster.chargeStatus = CHARGER_complete;
+ − 256 global.deviceDataSendToMaster.chargeStatus = CHARGER_complete;
+ − 257 battery_charger_counter = 30;
+ − 258 notifyChargeComplete = 1;
+ − 259 }
+ − 260 else
643
+ − 261 {
668
+ − 262 if(global.lifeData.battery_charge > 100.0) /* still charging but indicator is set to full => decrease to 99% to keep count increasing */
+ − 263 {
+ − 264 battery_gas_gauge_set(99.0);
+ − 265 }
662
+ − 266 if(batteryChargerState == Charger_Finished) /* voltage dropped below the hysteresis again => charging restarted */
+ − 267 {
+ − 268 batteryChargerState = Charger_Active;
+ − 269 notifyChargeComplete = 0;
+ − 270 }
643
+ − 271 }
+ − 272
662
+ − 273 /* restore high impedance to be able to detect disconnection */
+ − 274 GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+ − 275 GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ − 276 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 277 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 278 HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
+ − 279 HAL_Delay(1);
+ − 280 break;
643
+ − 281
662
+ − 282 default: /* wait for disconnection */
+ − 283 break;
+ − 284 }
643
+ − 285 }
+ − 286 }
+ − 287 #else
38
+ − 288 /* on disconnection or while disconnected */
+ − 289 if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN))
+ − 290 {
+ − 291 if(battery_charger_counter)
+ − 292 {
+ − 293 battery_charger_counter--;
+ − 294 global.dataSendToMaster.chargeStatus = CHARGER_lostConnection;
+ − 295 global.deviceDataSendToMaster.chargeStatus = CHARGER_lostConnection;
+ − 296 }
+ − 297 /* max count down to 127+5 or 127+20 */
+ − 298 if((battery_i_charge_status == 255) && battery_charger_counter < 127)
+ − 299 {
+ − 300 // battery_gas_gauge_set_charge_full();
+ − 301 // scheduleUpdateDeviceDataChargerFull();
+ − 302 battery_charger_counter = 0;
+ − 303 }
+ − 304
+ − 305 if(battery_charger_counter == 0)
+ − 306 {
+ − 307 battery_i_charge_status = 0;
+ − 308 global.dataSendToMaster.chargeStatus = CHARGER_off;
+ − 309 global.deviceDataSendToMaster.chargeStatus = CHARGER_off;
+ − 310
+ − 311 }
+ − 312 return;
+ − 313 }
+ − 314
+ − 315 /* connected */
+ − 316
+ − 317 /* wait for disconnection to write and reset */
+ − 318 if(battery_i_charge_status == 255)
+ − 319 {
+ − 320 global.dataSendToMaster.chargeStatus = CHARGER_complete;
+ − 321 global.deviceDataSendToMaster.chargeStatus = CHARGER_complete;
+ − 322
643
+ − 323 if(((cycleTimeBase > 1) && (battery_charger_counter < 127+5)) || (battery_charger_counter < 127+20))
38
+ − 324 battery_charger_counter++;
+ − 325 return;
+ − 326 }
+ − 327
+ − 328 if(battery_charger_counter == 0)
+ − 329 battery_i_charge_status = 1;
+ − 330
+ − 331 /* charger is connected and didn't signal full yet */
+ − 332 global.dataSendToMaster.chargeStatus = CHARGER_running;
+ − 333 global.deviceDataSendToMaster.chargeStatus = CHARGER_running;
+ − 334
+ − 335 GPIO_InitTypeDef GPIO_InitStructure;
643
+ − 336 GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+ − 337 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
+ − 338 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 339 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 340 HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
38
+ − 341 HAL_GPIO_WritePin(CHARGE_OUT_GPIO_PORT, CHARGE_OUT_PIN,GPIO_PIN_SET);
+ − 342 HAL_Delay(1);
+ − 343
+ − 344
+ − 345 if(battery_charger_counter < 120)
+ − 346 {
643
+ − 347 if(cycleTimeBase == 1)
38
+ − 348 battery_charger_counter++;
+ − 349 else
+ − 350 {
+ − 351 battery_charger_counter += 30;
+ − 352 if(battery_charger_counter >= 127)
+ − 353 battery_charger_counter = 126;
+ − 354 }
+ − 355 }
+ − 356 else
+ − 357 if(battery_charger_counter < 127)
+ − 358 {
+ − 359 battery_charger_counter = 127;
+ − 360 if(battery_i_charge_status < 2)
+ − 361 {
+ − 362 battery_i_charge_status = 2;
+ − 363 scheduleUpdateDeviceDataChargerCharging();
+ − 364 }
+ − 365 }
+ − 366
+ − 367 if(battery_charger_counter >= 127)
+ − 368 {
+ − 369 if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN) || (get_voltage() >= 4.1f))
+ − 370 {
+ − 371 battery_charger_counter++;
643
+ − 372 if(((cycleTimeBase > 1) && (battery_charger_counter > 127+5)) || (battery_charger_counter > 127+20))
38
+ − 373 {
+ − 374 battery_charger_counter = 127;
+ − 375 if(get_voltage() >= 4.1f)
+ − 376 {
+ − 377 battery_i_charge_status = 255;
+ − 378 battery_gas_gauge_set_charge_full();
+ − 379 scheduleUpdateDeviceDataChargerFull();
+ − 380 }
+ − 381 }
+ − 382 }
+ − 383 else
+ − 384 battery_charger_counter = 127;
+ − 385 }
+ − 386
+ − 387 GPIO_InitStructure.Pin = CHARGE_OUT_PIN;
+ − 388 GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
+ − 389 GPIO_InitStructure.Pull = GPIO_NOPULL;
+ − 390 GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ − 391 HAL_GPIO_Init(CHARGE_OUT_GPIO_PORT, &GPIO_InitStructure);
643
+ − 392 #endif
38
+ − 393 }
+ − 394
+ − 395 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/