cc_cv_charging.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "cc_cv_charging.h"
  2. #include "src/config.h"
  3. #include "src/battery_data/battery.h"
  4. #include <stdio.h>
  5. #include "ti/driverlib/dl_gpio.h"
  6. #include "ti_msp_dl_config.h"
  7. #include "src/controller/controller.h"
  8. static ChargingState charging_state= STATE_IDLE;
  9. static uint16_t cycle_count = 0;
  10. // declaring static global variables to retain their values between multiple function calls till the end of the program
  11. static uint16_t batt_voltage;
  12. static int16_t batt_current;
  13. static uint16_t batt_min_voltage;
  14. static uint16_t batt_max_voltage;
  15. static uint16_t batt_cutoff_current;
  16. static uint16_t batt_capacitance;
  17. static int16_t batt_charge_discharge;
  18. // Functions for Charging and Discharging State
  19. void CC_CV_UpdateChargingState(uint8_t slot_id) {
  20. //static variable to keep a log on the transition during charging and dischrging phases
  21. static ChargingState previous_state= STATE_IDLE;
  22. // Flag for CV charging, the charging mode flips back to CC mode
  23. static bool cv_charging_started = false;
  24. batt_voltage = battery_data[slot_id].battery_measurement.voltage;
  25. batt_current = battery_data[slot_id].battery_measurement.current;
  26. batt_min_voltage = battery_data[slot_id].min_voltage;
  27. batt_max_voltage = battery_data[slot_id].max_voltage;
  28. batt_cutoff_current = battery_data[slot_id].cut_off_current;
  29. batt_capacitance = battery_data[slot_id].capacitance;
  30. batt_charge_discharge= battery_data[slot_id].charge_discharge;
  31. //Log for transitions
  32. if(charging_state != previous_state){
  33. printf("State transition: %d -> %d\n", previous_state, charging_state);
  34. previous_state= charging_state;
  35. }
  36. //Check if the slot is empty or if the battery limits are not set
  37. if (battery_data[slot_id].battery_state == STATE_EMPTY || (batt_min_voltage == 0 && batt_max_voltage == 0 &&
  38. batt_cutoff_current== 0 && batt_capacitance== 0)) {
  39. charging_state = STATE_IDLE;
  40. return;
  41. }
  42. //Check if the battery is overcharged
  43. if (batt_voltage > batt_max_voltage) {
  44. charging_state = STATE_ERROR;
  45. return;
  46. }
  47. //1. Pre Charge: if the battery is deeply discharged
  48. if ((batt_voltage < batt_min_voltage)) {
  49. charging_state = STATE_PRE_CHARGE;
  50. cv_charging_started = false;
  51. }
  52. // 2. Fast Charging Condition: CC Charging: cv_charging_started condition
  53. // added to avoid toggling back to CC after CV state is reached
  54. else if (!cv_charging_started &&
  55. (batt_voltage >= batt_min_voltage) &&
  56. (batt_voltage < batt_max_voltage - BATTERY_THRESHOLD)) {
  57. charging_state = STATE_CC_CHARGING;
  58. }
  59. // 3. CV Charging condition: Changing the cv_charging_state to True, once the
  60. // CV mode is reached
  61. else if (batt_voltage >= batt_max_voltage - BATTERY_THRESHOLD) {
  62. charging_state = STATE_CV_CHARGING;
  63. cv_charging_started = true;
  64. }
  65. // 4. Cut-off check inside CV
  66. else if ((charging_state == STATE_CV_CHARGING) &&
  67. (batt_current <= batt_cutoff_current + BATTERY_THRESHOLD)) {
  68. if (cycle_count < MAX_CYCLES) {
  69. charging_state = STATE_DISCHARGING;
  70. cycle_count++;
  71. } else {
  72. charging_state = STATE_FINAL_DISCHARGE;
  73. }
  74. }
  75. // 5. State Discharging condition
  76. else if (charging_state == STATE_DISCHARGING &&
  77. batt_voltage <= batt_min_voltage + BATTERY_THRESHOLD) {
  78. DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  79. charging_state = STATE_CC_CHARGING;
  80. cv_charging_started = false;
  81. }
  82. // 6. Hold previous state if none of the condition matches (Previously,
  83. // CV_STATE was jumping directly to STATE_ERROR in else statement, to handle
  84. // the condition better, else condition is being changed).
  85. else {
  86. printf("[CC-CV] Current state: Voltage= %d mV, Current= %d mA\n",
  87. batt_voltage, batt_current);
  88. }
  89. }
  90. /*
  91. Function for Battery Charging and Discharging:
  92. ** Pre Charge: Once the battery is in discharged state, pre-charging
  93. begins. Starts charging safely with a typically low current C/10
  94. ** Constant Current: Continues until the battery voltage has reached the "full"
  95. or floating voltage level
  96. ** Constant Voltage: CV voltage starts once the maximum
  97. voltage threshold is obtained.
  98. */
  99. void CC_CV_ControlCharging(uint8_t slot_id, int16_t charge_current) {
  100. // Calling function to get all the conditional states
  101. CC_CV_UpdateChargingState(slot_id);
  102. //batt_voltage = battery_data[slot_id].battery_measurement.voltage;
  103. //batt_current= battery_data[slot_id].battery_measurement.current;
  104. batt_min_voltage= battery_data[slot_id].min_voltage;
  105. batt_max_voltage= battery_data[slot_id].max_voltage;
  106. batt_cutoff_current = battery_data[slot_id].cut_off_current;
  107. batt_capacitance= battery_data[slot_id].capacitance;
  108. batt_charge_discharge= battery_data[slot_id].charge_discharge;
  109. // DAC channel value:
  110. // dac_channel_value is for CV mode where the charge current is calibrated till battery current is less than (cutoff current+threshold)
  111. // Adding a variable to check the stepness in the voltage drop in CV charging
  112. // mode:
  113. static uint16_t last_voltage = 0;
  114. //flag for DAC: so that the dac value is initialized only once and then can be decremented rather than resetting to the initial value
  115. static bool dac_initialized= false;
  116. switch (charging_state) {
  117. // PRE CHARGE STATE: Battery Voltage is lesser than 3000 mVolts
  118. case STATE_PRE_CHARGE:
  119. //DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB6_PIN);
  120. DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  121. controller_SetCurrent(TARGET_MCU_ADDRESS, slot_id, charge_current);
  122. if (true) {
  123. printf("PRE CHARGING: Slot %d at %d mA.\n", slot_id, charge_current);
  124. }
  125. break;
  126. // CC CHARGING STATE: Keeps on checking the condition until battery voltage
  127. // reaches to (MAXIMUM_VOLTAGE-BATTERY_THRESHOLD)= 4150 mVolts
  128. case STATE_CC_CHARGING:
  129. DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  130. controller_SetCurrent(TARGET_MCU_ADDRESS, slot_id, charge_current);
  131. printf("CC CHARGING: Slot %d, Current: %d mA, Voltage: %d mV.\n", slot_id, batt_current, batt_voltage);
  132. break;
  133. // CV CHARGING STATE: Keeps on checking the condition until battery current
  134. // decreases till it exceeds (CUTOFF_CURRENT_MA + BATTERY_THRESHOLD)= 290 mAs
  135. case STATE_CV_CHARGING:
  136. DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  137. if (batt_current >= batt_cutoff_current + BATTERY_THRESHOLD) {
  138. // Detect steep voltage drop:
  139. if (last_voltage != 0 && (last_voltage - batt_voltage) > 100) {
  140. printf("!!! CV CHARGING: Voltage dropped too fast: %d -> %d mV.\n", last_voltage, batt_voltage);
  141. charging_state= STATE_ERROR;
  142. break;
  143. }
  144. controller_SetCurrent(TARGET_MCU_ADDRESS, slot_id, charge_current);
  145. }else {
  146. charging_state = STATE_FINAL_DISCHARGE;
  147. dac_initialized= false;
  148. }
  149. last_voltage = batt_voltage;
  150. break;
  151. case STATE_DISCHARGING:
  152. DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB6_PIN);
  153. DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  154. controller_SetCurrent(TARGET_MCU_ADDRESS, slot_id, charge_current);
  155. printf("DISCHARGING: Slot %d at %d mA.\n", slot_id, batt_current);
  156. //Safety Check
  157. if(batt_voltage< batt_min_voltage){
  158. charging_state= STATE_ERROR;
  159. printf("ERROR: Battery voltage below minimum voltage during discharge\n");
  160. }
  161. break;
  162. case STATE_FINAL_DISCHARGE:
  163. //Once the cycle gets done, the battery state transitions to "STATE_MEASUREMENT_DONE"
  164. battery_data[slot_id].battery_state= STATE_MEASUREMENT_DONE;
  165. DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB6_PIN);
  166. DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  167. controller_SetCurrent(TARGET_MCU_ADDRESS, slot_id, 0);
  168. charging_state = STATE_IDLE;
  169. break;
  170. case STATE_ERROR:
  171. DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB6_PIN);
  172. DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  173. printf("ERROR: Slot %d.\n", slot_id);
  174. break;
  175. case STATE_IDLE:
  176. DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB6_PIN);
  177. DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB7_PIN);
  178. charging_state = STATE_PRE_CHARGE;
  179. break;
  180. default:
  181. break;
  182. }
  183. }
  184. // End of the file