5 Commity 172b023c1b ... 0a6dffb608

Autor SHA1 Správa Dátum
  Heinrich Blatt 0a6dffb608 Berechnung der Auflösung funktioniert jetzt korrekt 7 mesiacov pred
  Heinrich Blatt fb29f92c12 * Battery.c: Spannungsmessung gefixt (floating point bug gelöst) 7 mesiacov pred
  Heinrich Blatt b516164b78 Merge branch '4pwm-config' into control-and-refacotring-improvements 7 mesiacov pred
  Heinrich Blatt 2de36d406b Fix: Improved ADC code for calculation 7 mesiacov pred
  Heinrich Blatt 6b5795652d Erweiterung: 4-Channel-Support 8 mesiacov pred

+ 49 - 10
main_target.syscfg

@@ -16,6 +16,9 @@ const I2C1          = I2C.addInstance();
 const I2C2          = I2C.addInstance();
 const PWM           = scripting.addModule("/ti/driverlib/PWM", {}, false);
 const PWM1          = PWM.addInstance();
+const PWM2          = PWM.addInstance();
+const PWM3          = PWM.addInstance();
+const PWM4          = PWM.addInstance();
 const SYSCTL        = scripting.addModule("/ti/driverlib/SYSCTL");
 const ProjectConfig = scripting.addModule("/ti/project_config/ProjectConfig");
 
@@ -25,7 +28,7 @@ const ProjectConfig = scripting.addModule("/ti/project_config/ProjectConfig");
 GPIO1.$name                         = "GPIOS";
 GPIO1.associatedPins[0].direction   = "INPUT";
 GPIO1.associatedPins[0].$name       = "ADDR";
-GPIO1.associatedPins[0].pin.$assign = "PA22";
+GPIO1.associatedPins[0].pin.$assign = "PA24/OPA0.IN0-";
 
 const Board                       = scripting.addModule("/ti/driverlib/Board", {}, false);
 Board.peripheral.$assign          = "DEBUGSS";
@@ -68,14 +71,51 @@ I2C2.sclPinConfig.onlyInternalResistor = scripting.forceWrite(false);
 I2C2.sclPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
 I2C2.sclPinConfig.enableConfig         = true;
 
-PWM1.$name                      = "PWM_0";
-PWM1.ccIndex                    = [0];
-PWM1.timerCount                 = 320;
-PWM1.timerStartTimer            = true;
-PWM1.peripheral.ccp0Pin.$assign = "PA26";
-PWM1.PWM_CHANNEL_0.$name        = "ti_driverlib_pwm_PWMTimerCC0";
-PWM1.PWM_CHANNEL_0.dutyCycle    = 10;
-PWM1.ccp0PinConfig.$name        = "ti_driverlib_gpio_GPIOPinGeneric4";
+PWM1.timerCount                         = 320;
+PWM1.timerStartTimer                    = true;
+PWM1.ccIndex                            = [1];
+PWM1.$name                              = "PWM_3";
+PWM1.peripheral.$assign                 = "TIMG0";
+PWM1.peripheral.ccp1Pin.$assign         = "PA6";
+PWM1.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric11";
+PWM1.ccp1PinConfig.direction            = scripting.forceWrite("OUTPUT");
+PWM1.ccp1PinConfig.hideOutputInversion  = scripting.forceWrite(false);
+PWM1.ccp1PinConfig.onlyInternalResistor = scripting.forceWrite(false);
+PWM1.ccp1PinConfig.passedPeripheralType = scripting.forceWrite("Digital");
+PWM1.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC0";
+
+PWM2.ccIndex                            = [1];
+PWM2.$name                              = "PWM_2";
+PWM2.peripheral.$assign                 = "TIMG1";
+PWM2.peripheral.ccp1Pin.$assign         = "PA2";
+PWM2.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric6";
+PWM2.ccp1PinConfig.direction            = scripting.forceWrite("OUTPUT");
+PWM2.ccp1PinConfig.hideOutputInversion  = scripting.forceWrite(false);
+PWM2.ccp1PinConfig.onlyInternalResistor = scripting.forceWrite(false);
+PWM2.ccp1PinConfig.passedPeripheralType = scripting.forceWrite("Digital");
+PWM2.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC1";
+
+PWM3.ccIndex                            = [1];
+PWM3.$name                              = "PWM_1";
+PWM3.peripheral.$assign                 = "TIMG2";
+PWM3.peripheral.ccp1Pin.$assign         = "PA22";
+PWM3.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric8";
+PWM3.ccp1PinConfig.direction            = scripting.forceWrite("OUTPUT");
+PWM3.ccp1PinConfig.hideOutputInversion  = scripting.forceWrite(false);
+PWM3.ccp1PinConfig.onlyInternalResistor = scripting.forceWrite(false);
+PWM3.ccp1PinConfig.passedPeripheralType = scripting.forceWrite("Digital");
+PWM3.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC2";
+
+PWM4.ccIndex                            = [1];
+PWM4.$name                              = "PWM_0";
+PWM4.peripheral.$assign                 = "TIMG4";
+PWM4.peripheral.ccp1Pin.$assign         = "PA25";
+PWM4.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric10";
+PWM4.ccp1PinConfig.direction            = scripting.forceWrite("OUTPUT");
+PWM4.ccp1PinConfig.hideOutputInversion  = scripting.forceWrite(false);
+PWM4.ccp1PinConfig.onlyInternalResistor = scripting.forceWrite(false);
+PWM4.ccp1PinConfig.passedPeripheralType = scripting.forceWrite("Digital");
+PWM4.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC3";
 
 SYSCTL.disableNRSTPin     = true;
 SYSCTL.peripheral.$assign = "SYSCTL";
@@ -88,4 +128,3 @@ ProjectConfig.migrationCondition = true;
  * re-solve from scratch.
  */
 I2C2.peripheral.$suggestSolution = "I2C0";
-PWM1.peripheral.$suggestSolution = "TIMG1";

+ 31 - 5
src/battery_data/battery.c

@@ -17,7 +17,7 @@ static void set_dac(uint8_t slot, uint16_t value) {
 }
 static void set_pwm(uint8_t slot, uint16_t value) {
     battery_slots[slot].pwm_value = value;
-    DL_TimerG_setCaptureCompareValue(battery_slots[0].timer, value, DL_TIMER_CC_0_INDEX);
+    DL_TimerG_setCaptureCompareValue(battery_slots[0].timer, value, DL_TIMER_CC_1_INDEX);
 }
 static void batteryslots_disable(uint8_t slot) {
     if (battery_slots[slot].dac_value != 0) {
@@ -33,6 +33,11 @@ static void batteryslots_init() {
 
     // initialize data structures
     battery_slots[0].timer = PWM_0_INST;
+#if NUM_SLOTS == 4
+    battery_slots[1].timer = PWM_1_INST;
+    battery_slots[2].timer = PWM_2_INST;
+    battery_slots[3].timer = PWM_3_INST;
+#endif
 
     for(uint8_t i=0; i< NUM_SLOTS; i++){
 
@@ -78,11 +83,32 @@ 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.0/56+1)*bare_voltage; // We have that voltage divider
+
+    // 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/1000; // current comes in microvolts
+#ifdef DEBUG_TRACE_CTRL
+        printf("Slot %d voltage: %d mV and %d mA (dac shunt)\n", slot, battery_slots[slot].measurement.voltage, battery_slots[slot].measurement.current);
+#endif
+    } 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;
 
-    // step 2: read channel 1 (current reading on charge)
-    updateADCReading(slot, 1);
+        // 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;
+#ifdef DEBUG_TRACE_CTRL
+        printf("Slot %d voltage: %d mV and %d mA (pwm shunt) (hi side voltage: %d mV, hi side current: %d mA)\n", slot, battery_slots[slot].measurement.voltage, battery_slots[slot].measurement.current, hi_voltage, shunt_current);
+#endif
+    }
 }
 
 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

+ 2 - 2
src/config.h

@@ -5,7 +5,7 @@
 
 // How many slots do we currently support?
 // use 1 for debugging, 4 for production
-#define NUM_SLOTS 1
+#define NUM_SLOTS 4
 
 //Battery Tolerance
 // how much tolerance do we allow if we charge / discharge before we 
@@ -86,4 +86,4 @@
 // controller mode only
 // (target for the other MCU is treated differently)
 #define I2C_TX_MAX_PACKET_SIZE 5
-#define I2C_RX_MAX_PACKET_SIZE 5  
+#define I2C_RX_MAX_PACKET_SIZE 5

+ 32 - 14
src/peripherals/adc/adc.c

@@ -11,20 +11,32 @@
 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) {
         
         case ADC_STATE_CONFIGURE:
             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;
+                adc_params.factor = 1;
+            } else {
+                // current measurement
+                // -> maximum gain, max resolution
+                adc_params.gain = 8;
+                adc_params.resolution = 16;
+                adc_params.factor = 1000; // get microvolts
+            }
             //printf("Config: Memory address of batteries: %p\n", &batteries[0]);
             adc_hal.configure(slot, &adc_params);
-            if (adc_params.continuous == 1) {
+            if (adc_params.continuous != 1) {
                 // in one shot mode we wait first to get the result
                 adc_state = ADC_STATE_WAIT;
             } else {
@@ -41,16 +53,13 @@ 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;
+            adc_voltage = adc_hal.read_voltage(slot, &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 \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

+ 24 - 52
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;
@@ -186,69 +189,38 @@ static int16_t read_adc_raw_data(uint8_t slot_id, ADC_Params *params) {
     
     i2c_hal.read(ADC_TARGET_BASE_ADDRESS + slot_id);
     while(!controllerRxPackage.complete);
-#ifdef DEBUG_ADC
-    printf("ADC Read:: gRxADClen: %d, gRxADCcount: %d\n", controllerRxPackage.len, controllerRxPackage.count);
-    printf("Bytes: 0x%02X 0x%02X 0x%02X (%d %d %d)\n", controllerRxPackage.packet[0], controllerRxPackage.packet[1],  controllerRxPackage.packet[2], controllerRxPackage.packet[0], controllerRxPackage.packet[1],  controllerRxPackage.packet[2]);
-#endif
     uint8_t msb = controllerRxPackage.packet[0];
     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;
-    }
-#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;
-}
-
-/* Function to Convert ADC Reading to Voltage */
-static uint16_t adc_voltage(int16_t adc_value, ADC_Params *params) {
-    uint16_t measured_voltage = 0;
-    uint16_t LSB = 0;
-    uint32_t max_adc_value = 1;
+    uint32_t max_adc_val = 0;
 
     switch (params->resolution) {
-    case 12: // 12-bit
-        max_adc_value = 4095;
-        break;
-    case 14: // 14-bit
-        max_adc_value = 16383;
-        break;
-    case 16: // 16-bit
-        max_adc_value = 65535;
-        break;
-    default:
-        //printf("Error: Unknown ADC Resolution!\n");
-        return 0;
+        case 12: // 12-bit
+            raw_adc = ((msb & 0b00001111) << 8) | lsb;
+            max_adc_val = 4096;
+            break;
+        case 14: // 14-bit
+            raw_adc = ((msb & 0b00111111) << 8) | lsb;
+            max_adc_val = 16384;
+            break;
+        case 16: // 16-bit
+            raw_adc = ((msb & 0b11111111) << 8) | lsb;
+            max_adc_val = 65536;
+            break;
+        default:
+            //printf("Error: Unknown ADC Resolution!\n");
+            break;
     }
-    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;
+#ifdef DEBUG_ADC
+    printf("Raw ADC: %d, MSB: 0x%02X (%d) LSB: 0x%02X (%d) Config: 0x%02X\n", raw_adc, msb, msb, lsb, lsb, config_adc_byte);
+#endif
+    return raw_adc * params->factor * 2048 / (max_adc_val/2) / params->gain;
 }
 
-
 ADC_Interface adc_hal= {
     .configure= adc_configure,
-    .read_raw= read_adc_raw_data,
+    .read_voltage = read_adc_raw_data,
     .is_ready= adc_is_ready,
-    .convert_voltage= adc_voltage,
-    .convert_current= adc_current
 };

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

@@ -11,16 +11,14 @@ typedef struct {
     uint8_t resolution;
     bool continuous;
     uint8_t gain;
+    uint16_t factor;
 } ADC_Params;
 
 // 14.04: added pointer for ADC_Params
 typedef struct {
     bool (*configure)(uint8_t slot_id, ADC_Params *params);
+    int16_t (*read_voltage)(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);
-    
 } ADC_Interface;
 
 extern ADC_Interface adc_hal;