cc_cv_charging.c 10 KB

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