Battery 1 charge control - owntech-foundation/Tutorials GitHub Wiki

Objectives

The goal of this tutorial is to use the O2 to charge a lead-acid battery. We will implement a PID controller that tracks a reference current or voltage, according to a CC-CV charge 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

  1. 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 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 branch battery_1
git checkout battery_1
  1. On the bottom menu, check that you are now in the buck branch.

step1

Step-by-step implementation

  1. Define the variables

In src/main.cpp, in the section USER VARIABLE DECLARATIONS, add the current reference, change the voltage reference, add a constant current mode boolean and a constant voltage mode boolean. Keep all the previous variables.

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

static float32_t voltage_reference = 14; //voltage reference (app task)

static float32_t current_reference = 1; //current reference (app task)
static bool cc_mode = false; //boolean for the constant current mode (app task)
static bool cv_mode = false; //boolean for the constant voltage mode (app task)

  1. Configure the hardware peripherals

In src/main.cpp, in the setup_hardware() function, do not modify anything.

  1. Configure the software scheduling

In src/main.cpp, in the setup_software() function, do not modify anything.

  1. 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 CHARGEMODE.

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

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

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 CHARGEMODE.

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 c : battery charge 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 'c':
                printk("Battery charge mode on!\n");
                mode = CHARGEMODE;
                break;
            default:
                break;

        }
    }
}
  1. 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 CHARGEMODE, the value of the current_reference will change depending on the battery voltage. Above a certain threshold, the converter will go from current to voltage mode.

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==CHARGEMODE) {
            hwConfig.setLedOn();
            if(Vhigh_value<voltage_reference){
                cc_mode = true;
                cv_mode = false;
            }else{
                cc_mode = false;
                cv_mode = true;
            }
        }

        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);

                
        k_msleep(100);    
    }
}
  1. 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==CHARGEMODE) {


        if(!pwm_enable) {
            pwm_enable = true;
            hwConfig.setInterleavedOn();
        }

        if(mode==CHARGEMODE) {
            if(cc_mode) duty_cycle = opalib_control_interleaved_pid_calculation(current_reference, i1_low_value+i2_low_value);
            if(cv_mode) duty_cycle = opalib_control_interleaved_pid_calculation(voltage_reference, V1_low_value);
        }

        //Sends the PWM to the switches
	hwConfig.setInterleavedDutyCycle(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 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.

step6

  1. Build and Upload (build_icon+ flash_icon).

Expected outputs

  • Press i to switch to IDLEMODE: stop printing measurement and turns the LED1 OFF.
  • Press p to switch to POWERMODE: print measurements and turns the LED1 ON.
  • Press b to switch to CHARGEMODE: maintains a constant current of 1A below 14V and keeps the voltage at 14V.
  • Press u to increase the duty_cycle.
  • Press d to decrease the duty_cycle.

SerialPlot 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. 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.

serialPlot Open connection

  1. In SerialPlot, in the Data Format tab, choose the setup shown below.

Data Format setup

  1. In SerialPlot, in the Plot tab, choose the setup shown below.

plot_tab

  1. In SerialPlot, in the Commands tab, choose the setup shown below.

command_123

  1. When you send the c command the output should track a current for 1 A for voltages lower than 14V or maintain a fixed voltage of 14V.

overview_serialPlot

  1. 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