7 Achegas 0a6dffb608 ... 1c24f24635

Autor SHA1 Mensaxe Data
  Heinrich Blatt 1c24f24635 Fixed i2c communication with external mcu hai 7 meses
  Heinrich Blatt ede0a220f9 * i2c-target speicher-optimiert hai 7 meses
  Heinrich Blatt e4aa74cb79 Bugfix auf dem ADC: Das erste Kommando funktioniert jetzt direkt (buffer geleert) hai 7 meses
  Heinrich Blatt 566a29c1cf Änderungen im config header hai 7 meses
  Heinrich Blatt 8ba47ea719 PWM Control-loop gefixt. Stromoffset-Problem der High-Side besteht noch. hai 7 meses
  Heinrich Blatt d0c13cb239 Fix clock cycles aller PWMs auf 100kHz hai 7 meses
  Heinrich Blatt 32ed47067b Verbesserungen: hai 7 meses

+ 1 - 2
main_target.c

@@ -79,7 +79,6 @@ void I2C_target_INST_IRQHandler(void) {
   case DL_I2C_IIDX_TARGET_STOP:
     mcu_CommandPending= true;
     DL_I2C_flushTargetTXFIFO(I2C_target_INST);
-    DL_I2C_flushTargetRXFIFO(I2C_target_INST);
     break;
   case DL_I2C_IIDX_TARGET_RXFIFO_TRIGGER:
     if (DL_I2C_isTargetRXFIFOEmpty(I2C_target_INST)) {
@@ -114,7 +113,7 @@ int main(void)
             printf("Calling MCU target action\n");
 #endif
             mcu_i2c_handle(I2C_target_INST);
-            mcu_CommandPending= false;
+            mcu_CommandPending = false;
         }
         
         for(uint8_t slot= 0; slot< NUM_SLOTS; slot++){

+ 12 - 5
main_target.syscfg

@@ -72,50 +72,57 @@ I2C2.sclPinConfig.passedPeripheralType = scripting.forceWrite("Digital");
 I2C2.sclPinConfig.enableConfig         = true;
 
 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.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric11";
 PWM1.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC0";
+PWM1.PWM_CHANNEL_1.invert               = true;
+PWM1.PWM_CHANNEL_1.ccValue              = 320;
 
 PWM2.ccIndex                            = [1];
 PWM2.$name                              = "PWM_2";
+PWM2.timerCount                         = 320;
 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.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric6";
 PWM2.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC1";
+PWM2.PWM_CHANNEL_1.invert               = true;
 
 PWM3.ccIndex                            = [1];
 PWM3.$name                              = "PWM_1";
+PWM3.timerCount                         = 320;
 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.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric8";
 PWM3.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC2";
+PWM3.PWM_CHANNEL_1.invert               = true;
 
 PWM4.ccIndex                            = [1];
 PWM4.$name                              = "PWM_0";
+PWM4.timerCount                         = 320;
 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.ccp1PinConfig.$name                = "ti_driverlib_gpio_GPIOPinGeneric10";
 PWM4.PWM_CHANNEL_1.$name                = "ti_driverlib_pwm_PWMTimerCC3";
+PWM4.PWM_CHANNEL_1.invert               = true;
 
 SYSCTL.disableNRSTPin     = true;
 SYSCTL.peripheral.$assign = "SYSCTL";

+ 21 - 20
src/battery_data/battery.c

@@ -1,5 +1,6 @@
 #include "battery.h"
 #include "ti/driverlib/dl_i2c.h"
+#include "ti/driverlib/dl_timerg.h"
 #include "ti_msp_dl_config.h"
 #include "src/peripherals/dac/dac.h"
 #include "src/peripherals/adc/adc.h"
@@ -52,10 +53,13 @@ static void batteryslots_init() {
         battery_slots[i].measurement.temperature = 0;
         battery_slots[i].set_current = 0;
 
+        DL_TimerG_startCounter(battery_slots[i].timer);
         set_pwm(i, 0);
+        delay_cycles(PWM_INITIALIZATION_DELAY);
     }
 
-    if (!i2c_discover(DAC_TARGET_ADDRESS)) {
+    
+    /*if (!i2c_discover(DAC_TARGET_ADDRESS)) {
         // there is only 1 DAC for all 4 slots
         for(uint8_t i=0; i< NUM_SLOTS; i++) {
             *battery_slots[i].state = SLOT_ERR_NO_DAC;
@@ -67,12 +71,12 @@ static void batteryslots_init() {
     for(uint8_t i=0; i< NUM_SLOTS; i++){
 
         set_dac(i, 0);
-
+        
         if (!i2c_discover(ADC_TARGET_BASE_ADDRESS+i)) {
             // this automatically translates to the other addresses
             *battery_slots[i].state = SLOT_ERR_NO_ADC1+i;
         }
-    }
+    }*/
 }
 static void batteryslots_read_state(uint8_t slot) {
     /*
@@ -85,27 +89,29 @@ static void batteryslots_read_state(uint8_t slot) {
  
     // 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
+    battery_slots[slot].measurement.voltage = bare_voltage*(56+100)/56; // 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
+#ifdef DEBUG_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;
+        uint16_t shunt_current = 10*read_adc_channel(slot, 2)/1000;
 
         // read channel 3 (current reading after step conversion, 5V side)
-        int16_t hi_voltage = read_adc_channel(slot, 3)*100/56;
+        uint16_t hi_voltage = read_adc_channel(slot, 3)*(56+100)/56;
+
+        uint32_t hi_power = shunt_current*hi_voltage;
 
         // calculate the result
-        battery_slots[slot].measurement.current = -1*shunt_current*hi_voltage/battery_slots[slot].measurement.voltage;
-#ifdef DEBUG_TRACE_CTRL
+        battery_slots[slot].measurement.current = (int16_t)(hi_power/battery_slots[slot].measurement.voltage)*-1;
+#ifdef DEBUG_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
     }
@@ -114,7 +120,7 @@ static void batteryslots_read_state(uint8_t slot) {
 static void batteryslots_adjust_current(uint8_t slot) {
 
 #ifdef DEBUG_TRACE_CTRL
-    printf("Ctrl: Adjusting battery current. Set current: %d mA, measured current: %d mA\n",
+    printf("Ctrl: Checking to adjust battery current. Set current: %d mA, measured current: %d mA\n",
         battery_slots[slot].set_current,
         battery_slots[slot].measurement.current
         );
@@ -132,7 +138,7 @@ static void batteryslots_adjust_current(uint8_t slot) {
             set_pwm(slot, 0);
         }
 
-        if (battery_slots[slot].set_current + BATTERY_CURRENT_THRESHOLD > battery_slots[slot].measurement.current) {
+        if (battery_slots[slot].set_current + BATTERY_CURRENT_THRESHOLD < battery_slots[slot].measurement.current) {
             // we are outside of the tolerance band
             // exceeded to the upper limit
             // -> update dac value, decrease the voltage
@@ -149,7 +155,7 @@ static void batteryslots_adjust_current(uint8_t slot) {
 #endif
                 *battery_slots[slot].state = SLOT_WARN_LOWER_DAC_NOT_POSSIBLE;
             }
-        } else if (battery_slots[slot].set_current - BATTERY_CURRENT_THRESHOLD < battery_slots[slot].measurement.current) {
+        } else if (battery_slots[slot].set_current - BATTERY_CURRENT_THRESHOLD > battery_slots[slot].measurement.current) {
             // we are outside of the tolerance band
             // exceeded to the upplowerer limit
             // -> update dac value, increase the voltage
@@ -179,17 +185,12 @@ static void batteryslots_adjust_current(uint8_t slot) {
             set_dac(slot, 0);
         }
 
-        if (battery_slots[slot].set_current + BATTERY_CURRENT_THRESHOLD > battery_slots[slot].measurement.current) {
+        if (battery_slots[slot].set_current + BATTERY_CURRENT_THRESHOLD < battery_slots[slot].measurement.current) {
             // we are outside of the tolerance band
             // exceeded to the upper limit
             // -> update pwm value, decrease the voltage
-            
-            // @todo debugging & validation: ensure that this directive works
-#ifdef DEBUG_CTRL
-            printf("timer count: %d\n", DL_Timer_getTimerCount(battery_slots[0].timer));
-#endif
 
-            if (battery_slots[slot].pwm_value+1 <= DL_Timer_getTimerCount(battery_slots[0].timer)) {
+            if (battery_slots[slot].pwm_value+1 <= MAX_PWM_CYCLE) {
                 // pwm is inverse to the DAC since dragging more current means more negative
 #ifdef DEBUG_TRACE_CTRL
                 printf("Ctrl: Increasing PWM to %d\n", battery_slots[slot].pwm_value+1);
@@ -203,7 +204,7 @@ static void batteryslots_adjust_current(uint8_t slot) {
 #endif
                 *battery_slots[slot].state = SLOT_WARN_HIGHER_PWM_NOT_POSSIBLE;
             }
-        } else if (battery_slots[slot].set_current - BATTERY_CURRENT_THRESHOLD < battery_slots[slot].measurement.current) {
+        } else if (battery_slots[slot].set_current - BATTERY_CURRENT_THRESHOLD > battery_slots[slot].measurement.current) {
             // we are outside of the tolerance band
             // exceeded to the upplowerer limit
             // -> update pwm value, increase the voltage

+ 13 - 4
src/config.h

@@ -5,7 +5,7 @@
 
 // How many slots do we currently support?
 // use 1 for debugging, 4 for production
-#define NUM_SLOTS 4
+#define NUM_SLOTS 1
 
 //Battery Tolerance
 // how much tolerance do we allow if we charge / discharge before we 
@@ -19,12 +19,20 @@
 // production e.g. 320000 (10ms) (Validate that this is really the case!)
 // should be large for debugging, (e.g. )
 // small for production
-#define MAINLOOP_DELAY (32000000*5)
+#define MAINLOOP_DELAY (3200)
 
 // i2c address for acting as target
 // (based on the GPIO 1 integer is added)
 #define I2C_TARGET_BASE_ADDRESS 0x48
 
+// PWM Initalization delay
+// in order to ensure they don't go in exactly the same frequency to
+// avoid EMV peaks
+#define PWM_INITIALIZATION_DELAY 100
+
+// PWM Define max CC period
+#define MAX_PWM_CYCLE 320
+
 //------------
 // Section for configuring debugging outputs
 //------------
@@ -45,7 +53,7 @@
 #define DEBUG_I2C_ERR 1
 
 // printf i2c traffic (tx)
-#define DEBUG_I2C_TX 1
+//#define DEBUG_I2C_TX 1
 
 // printf target i2c interrupts (where the mcu is the i2c target)
 #define DEBUG_TARGET 1
@@ -80,7 +88,8 @@
 // ensure that the measurement is ready. (set the define to 0 if it should be one-shot)
 // (it could be the case that the channel is switched and wrong data is fetched)
 #define ADC_MEASUREMENT_IS_CONTINUOUS 1
-#define ADC_CONTINUOUS_DELAY_CYCLES (32000) // 32000 is 1ms (32MHz clock)
+#define ADC_CONTINUOUS_DELAY_CYCLES_VOLTAGES (32000*10) // 32000 is 1ms (32MHz clock)
+#define ADC_CONTINUOUS_DELAY_CYCLES_SHUNT (32000*75)
 
 // Packet buffer sizes for RX and TX for the
 // controller mode only

+ 24 - 24
src/interfaces/i2c_target.c

@@ -33,9 +33,12 @@ void initialize_target_address() {
 // need to select the right one, passing a pointer as an argument
 
 void mcu_i2c_handle(I2C_Regs *i2c) {
-    uint8_t receivedCommand = DL_I2C_receiveTargetData(i2c);
+    uint8_t receivedByte = DL_I2C_receiveTargetData(i2c);
+    uint8_t receivedCommand = (receivedByte & 0x0F);
+    uint8_t slot = (receivedByte & 0xF0);
+
 #ifdef DEBUG_TARGET
-    printf("[SLAVE] Received Command: 0x%02X\n", receivedCommand);
+    printf("[SLAVE] Received Byte: 0x%02X\n", receivedByte);
 #endif
     uint8_t tx_buffer[8] = {0};
     // changed to volatile variable, so that the compiler cannot optimize the
@@ -43,27 +46,24 @@ void mcu_i2c_handle(I2C_Regs *i2c) {
     volatile uint8_t rx_buffer[8] = {0};
     /*Handling GET commands with bitmasking*/
     // GET command for ADC(Battery Measurement): Voltage, Current, Temperature
-    if ((receivedCommand & 0x0F) == CMD_GET_MEASUREMENT) {
-        uint8_t slot = receivedCommand & 0xF0;
+    if (receivedCommand == CMD_GET_MEASUREMENT) {
         if (slot > NUM_SLOTS) {
             DL_I2C_flushTargetTXFIFO(i2c);
             return;
         }
 
-        // Copying the memory block from battery_measure struct to tx_buffer:
-        // @todo check if this memcpy is even needed, probably 
-        // &battery_slots[slot].measurement can be directly used as buffer for DL_I2C_fillTargetTXFIFO
-        memcpy(tx_buffer, &battery_slots[slot].measurement, sizeof(BatteryMeasurement));
-        DL_I2C_fillTargetTXFIFO(i2c, tx_buffer, sizeof(BatteryMeasurement));
+        DL_I2C_fillTargetTXFIFO(i2c, &battery_slots[slot].measurement, sizeof(BatteryMeasurement));
+
 #ifdef DEBUG_TARGET
         printf("Battery Measurement Sent to MCU. \n");
 #endif
+        printf("");
         DL_I2C_flushTargetTXFIFO(i2c);
   
     } else if (receivedCommand == CMD_SET_CURRENT) {
         // Read incoming bytes from the Controller:
         uint8_t rx_index = 0;
-        while (rx_index < 4) {
+        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)) {
@@ -71,29 +71,29 @@ void mcu_i2c_handle(I2C_Regs *i2c) {
               rx_index++;
             }
         }
-        // we expect 4 bytes:
-        // 1. command
-        // 2. slot_id
-        // 3 + 4. current (int16)
-        if (rx_index != 4) {
+        // we expect 3 bytes:
+        // 1. <slot_id><command>
+        // 2 + 3. current (int16)
+        if (rx_index != 2) {
 #ifdef DEBUG_TARGET
-            printf("ERROR: Incomplete I2C Rx: received %d%zu bytes\n", rx_index, 4);
+            printf("ERROR: Incomplete I2C Rx: received %d bytes\n", rx_index);
 #endif
             DL_I2C_flushTargetRXFIFO(i2c);
             rx_index = 0;
             return;
         }
-        uint8_t slot = rx_buffer[1]; // first byte is the slot id (0..3)
-        battery_slots[slot].set_current = *((rx_buffer)+2); // byte 3+4 is the current
+        battery_slots[slot].set_current = *((int16_t*)(&rx_buffer[0])); // byte 2+3 is the current
+        
 #ifdef DEBUG_TARGET
-        printf("Slot id: %d, Current: %" SCNd16 "\n", slot, battery_slots[slot].set_current);
+        printf("Slot id: %d, Current: %" SCNd16 " (Bytes 0x%02X 0x%02X)\n", slot, battery_slots[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_startCounter(PWM_0_INST);
-            DL_TimerG_setCaptureCompareValue(PWM_0_INST, -1*battery_slots[slot].set_current, DL_TIMER_CC_0_INDEX); // update ccr0 value
+            DL_TimerG_setCaptureCompareValue(PWM_0_INST, -1*battery_slots[slot].set_current, DL_TIMER_CC_1_INDEX);
 
         } else {
             // do nothing, charge or discharge
@@ -102,13 +102,13 @@ void mcu_i2c_handle(I2C_Regs *i2c) {
 #else
             ;
 #endif
-        }
+        } */
     } else if (receivedCommand == CMD_CELAR_ERR) {
-        uint8_t slot = receivedCommand & 0xF0;
         if (slot > NUM_SLOTS) {
             DL_I2C_flushTargetTXFIFO(i2c);
             return;
         }
         *battery_slots[slot].state = SLOT_STATE_OK;
     }
+    DL_I2C_flushTargetRXFIFO(i2c);
 }

+ 1 - 2
src/interfaces/i2c_target.h

@@ -10,8 +10,7 @@
 typedef enum{
     CMD_SET_CURRENT= 0x05,
     CMD_GET_MEASUREMENT= 0x06, 
-    CMD_GET_BATTERY_STATE= 0x07, 
-    CMD_CELAR_ERR= 0x08
+    CMD_CELAR_ERR= 0x07
 }mcu_I2C_command;
 
 void initialize_target_address();

+ 5 - 31
src/peripherals/adc/adc.c

@@ -42,7 +42,11 @@ uint16_t read_adc_channel(uint8_t slot, uint8_t channel) {
             } else {
                 // in continuous mode we can directly read
                 adc_state = ADC_STATE_READ;
-                delay_cycles(ADC_CONTINUOUS_DELAY_CYCLES);
+                if (adc_params.resolution == 16) {
+                    delay_cycles(ADC_CONTINUOUS_DELAY_CYCLES_SHUNT);
+                } else {
+                    delay_cycles(ADC_CONTINUOUS_DELAY_CYCLES_VOLTAGES);
+                }
             }
             break;
 
@@ -58,36 +62,6 @@ uint16_t read_adc_channel(uint8_t slot, uint8_t channel) {
             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);
-                battery_slots[slot].measurement.current =
-                    adc_hal.convert_current(raw_adc_current, &adc_params);
-                adc_state = ADC_STATE_DONE;
-#ifdef DEBUG_ADC
-                printf("[ADC] Battery Current in slot %d is %d mA.\n", slot, battery_slots[slot].measurement.current);
-#endif
-            } 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].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;

+ 1 - 24
src/peripherals/dac/dac.c

@@ -7,27 +7,6 @@
 #include <stdio.h>
 #include "src/config.h"
 
-
-// The device updates all DAC analog output(vout) at the same time
-
-void DAC_UpdateOutput() {
-  uint8_t general_call_command = 0x08; // General Call Update Command
-  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
-         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
-    ;
-
-  // Start I2C transaction
-  DL_I2C_startControllerTransfer(I2C_controller_INST, 0x00,
-                                 DL_I2C_CONTROLLER_DIRECTION_TX, 1);
-
-  while (DL_I2C_getControllerStatus(I2C_controller_INST) &
-         DL_I2C_CONTROLLER_STATUS_BUSY_BUS)
-    ;
-
-  DL_I2C_fillControllerTXFIFO(I2C_controller_INST, &general_call_command, 1);
-}
-
-
 bool DAC_SingleWrite(uint8_t slot, uint16_t channel_value) {
     if(channel_value > MAX_DAC_VALUE) {
 #ifdef DEBUG_DAC
@@ -37,7 +16,7 @@ bool DAC_SingleWrite(uint8_t slot, uint16_t channel_value) {
         return false;
     }
     controllerTxPackage.len = 3;
-    controllerTxPackage.packet[0] = (0b01011000 | slot << 1);
+    controllerTxPackage.packet[0] = (0b01000000 | slot << 1);
     controllerTxPackage.packet[1] = (0x10) | ((channel_value >> 8) & 0x0F);
     controllerTxPackage.packet[2] = (channel_value & 0xFF);
 
@@ -58,7 +37,5 @@ bool DAC_SingleWrite(uint8_t slot, uint16_t channel_value) {
         return false;
     }
 
-    DAC_UpdateOutput();
-
     return true;
 }

+ 59 - 0
test-mcu.py

@@ -0,0 +1,59 @@
+from smbus2 import SMBus, i2c_msg
+import struct
+import time
+
+# Beispiel: I2C-Adresse des Geräts
+DEVICE_ADDRESS = 0x48  # z.B. EEPROM oder Sensoradresse
+I2C_BUS = 1            # I2C-1 ist meist Standard beim Raspberry Pi
+
+slot = input("Slot id (default: 0): ")
+if slot == "": slot = 0
+else: slot = int(slot)
+
+def read_status(bus):
+    data_to_write = [(0x06 | slot << 4)]
+
+    write = i2c_msg.write(DEVICE_ADDRESS, data_to_write)
+    bus.i2c_rdwr(write)
+
+    # Lesen von 3 Bytes roher Binärdaten
+    read = i2c_msg.read(DEVICE_ADDRESS, 8)
+    bus.i2c_rdwr(read)
+    data_read = bytes(read)
+    print("data:", data_read.hex())
+
+    data = struct.unpack("<HhHH", data_read)
+
+    # data[0] is voltage in mV
+    print(f"Spannung: {data[0]/1000:.2f}V, Strom: {data[1]}mA, Temperatur: {data[2]}°C, Error: 0x{data[3]:02X}")
+
+with SMBus(I2C_BUS) as bus:
+    # Schreiben von Rohdaten
+
+    while True:
+        
+        print("Mögliche Aktionen:")
+        print("  r <n>     n Zyklen lesen")
+        print("  w <i>     i mA Strom positiv: laden (DAC), negativ entladen: (PWM)")
+        act = input("nächste Aktion: ")
+        if act[0] == "r":
+            n = int(act.split(" ")[1])
+            for i in range(n):
+                time.sleep(1)
+                try:
+                    read_status(bus)
+                except:
+                    print("Bus error.")
+        elif act[0] == "w":
+            i = int(act.split(" ")[1])
+            # 5 is the command for setting the current
+            byte_str = struct.pack("<Bh", (5 + (slot << 4)), int(i))
+            print("Sending bytes", byte_str.hex())
+
+            write = i2c_msg.write(DEVICE_ADDRESS, list(byte_str))
+            bus.i2c_rdwr(write)
+
+
+        else:
+            "Ungültiges Kommando."
+