Prechádzať zdrojové kódy

Pi READ, WRITE chain and state machine transition: Pre-Charge/CC/CV/Discharge/CC

namrota ghosh 8 mesiacov pred
rodič
commit
d2427b0299
3 zmenil súbory, kde vykonal 89 pridanie a 101 odobranie
  1. 82 90
      src/cc_cv_charging.c
  2. 6 10
      src/i2c_target.c
  3. 1 1
      src/i2c_target.h

+ 82 - 90
src/cc_cv_charging.c

@@ -1,3 +1,10 @@
+/*
+References:
+https://www.monolithicpower.com/learning/resources/how-to-select-lithium-ion-battery-charge-management-ic
+https://www.monolithicpower.com/learning/resources/battery-charger-fundamentals
+
+*/
+
 #include "cc_cv_charging.h"
 #include "adc.h"
 #include "battery.h"
@@ -8,95 +15,75 @@
 #include <stdio.h>
 
 // #define BATTERY_CAPACITY_MAH (2000)
-#define MAX_VOLTAGE_MV (4200)
-#define MIN_VOLTAGE_MV (3000)
-#define CC_CURRENT_LIMIT_MA (500)
+//#define MAX_VOLTAGE_MV (4200)
+//#define MIN_VOLTAGE_MV (3000)
+//#define CC_CURRENT_LIMIT_MA (500)
 // Cut off current has been set for CC-CV charging test simulation with DC Power
 // Supplies
-#define CUTOFF_CURRENT_MA (240)
+//#define CUTOFF_CURRENT_MA (240)
 #define MAX_CYCLES (2)
 #define CONSTANT_VALUE (1)
 #define SHUNT_RESISTOR (0.1)
 
 // Pre Charge
-#define PRE_CHARGE_CURRENT_MA (BATTERY_CAPACITY_MAH / 10)
-//static ChargingState charging_state = STATE_PRE_CHARGE;
+//#define PRE_CHARGE_CURRENT_MA (BATTERY_CAPACITY_MAH / 10)
+// static ChargingState charging_state = STATE_PRE_CHARGE;
 static ChargingState charging_state = STATE_IDLE;
 static uint16_t cycle_count = 0;
 
+//uint16_t charge_current_mA =(batt_capacitance* batteries[slot_id].charge_fraction) /100;
+//uint16_t charge_current_limit_ma = charge_current_mA / 10;
+
+
 // Functions for Charging and Discharging State
 
 void CC_CV_UpdateChargingState(uint8_t slot_id) {
-  uint16_t batt_voltage = batteries[slot_id].voltage;
-  int16_t batt_current = batteries[slot_id].current;
   // Flag for CV charging, the charging mode flips back to CC mode
   static bool cv_charging_started = false;
+  uint16_t batt_voltage = batteries[slot_id].voltage;
+  int16_t batt_current= batteries[slot_id].current;
+  uint16_t batt_min_voltage= batteries[slot_id].min_voltage;
+  uint16_t batt_max_voltage= batteries[slot_id].max_voltage;
+  uint16_t batt_cutoff_current = batteries[slot_id].cut_off_current;
+  uint16_t batt_capacitance= batteries[slot_id].capacitance;
 
-  // Handling condition for STATE_ERROR: When the battery voltage exceeds the
-  // MAXIMUM_VOLTAGE regardless of the current state
-  /*if (batt_voltage > MAX_VOLTAGE_MV) {
-    charging_state = STATE_ERROR;
+  if (batteries[slot_id].state == STATE_EMPTY ||
+      (batt_min_voltage == 0 && batt_max_voltage == 0 &&
+       batt_cutoff_current== 0 && batt_capacitance== 0)) {
+    charging_state = STATE_IDLE;
     return;
-  }*/
-
-  if (batt_voltage > batteries[slot_id].max_voltage) {
-    charging_state = STATE_ERROR;
   }
 
-  // if state is IDLE or ERROR then RETURN
-  if (charging_state == STATE_IDLE || charging_state == STATE_ERROR) {
+  if (batt_voltage > batt_max_voltage) {
+    charging_state = STATE_ERROR;
     return;
   }
 
-  // 1. Deeply discharged: Pre-charge state
-  /*if ((batt_voltage < MIN_VOLTAGE_MV)) {
-    charging_state = STATE_PRE_CHARGE;
-    cv_charging_started = false;
-  }*/
-  if ((batt_voltage < batteries[slot_id].min_voltage)) {
+  //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 >= MIN_VOLTAGE_MV) &&
-           (batt_voltage < MAX_VOLTAGE_MV - BATTERY_THRESHOLD)) {
-    charging_state = STATE_CC_CHARGING;
-  }*/
 
   else if (!cv_charging_started &&
-           (batt_voltage >= batteries[slot_id].min_voltage) &&
-           (batt_voltage <
-            batteries[slot_id].max_voltage - BATTERY_THRESHOLD)) {
+           (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 >= MAX_VOLTAGE_MV - BATTERY_THRESHOLD) {
-    charging_state = STATE_CV_CHARGING;
-    cv_charging_started = true;
-  }*/
 
-  else if (batt_voltage >= batteries[slot_id].max_voltage - BATTERY_THRESHOLD) {
+  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 <= CUTOFF_CURRENT_MA + BATTERY_THRESHOLD)) {
-
-    if (cycle_count < MAX_CYCLES) {
-      charging_state = STATE_DISCHARGING;
-      cycle_count++;
-    } else {
-      charging_state = STATE_FINAL_DISCHARGE;
-    }
-  }*/
 
   else if ((charging_state == STATE_CV_CHARGING) &&
-           (batt_current <=
-            batteries[slot_id].cut_off_current + BATTERY_THRESHOLD)) {
+           (batt_current <= batt_cutoff_current + BATTERY_THRESHOLD)) {
     if (cycle_count < MAX_CYCLES) {
       charging_state = STATE_DISCHARGING;
       cycle_count++;
@@ -106,14 +93,10 @@ void CC_CV_UpdateChargingState(uint8_t slot_id) {
   }
 
   // 5. State Discharging condition
-  /*else if (charging_state == STATE_DISCHARGING &&
-           batt_voltage <= MIN_VOLTAGE_MV + BATTERY_THRESHOLD) {
-    charging_state = STATE_CC_CHARGING;
-    cv_charging_started = false;
-  }*/
 
   else if (charging_state == STATE_DISCHARGING &&
-           batt_voltage <= batteries[slot_id].min_voltage + BATTERY_THRESHOLD) {
+           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;
   }
@@ -141,29 +124,40 @@ void CC_CV_ControlCharging(uint8_t slot_id) {
   // Calling function to get all the conditional states
   CC_CV_UpdateChargingState(slot_id);
   uint16_t batt_voltage = batteries[slot_id].voltage;
-  int16_t batt_current = batteries[slot_id].current;
+  int16_t batt_current= batteries[slot_id].current;
+  uint16_t batt_min_voltage= batteries[slot_id].min_voltage;
+  uint16_t batt_max_voltage= batteries[slot_id].max_voltage;
   uint16_t batt_cutoff_current = batteries[slot_id].cut_off_current;
-  uint16_t charge_current_mA =(batteries[slot_id].capacitance * batteries[slot_id].charge_fraction) / 100;
-  uint16_t charge_current_limit_ma = charge_current_mA / 10;
-
+  uint16_t batt_capacitance= batteries[slot_id].capacitance;
+  batteries[slot_id].charge_discharge_current= 1000;
+  //pre charge: charging current C/10
+  uint16_t precharge_current_mA= (batt_capacitance/10);
+  // charge currents between 0.5C and 3C
+  uint16_t fastcharge_current_mA= (batt_capacitance * 0.5);
+  
+  
   //  DAC channel value:
-  //static uint16_t dac_channel_VoutA = 1000;
+  // 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;
-
+  static uint16_t dac_channel_value;
+  //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; 
+  //dac_channel_value= fastcharge_current_mA;
   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);
-    
-    //DAC_SingleWrite(dac_channel_VoutA);
-    DAC_SingleWrite(charge_current_limit_ma);
+
+    // DAC_SingleWrite(dac_channel_VoutA);
+    DAC_SingleWrite(precharge_current_mA);
     if (true) {
-      //printf("PRE CHARGING: Slot %d at %d mA.\n", slot_id, );
-      printf("PRE CHARGING: Slot %d at %d mA.\n", slot_id, charge_current_limit_ma);
+      // printf("PRE CHARGING: Slot %d at %d mA.\n", slot_id, );
+      printf("PRE CHARGING: Slot %d at %d mA.\n", slot_id,
+             precharge_current_mA);
     }
     break;
 
@@ -172,8 +166,8 @@ void CC_CV_ControlCharging(uint8_t slot_id) {
   case STATE_CC_CHARGING:
     DL_GPIO_setPins(GPIO_Battery_Charging_PORT,
                     GPIO_Battery_Charging_PIN_PB4_PIN);
-    //DAC_SingleWrite(dac_channel_VoutA);
-    DAC_SingleWrite(charge_current_limit_ma);
+    // DAC_SingleWrite(dac_channel_VoutA);
+    DAC_SingleWrite(fastcharge_current_mA);
     printf("CC CHARGING: Slot %d, Current: %d mA, Voltage: %d mV.\n", slot_id,
            batt_current, batt_voltage);
     break;
@@ -183,33 +177,28 @@ void CC_CV_ControlCharging(uint8_t slot_id) {
   case STATE_CV_CHARGING:
     DL_GPIO_setPins(GPIO_Battery_Charging_PORT,
                     GPIO_Battery_Charging_PIN_PB4_PIN);
-    // battery cut off current usually we get from Pi
-    //if (batt_current >= CUTOFF_CURRENT_MA + BATTERY_THRESHOLD) {
-    if(batt_current >= batteries[slot_id].cut_off_current + BATTERY_THRESHOLD){
+    if(!dac_initialized){
+        dac_channel_value= fastcharge_current_mA;
+        dac_initialized= true;
+    }
+    if (batt_current >= batteries[slot_id].cut_off_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. DAC "
-               "value: %d\n",
-               last_voltage, batt_voltage, charge_current_limit_ma);
+        printf("!!! CV CHARGING: Voltage dropped too fast: %d -> %d mV.\n",
+               last_voltage, batt_voltage);
       }
-      // Clamping the DAC to avoid going too low too fast, causing the battery
-      // voltage to dip
-      //if (dac_channel_VoutA > 825) {
-      //  dac_channel_VoutA -= 25;
-      //} else {
-      //  dac_channel_VoutA = 825;
-      //}
-
+      dac_channel_value-= 50 ;
       printf("CV CHARGING: Slot: %d, DAC_Value: %d, Battery Voltage: %d, "
-             "Battery Current:%d \n",
-             slot_id, charge_current_limit_ma, batt_voltage, batt_current);
+             "Battery Current:%d\n",
+             slot_id, dac_channel_value, batt_voltage, batt_current);
     } else {
-      //dac_channel_VoutA = 0;
+      // dac_channel_VoutA = 0;
       charging_state = STATE_FINAL_DISCHARGE;
+      dac_initialized= false;
     }
     last_voltage = batt_voltage;
-    //DAC_SingleWrite(dac_channel_VoutA);
-    DAC_SingleWrite(charge_current_limit_ma);
+    // DAC_SingleWrite(dac_channel_VoutA);
+    DAC_SingleWrite(dac_channel_value);
     break;
 
   case STATE_DISCHARGING:
@@ -218,11 +207,13 @@ void CC_CV_ControlCharging(uint8_t slot_id) {
     DL_GPIO_setPins(GPIO_Battery_Discharging_PORT,
                     GPIO_Battery_Discharging_PIN_PB12_PIN);
     // TODO: DAC channel value need to recheck
-    DAC_SingleWrite(charge_current_limit_ma);
+    DAC_SingleWrite(fastcharge_current_mA);
     printf("DISCHARGING: Slot %d at %d mA.\n", slot_id, batt_voltage);
-    DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT,
-                      GPIO_Battery_Discharging_PIN_PB12_PIN);
-    if (batt_voltage < MIN_VOLTAGE_MV) {
+    // TODO: This logic handles the condition if voltage drops below the minimum voltage, still to be discussed if required
+    if (batt_voltage <= batteries[slot_id].min_voltage + BATTERY_THRESHOLD) {
+      printf("Clearing discharge relay — Voltage: %d, Min+Thresh: %d\n", batt_voltage, batteries[slot_id].min_voltage + BATTERY_THRESHOLD);
+      DL_GPIO_clearPins(GPIO_Battery_Discharging_PORT, GPIO_Battery_Discharging_PIN_PB12_PIN);
+      dac_initialized= false;
       charging_state = STATE_PRE_CHARGE;
     }
     break;
@@ -252,6 +243,7 @@ void CC_CV_ControlCharging(uint8_t slot_id) {
                       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:

+ 6 - 10
src/i2c_target.c

@@ -25,7 +25,7 @@ uint32_t piTxLen, piTxCount;
 uint32_t piRxLen, piRxCount;
 
 volatile uint8_t rx_buffer[I2C_MAX_BYTES];
-
+//volatile bool batteryLimitReceived= false;
 /*
 - command: as defined in the Wiki for Pi 0x01, 0x02, 0x03, refer to i2c_target.h
 file
@@ -49,7 +49,7 @@ void pi_i2c_mcu() {
     DL_I2C_fillTargetTXFIFO(I2C_target_INST, battery_state, 8);
     while (DL_I2C_transmitTargetDataCheck(I2C_target_INST, 0x00) != false)
       ;
-    printf("Sent Data\n");
+    //printf("Sent Data\n");
   }
   // **Condition to GET Battery Measurement: Voltage, Current, Temperature
   else if ((receivedCommand & 0xF0) == 0x20) {
@@ -57,7 +57,6 @@ void pi_i2c_mcu() {
     // printf("Received Command: 0x%02X\n", receivedCommand);
     uint8_t requestedSlot = (receivedCommand & 0x07);
     //printf("Requested slot:%d\n", requestedSlot);
-    //  piTxCount = 0;
     piTxLen = sizeof(BatteryData);
     BatteryData battery_data;
 
@@ -67,7 +66,7 @@ void pi_i2c_mcu() {
       return;
     }
     Battery *battery = &batteries[requestedSlot];
-    battery_data.slot_id = battery->slot_id; // !TODO: recheck if necessary
+    battery_data.slot_id = battery->slot_id; // !! **If slot removed from READ, the I2C communication gives READ FAILED error**
     battery_data.voltage = battery->voltage;
     battery_data.current = battery->current;
     battery_data.temperature = battery->temperature;
@@ -104,7 +103,7 @@ void pi_i2c_mcu() {
     }
 
     
-    printf("index:%d\n", rx_index);
+    //printf("index:%d\n", rx_index);
     
 
     if (rx_index == sizeof(BatteryLimitMsg)) {
@@ -117,16 +116,13 @@ void pi_i2c_mcu() {
         battery->cut_off_current = battery_limits.cut_off_current;
         battery->capacitance = battery_limits.capacitance;
         battery->charge_fraction = battery_limits.charge_fraction;
+        battery->batteryLimitReceived= true;
       }
+      
     }
 
     rx_index= 0;
     DL_I2C_flushTargetRXFIFO(I2C_target_INST);
-    printf("*** Battery Limits: Slot: %u, Max Voltage:%u, Min Voltage:%u, "
-           "Cutoff Current: %u, Capacitance:%u, Charge Fraction:%u ***\n",
-           batteries[0].slot_id, batteries[0].max_voltage,
-           batteries[0].min_voltage, batteries[0].cut_off_current,
-           batteries[0].capacitance, batteries[0].charge_fraction);
     
     
   }

+ 1 - 1
src/i2c_target.h

@@ -26,7 +26,7 @@ extern uint32_t piRxLen, piRxCount;
 
 //Structure for Battery Data Message (GET battery data)
 
-typedef struct __attribute__((packed)){
+typedef struct{
     uint8_t slot_id;
     uint16_t voltage;
     uint16_t current;