Inverter mode open loop - owntech-foundation/Tutorials GitHub Wiki

Objective

The goal of this tutorial is to build the base open-loop block of an DC-AC conversion.

Twist on inverter mode

This figure shows how the inverter is set from the TWIST board.

image

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

Required hardware

  • TWIST v_1_1_2 or later
  • PC 64-bits (windows or linux)
  • DC power supply (48 V, 2 A)
  • Resistive load
  • Oscilloscope or multimeter

Required software

  • Git
  • Visual Studio Code with PlatformIO (see Blinky tutorial)
  • OwnPlot (see SerialPlot tutorial)

Create the project

  1. We save our progress by committing our work.

  2. In the side menu, click on the Source Control button, which will open a new menu.

source_control_button

You can see that the only changes on your code are located at the 'main.cpp' file. We are going to commit these changes as to keep track of our progress.

  1. Click on the + button on the right side of the main.cpp file to "stage" the changes. You can add a comment to explain what these changes are useful for. It is good practice to describe your changes when you commit them in git. Click on the + Commit button. Your work has now been committed. We can come back to it later if necessary.

staged_changes_buck_3_tutorial

Staged changes for the buck-3 tutorial

Step-by-step implementation

  1. Define the variables

In src/main.cpp, in the section USER VARIABLE DECLARATIONS, add the direction variable below. It will be used to create the sine wave.

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

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(TWIST_v_1_1_2);
    hwConfig.initFullBridgeBuckModeCenterAligned(bipolar);
    hwConfig.setNgndOff();
    dataAcquisition.enableTwistDefaultChannels();
    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()
{
    application_task_number = scheduling.defineAsynchronousTask(loop_application_task);
    communication_task_number = scheduling.defineAsynchronousTask(loop_communication_task);
    scheduling.defineUninterruptibleSynchronousTask(&loop_control_task,control_task_period);

    scheduling.startAsynchronousTask(application_task_number);
    scheduling.startAsynchronousTask(communication_task_number);
    scheduling.startUninterruptibleSynchronousTask();
}
  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()
{
    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 all the variables of the system.

In src/main.cpp, in the function loop_application_task(), add the following code. The IDLEMODE stops the power flow and turns the LED1 off. The POWERMODE turns the LED1 is ON and activates the manual duty cycle mode. The INVERTERMODE turns on the inverter mode with a fixed frequency and toggles the LED.

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


    printk("%f:", duty_cycle);
    printk("%f:", Vhigh_value);
    printk("%f:", V1_low_value);
    printk("%f:", V2_low_value);
    printk("%f:", ihigh_value);
    printk("%f:", i1_low_value);
    printk("%f\n", i2_low_value);
    
    scheduling.suspendCurrentTaskMs(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 block.

In src/main.cpp, in the function loop_control_task(), add the following code. It states that if the IDLEMODE is on, the power conversion stops. If POWERMODE is on, then the power conversion resumes, the duty cycle can be set by hand and is sent to power hardware. If INVERTERMODE is on, the power converter will output a sine wave form with a fixed frequency.

void loop_control_task()
{
    meas_data = dataAcquisition.getLatest(V_HIGH);
    if(meas_data!=NO_VALUE) Vhigh_value = meas_data;

    meas_data = dataAcquisition.getLatest(V1_LOW);
    if(meas_data!=NO_VALUE) V1_low_value = meas_data;

    meas_data = dataAcquisition.getLatest(V2_LOW);
    if(meas_data!=NO_VALUE) V2_low_value= meas_data;

    meas_data = dataAcquisition.getLatest(I_HIGH);
    if(meas_data!=NO_VALUE) ihigh_value = meas_data;

    meas_data = dataAcquisition.getLatest(I1_LOW);
    if(meas_data!=NO_VALUE) i1_low_value = meas_data;

    meas_data = dataAcquisition.getLatest(I2_LOW);
    if(meas_data!=NO_VALUE) i2_low_value = meas_data;

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

        if(!pwm_enable) {
            pwm_enable = true;
            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;
        }
       
        hwConfig.setFullBridgeBuckDutyCycle(duty_cycle);
    }
}
  1. Connect hardware

Now we will connect your TWIST board to the power supply and to the PC via the STLink.

  • Connect the pins Vhigh and GND of the TWIST to the DC power supply (set its current limitation at 1 A).
  • Connect the pins VLow1, Vlow2 and GND of the TWIST to a resistive load.
  • Connect the micro-JTAG connector of the SPIN to the PC thanks to the STLinkV3.
  • Switch ON the DC power supply. Choose a voltage between 0 and 48 V.

Twist_inverter_circuit_v1

  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. Press the p button, you should see some data show on the terminal:

data_upload

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 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 sine wave form

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

OwnPlot Visualization

  1. First kill the Serial Monitor by clicking on the trash button on the right hand side of the window as shown in the image below.

Kill serial monitor

  1. Launch OwnPlot. In Port tab, choose the STLinkV3. Click on the Closed button to open the port.

:warning: The Port might have a different name depending on your operating system.

open_port_running

  1. In OwnPlot, Settings tab, set the # of channels to 7.

ownplot_settings_buck-2

  1. In OwnPlot, in the Chart tab, change the same of the datasets as shown below:

ownplot_chart_buck-2

  1. In OwnPlot, in the Send tab, add the commands below by typing the command name and its associated character.

ownplot_send_inverter-1

  1. When you click on the Inverter button the converter will output a sine wave form.

ownplot_counter_up_down

  1. In OwnPlot, click on the Idle button corresponding to the i command to switch to IDLEMODE and turn the LED1 OFF.

That’s it!

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