PV 1 MPPT - owntech-foundation/Tutorials GitHub Wiki
Objectives
The goal of this tutorial is to use the O2 to track the maximum power point of production of a PV module. We will implement a PID controller that tracks a voltage which is updated by the MPPT algorithm. We will start from the Buck 3 tutorial.
Required hardware
- O2
v_1_1_2
- STLinkV3
- PC (windows or linux)
- power supply (40 V, 2 A)
Required software
- SerialPlot
Create the project
- We will create the project by copying the Buck 3 tutorial in a new branch, that will be called battery_1. In the bottom menu, click on the 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 replace this message)"
git branch PV_1
git checkout PV_1
- On the bottom menu, check that you are now in the
PV_1
branch.
Step-by-step implementation
- Define the variables
In src/main.cpp
, in the section USER VARIABLE DECLARATIONS
, add variables that contain the power calculated on the current cycle, on the previous cycle, the voltage step and the sign of the change. Change the voltage reference to match the PV panel used with the O2 board. Keep all the previous variables.
//--------------USER VARIABLES DECLARATIONS----------------------
static float32_t voltage_reference = 33; //voltage reference (app task)
static float32_t power_now = 0; //current reference (app task)
static float32_t power_before = 0; //current reference (app task)
static float32_t disturb_sign = 1; //boolean for the constant current mode (app task)
- Configure the hardware peripherals
In src/main.cpp
, in the setup_hardware()
function, do not modify anything.
- Configure the software scheduling
In src/main.cpp
, in the setup_software()
function, do not modify anything.
- Loop communication task
In the communication task you will change the commands to enable the battery charge. To do so you will create a new mode called MPPTMODE
.
Find the enum serial_interface_menu_mode
. Add the following code to declare a new mode called MPPTMODE.
enum serial_interface_menu_mode //LIST OF POSSIBLE MODES FOR THE OWNTECH CONVERTER
{
IDLEMODE =0,
SERIALMODE,
POWERMODE,
MPPTMODE,
};
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 MPPTMODE.
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 m : mppt 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 'm':
printk("MPPT mode on!\n");
mode = MPPTMODE;
break;
default:
break;
}
}
}
- Define the application task
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. In MPPTMODE
, the value of the voltage_reference
will change depending on the power difference between iterations.
void loop_application_task()
{
while(1){
if(mode==IDLEMODE) {
hwConfig.setLedOff();
}else if(mode==SERIALMODE) {
hwConfig.setLedOn();
}else if(mode==POWERMODE) {
hwConfig.setLedOn();
}else if(mode==MPPTMODE) {
hwConfig.setLedOn();
power_now = V1_low_value * (i1_low_value+i2_low_value);
if (power_now>power_before){
MPPT_step_sign = MPPT_step_sign;
}
else
{
MPPT_step_sign = -MPPT_step_sign;
}
voltage_reference = voltage_reference + MPPT_step_sign*MPPT_step;
power_before = power_now;
printk("%f:", power_before);
}
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:", i2_low_value);
printk("%f:", voltage_reference);
printk("%f\n", power_now);
}
scheduling.suspendCurrentTaskMs(100);
}
}
- Loop control task
In src/main.cpp
, in the function loop_control_task()
, add the following code. In CHARGEMODE
, the PID tracks the voltage_reference
or the current_reference
depending on the charge mode.
void loop_control_task()
{
meas_data = dataAcquisition.getVHigh();
if(meas_data!=-10000) Vhigh_value = meas_data;
meas_data = dataAcquisition.getV1Low();
if(meas_data!=-10000) V1_low_value = meas_data;
meas_data = dataAcquisition.getV2Low();
if(meas_data!=-10000) V2_low_value= meas_data;
meas_data = dataAcquisition.getIHigh();
if(meas_data!=-10000) ihigh_value = meas_data;
meas_data = dataAcquisition.getI1Low();
if(meas_data!=-10000) i1_low_value = meas_data;
meas_data = dataAcquisition.getI2Low();
if(meas_data!=-10000) i2_low_value = meas_data;
if(mode==IDLEMODE || mode==SERIALMODE) {
pwm_enable = false;
hwConfig.setInterleavedOff();
}else if(mode==POWERMODE || mode==MPPTMODE)) {
if(!pwm_enable) {
pwm_enable = true;
hwConfig.setInterleavedOn();
}
if(mode==BUCKMODE) duty_cycle = opalib_control_interleaved_pid_calculation(voltage_reference, V1_low_value);
if(mode==MPPPTMODE) opalib_control_interleaved_pid_calculation(voltage_reference, V1_low_value);
//Sends the PWM to the switches
hwConfig.setInterleavedDutyCycle(duty_cycle);
}
}
- 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 the 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.
- Build and Upload (+ ).
Expected outputs
- Press
i
to switch toIDLEMODE
: stop printing measurement and turns the LED1 OFF. - Press
p
to switch toPOWERMODE
: print measurements and turns the LED1 ON. - Press
m
to switch toMPPTMODE
: maintains a constant current of 1A below 14V and keeps the voltage at 14V. - Press
u
to increase theduty_cycle
. - Press
d
to decrease theduty_cycle
.
SerialPlot 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.
- In SerialPlot, choose the STLinkV3 and set the baud to 115200. Click on Open button. When you open the serial port data will start to flow in the screen.
:warning: The Port might have a different name depending on your operating system.
- In SerialPlot, in the Data Format tab, choose the setup shown below.
- In SerialPlot, in the Plot tab, choose the setup shown below.
- In SerialPlot, in the Commands tab, choose the setup shown below.
- When you send the
m
command the output should track the maximum available power of the PV module.
- In SerialPlot, click on the send button corresponding to the
i
command. The LED1 will turn OFF.
That’s it!
Contributors
- 2022.03.13: Luiz Villa
- 2023.03.07: Luiz Villa and Noemi Lanciotti