Mercurial > public > ostc4
annotate Small_CPU/Src/batteryCharger.c @ 686:b1e24513b83e Betatest
Bugfix Battery charge complete event:
In previous version it could happen that the battery charge state was set to 100% even the battery was not completly charged. Rootcause was that the external charger IC signals sometimes completion because e.g. the connection between charger unit and OSTC is disconnected within a short time slot. This may happen while the user is trying to get the OSTC in a good charging position. To avoid this the state machine now checks the voltage everytime for valid charging complete range before a charging complete is signaled.
author | Ideenmodellierer |
---|---|
date | Fri, 05 Aug 2022 14:56:17 +0200 |
parents | 079bb5b22c06 |
children | d32901746950 |
rev | line source |
---|---|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
37 /* Use This compile switch to select the new charger status control implementation */ |
644 | 38 #define ENABLE_CHARGER_STATUS_V2 |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
44 |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
45 #ifdef ENABLE_CHARGER_STATUS_V2 |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
46 static chargerState_t batteryChargerState = Charger_NotConnected; |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
140 void battery_charger_get_status_and_contral_battery_gas_gauge(uint8_t cycleTimeBase) |
38 | 141 { |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
142 #ifdef ENABLE_CHARGER_STATUS_V2 |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
143 static uint8_t notifyChargeComplete = 0; |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
144 #endif |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
145 |
38 | 146 #ifdef OSTC_ON_DISCOVERY_HARDWARE |
147 return; | |
148 #endif | |
149 | |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
150 #ifdef ENABLE_CHARGER_STATUS_V2 |
662 | 151 |
152 if(batteryChargerState == Charger_ColdStart) /* wait for the first valid voltage meassurement */ | |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
153 { |
686 | 154 if((global.lifeData.battery_voltage != BATTERY_DEFAULT_VOLTAGE) && (global.lifeData.battery_voltage < BATTERY_CHARGER_CONNECTED_VOLTAGE)) |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
161 } |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
162 } |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
163 else |
662 | 164 { /* on disconnection or while disconnected */ |
165 if(HAL_GPIO_ReadPin(CHARGE_IN_GPIO_PORT,CHARGE_IN_PIN)) | |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
271 } |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
281 |
662 | 282 default: /* wait for disconnection */ |
283 break; | |
284 } | |
643
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
285 } |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
286 } |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
336 GPIO_InitStructure.Pin = CHARGE_OUT_PIN; |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
337 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
338 GPIO_InitStructure.Pull = GPIO_NOPULL; |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
339 GPIO_InitStructure.Speed = GPIO_SPEED_LOW; |
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
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
5149cd644fbc
Reimplemented charger status generation (deactivated):
Ideenmodellierer
parents:
38
diff
changeset
|
392 #endif |
38 | 393 } |
394 | |
395 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/ |