Взято тут:
Buck-boost преобразователь с цифровым управлением на STM32F334 в режиме CC/CV
https://habr.com/ru/post/508768/


напишем простой П-регулятор:

// Текущее значение коэффициента заполнения для ШИМ-сигнала
uint16_t dutyPWM = 0;

// Задаем значение, которое нужно поддерживать на выходе
const float referenceOutputVoltage = 10.0f;

// Устанавливаем значение пропорционального коэффициента
const float Kp = 1.0f;

// Настраиваем прерывание по таймеру, например, на 1 кГц
void sTim3::handler (void) {
    float outputVoltage = GetOutputVoltage();
    float error = referenceOutputVoltage - outputVoltage;
    dutyPWM += Kp * error;
}


Собственно что тут происходит… Мы вычисляем ошибку и если реальное измеренное 
напряжение на выходе будет больше заданного, то ошибка примет отрицательное 
значение, а дальше мы ее суммируем к текущему значению заполнения ШИМ 
(dutyPWM) и в случае топологии buck это приведет к уменьшению заполнения и, 
следовательно, к уменьшению напряжения на выходе. Если же измеренное 
напряжение окажется меньше, чем заданное (reference), то ошибка примет 
положительное значение и при суммировании с dutyPWM это приведет к увеличению 
заполнения ШИМ сигнала на затворе реального транзистора и тем самым увеличит 
выходное напряжение.


Реализация ПИД-регулятора на С++
https://github.com/RedCommissary/mppt-2420-firmware/blob/master/firmware/library/dsp/Pid.h
