Close

Characterizing the Buck Converter

A project log for Solar MPPT Charger for 24/7 "IOT" devices

An inexpensive charge controller and 2A 5V power supply designed to supply remote power for devices ranging from Arduino to Pi 3 class.

dan-julioDan Julio 11/03/2018 at 20:400 Comments

First up, the latest revision.  Small changes from the last version including tightening up various current loops in the buck converter and moving the battery-side transient TVS diode to the anode side of the reverse-polarity protection diode to reduce the transient generated when the battery is reverse connected before the fuse blows.  Looks like a good candidate for production but some more testing to finish.  New schematic in the repository.

One measurement available through the I2C interface is an estimated battery charge current (IC).  It is also used as part of a calculation to determine when the Absorption charge phase is finished and the charger should move to Float charge (battery charge current falls off).  It is estimated instead of measured because unlike all other paths in the charger where current flows one way, current can flow into or out of the battery and it would take a more complex (and expensive) circuit to measure a bi-directional current than the TI INA180 current amplifiers I am using.

The calculation is straightforward but requires an estimate of the buck converter efficiency.

EstimateBuckOutputCurrent = MeasuredSolarInputCurrent * (BUCK_INPUT_V / BUCK_OUTPUT_V) * BuckEfficiency

BatteryChargeCurrent = EstimateBuckOutputCurrent - MeasuredLoadCurrent

I had done some measurements with an early prototype and found an efficiency of about 90% at a mid-range current so I hardcoded this into the calculation.  However the buck efficiency is dependent on the power level and falls off very quickly for low power levels making the calculation inaccurate.  I finally got around to characterizing it more fully which resulted in the addition of a fast piece-wise lookup table in the code translating solar power (VS * IS) into an efficiency value for the calculation.  I hacked the firmware so the buck converter regulated on the output voltage (VB) instead of attempting to hold the input voltage (VS).  Then made a series of measurements (efficiency vs. input power) for five sets of conditions (varying VS between 15V, 18V and 21V and VB between 13.65 for float and 14.7 for bulk/absorption).  As expected the converter is most efficient when the difference between input and output voltage is the smallest and reaches 90% efficiency at about 5 watts.  Peak efficiency reaches 93-94% at between 10-20 watts.  Not bad for an asynchronous converter.

To make the efficiency table, I played around unsuccessfully for a bit with curve fitting before giving up and just hand-picking points that represented reasonable piece-wise values in a graph of all the measurements.  I centered the values around the VS=18V curve since that was the middle measurement and hopefully where an MPPT charger will spend time.  The highlighted graph are my hand-picked values.  The X-axis is solar power (W) and Y-axis converter efficiency (%).

The code is then pretty easy and efficient on an 8-bit micro.

//-----------------------------------------------------------------------------
// Efficiency lookup table - efficiency (percent) as a function of input power (mW)
//   determined via hardware measurement
//-----------------------------------------------------------------------------

#define BUCK_NUM_EFF_ENTRIES 22
code const uint16_t buckEffPowerPoints[BUCK_NUM_EFF_ENTRIES] = {
    250, 375, 500, 750, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000, 3250, 3500, 4000, 5000, 6000, 7500, 11500, 25000, 35000
};

code const uint8_t buffEffValues[BUCK_NUM_EFF_ENTRIES] = {
    5662677175,   77,   78,   80,   81,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,    93,    92
};


uint8_t BUCK_GetEfficiency(uint16_t ps)
{
    uint8_t i = 0;

    // Find the efficiency value for the first power point immediately
    // above the current solar power input
    while (i < (BUCK_NUM_EFF_ENTRIES-1)) {
        if (ps < buckEffPowerPoints[i]) {
            break;
        }
        i++;
    }

    return(buffEffValues[i]);
}

Another recent change is to change the buck converter PWM from 8-bit to 10-bit.  This slightly slows its response time (since it takes longer to make big changes) but significantly reduces the MPPT P&O algorithm jitter because a single count change in buck PWM has a smaller effect on the solar input voltage.  I have an arduino with LCD as a text fixture displaying all the measurements as fast as it can and the jitter in VS, IS and IC are all much smaller.

Discussions