Lämpötilaohjattu askelmoottori

Eipä tahdo tuo PID oikein aueta. Siis netissä on koodeja vaikka millä määrin mitä voisi kopioida ja muokata ja käyttää omassa projektissa, mutta mieluusti purkaisi myös koodin auki ja täten tietäisi mitä tehdä.

Lueskellut monta webbisivua, muttä tämä tähän mennessä aukaissut asiaa eniten:

inpharmix.com/jps/PID_Contro … obots.html

Vaatii melkoisen hurjasti opiskelua… :slight_smile:


Tuomo

Olen ollut samassa tilanteessa. Itse opiskelin. Simppeli asia ja kaikki esittävät sen vaikeasti.

Suurin piirtein näin voit sitä ajatella:

virhe* P on P osa
(virhe + virheiden summa ) * I on I osa
(edellinen virhe - virhe ) * D on D osa
P + I - D on sitten ohjaus.

Tuo oikoi hiukan.
Aikasemmin mainitsemani PID ilman PHD:tä on myös hyvää kamaa. Kokeile lukea ajatuksella läpi.

Itse visualisoin tämän homman nukku.net/vuokko/PID-controller.avi videon pätkäksi. videon kululla ei ole merkitystä. Itse olen tuota ihmetellyt lähes aina editorissa ja miettinyt yksittäisten framejen eroavaisuuksia. Ylhäällä menee kertoimet ja ohjaus vaikuttaa suoraan sisääntuloon ja aluksi hyppää nollasta ykköseen säätö. Noh kai se on itsestään selkeä kuvaus.

Joop…

Kyllä sitä ihminen itsensä tyhmäks tuntee… Mulla kai jossai alitajunnassa joky psyykkinen blokki että en vaan saa tota PID hommaa aukeemaan…

Kaikkia ohjeita ja juttuja mitä netissä lukenu ni joo, niistä ymmärtää täysin jo sen mitä mikäkin osanen tekee (P, I, D), mutta siihen se jääkin. Ohjeet netissä on hyviä, ei oo annettu valmiita koodeja ja laitetaan lukija miettimään, mutta ei näimmä sovi mulle.

Tuo Vuokon heittämä Pid w/o PHD on kyllä hyvä ja hyvin selitetty, mut meikä tippuu matkasta jo ensimmäisen koodiesimerkin kohdilla, karkeistettuna näin:

double UpdatePID(SPid * pid, double error, double position) { . . . }

Miten voin kuvitella omaa caseani tohon kun oon sitä PID käskyä opettelemassa, niin enhän mä voi sijottaa sitä pid:ä tohon lausekkeeseen ku en tiedä vielä siittä mitään… :astonished:

Saa flamee luvalla…


Tuomo

Aloin päätä seinään hakkaamalla ratkoa ongelmaa niin, että otin toimivan tasapainottelurobotin koodin toiseen ruutuun auki ja aloin päivittämään omaa ohjelmaani… No… Ohjelmassa ei ainakaan virheitä ole, mutta ei se kyllä oikein toimikkaan…

Mihin mun pitäs tota PIDiä oikein käyttää? No helppo vastaus: tasottamaan moottorin liikettä, no mites?

Käytänkö PID lausekkeessa ulkolämpötilaa, patteriverkon veden lämpötilaa, servon asentoa, haluttua lämpötilaa tietylle ulkolämpötilalle vai pitääkö erikseen lisätä vielä jokin potikka tuohon servon kaveriksi joka kertoo asentoa?

Mistä mä keksin kP, kI ja kD arvot? entä servon mistä tekasen sen arvon jolla säädetään?

Hohhoijaa…

No tässä viritys jonka tein:

[code]#include <Servo.h>

Servo shuntti;

int ulkoMittaus = 0;
int vesiMittaus = 0;
int asento;
double ulkolampoYHT = 0;
double vesilampoYHT = 0;
int ulkolampoKA = 0;
int vesilampoKA = 0;
int EDvesilampoKA = 0;

int EDasento = 0;

int ulkoanturi = A0;
int vesianturi = A1;
int vikaled = 13;
int powerled =12;

//PIDiä varten
float time = 0;

float P = 0;
float I = 0;
float D = 0;

float kP = 10;
float kI = 0;
float kD = 0;

void setup()
{
pinMode(vikaled, OUTPUT);
pinMode(ulkoanturi, INPUT);
pinMode(vesianturi, INPUT);
shuntti.attach(9);
Serial.begin(9600);
}

void mittaus()
{
digitalWrite(12, HIGH);
for (int toisto=0; toisto < 600; toisto++)
{
ulkoMittaus = analogRead(ulkoanturi);
double ulkolampo = ulkoMittaus * (4950.00 / 1024); // 4720 on mitattu jännite anturin nastoista, eli 4.72V
ulkolampoYHT = ulkolampoYHT + ulkolampo;
delay(20);
vesiMittaus = analogRead(vesianturi);
double vesilampo = vesiMittaus *(4950.00 / 1024);
vesilampoYHT = vesilampoYHT + vesilampo;
delay(20);
}
}
void KAlaskenta(){
ulkolampoKA = ulkolampoYHT / 10 / 600; // ensimmäinen jako muuttaa asteiksi, toinen jako laskee keskiarvon
vesilampoKA = vesilampoYHT / 10 / 600;
if (ulkolampoKA > 45){
digitalWrite(13, HIGH); // vikavalo syttyy jos lämpötilamittaus totaalisen pielessä / anturia ei tunnisteta
ulkolampoKA = 0;
}
}

void loop(){
mittaus();
KAlaskenta();

float previousTime = time;
time = millis();
float interval = time - previousTime;
P = vesilampoKA / kP;
I = I + (P * interval) / kI;
D = (vesilampoKA - EDvesilampoKA) / interval / kD;
float PID = P + I + D;

shuntti.write(100 - PID); //tänne laitettu arvoksi vaan rannetta ravistamalla 100, ei perustu mihinkään

Serial.print("TEMP: "); 
Serial.print(ulkolampoKA);
Serial.println("c");
Serial.print("TEMP_v: ");
Serial.print(vesilampoKA);
Serial.println("c");

Serial.print("P: ");
Serial.println(P);
Serial.print("I: ");
Serial.println(I);
Serial.print("D: ");
Serial.println(D);
Serial.print("interval: ");
Serial.println(interval);
Serial.print("Servon asento: ");
Serial.println(asento);
Serial.print("PID: ");
Serial.println(PID);
Serial.println("");
Serial.println("");
ulkolampoYHT = 0;
vesilampoYHT = 0;
ulkolampoKA = 0;
vesilampoKA = 0;
EDvesilampoKA = vesilampoKA;

}

[/code]


Tuomo

Oliskos jotai sähköventtiiliä tuollaisen “normaalin” palloventtiilin tilalle… eli semmoisen kahvalla käännettävän venttiilin sijaan, olis tarkoitus laittaa ohitus pikkuvaraajalle niin olis kätevää jos sen sais automaattisesti ohjattua jos lämpötila isommassa varaaajassa on riittävä?