Bläddra i källkod

Fixes: Spannungsmessung funktioniert halbwegs, fluktiert noch stark.

Heinrich Blatt 4 månader sedan
förälder
incheckning
5e922bcf86
6 ändrade filer med 101 tillägg och 69 borttagningar
  1. 5 8
      main_target.c
  2. 19 21
      main_target.syscfg
  3. 1 3
      src/battery_data/battery.c
  4. 1 1
      src/config.h
  5. 60 30
      src/interfaces/i2c_target.c
  6. 15 6
      src/peripherals/adc.c

+ 5 - 8
main_target.c

@@ -57,20 +57,14 @@ int main(void)
     DL_ADC12_startConversion(ADC12_0_INST);
     DL_ADC12_enableConversions(ADC12_0_INST);
 
-    delay_cycles(320000*4);
-    slot.set_current = 800;
-
     while (1) {
 
         if (handle_read_pending_slot != -1) {
             mcu_i2c_handle_read(I2C_target_INST);
             handle_read_pending_slot = -1;
         }
-    
-        // step 1: update the voltage readings
-        slot_read_state();
 
-        // step 2: control loop to adjust the dac / adc values,
+        // control loop to adjust the dac / adc values,
         // but only if no error happens
         // (0x80 is the error flag of the state)
         if ((*slot.state & 0x80) == 0) {
@@ -79,6 +73,9 @@ int main(void)
             slot_disable();
         }
 
-        delay_cycles(320000*4);
+        bool runs;
+        runs = DL_ADC12_isConversionStarted(ADC12_0_INST);
+        
+        delay_cycles(32000*4);
     }
 }

+ 19 - 21
main_target.syscfg

@@ -20,7 +20,6 @@ const I2C           = scripting.addModule("/ti/driverlib/I2C", {}, false);
 const I2C1          = I2C.addInstance();
 const OPA           = scripting.addModule("/ti/driverlib/OPA", {}, false);
 const OPA1          = OPA.addInstance();
-const OPA2          = OPA.addInstance();
 const PWM           = scripting.addModule("/ti/driverlib/PWM", {}, false);
 const PWM1          = PWM.addInstance();
 const SYSCTL        = scripting.addModule("/ti/driverlib/SYSCTL");
@@ -35,7 +34,10 @@ ADC121.enabledInterrupts   = ["DL_ADC12_INTERRUPT_MEM0_RESULT_LOADED"];
 ADC121.sampClkDiv          = "DL_ADC12_CLOCK_DIVIDE_8";
 ADC121.powerDownMode       = "DL_ADC12_POWER_DOWN_MODE_MANUAL";
 ADC121.sampleTime0         = "125 us";
-ADC121.adcMem0vref         = "VREF";
+ADC121.adcMem0avgen        = true;
+ADC121.hwNumerator         = "DL_ADC12_HW_AVG_NUM_ACC_32";
+ADC121.hwDenominator       = "DL_ADC12_HW_AVG_DEN_DIV_BY_32";
+ADC121.adcMem1vref         = "VREF";
 ADC121.peripheral.$assign  = "ADC0";
 ADC121.adcPin0Config.$name = "ti_driverlib_gpio_GPIOPinGeneric4";
 
@@ -44,18 +46,27 @@ Board.peripheral.$assign          = "DEBUGSS";
 Board.peripheral.swclkPin.$assign = "PA20";
 Board.peripheral.swdioPin.$assign = "PA19";
 
-COMP1.$name         = "COMP_0";
-COMP1.controlSelect = "DL_COMP_DAC_CONTROL_SW";
-COMP1.vSource       = "DL_COMP_REF_SOURCE_VDDA_DAC";
+COMP1.$name          = "COMP_0";
+COMP1.vSource        = "DL_COMP_REF_SOURCE_VDDA_DAC";
+COMP1.controlSelect  = "DL_COMP_DAC_CONTROL_SW";
+COMP1.hysteresis     = "DL_COMP_HYSTERESIS_10";
+COMP1.terminalSelect = "DL_COMP_REF_TERMINAL_SELECT_NEG";
 
 GPIO1.$name                         = "ADDR";
-GPIO1.associatedPins.create(2);
+GPIO1.associatedPins.create(3);
 GPIO1.associatedPins[0].$name       = "A0";
 GPIO1.associatedPins[0].direction   = "INPUT";
+GPIO1.associatedPins[0].polarity    = "RISE_FALL";
+GPIO1.associatedPins[0].interruptEn = true;
 GPIO1.associatedPins[0].pin.$assign = "PA4";
 GPIO1.associatedPins[1].$name       = "A1";
 GPIO1.associatedPins[1].direction   = "INPUT";
+GPIO1.associatedPins[1].interruptEn = true;
+GPIO1.associatedPins[1].polarity    = "RISE_FALL";
 GPIO1.associatedPins[1].pin.$assign = "PA11";
+GPIO1.associatedPins[2].$name       = "A2";
+GPIO1.associatedPins[2].direction   = "INPUT";
+GPIO1.associatedPins[2].pin.$assign = "PA16";
 
 I2C1.$name                             = "I2C_target";
 I2C1.basicEnableTarget                 = true;
@@ -83,25 +94,11 @@ I2C1.sclPinConfig.enableConfig         = true;
 OPA1.$name                     = "OPA_0";
 OPA1.cfg0OutputPin             = "ENABLED";
 OPA1.cfg0PSELChannel           = "DAC8_OUT";
-OPA1.cfg0NSELChannel           = "RTAP";
-OPA1.cfg0MSELChannel           = "GND";
+OPA1.cfg0NSELChannel           = "RTOP";
 OPA1.peripheral.$assign        = "OPA0";
 OPA1.peripheral.OutPin.$assign = "PA22";
 OPA1.OutPinConfig.$name        = "ti_driverlib_gpio_GPIOPinGeneric0";
 
-OPA2.$name                        = "OPA_1";
-OPA2.cfg0PSELChannel              = "IN0_POS";
-OPA2.cfg0NSELChannel              = "IN1_NEG";
-OPA2.cfg0OutputPin                = "ENABLED";
-OPA2.cfg0MSELChannel              = "IN1_NEG";
-OPA2.peripheral.$assign           = "OPA1";
-OPA2.peripheral.In0PosPin.$assign = "PA18";
-OPA2.peripheral.In1NegPin.$assign = "PA17/OPA1.IN0-";
-OPA2.peripheral.OutPin.$assign    = "PA16";
-OPA2.In0PosPinConfig.$name        = "ti_driverlib_gpio_GPIOPinGeneric5";
-OPA2.In1NegPinConfig.$name        = "ti_driverlib_gpio_GPIOPinGeneric6";
-OPA2.OutPinConfig.$name           = "ti_driverlib_gpio_GPIOPinGeneric7";
-
 PWM1.$name                              = "PWM";
 PWM1.ccIndex                            = [1];
 PWM1.timerCount                         = 320;
@@ -118,6 +115,7 @@ PWM1.PWM_CHANNEL_1.invert               = true;
 SYSCTL.disableNRSTPin     = true;
 SYSCTL.peripheral.$assign = "SYSCTL";
 
+VREF.basicIntVolt = "DL_VREF_BUFCONFIG_OUTPUT_2_5V";
 
 ProjectConfig.migrationCondition = true;
 ProjectConfig.genLibIQ           = true;

+ 1 - 3
src/battery_data/battery.c

@@ -9,6 +9,7 @@ BatterySlot slot;
 
 static void set_dac(uint16_t value) {
     slot.dac_value = value;
+    printf("dac: %d\n", value);
     DL_COMP_setDACCode0(COMP_0_INST, value);
 }
 static void set_pwm(uint16_t value) {
@@ -47,9 +48,6 @@ void slot_init() {
     set_pwm(0);
     set_dac(0);
 }
-void slot_read_state() {
-   ;
-}
 
 void slot_adjust_current() {
 

+ 1 - 1
src/config.h

@@ -27,7 +27,7 @@
 #define PWM_INITIALIZATION_DELAY 100
 
 // PWM Define max CC period
-#define MAX_PWM_CYCLE 300
+#define MAX_PWM_CYCLE 128
 
 #define MAX_DAC_VALUE 255
 

+ 60 - 30
src/interfaces/i2c_target.c

@@ -23,10 +23,13 @@ https://stackoverflow.com/questions/246127/why-is-volatile-needed-in-c
 void initialize_target_address() {
     uint8_t add = 0;
     if (DL_GPIO_readPins(ADDR_PORT, ADDR_A0_PIN)) {
-        add = 1;
+        add += 1;
     }
     if (DL_GPIO_readPins(ADDR_PORT, ADDR_A1_PIN)) {
-        add = 2;
+        add += 2;
+    }
+    if (DL_GPIO_readPins(ADDR_PORT, ADDR_A2_PIN)) {
+        add += 4;
     }
     DL_I2C_setTargetOwnAddress(I2C_target_INST, I2C_TARGET_BASE_ADDRESS+add);
     DL_I2C_enableTargetOwnAddress(I2C_target_INST);
@@ -58,43 +61,70 @@ int8_t mcu_i2c_handle(I2C_Regs *i2c) {
 
 void mcu_i2c_handle_read(I2C_Regs *i2c) {
     // Read incoming bytes from the Controller:
-        uint8_t rx_index = 0;
-        uint8_t rx_buffer[2] = {0x00, 0x00};
-        while (rx_index < 2) {
-            // TODO: Need to have a workaround, currently the code is getting stuck on
-            // the first trigger and provides result on the second trigger
-            if (!DL_I2C_isTargetRXFIFOEmpty(i2c)) {
-                rx_buffer[rx_index] = DL_I2C_receiveTargetData(i2c);
-                rx_index++;
-            }
+    uint8_t rx_index = 0;
+    uint8_t rx_buffer[2] = {0x00, 0x00};
+    while (rx_index < 2) {
+        // TODO: Need to have a workaround, currently the code is getting stuck on
+        // the first trigger and provides result on the second trigger
+        if (!DL_I2C_isTargetRXFIFOEmpty(i2c)) {
+            rx_buffer[rx_index] = DL_I2C_receiveTargetData(i2c);
+            rx_index++;
         }
-        if (rx_index != 2) {
+    }
+    if (rx_index != 2) {
 #ifdef DEBUG_TARGET
-            printf("ERROR: Incomplete I2C Rx: received %d bytes\n", rx_index);
+        printf("ERROR: Incomplete I2C Rx: received %d bytes\n", rx_index);
 #endif
-            DL_I2C_flushTargetRXFIFO(i2c);
-            rx_index = 0;
-            return;
-        }
-        slot.set_current = *((int16_t*)(&rx_buffer[0]));
+        DL_I2C_flushTargetRXFIFO(i2c);
+        rx_index = 0;
+        return;
+    }
+    slot.set_current = *((int16_t*)(&rx_buffer[0]));
         
 #ifdef DEBUG_TARGET
-        printf("Current: %d mA (Bytes 0x%02X 0x%02X)\n", slot.set_current, rx_buffer[0], rx_buffer[1]);
+    printf("Current: %d mA (Bytes 0x%02X 0x%02X)\n", slot.set_current, rx_buffer[0], rx_buffer[1]);
 #endif
-        /*
-        // This code is for debugging:
-        // you can shoot directly code to the DAC / PWM for debugging
-        if (battery_slots[slot].set_current >= 0) {
-            DAC_SingleWrite(slot, battery_slots[slot].set_current);
-        } else if (battery_slots[slot].set_current < 0) {
-            DL_TimerG_setCaptureCompareValue(PWM_0_INST, -1*battery_slots[slot].set_current, DL_TIMER_CC_1_INDEX);
 
+    /*
+    DL_TimerG_stopCounter(PWM_INST);
+    if (value > 0) {
+        DL_COMP_setDACCode0(COMP_0_INST, value);
+        slot.dac_value = value;
+        slot.pwm_value = 0;
+    } else {
+        uint16_t pwm_val = -1*value;
+        DL_COMP_setDACCode0(COMP_0_INST, 0);
+        slot.dac_value = 0;
+        if (DL_GPIO_readPins(ADDR_PORT, ADDR_A1_PIN)) {
+            DL_TimerG_PWMConfig gPWMConfig = {
+                .pwmMode = DL_TIMER_PWM_MODE_EDGE_ALIGN,
+                .period = pwm_val,
+                .isTimerWithFourCC = false,
+                .startTimer = DL_TIMER_STOP,
+            };
+            DL_TimerG_initPWMMode(
+                PWM_INST, (DL_TimerG_PWMConfig *) &gPWMConfig);
         } else {
-            // do nothing, charge or discharge
+            DL_TimerG_setCaptureCompareValue(PWM_INST, pwm_val, DL_TIMER_CC_1_INDEX);
+            slot.pwm_value = pwm_val;
+        }
+        DL_TimerG_startCounter(PWM_INST);
+    }*/
+
+    /*
+    // This code is for debugging:
+    // you can shoot directly code to the DAC / PWM for debugging
+    if (battery_slots[slot].set_current >= 0) {
+        DAC_SingleWrite(slot, battery_slots[slot].set_current);
+    } else if (battery_slots[slot].set_current < 0) {
+        DL_TimerG_setCaptureCompareValue(PWM_0_INST, -1*battery_slots[slot].set_current, DL_TIMER_CC_1_INDEX);
+
+    } else {
+        // do nothing, charge or discharge
 #ifdef DEBUG_TARGET
-            printf("state is idle");
+        printf("state is idle");
 #else
-            ;
+        ;
 #endif
-        } */
+    } */
 }

+ 15 - 6
src/peripherals/adc.c

@@ -28,6 +28,8 @@ const uint8_t measurement_channels[N_CHANNELS] = {
     DL_ADC12_INPUT_CHAN_11,
 };
 
+#define REV_VOLTAGE 3300
+
 uint8_t ch=0;
 
 uint16_t measurement_results[N_CHANNELS] = { 0 };
@@ -38,19 +40,23 @@ void ADC12_0_INST_IRQHandler(void)
 {
     switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
         case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
-            measurement_results[ch] = ((uint32_t)DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0))*3300/4096;
+
+            //measurement_results[ch] = ((uint32_t)DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0))*REV_VOLTAGE/4096;
+            measurement_results[ch] = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
+
             if (ch == 1) {
                 // We have upper and lower temperature of the cell
                 // -> difference is the cell voltage
-
-                // WTF, teh voltage divider is bridged?
-                slot.measurement.voltage = (measurement_results[1]-measurement_results[0])*(56+100)/56;
+                uint32_t batt_plus = ((uint32_t)measurement_results[1])*(82+100)/82;
+                uint32_t batt_minus = ((uint32_t)measurement_results[0]);
+                slot.measurement.voltage = (batt_plus-batt_minus)*REV_VOLTAGE/4096;
             }
             if (ch == 2 && slot.dac_value > 0) {
-                slot.measurement.current = (measurement_results[2])*10; // 100mOhms
+                uint32_t shunt_current = ((uint32_t)(measurement_results[2]-measurement_results[1]))*10*(82+100)/82*REV_VOLTAGE/4096;
+                slot.measurement.current = shunt_current;
             }
             if (ch == 4 && slot.pwm_value > 0) {
-                int32_t hi_side_votlage = measurement_results[3]*(56+100)/56; // high side (5V voltage level) in volts
+                int32_t hi_side_votlage = measurement_results[3]*(82+100)/82; // high side (5V voltage level) in volts
                 slot.measurement.current = hi_side_votlage*measurement_results[4]/slot.measurement.voltage*-1; // 1:1 - 100mOhm Shunt, aber Faktor 10 über den OpAmp
             }
             if (slot.dac_value == 0 && slot.pwm_value == 0) {
@@ -71,6 +77,9 @@ void ADC12_0_INST_IRQHandler(void)
                 ch = 0;
             }
             DL_ADC12_stopConversion(ADC12_0_INST);
+            DL_ADC12_configHwAverage(ADC12_0_INST,
+                                    DL_ADC12_HW_AVG_NUM_ACC_8,
+                                    DL_ADC12_HW_AVG_DEN_DIV_BY_8);
             DL_ADC12_configConversionMem(ADC12_0_INST, 
                                          ADC12_0_ADCMEM_0,
                                          measurement_channels[ch],