Parcourir la source

Fix: Improved ADC code for calculation

Heinrich Blatt il y a 7 mois
Parent
commit
2de36d406b

+ 20 - 4
src/battery_data/battery.c

@@ -78,11 +78,27 @@ static void batteryslots_read_state(uint8_t slot) {
      * 3. the adc updates the battery slot value directly
      */
  
-     // step 1: read channel 0 (voltage reading of the cell)
-    updateADCReading(slot, 0);
+    // step 1: read channel 0 (voltage reading of the cell)
+    uint16_t bare_voltage = read_adc_channel(slot, 0);
+    battery_slots[slot].measurement.voltage = 100/56*bare_voltage; // We have that voltage divider
 
-    // step 2: read channel 1 (current reading on charge)
-    updateADCReading(slot, 1);
+    // DAC branch: we can calculate the current based on the shunt
+    if (battery_slots[slot].set_current >= 0) {
+        // read channel 1 (current reading on charge)
+        bare_voltage = read_adc_channel(slot, 1);
+        battery_slots[slot].measurement.current = bare_voltage*10;
+
+    } else {
+        // we are in PWM mode, the shunt is on the high side
+        // read channel 2 (voltage reading on 5V side)
+        int16_t shunt_current = read_adc_channel(slot, 2)*10;
+
+        // read channel 3 (current reading after step conversion, 5V side)
+        int16_t hi_voltage = read_adc_channel(slot, 3)*100/56;
+
+        // calculate the result
+        battery_slots[slot].measurement.current = -1*shunt_current*hi_voltage/battery_slots[slot].measurement.voltage;
+    }
 }
 
 static void batteryslots_adjust_current(uint8_t slot) {

+ 2 - 0
src/battery_data/battery.h

@@ -47,6 +47,8 @@ typedef struct {
     uint16_t pwm_value;
     GPTIMER_Regs *timer;
     SlotState *state;
+    int16_t high_side_voltage;
+
 } BatterySlot;
 
 //global battery array declaration: extending visiblity of the variable to multiple source files: variable declaration

+ 30 - 12
src/peripherals/adc/adc.c

@@ -11,9 +11,10 @@
 static ADC_MeasurementState adc_state = ADC_STATE_CONFIGURE;
 
 
-void updateADCReading(uint8_t slot, uint8_t channel) {
+uint16_t read_adc_channel(uint8_t slot, uint8_t channel) {
   //printf("Slot: %d, Channel: %d\n", slot, channel);
   ADC_Params adc_params= {0}; 
+  uint16_t adc_voltage = 0;
   while (adc_state != ADC_STATE_DONE) {
     switch (adc_state) {
         
@@ -21,7 +22,17 @@ void updateADCReading(uint8_t slot, uint8_t channel) {
             adc_params.channel = channel;
             adc_params.resolution = 12;
             adc_params.continuous = ADC_MEASUREMENT_IS_CONTINUOUS;
-            adc_params.gain = 1;
+            if (channel == 0 || channel == 3) {
+                // voltage measurement
+                // -> we can measure directly
+                adc_params.gain = 1;
+                adc_params.resolution = 12;
+            } else {
+                // current measurement
+                // -> maximum gain, max resolution
+                adc_params.gain = 8;
+                adc_params.resolution = 16;
+            }
             //printf("Config: Memory address of batteries: %p\n", &batteries[0]);
             adc_hal.configure(slot, &adc_params);
             if (adc_params.continuous == 1) {
@@ -41,16 +52,14 @@ void updateADCReading(uint8_t slot, uint8_t channel) {
             break;
 
         case ADC_STATE_READ:
-            if (channel == 0) {
-
-                int16_t raw_adc_voltage = adc_hal.read_raw(slot, &adc_params);
-                battery_slots[slot].measurement.voltage =
-                    adc_hal.convert_voltage(raw_adc_voltage, &adc_params);
-                adc_state = ADC_STATE_DONE;
+            uint16_t raw_adc_voltage = adc_hal.read_raw(slot, &adc_params);
+            adc_voltage = adc_hal.get_voltage(raw_adc_voltage, &adc_params);
 #ifdef DEBUG_ADC
-                printf("[ADC] Battery Voltage in slot %d is %d mV.\n", slot, battery_slots[slot].measurement.voltage);
+            printf("[ADC] ADC reading completed. Slot %d Channel %d is %d mV.\n", slot, channel, adc_voltage);
 #endif
+            adc_state = ADC_STATE_DONE;
 
+            /*
             } else if (channel == 1) {
 
                 int16_t raw_adc_current = adc_hal.read_raw(slot, &adc_params);
@@ -63,14 +72,22 @@ void updateADCReading(uint8_t slot, uint8_t channel) {
             } else if (channel == 2) {
                 // @fixme: this is the third adc channel, needed for current meausrement on disharge mode
                 int16_t raw_adc_voltage = adc_hal.read_raw(slot, &adc_params);
-                battery_slots[slot].measurement.voltage =
+                battery_slots[slot].high_side_voltage =
                     adc_hal.convert_voltage(raw_adc_voltage, &adc_params); 
                 adc_state = ADC_STATE_DONE;
 #ifdef DEBUG_ADC
                 printf("[ADC] Ch3 Voltage in slot %d is %d mV.\n", slot, battery_slots[slot].measurement.voltage);
 #endif
-
-            }
+            } else if (channel == 3) {
+                // @fixme: this is the third adc channel, needed for current meausrement on disharge mode
+                int16_t raw_adc_voltage = adc_hal.read_raw(slot, &adc_params);
+                int16_t high_i = adc_hal.convert_voltage(raw_adc_voltage, &adc_params); 
+                battery_slots[slot].measurement.current = high_i*battery_slots[slot].high_side_voltage/battery_slots[slot].measurement.voltage;
+                adc_state = ADC_STATE_DONE;
+#ifdef DEBUG_ADC
+                printf("[ADC] Ch4 Voltage in slot %d is %d mV.\n", slot, battery_slots[slot].measurement.voltage);
+#endif
+            }*/
             break;
         default:
             channel = 0;
@@ -80,4 +97,5 @@ void updateADCReading(uint8_t slot, uint8_t channel) {
   }
 
   adc_state = ADC_STATE_CONFIGURE;
+  return adc_voltage;
 }

+ 1 - 3
src/peripherals/adc/adc.h

@@ -12,8 +12,6 @@ typedef enum{
     ADC_STATE_DONE
 }ADC_MeasurementState;
 
-
-
-void updateADCReading(uint8_t slot, uint8_t channel); //belongs to battery module
+uint16_t read_adc_channel(uint8_t slot, uint8_t channel); //belongs to battery module
 
 #endif

+ 26 - 21
src/peripherals/adc/adc_hal.c

@@ -103,6 +103,9 @@ static uint8_t construct_config_byte(ADC_Params *params) {
         case 4:
             config |= (0b10);
             break;
+        case 8:
+            config |= (0b11);
+            break;
         default:
             //printf("ERROR: Invalid Gain!\n");
             return 0;
@@ -194,17 +197,33 @@ static int16_t read_adc_raw_data(uint8_t slot_id, ADC_Params *params) {
     uint8_t lsb = controllerRxPackage.packet[1];
     uint8_t config_adc_byte = controllerRxPackage.packet[2];
 
-    if (params->resolution == 12) {
-      raw_adc = ((msb & 0b00001111) << 8) | lsb;
-      if (raw_adc > 2047)
-        raw_adc -= 4096;
+    switch (params->resolution) {
+        case 12: // 12-bit
+            raw_adc = ((msb & 0b00001111) << 8) | lsb;
+            if (raw_adc > 2047)
+                raw_adc -= 4096;
+            break;
+        case 14: // 14-bit
+            raw_adc = ((msb & 0b00111111) << 8) | lsb;
+            if (raw_adc > 16384/2)
+                raw_adc -= 16384;
+            break;
+        case 16: // 16-bit
+            raw_adc = ((msb & 0b11111111) << 8) | lsb;
+            if (raw_adc > 65536/2)
+                raw_adc -= 65536;
+            break;
+        default:
+            //printf("Error: Unknown ADC Resolution!\n");
+            break;
     }
+
 #ifdef DEBUG_ADC
     printf("MSB: 0x%02X (%d)\n", msb, msb);
     printf("LSB: 0x%02X (%d)\n", lsb, lsb);
     printf("Config Byte response: 0x%02X \n", config_adc_byte);
 #endif
-    return raw_adc;
+    return raw_adc / params->gain;
 }
 
 /* Function to Convert ADC Reading to Voltage */
@@ -227,28 +246,14 @@ static uint16_t adc_voltage(int16_t adc_value, ADC_Params *params) {
         //printf("Error: Unknown ADC Resolution!\n");
         return 0;
     }
-    measured_voltage = (((uint32_t)adc_value) * 2.7);
+    measured_voltage = (((uint32_t)adc_value)) //* 2.7);
     //printf("Measured ADC voltage: %d\n", measured_voltage);
     return (uint16_t)measured_voltage;
 }
 
-/* Function to Convert ADC Reading to Voltage */
-uint16_t adc_current(int16_t adc_value, ADC_Params *params) {
-    int16_t current_mA = 0;
-    // Convert ADC value to voltage across shunt resistor:
-    uint16_t voltage_mV = adc_voltage(adc_value, params);
-    uint8_t gain_multiplier = (1 << (params->gain - 1));
-    // Convert voltage drop across shunt resistor to current
-    current_mA = (adc_value) * (10 * gain_multiplier);
-    //printf("[ADC] Battery current is %u mA.\n", current_mA);
-    return (int16_t)current_mA;
-}
-
-
 ADC_Interface adc_hal= {
     .configure= adc_configure,
     .read_raw= read_adc_raw_data,
     .is_ready= adc_is_ready,
-    .convert_voltage= adc_voltage,
-    .convert_current= adc_current
+    .get_voltage = adc_voltage
 };

+ 2 - 4
src/peripherals/adc/adc_interface.h

@@ -16,11 +16,9 @@ typedef struct {
 // 14.04: added pointer for ADC_Params
 typedef struct {
     bool (*configure)(uint8_t slot_id, ADC_Params *params);
-    bool (*is_ready)(uint8_t slot_id, ADC_Params *params);
     int16_t (*read_raw)(uint8_t slot_id, ADC_Params *params);
-    uint16_t (*convert_voltage)(int16_t raw, ADC_Params *params);
-    uint16_t (*convert_current)(int16_t raw, ADC_Params *params);
-    
+    bool (*is_ready)(uint8_t slot_id, ADC_Params *params);
+    uint16_t (*get_voltage)(int16_t raw, ADC_Params *params);
 } ADC_Interface;
 
 extern ADC_Interface adc_hal;