Open loop PWM - owntech-foundation/Tutorials GitHub Wiki
Objective
The goal of this tutorial is to lower the power using a duty cycle. We will use our TWIST as a buck converter in an open-loop to divide our voltage by 2.
Background
-
What is a PWM ? In our case, PWM is used to control the converter voltage. The principle is to create a logic signal (0 or 1), raising or lowering the voltage. The average value of this signal corresponds to the voltage we want to obtain.
-
What is a duty cycle ? The cyclic time is the ratio between the active state and the period the system is closed or open. It is the mathematical tool of PWM. The average of its duty cycle gives the voltage value. In many fields, like electrical engineering, duty cycles are important to provide power efficiently and effectively for a specific situation. Many applications of motors, physical electronics, and even music use something called pulse width modulation or PWM to control the duty cycle and the necessary applied power (which can be referred to as input voltage or current). The duty factor plays a key role in representing the ratio of on time and off time for a given power supply.
-
Deadtime It corresponds to the inactive time between the activation or deactivation of a switch or PWM cycle change.
The deadtime can be of multiple formats, as shown in the image below.(https://microchipdeveloper.com/pwr3101:pwm-edge-center-aligned-modes). The length of the deadtime in either the rising or falling edges depends on the application.
Required hardware
- TWIST
v_1_3
or higher - PC 64-bits (windows or linux)
- DC power supply (48 V, 2 A)
- Resistive load
- Oscilloscope or multimeter
Required software
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.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.
Step-by-step implementation
- Define the variables
In src/main.cpp
, in the section USER VARIABLE DECLARATIONS
, add the variables below.
The initial duty cycle is 0.5. The duty cycle steps are set to 0.05. A boolean indicates the state of 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.05; //[-] duty cycle step (comm task)
static bool pwm_enable = false; //[bool] state of the PWM (ctrl task)
static uint32_t control_task_period = 50; //[us] period of the control task
- Configure the hardware peripherals and the software scheduling
In src/main.cpp
, in the setup_routine()
function, paste the code below. It initializes the buck mode. The Twist converter has two legs which can be operated independently or interleaved. In this example, the legs will be interleaved, which means both will share the total current flowing through the power converter. Both legs are set to work on buck mode. This is done with the function initAllBuck()
. It also starts the control task, the communication task and the application task. Due to its time criticality, the control task has a precise period and not a priority as the others.
void setup_routine(){
console_init();
// Setup the hardware first
spin.version.setBoardVersion(SPIN_v_1_0);
// Buck mode initialization
twist.setVersion(shield_TWIST_V1_3);
twist.initAllBuck();
// Then declare tasks
uint32_t app_task_number = task.createBackground(loop_application_task);
uint32_t comm_task_number = task.createBackground(loop_communication_task);
task.createCritical(loop_critical_task, 500); // Uncomment if you use the critical task
// Finally, start tasks
task.startBackground(app_task_number);
task.startBackground(comm_task_number);
task.startCritical(); // Uncomment if you use the critical task
}
- Loop communication task
In the communication task, in comparison to the OwnPlot tutorial, we change the commands to update the duty cycle
instead of the counter
variable. We also add a new mode, called POWERMODE
.
In src/main.cpp
, in the list enum serial_interface_menu_mode
, declare a new mode called POWERMODE.
enum serial_interface_menu_mode //LIST OF POSSIBLE MODES FOR THE OWNTECH CONVERTER
{
IDLEMODE =0,
SERIALMODE,
POWERMODE
};
In src/main.cpp
, in the function loop_communication_task()
, paste the following code. This code listens to the serial port. Depending on the character it has received, it switches between IDLEMODE, SERIAL and POWERMODE. In POWERMODE, the PWM is enabled thus activating the power conversion.
void loop_communication_task()
{
received_serial_char = console_getchar();
switch (received_serial_char) {
case 'h':
//----------SERIAL INTERFACE MENU-----------------------
printk(" ________________________________________\n");
printk("| ------- MENU --------- |\n");
printk("| press i : idle mode |\n");
printk("| press s : serial mode |\n");
printk("| press p : power mode |\n");
printk("| press u : duty cycle UP |\n");
printk("| press d : duty cycle DOWN |\n");
printk("|________________________________________|\n\n");
//------------------------------------------------------
break;
case 'i':
printk("idle mode\n");
mode = IDLEMODE;
break;
case 's':
printk("serial mode\n");
mode = SERIALMODE;
break;
case 'p':
printk("power mode\n");
mode = POWERMODE;
break;
case 'u':
printk("duty cycle UP: %f\n", duty_cycle);
duty_cycle = duty_cycle + duty_cycle_step;
if(duty_cycle>1.0) duty_cycle = 1.0;
break;
case 'd':
printk("duty cycle DOWN: %f\n", duty_cycle);
duty_cycle = duty_cycle - duty_cycle_step;
if(duty_cycle<0.0) duty_cycle = 0.0;
break;
default:
break;
}
}
- Loop application task
The application task will print the value of duty cycle
.
In src/main.cpp
, in the function loop_application_task()
, paste 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.
void loop_application_task()
{
if(mode==IDLEMODE) {
spin.led.turnOff();
}else if(mode==SERIALMODE || mode==POWERMODE) {
spin.led.turnOn();
printk("%f \n", duty_cycle);
}
task.suspendBackgroundMs(100);
}
- Loop critical task
The critical task will turn on/off the power conversion and send the duty cycle to the TWIST power block.
In src/main.cpp
, in the function loop_control_task()
, paste 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.
void loop_critical_task()
{
if(mode==IDLEMODE || mode==SERIALMODE)
{
pwm_enable = false;
twist.stopAll();
}
else if(mode==POWERMODE)
{
if(!pwm_enable) {
pwm_enable = true;
twist.startAll();
}
//Sends the PWM to the switches
twist.setAllDutyCycle(duty_cycle);
}
}
- Connect hardware
Now we will connect your TWIST board to the power supply and to the PC via the USBC cable.
- Connect the pins Vhigh and GND of the TWIST to the DC power supply (set its current limitation at 1A).
- 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
h
key. Press thep
key, you should see the current value ofduty cycle
on the Serial Monitor. Remember to click on theopen
button in OwnPlot to liberate the serial interface.
Expected outputs
- Press the
i
key to switch to IDLEMODE: disables the power conversion, stops printingduty_cycle
and turns the LED1 OFF. - Press the
s
key to switch to SERIALMODE: disables the power conversion, prints theduty_cycle
and turns the LED1 ON. - Press the
p
key to switch to POWERMODE: enables the power conversion, printsduty_cycle
and turns the LED1 ON. - Press the
u
key to increase theduty_cycle
. - Press the
d
key to decrease theduty_cycle
.
You can measure the DC output voltage thanks to an oscilloscope or a multimeter.
That’s it!
Contributors
- 2024.02.25: Luiz Villa, Ayoub Farah
- 2021.11.04: Romain Delpoux, Loïc Quéval, Adrien Prévost
- 2021.11.07: Luiz Villa, Antoine Boche
- 2022.01.24: Luiz Villa, Loïc Quéval
- 2022.02.01: Luiz Villa
- 2022.03.13: Luiz Villa
- 2022.06.23: Loïc Quéval
- 2023.07.10: Luiz Villa
- 2023.10.09: Mathilde Longuet