Доброго!
Имею проблемы с построением правильного алгоритма работы функции.
Устройство представляет собой регулятор мощности. Вводные данные: Замер мощности производиться с помощью PZEM 004t. Регулировка при помощи двух “переменных резисторов”, в функции они именуются StepMajor - грубая регулировка, и StepMinor - точная. Значения от 255 до 0, чем меньше значение, тем выше мощность на выходе.
Сейчас наговнокодил так - Допустим, нужная мощность 100. при включении устройства StepMajor = 255, StepMinor=128 т.е. один на минимуме, второй посередине. Плавно снижаю StepMajor, пока мощность не приблизиться к нужной, подгоняю ± и дальше вторым, StepMinor уже поддерживаю нужную цифру. В целом норм. Вот только проблемы начинаются если захочу в процессе изменить мощность, например на 20. Пока я так-же как и при старте скидываю значения и снова подгоняю к нужной мощности. Не нравится.
Если изменить на 1 ватт, то и двигать ничего не надо, само отрегулируется StepMinor. Если на 20 то уже надо StepMajor двигать. Плюс есть большая зависимость от подключенного устройства - если лампа накаливания на 100 ватт, то разброс довольно большой, шаги регулировки мелкие. Если ТЭН на киловатт, то уже и шаги резкие. Хочу универсальности. Так-же PZEMка имеет небольшую инертность, при регулировке могу скакать вверх и вниз, пока она отреагирует правильно. Что, соответственно влияет на время.
Могу всё описать IF-ELSE, добавить массив констант под разные мощности, но получиться портянка говнокода. Может кто поделиться правильными мыслями в подходе.
// Значения на входе функции:
// power - текущая мощность от PZEM
// npower - значения необходимой мощности
// Значения на выходе функции:
// StepMajor - Значение грубой регулировки 0..255 (меньше - выше мощность)
// StepMinor - Значение плавной регулировки 0..255
if (PowerAdjust){ // Режим грубой настройки
(power == 0 ? Temp = 1 : Temp = 3); // Пока мощность на 0 читаем по 1 разу, потом суммируем из трёх замеров
PowerCalc += power;
if (Step++ >= Temp){
PowerCalc /= Temp;
int16_t calcPower = PowerCalc - npower;
int16_t newCount = StepMajor;
if (calcPower <= -30) { // в зависимости от различия нужной и текущей мощности изменяем количество ступеней
newCount-=10;
} else if (calcPower <= -10){
newCount-=2;
} else if (calcPower <= -5){
newCount-=1;
} else if (calcPower <= -1){
newCount-=1;
down = true;
} else if (calcPower == 0){
PowerAdjust = false; // мощность совпала - выходим
} else if (calcPower >= 30){
newCount+=10;
} else if (calcPower >= 10){
newCount+=2;
} else if (calcPower >= 5){
newCount+=1;
} else if (calcPower >= 1){
newCount+=1;
up = true;
}
if (newCount < 0){
newCount = 0;
} else if (newCount > 255) {
newCount = 255;
}
StepMajor = newCount;
if (up && down) { PowerAdjust = false; } // если и вверх и вниз двигали, то переходим к плавной подгонке
Step = 1;
PowerCalc = 0;
}
if (!PowerAdjust){
up = false;
down = false;
PowerCalc = 0;
Step = 1;
}
} else { // Режим плавной регулировки, поддержания
PowerCalc += power;
if (Step++ == 3){
PowerCalc /= 3;
int16_t calcPower = PowerCalc - npower;
int16_t newCount = StepMinor;
if (calcPower <= -10) {
newCount-=10;
} else if (calcPower <= -5){
newCount-=3;
} else if (calcPower <= -2){
newCount-=1;
} else if (calcPower >= 10){
newCount+=10;
} else if (calcPower >= 5){
newCount+=3;
} else if (calcPower >= 2){
newCount+=1;
}
if (newCount < 0){
newCount = 128;
StepMajor--;
} else if (newCount > 255) {
newCount = 128;
StepMajor++;
}
Step = 1;
PowerCalc = 0;
StepMinor = newCount;
}
}