cc_cv_charging.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * MIN_VOLTAGE_MV, MAXIMUM_VOLTAGE will be replaced by the value a slot gets from Pi
  3. * Article referred:
  4. * https://www.monolithicpower.com/learning/resources/battery-charger-fundamentals
  5. * https://www.instructables.com/Programming-a-Lithium-ion-Battery-Charger-Using-a-/
  6. */
  7. #include "cc_cv_charging.h"
  8. #include "battery.h"
  9. #include "dac.h"
  10. #include "adc.h"
  11. #include "ti/devices/msp/m0p/mspm0g350x.h"
  12. #include "ti/driverlib/dl_gpio.h"
  13. #include <stdio.h>
  14. //#define BATTERY_CAPACITY_MAH (2000)
  15. #define MAX_VOLTAGE_MV (4200)
  16. #define MIN_VOLTAGE_MV (3000)
  17. #define CC_CURRENT_LIMIT_MA (500)
  18. #define CUTOFF_CURRENT_MA (50)
  19. #define MAX_CYCLES (2)
  20. #define CONSTANT_VALUE (1)
  21. #define SHUNT_RESISTOR (0.1)
  22. //********** Not used **************************
  23. // if the battery is deeply discharged then 50mA of trickle charge is given for a set timer
  24. //#define TRICKLE_CHARGE_CURRENT_MA (50)
  25. //#define TRICKLE_CHARGE_VOLTAGE_MV (2100)
  26. //#define TRICKLE_CHARGE_TIMEOUT_MS (5000) //5 mseconds
  27. //Pre Charge
  28. //#define PRE_CHARGE_CURRENT_MA (BATTERY_CAPACITY_MAH/ 10)
  29. static ChargingState charging_state= STATE_PRE_CHARGE;
  30. static uint16_t cycle_count= 0;
  31. static uint32_t pre_charge_start_time= 0;
  32. //Functions for Charging and Discharging
  33. void CC_CV_UpdateChargingState(uint8_t slot_id){
  34. uint16_t batt_voltage= batteries[slot_id].voltage;
  35. int16_t batt_current= batteries[slot_id].current;
  36. if(batt_voltage < MIN_VOLTAGE_MV){
  37. charging_state= STATE_PRE_CHARGE;
  38. }
  39. else if(batt_voltage >= MIN_VOLTAGE_MV && batt_voltage < MAX_VOLTAGE_MV - BATTERY_THRESHOLD){
  40. charging_state= STATE_CC_CHARGING;
  41. }
  42. else if(batt_voltage >= MAX_VOLTAGE_MV - BATTERY_THRESHOLD){
  43. charging_state= STATE_CV_CHARGING;
  44. }
  45. else if(charging_state == STATE_CV_CHARGING && batt_current <= CUTOFF_CURRENT_MA + BATTERY_THRESHOLD){
  46. if(cycle_count < MAX_CYCLES){
  47. charging_state= STATE_DISCHARGING;
  48. }
  49. else{
  50. charging_state = STATE_FINAL_DISCHARGE;
  51. }
  52. }
  53. else if(charging_state == STATE_DISCHARGING && batt_voltage <= MIN_VOLTAGE_MV + BATTERY_THRESHOLD) {
  54. charging_state= STATE_CC_CHARGING;
  55. }
  56. else{
  57. charging_state= STATE_ERROR;
  58. }
  59. }
  60. /*
  61. Function for Battery Charging and Discharging:
  62. Trickle Charge: Only used when the battery voltage < ~2.1 V.
  63. - In this state, the batteries internal protection may have been previously disconnected.
  64. Pre Charge: Once the battery is in discharged state, pre-charging begins.
  65. - Starts charging safely with a typically low current C/10
  66. Constant Current: Continues until the battery voltage has reached the "full" or floating voltage level
  67. Constant Voltage: CV volatge starts once the maximum voltage threshold is obtained
  68. */
  69. void CC_CV_ControlCharging(uint8_t slot_id){
  70. //Calling function to get all the conditional states
  71. CC_CV_UpdateChargingState(slot_id);
  72. uint16_t batt_voltage= batteries[slot_id].voltage;
  73. int16_t batt_current= batteries[slot_id].current;
  74. uint16_t batt_cutoff_current= batteries[slot_id].cut_off_current;
  75. uint16_t charge_current_mA= (batteries[slot_id].capacitance * batteries[slot_id].charge_fraction)/100;
  76. int16_t dac_channel_VoutA;
  77. switch(charging_state){
  78. case STATE_PRE_CHARGE:
  79. DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
  80. uint16_t pre_charge_current_limit_ma = charge_current_mA/10;
  81. DAC_fastWrite(pre_charge_current_limit_ma);
  82. printf("[CC-CV] Pre Charging: Slot %d at %d mA.\n", slot_id, pre_charge_current_limit_ma);
  83. break;
  84. case STATE_CC_CHARGING:
  85. DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
  86. DAC_fastWrite(charge_current_mA);
  87. printf("[CC-CV] CC Charging: Slot %d at %d mA.\n", slot_id, CC_CURRENT_LIMIT_MA);
  88. break;
  89. case STATE_CV_CHARGING:
  90. DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
  91. if(batt_current >= batt_cutoff_current+BATTERY_THRESHOLD){
  92. //Reducing by 5%
  93. dac_channel_VoutA= (batt_current - (batt_current-0.05));
  94. }
  95. else{
  96. dac_channel_VoutA= 0;
  97. charging_state= STATE_FINAL_DISCHARGE;
  98. }
  99. DAC_fastWrite(dac_channel_VoutA);
  100. printf("[CC-CV] CV Charging: Slot %d at %d mA.\n", slot_id, CUTOFF_CURRENT_MA);
  101. break;
  102. case STATE_DISCHARGING:
  103. DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
  104. DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
  105. //still unsure about the value for channel VoutA:
  106. DAC_fastWrite(batt_voltage);
  107. printf("[CC-CV] Discharging: Slot %d at %d mA.\n", slot_id, batt_voltage);
  108. break;
  109. case STATE_FINAL_DISCHARGE:
  110. DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
  111. DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
  112. printf("[CC-CV] Final Discharge: Slot %d..\n", slot_id);
  113. DAC_fastWrite(0);
  114. case STATE_ERROR:
  115. DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
  116. DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
  117. printf("[CC-CV] Error: Slot %d.\n", slot_id);
  118. default:
  119. break;
  120. }
  121. }