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.
This figure shows how the inverter is set from the TWIST board.

This figure shows the bi-polar modulation used in this example
Required hardware
- TWIST
v_1_1_2or 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
-
We save our progress by committing our work.
-
In the side menu, click on the Source Control button, which will open a new menu.

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.
- Click on the
+button on the right side of themain.cppfile 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+ Commitbutton. Your work has now been committed. We can come back to it later if necessary.

Staged changes for the
buck-3tutorial
Step-by-step implementation
- 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
- 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();
}
- 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();
}
- 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;
}
}
- 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);
}
- 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);
}
}
- 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.

-
Build and Upload (
+
). -
In the bottom toolbar, click on the Serial Monitor icon
. Select it and press the hkey. Press thepbutton, you should see some data show on the terminal:

Expected outputs
- Press the
ikey to switch to IDLEMODE: disables the power flow, stops printingduty_cycleand turns the LED1 OFF. - Press the
pkey to switch to POWERMODE: enables the power flow, printduty_cycleand turns the LED1 ON. - Press the
ukey to increase theduty_cycle. - Press the
dkey to decrease theduty_cycle. - Press the
vkey to switch to INVERTERMODE: enables the sine wave form
You can measure the output voltage thanks to an oscilloscope or a multimeter.
OwnPlot Visualization
- 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.

- Launch OwnPlot. In Port tab, choose the STLinkV3. Click on the
Closedbutton to open the port.
:warning: The Port might have a different name depending on your operating system.

- In OwnPlot, Settings tab, set the
# of channelsto 7.

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

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

- When you click on the
Inverterbutton the converter will output a sine wave form.

- In OwnPlot, click on the
Idlebutton corresponding to theicommand 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