AC 1 open loop - owntech-foundation/Tutorials GitHub Wiki

Objective

NOTE: THIS IS AN OLD VERSION (for backup). For this tutorial group, we want to use directly half bridge topology for the DC/AC converter. See tutorial DC/AC 1b.

The goal of this tutorial is to build the base open-loop block of an DC-AC conversion. In practice, you will deactivate the NGND and control the switches such that a bi-polar modulation can take place.The O² converter will be in open-loop.

Inverter_connection

This figure shows how the inverter is set from the O² board. It shows the NGND switch is off.

image

This figure shows the bi-polar modulation used in this example

Required hardware

  • O2 v_1_1_2
  • STLinkV3
  • PC (windows or linux)
  • Power supply (40 V, 2 A)
  • Oscilloscope or multimeter

Required software

  • SerialPlot

Create the project

  1. We will create the project by copying the Buck 1 Task tutorial in a new branch, that will be called inverter_1 in the bottom menu, click on the New Terminal icon new_terminal_icon. This will open a new terminal into which you can write the commands below to create a new git branch.
git status
git add --all
git commit -m "work done on the previous branch (you can change this message)"
git branch inverter_1
git checkout inverter_1
  1. In the bottom menu, check that you are now in the inverter_1 branch.

buck_1_branch_view

Step-by-step implementation

  1. Define the variables

In src/main.cpp, in the section USER VARIABLE DECLARATIONS, add the variables below. We start the duty cycle at 0.5. The duty cycle steps are set to 0.01. A boolean will indicate the state the PWM (ON or OFF). A variable will also define the period of the control task.

//--------------USER VARIABLES DECLARATIONS----------------------

static float32_t duty_cycle = 0.5; //duty cycle (comm task)
static float32_t duty_cycle_step = 0.01; //duty cycle step (comm task)
static bool pwm_enable = false; //state of the PWM (ctrl task)
static uint32_t control_task_period = 50;  // sets the period of the control in micro-seconds

static float32_t V1_low_value; //store value of V1_low (app task)
static float32_t V2_low_value; //store value of V2_low (app task)
static float32_t Vhigh_value; //store value of Vhigh (app task)

static float32_t i1_low_value; //store value of i1_low (app task)
static float32_t i2_low_value; //store value of i2_low (app task)
static float32_t ihigh_value; //store value of ihigh (app task)

static float32_t data_value; //stores the value of the data converted by the ADC

static int8_t direction=1; //stores the direction of the waveform

  1. Configure the hardware peripherals

In src/main.cpp, in the setup_hardware() function, paste the code below. It initializes the inverter mode by setting a full bridge buck. In this example, the legs will be complementary, to set the bipolar modulation. This is done with the function hwConfig.initFullBridgeBuckMode().

void setup_hardware(){
    hwConfig.setBoardVersion(v_1_1_2);
    bool bipolar_mode = true; // declares a variable to set the modulation
    hwConfig.initFullBridgeBuckMode(bipolar_mode);  //sets the inverter as bipolar mode
    hwConfig.setNgndOff();
    hwConfig.configureAdcDefaultAllMeasurements();
    console_init();
}
  1. Configure the software scheduling

In src/main.cpp, in the function setup_software(), initialize all the scheduling functions. The data acquisition will be started here. This function also starts the control task along with the communication and application tasks.

Due to its time criticity, the control task has a precise period and with a higher priority over the others.

void setup_software()
{
    dataAcquisition.start();
    scheduling.startControlTask(loop_control_task,control_task_period);
    scheduling.startApplicationTask(loop_application_task,APPLICATION_THREAD_PRIORITY);
    scheduling.startCommunicationTask(loop_communication_task,COMMUNICATION_THREAD_PRIORITY);
}
  1. Loop communication task

In the communication task you will change the commands to update the duty cycle. You will also add a new mode to it, the INVERTERMODE.

Find the enum serial_interface_menu_mode. Add the following code to declare a new mode called INVERTERMODE.

enum serial_interface_menu_mode //LIST OF POSSIBLE MODES FOR THE OWNTECH CONVERTER
{
    IDLEMODE =0,
    SERIALMODE,
    POWERMODE,
    INVERTERMODE
};

In src/main.cpp, in the function loop_communication_task(), add the following code. This code listens to the Serial port. Depending on the character it has received, it switches between IDLEMODE, POWERMODE and INVERTERMODE.

In INVERTERMODE, it implements a gradual step change to the duty cycle that creates a triangular waveform.

void loop_communication_task()
{
    while(1) {
        received_serial_char = console_getchar();
        switch (received_serial_char) {
            case 'h':
                //----------SERIAL INTERFACE MENU-----------------------
	        printk(" ________________________________________\n");
                printk("|     Communication task Tutorial        |\n");
                printk("|     ------- MENU ---------             |\n");
                printk("|     press i : idle mode                |\n");
                printk("|     press s : serial mode              |\n");
                printk("|     press p : power mode on            |\n");
                printk("|     press u : duty cycle up by 0.01    |\n");
                printk("|     press d : duty cycle down by 0.01  |\n");
                printk("|     press v : inverter mode on         |\n");
                printk("|________________________________________|\n\n");
                //------------------------------------------------------
                break;
            case 'i':
                printk("idle mode\n");
                mode = IDLEMODE;
                break;
            case 's':
                printk("serial mode on!\n");
                mode = SERIALMODE;
                break;
            case 'p':
                printk("power mode on!\n");
                mode = POWERMODE;
                pwm_enable = true;
                break;
            case 'u':
                printk("Duty Cycle UP: %f\n", duty_cycle);
                duty_cycle = duty_cycle + duty_cycle_step;
                break;
            case 'd':
                printk("Duty Cycle DOWN: %f\n", duty_cycle);
                duty_cycle = duty_cycle - duty_cycle_step;
                break;
            case 'v':
                printk("inverter mode on!");
                mode = INVERTERMODE;
                break;
            default:
                break;

        }
    }
}
  1. Loop application task

This application task will print the value of the duty cycle.

In src/main.cpp, in the function loop_application_task(), add the following code. The IDLEMODE stops the power flow, the transmission of data and turns the LED1 off. The SERIALMODE only turns on the LED1. The POWERMODE turns the LED1 is ON and prints the values of duty_cycle on the Serial Monitor. The INVERTERMODE turns on the inverter mode with a fixed frequency.

void loop_application_task()
{
    while(1){

        if(mode==IDLEMODE) {
            hwConfig.setLedOff();
        }else if(mode==POWERMODE) {
            hwConfig.setLedOn();
        }else if(mode==INVERTERMODE) {
            hwConfig.setLedOn();
        }

        printk("%f:", V1_low_value);
        printk("%f:", V2_low_value);
        printk("%f:", i1_low_value);
        printk("%f:", i2_low_value);
        printk("%f\n", duty_cycle);


        k_msleep(100);    
    }

}
  1. Loop control task

The control task will have the purpose of turning the power conversion on or off and sending the duty cycle to the power converter.

In src/main.cpp, in the function loop_control_task(), add the following code. It states that if either the IDLEMODE or SERIALMODE are on, the power conversion stops. If POWERMODE is on, then the power conversion resumes and the duty cycle is sent to the drivers and to the power hardware. If INVERTERMODE is on, the power converter will output a triangular wave form with a fixed frequency.

void loop_control_task()
{
    data_value = dataAcquisition.getV1Low();
    if(data_value != -10000) V1_low_value = data_value;

    data_value = dataAcquisition.getV2Low();
    if(data_value != -10000) V2_low_value = data_value;

    data_value = dataAcquisition.getI1Low();
    if(data_value != -10000) i1_low_value = data_value;

    data_value = dataAcquisition.getI2Low();
    if(data_value != -10000) i2_low_value = data_value;


    if(mode==IDLEMODE) {
        pwm_enable = false;
        hwConfig.setFullBridgeBuckOff();
    }else if(mode==POWERMODE || mode==INVERTERMODE) {

        if(!pwm_enable) {
            pwm_enable = true;
            if(mode==POWERMODE) hwConfig.setInterleavedOn();
            if(mode==INVERTERMODE) hwConfig.setFullBridgeBuckOn();
        }

        if(mode==INVERTERMODE){
            if(direction < 0 && duty_cycle < 0.1) direction = 1;
            if(direction > 0 && duty_cycle > 0.9) direction = -1;
            duty_cycle = duty_cycle + direction*duty_cycle_step;
        }
       
        if(mode==POWERMODE) hwConfig.setInterleavedDutyCycle(duty_cycle);
        if(mode==INVERTERMODE) hwConfig.setFullBridgeBuckDutyCycle(duty_cycle);

    }
}
  1. Connect hardware

Now we will connect OwnTech’s O2 to the power supply and to the PC.

  • :warning: Make sure that the jumper JP4 is open.
  • Connect the USB power supply cable. The LED2 of the O2 should be ON.
  • Connect the pins Vhigh and GND of the O2 to the 40 V power supply (set its current limitation at 1 A).
  • Connect the micro-JTAG connector of the O2 to the PC thanks to the STLinkV3. The leds PWR and COM of the STLinkV3 should be ON.
  • Switch ON the power supply.

Overview_converter_connection

This image shows the connection of the power converter. Notice that the Neutral is not used and that the red and black wires are connected to the +V1Low and +V2Low.

  1. Build and Upload (build_icon+ flash_icon).
  2. In the bottom toolbar, click on the Serial Monitor icon serial_icon, select it and press the h key. Remember to click on the open button in the SerialPlot application to liberate the serial interface.

Expected outputs

  • Press the i key to switch to IDLEMODE: disables the power flow, stops printing duty_cycle and turns the LED1 OFF.
  • Press the s key to switch to SERIALMODE: disables the power flow, stops printing the duty_cycle and turns the LED1 ON.
  • Press the p key to switch to POWERMODE: enables the power flow, print duty_cycle and turns the LED1 ON.
  • Press the u key to increase the duty_cycle.
  • Press the d key to decrease the duty_cycle.
  • Press the v key to switch to INVERTERMODE: enables the triangular wave form

You can measure the output voltage thanks to an oscilloscope or a multimeter.

To go a little further

  • How would you change the frequency of the triangular waveform?
  • How would you create a sinusoidal waveform?
  • How can you create a square waveform?
  • How can you set the offset and the gain?
  • How can you close the loop and drive the single phase AC?

That’s it!

Contributors

  • 2021.11.04: Romain Delpoux, Loic Queval, Adrien Prévost
  • 2021.11.07: Luiz Villa, Antoine Boche
  • 2022.01.24: Luiz Villa, Loic Queval
  • 2022.02.01: Luiz Villa
  • 2022.03.13: Luiz Villa
  • 2022.04.19: Luiz Villa
  • 2022.06.23: Luiz Villa, Olivier Chevilley