|
|
@@ -0,0 +1,192 @@
|
|
|
+#include "cc_cv_charging.h"
|
|
|
+#include "src/config.h"
|
|
|
+#include "src/battery_data/battery.h"
|
|
|
+#include <stdio.h>
|
|
|
+#include "ti/driverlib/dl_gpio.h"
|
|
|
+
|
|
|
+static ChargingState charging_state= STATE_IDLE;
|
|
|
+static uint16_t cycle_count = 0;
|
|
|
+// declaring static global variables
|
|
|
+static uint16_t batt_voltage;
|
|
|
+static int16_t batt_current;
|
|
|
+static uint16_t batt_min_voltage;
|
|
|
+static uint16_t batt_max_voltage;
|
|
|
+static uint16_t batt_cutoff_current;
|
|
|
+static uint16_t batt_capacitance;
|
|
|
+static int16_t batt_charge_discharge;
|
|
|
+// Functions for Charging and Discharging State
|
|
|
+
|
|
|
+void CC_CV_UpdateChargingState(uint8_t slot_id) {
|
|
|
+ // Flag for CV charging, the charging mode flips back to CC mode
|
|
|
+ static bool cv_charging_started = false;
|
|
|
+ batt_voltage = battery_data[slot_id].battery_measurement.voltage;
|
|
|
+ batt_current = battery_data[slot_id].battery_measurement.current;
|
|
|
+ batt_min_voltage = battery_data[slot_id].battery_limits.min_voltage;
|
|
|
+ batt_max_voltage = battery_data[slot_id].battery_limits.max_voltage;
|
|
|
+ batt_cutoff_current = battery_data[slot_id].battery_limits.cut_off_current;
|
|
|
+ batt_capacitance = battery_data[slot_id].battery_limits.capacitance;
|
|
|
+ batt_charge_discharge= battery_data[slot_id].charge_discharge;
|
|
|
+ //Check if the slot is empty or if the battery limits are not set
|
|
|
+ if (battery_data[slot_id].battery_state == STATE_EMPTY || (batt_min_voltage == 0 && batt_max_voltage == 0 &&
|
|
|
+ batt_cutoff_current== 0 && batt_capacitance== 0)) {
|
|
|
+ charging_state = STATE_IDLE;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //Check if the battery is overcharged
|
|
|
+ if (batt_voltage > batt_max_voltage) {
|
|
|
+ charging_state = STATE_ERROR;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //1. Pre Charge: if the battery is deeply discharged
|
|
|
+ if ((batt_voltage < batt_min_voltage)) {
|
|
|
+ charging_state = STATE_PRE_CHARGE;
|
|
|
+ cv_charging_started = false;
|
|
|
+ }
|
|
|
+ // 2. Fast Charging Condition: CC Charging: cv_charging_started condition
|
|
|
+ // added to avoid toggling back to CC after CV state is reached
|
|
|
+
|
|
|
+ else if (!cv_charging_started &&
|
|
|
+ (batt_voltage >= batt_min_voltage) &&
|
|
|
+ (batt_voltage < batt_max_voltage - BATTERY_THRESHOLD)) {
|
|
|
+ charging_state = STATE_CC_CHARGING;
|
|
|
+ }
|
|
|
+ // 3. CV Charging condition: Changing the cv_charging_state to True, once the
|
|
|
+ // CV mode is reached
|
|
|
+
|
|
|
+ else if (batt_voltage >= batt_max_voltage - BATTERY_THRESHOLD) {
|
|
|
+ charging_state = STATE_CV_CHARGING;
|
|
|
+ cv_charging_started = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. Cut-off check inside CV
|
|
|
+
|
|
|
+ else if ((charging_state == STATE_CV_CHARGING) &&
|
|
|
+ (batt_current <= batt_cutoff_current + BATTERY_THRESHOLD)) {
|
|
|
+ if (cycle_count < MAX_CYCLES) {
|
|
|
+ charging_state = STATE_DISCHARGING;
|
|
|
+ cycle_count++;
|
|
|
+ } else {
|
|
|
+ charging_state = STATE_FINAL_DISCHARGE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. State Discharging condition
|
|
|
+
|
|
|
+ else if (charging_state == STATE_DISCHARGING &&
|
|
|
+ batt_voltage <= batt_min_voltage + BATTERY_THRESHOLD) {
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
|
|
|
+ charging_state = STATE_CC_CHARGING;
|
|
|
+ cv_charging_started = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. Hold previous state if none of the condition matches (Previously,
|
|
|
+ // CV_STATE was jumping directly to STATE_ERROR in else statement, to handle
|
|
|
+ // the condition better, else condition is being changed).
|
|
|
+ else {
|
|
|
+ printf("[CC-CV] Current state: Voltage= %d mV, Current= %d mA\n",
|
|
|
+ batt_voltage, batt_current);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+Function for Battery Charging and Discharging:
|
|
|
+** Pre Charge: Once the battery is in discharged state, pre-charging
|
|
|
+begins. Starts charging safely with a typically low current C/10
|
|
|
+** Constant Current: Continues until the battery voltage has reached the "full"
|
|
|
+or floating voltage level
|
|
|
+** Constant Voltage: CV voltage starts once the maximum
|
|
|
+voltage threshold is obtained.
|
|
|
+*/
|
|
|
+
|
|
|
+void CC_CV_ControlCharging(uint8_t slot_id, int16_t charge_current) {
|
|
|
+ // Calling function to get all the conditional states
|
|
|
+ CC_CV_UpdateChargingState(slot_id);
|
|
|
+
|
|
|
+ batt_voltage = battery_data[slot_id].battery_measurement.voltage;
|
|
|
+ batt_current= battery_data[slot_id].battery_measurement.current;
|
|
|
+ batt_min_voltage= battery_data[slot_id].battery_limits.min_voltage;
|
|
|
+ batt_max_voltage= battery_data[slot_id].battery_limits.max_voltage;
|
|
|
+ batt_cutoff_current = battery_data[slot_id].battery_limits.cut_off_current;
|
|
|
+ batt_capacitance= battery_data[slot_id].battery_limits.capacitance;
|
|
|
+ batt_charge_discharge= battery_data[slot_id].charge_discharge;
|
|
|
+
|
|
|
+
|
|
|
+ // DAC channel value:
|
|
|
+ // dac_channel_value is for CV mode where the charge current is calibrated till battery current is less than (cutoff current+threshold)
|
|
|
+ // Adding a variable to check the stepness in the voltage drop in CV charging
|
|
|
+ // mode:
|
|
|
+ static uint16_t last_voltage = 0;
|
|
|
+ //flag for DAC: so that the dac value is initialized only once and then can be decremented rather than resetting to the initial value
|
|
|
+ static bool dac_initialized= false;
|
|
|
+
|
|
|
+ switch (charging_state) {
|
|
|
+
|
|
|
+ // PRE CHARGE STATE: Battery Voltage is lesser than 3000 mVolts
|
|
|
+ case STATE_PRE_CHARGE:
|
|
|
+
|
|
|
+ DL_GPIO_setPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
|
|
|
+ controller_SetCurrent(TARGET_ADDRESS, slot_id, charge_current);
|
|
|
+ if (true) {
|
|
|
+ printf("PRE CHARGING: Slot %d at %d mA.\n", slot_id, );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ // CC CHARGING STATE: Keeps on checking the condition until battery voltage
|
|
|
+ // reaches to (MAXIMUM_VOLTAGE-BATTERY_THRESHOLD)= 4150 mVolts
|
|
|
+ case STATE_CC_CHARGING:
|
|
|
+
|
|
|
+ controller_SetCurrent(TARGET_ADDRESS, slot_id, charge_current);
|
|
|
+ printf("CC CHARGING: Slot %d, Current: %d mA, Voltage: %d mV.\n", slot_id, batt_current, batt_voltage);
|
|
|
+ break;
|
|
|
+
|
|
|
+ // CV CHARGING STATE: Keeps on checking the condition until battery current
|
|
|
+ // decreases till it exceeds (CUTOFF_CURRENT_MA + BATTERY_THRESHOLD)= 290 mAs
|
|
|
+ case STATE_CV_CHARGING:
|
|
|
+ if (batt_current >= batt_cutoff_current + BATTERY_THRESHOLD) {
|
|
|
+ // Detect steep voltage drop:
|
|
|
+ if (last_voltage != 0 && (last_voltage - batt_voltage) > 100) {
|
|
|
+ printf("!!! CV CHARGING: Voltage dropped too fast: %d -> %d mV.\n", last_voltage, batt_voltage);
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ charging_state = STATE_FINAL_DISCHARGE;
|
|
|
+ dac_initialized= false;
|
|
|
+ }
|
|
|
+ last_voltage = batt_voltage;
|
|
|
+ controller_SetCurrent(TARGET_ADDRESS, slot_id, charge_current);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STATE_DISCHARGING:
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
|
|
|
+ DL_GPIO_setPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
|
|
|
+ controller_SetCurrent(TARGET_ADDRESS, slot_id, charge_current);
|
|
|
+ printf("DISCHARGING: Slot %d at %d mA.\n", slot_id, batt_voltage);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STATE_FINAL_DISCHARGE:
|
|
|
+ //Once the cycle gets done, the battery state transitions to "STATE_MEASUREMENT_DONE"
|
|
|
+ batteries[slot_id].state= STATE_MEASUREMENT_DONE;
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
|
|
|
+ controller_SetCurrent(TARGET_ADDRESS, slot_id, 0);
|
|
|
+ charging_state = STATE_IDLE;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STATE_ERROR:
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
|
|
|
+ printf("ERROR: Slot %d.\n", slot_id);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case STATE_IDLE:
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Charging_PORT, GPIO_Battery_Charging_PIN_PB4_PIN);
|
|
|
+ DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
|
|
|
+ charging_state = STATE_PRE_CHARGE;
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+// End of the file
|