Унапређење #3
Аутоматско штимање PI/PID параметара.
Позадина
Примарна функција тахометра је увек била да буде основа за констуирање бољег погона за грамофон. Закључио сам да се то (боље, стабилније) може постићи једино имплементацијом затворене петље - зато што погон каишом је подложан drift-у, т.ј. флуктуацији (*) без оглед на степен стабилности који пружа идеални мотор, идеални лежај, идеални каиш (а ништа од ових није идеално).
(*) Бар три параметара коју имају утицај овде су (1) вањска температура собе, (2) комплијанса и затезање каиша, (3) унутрашња температура мотора и лежаја.
Екстерни контролер који користим је синусни генератор који генерира три фазе и има распон од 1Hz до 80Hz, са најмањим кораком од 0.01Hz. Имајући то у виду, ограничење са којим радим је (1) прецизност контролера и (2) немогућност да Ардуино прочита тренутну вредност фрекфенције.
Компромис
Ардуино "клика" тастере на екстерном контролеру и тако мења фрекфенцију синусоиде. Једина непозната вредност је "величина промене" коју један "клик" Ардуина ефектуира.
Та вредност се води у променљивој derivedQ:
float derivedQ = 0.01; // Indicates the correction in RPM derived from a single 0.01Hz step (single "click").
Што би значило да један "клик" Ардуина, који означује промену од 0.01Hz у фрекфенцији, једнако је промени од 0.01 ротацију у минути на стране грамофонског тањира. Ова вредност је била, благо речено одокативна (**) да би код прорадио.
(**) Одокативно је можда строго. Вредност је резултат мерења, споредби и прерачуна - па узета средња вредност.
Како се подвижни систем мења у зависности екстерних параметара, логично је да којефицијент промене (derivedQ) би требало да флуктуира да би увећао прецизност целог склопа.
Решење
Код већ укључује доста услова за имплементацију аутоматске калкулације овог параметра. Калкулација се почиње радити тек након регулација прође пар циклуса.
Приступ се онда своди на прерачун разлике броја ротације пре и након корекције, као и броја корака који су довели до те корекције.
derivedQ = abs(currentRPM - fixRPM) / fixSteps;
Код
Сва логика око калкулација просека се налази унутар процедури showRPM():
if (fixSteps > 1)
{
derivedQ = abs(currentRPM - fixRPM) / fixSteps;
if (derivedQ > setQ) { derivedQ = setQ; }
fixSteps = 0;
fixRPM = 0;
}
А регулира се уз помоћ пар променљива:
float fixRPM = 0, fixSteps = 0; // Variables for programmatic calculation of derivedQ.
const float setQ = 0.01;
Прве две променљиве садрже (1) стару вредност ротација и (2) број корака у том циклусу корекције. Константа setQ служи за имплементацију максималне вредности којефицијента. (***)
(***) Грешка у калкулацији, или вањски узроци могу да доведе до енормно (за овај систем) велике вредности којефицијента. Имплементација ове константе се осигурава да прерачунати којефицијент никад не пређе задану вредност.
Процедура је релативно једноставна:
Активира се само ако се уради корекција, и ако та корекција укључује бар 2 корака;
При активацији, fixRPM добија тренутну вредност ротација, а fixSteps тренутну вредност калкулираних корака (stepsX);
Након истека времена хлађења (correctionSpinCount) калкулира се нови којефицијент (разлика између старе и нове вредност ротација се дели бројем корака);
fixRPM и fixSteps се ресетирају како би били спремни за нову корекцију (ако до те корекције дође);
У случају промене брзине (33.3 према 45 и обратно) све вредности се ресетирају, и почињу се калкулирати тек након истека времена хлађења.
Такође сам допунио рутину за дебагирање да сада штампа (1) тренутну вредност ротације, (2) просечну вредност ротације, (3) тренутну вредност којефицијента корекције и (4) број слота у пољу за просеке (од 1 до averageTotal):
if (debugSerial)
{
Serial.print(currentX, 4);
Serial.print(" ");
Serial.print(currentRPM, 4);
Serial.print(" ");
Serial.print(derivedQ, 4);
Serial.print(" ");
Serial.print(averageCount);
Serial.println();
}
Резултати
Циљ је био увећавање прецизности регулације, т.ј. финија регулација:
RPM (true) RPM (average) derivedQ averageSlot
33.1941 33.1722 0.0100 9
33.1943 33.1746 0.0100 10
33.1984 33.1774 0.0100 11
33.1962 33.1799 0.0077 12
33.2046 33.1829 0.0077 13
33.2162 33.1864 0.0077 14
33.2255 33.1905 0.0077 15
33.2304 33.1952 0.0077 0
33.2343 33.1999 0.0077 1
33.2340 33.2041 0.0077 2
33.2361 33.2079 0.0077 3
33.2322 33.2110 0.0077 4
33.2328 33.2136 0.0077 5
33.2364 33.2160 0.0077 6
33.2395 33.2186 0.0087 7
33.2428 33.2217 0.0087 8
33.2520 33.2254 0.0087 9
Кључна је вредност derivedQ, као и брзина промене.
У овом примерку, derivedQ је добила прецизнију вредност од константе, а тиме и прецизнију регулацију. Број окидања игра велику улогу и брзини промене - тачно 12 окидања, односно укупно 3 пуне ротације тањира, било је довољно за две пуне калкулације derivedQ параметра.
Закључак
Циљ постигнут, сада се погон може користити са било којој комбинацији каиша и каишница без претходних мерења за фиксне параметре.
Код је, као и увек (108755f), овде:
https://github.com/stojnev/dwr-controller