ARM47 ir PID dalis #4

O dabar pašnekėsim apie STM32F4 serijos variantą ir source code. Pirmiausia- kodėl 4 serija? Todėl, kad tokia PCB pasitaikė po ranka. Ir tikrai ne dėl kažkokio mistinio FPU ar net DSP. Ir dar neaišku, ar mano turimas MCU yra originalas, o ne koks nors permarkiruotas šlamštas. Šaltinis solidus, bet kodėl jie juos išmetė? Reikia surasti kur nors panaudotą procesorių ir palyginti.

Source code yra sugeneruotas su CubeMX programa, kompiliuota su gcc. Ryšiai su kubiko paprogramėm tik per callback. Ir tai tik naudojam USB biblioteką (virtualus COM portas) ir taimerių pertraukimus. ADC skaitom blokavimo režime.

Pats PID skaičiavimas, float variantas visiškai toks pats kaip ir teoriniam variante:

float pid_generic(float measured, float setpoint, float amplif)
{
float output;
float deritative;
float error;
float proportional;
 
error = (setpoint - measured)/10;
proportional = error;
 
integral=integral + error * pid_dt;
deritative = (error - old_error) / pid_dt;
old_error = error;
 
output = (PID_KP * proportional + PID_KI * integral + PID_KD * deritative) * amplif;
 
return output;
}

Atsirado papildomas parametras “amplif” – tai bendro rezultato daugiklis, kaip ir sustiprinimas (ar susilpninimas). Teoriškai tą patį galima atlikti su pagrindiniais parametrais (P, I, D), bet taip lengviau priderinti prie “krosnelės” galingumo: kaitinimas dirba su integer skaičiais, ir PID rezultatas apsiapvalina. Taip prarandam “jautrumą”. Ir dar temperatūros parodymus pasmulkinam- tik dėl koeficientų.

uint32_t CalcTemp(void)
{
uint32_t a;
a=median_filter(adc_read_blocking(ADC_CHANNEL_4));
a=median_filter(adc_read_blocking(ADC_CHANNEL_4));
//a=median_filter(adc_read_blocking(ADC_CHANNEL_4));
// 786 - max t, 0.62V ->1655
// 3529 - kambario t, 2.83V -> 283
return (4096-a)/2; //12 bitų max apverčiam ir pašalinam LSB.
}
 

Dėl ADC blogumo, matuojam kelis kartus, invertuojam (dėl schemotechnikos išėjimas mažėja didėjant temperatūrai) ir pašalinam mažiausią bitą, nes jis rodo kvailystes. Funkcija “median filter” vogta iš interneto. Tai funkcija, kuri teoriškai turi išfiltruoti sporadiškus nukrypimus: jei eina 5, 6, 4, 3, 100 – tai tas šimtas kaip ir ne į temą. Kiek veikia per daug netikrinau. Manau, reikia dar padidinti buferį.

  1. readtemp=CalcTemp();
  2. pwm=PID(readtemp, SETTEMP);
  3. SetPWM(pwm);

O čia pats pagrindinis ciklas, kuris kartojamas sistemingai: 1 – nuskaitom, 2 – paskaičiuojam. 3 – valdom kaitinimą.

Visas likęs source kodas aptarnauja kontrolerio valdymą per terminalą (galima keisti parametrus) ir duomenų išmetimą analizei. Tai tik eksperimentinis variantas- darbiniam trūksta dar visokių apsaugų, normalaus valdymo ir indikacijos. Ir aišku, išėjimas čia PWM, kad tinkama mažam rezistoriui, bet ne tikram šildytuvui. Dar nesugalvojau, kaip padaryti korektiškai proporcinį valdymą realiai rėlei ar 50Hz simistoriniam reguliatoriui. Jei užteks kantrybės, tema bus vystoma.

Pats pilnas STM32F446 PID controller source code skirtas gcc ir kartu CubeMX projekto failas (versija užrakinta posto datai, galimi patobulinimai). Prie papildų- median filter, ftoa ir usb paprogramės. Visa mano kūryba “USER” aplanke.

7 replies on “ARM47 ir PID dalis #4”

  1. Kiek patobulintas softas: pradžioje tik P kontroleris, ir tik pasikeitus klaidos ženklui (overshot) įsijungia PID.

    PID šaldymo kompensacija

    Ten, kur viduryje grafiko pakilimas kaitinime, tai šaldžiau rezistorių su pirštais, todėl, kad kompensuoti temperatūros nukrypimus, PID kontroleris panaudojo daugiau galios.

  2. Sveiki. Vis paskaitau temas. Norejau paklausti ar bandet daryt PID per valdikliui pertraukimus ? Pats dirbu su pramoniniais valdikliais, nors kiek suprantu ten tas pat. Float irgi vengiu ir paprastinimas igi sveikuju skaiciu. Veikia gan gerai, nors plc apkrauna. Max padares ant vieno valdiklio 3 PiID. Ciklo laikas kazkur gal apie 20 ms.

  3. Edmundui- prašom patikslinti “per pertraukimus”. Nes dabar naudojamas taimerio pertraukimas, jei reikės daugiau resursų- ADC irgi per pertraukimus. Manau ir USB dirba per pertraukimus. Manau, kad šiuo metu MCU tinginiauja- 120MHz clock tikrai per daug.
    Šiuo metu perrašinėju tą patį softą į 103 versiją, jau bus su LCD ekraniuku ir panašiai. F103 lėtesnis, tai gal tada ir pažiūrėsim, kai su resursai. Aišku, jei nenusibos. Nes du omron susiremontovau 🙂

  4. Nepastebėjau. Tą patį darot, nes reikia daugmaž skaičiavimams pastoviosios laiko dedamosios. Su C kalba beveik nesusiduriu, tad skaityti kodą sunkiau. Patinka ką darot 🙂 Laukiu tolimesnių straipsnių.

  5. Paprastai didesnei sistemai ciklo laikas būna apie 10 ms. PID daręs su slėgio palaikymu ir temperatūrom. Parametrų perskaičiavimus gal kas 50 ms darydavau, bet procesai gan lėti. Daugiau problemų būdavo dėl šilumos nuostolių, nes didesni nuostoliai esant didesniai temperatūrai. Pirmą PID darydavau grubų, o paskiau privedinedavau nuo tam tikros temperatūros su kitu.

Leave a Reply

Your email address will not be published. Required fields are marked *