Forum: Mikrocontroller und Digitale Elektronik PID-Regeler Leuchtsteuerung


von Max (Gast)


Lesenswert?

Hallo zusammen!

Ich bin ein bisschen am verzweifeln. Folgendes:

Ich hab einen Lichtsensor. Und eine Lampe die per PWM angesteuert wird. 
Soweit zu gut. Die soll einen gewissen Luxwert halten.

Ich hab versucht mittels eine PID, PD, PI diese Regelung aufzubauen. Ich 
schaffe es einen fast stabile Reglung hinzubekommen. Allerdings nie mit 
der vollen Helligkeit.

Angenommen ich hab einen Luxsollwert von 300 Lux. Halte jetzt den 
Lichtsensor zu, dann schaffe ich maximal 180 (0 - 254). Eigentlich 
sollte er 254 erreichen in dem Fall.

Kp wurde so bestimmt, dass ich fast an einer schlechter werden Dämpfung 
bin. Dann habe ich versucht Ki einzustellen. Das geht allerdings nur bis 
zu einem gewissen Grad. Dann fängt das System dermaßen anzuschwingen, 
dass es nimmer lustig ist.

Vielleicht kann mir ja jemand helfen... Wäre super! ;-)

von Uhu U. (uhu)


Lesenswert?

Da wirst du dich schon etwas ausfühlicher über dein Programm verbeiten 
müssen - Hellseher sind hier leider ziemlich rar.

von BlabLa (Gast)


Lesenswert?

Hi,

also ein komilitone von mir hat im labor so nen ähnlichen versuch 
gemacht wie du den gerade vorhast. ich erinnere mich jetzt nichtmehr an 
alle einzelheiten, aber ich weiss noch das er den messwert mit einem 
p-t1 glied dämpfenb musste, weil das messsignal sehr verrauscht war um 
das system einiger massen gut regeln zu können.

hoffe das ich dir weiter geholfen habe.

Gruß
BlaBla

von Anja (Gast)


Lesenswert?

Max schrieb:
> Angenommen ich hab einen Luxsollwert von 300 Lux. Halte jetzt den
> Lichtsensor zu, dann schaffe ich maximal 180 (0 - 254). Eigentlich
> sollte er 254 erreichen in dem Fall.

Ich fürchte dein I-Anteil ist zu gering.

Im fall einer Helligkeitsregelung würde ich 2-Stufig vorgehen.
1. Steuerung des PWM-Wertes anhand von Sollwert (und ggf. 
Betriebsspannung)
   Die Steuerung sollte auch ohne Regleranteil die PWM schon auf +/- 10%
   Genauigkeit stellen.

2. Regler für Feinabgleich
   (Umgebungshelligkeit, Alterung des Leuchtmittels usw.)

Gruß Anja

von Max (Gast)


Lesenswert?

@uhuu

Ich hab versucht einen einfachen PID Regler zu realisieren. Leider 
bisher ohne erfolgt

http://www.rn-wissen.de/index.php/Regelungstechnik

@Bla

Das mit der Dämpfung ist ein sehr guter Tip. Dann schau ich mir das 
nochmal an. Denn mit einem normalen PID Regler komm ich irgendwie nicht 
weiter.
Regelungstechnik ist leider bei mir schon fast 2 Jahre ehr. Und damals 
hätte ich nicht gedacht, dass ich das nochmal so schnell brauche! ;-) 
Studenteneinbildung halt! :P

@Anja

Ja das habe ich mir auch gedacht. Deswegen hab ich ihn hochgesetzt. Und 
dann flackerte es bei direkter Rückkopplung (Sensor - Lichtquelle) noch 
stärker.


Komisch ist nur, dass wenn ich den Lichsensor direkt auf die Lampe halte 
Blinkt es nicht mehr!??! Nur wenn er horizontal bzw. in weiterer 
Entfernung zur Lichtquelle ist.

von BlabLa (Gast)


Lesenswert?

schau dir doch einfach mal das signal vom lichtsensor mal mit einem 
oszilloskop an, ich habe die vermutung das es da rauscht wie nichts 
gutes, aber das hatte ich ja schon erwähnt. aber dann hättest du ja 
zumindest mal gewissen darüber :-)

von Max (Gast)


Lesenswert?

Was ich mal gemacht habe ich, die abfallende Spannung am Lichtsensor 
gemessen. Na ja ist nicht gerade eine dünne Linie, aber extrem rauschen 
tut die jetzt nicht. Ich schau mal, dass ich heute abend mal ein Foto 
davon mache! ;-)

Kann es auch am AD Wandler liegen?! Bzw. warum kann ich nur bis zu einer 
gewissen Lichthelligkeit kontrolliert regeln?!

von Michael R. (mexman) Benutzerseite


Lesenswert?

Hallo Max,


von "...bis xxx regeln" kann man ja wohl nicht sprechen.
Da regelt nichts!
Und wenn Du bei einer Vorgabe von 300 einen Wert von 256 erreichen 
willst, ist da auch noch nichts von PID zu sehen.

Da hier keiner Deine Regler und Strecken-Eigenschaften kennt, stimmt der 
Tip schon:

Oszilliskop anschliessen, altes Regelungstechnik Skript rausholen oder 
im Netz suchen, Sprungantwort ansehen......

Kann Dir keiner abnehmen.


Gruss

Michael


(PS.: Vielleicht rennt irgendwo irgendwas an einen Anschlage.... 
Oszilloskop findet's)

von Di P. (drpepper) Benutzerseite


Lesenswert?

ich vermute einen fehler im code.
zeig den doch mal.

von Max (Gast)


Lesenswert?

@Michael Roek-ramirez
Wer ich machen!

Ist es denn richtig, dass wenn ich den Lichtsensor zu halte die Regelung 
die maximal mögliche Stellgröße anlegen müsste - also 254 in meinem 
Fall?!

@ Di Pi
Ich habe mich praktisch daran orientiere. Werde aber heute abend mal den 
Code posten. :-)

http://spurt.uni-rostock.de/lego.pdf

von Max (Gast)


Lesenswert?

1
uint16_t controlEVG (uint8_t *channel, uint16_t *sollLuxWert)
2
{
3
  static float esum = 0;
4
  static float ealt = 0;
5
  uint16_t istADCWert;
6
  float sollADCWert;
7
  float differenz;
8
  int16_t controlResult;
9
  float taInSek = (float) TA / 1000;
10
11
  //Auslesen des Istwerts
12
  istADCWert = readLightSensor(channel);
13
14
  //Umrechnung von LUX -> ADC-Wert
15
  //0 für 0 Volt und 1023 für VREF
16
  sollADCWert =  ((float) MAXADCATMAXLUX / (float) MAXLUXATMAXADC) * (*sollLuxWert);
17
18
  /* PID Regler berechnung */
19
  differenz = sollADCWert - istADCWert;                //Vergleich
20
  esum = esum + differenz;                      //Integration I-Anteil
21
  
22
  //Begrenzung des I-Anteils um einen Windup Effekt zu verhindern.
23
  if (esum < -BEGRENZUGIANTEIL) 
24
  {
25
    esum = -BEGRENZUGIANTEIL;
26
  }
27
  if (esum > BEGRENZUGIANTEIL)
28
  {
29
    esum = BEGRENZUGIANTEIL;
30
  }                    
31
  controlResult = KP * differenz +                   //PID - Reglergleichung
32
          KI * taInSek * esum + 
33
          KD/TA * (differenz - ealt);              
34
  ealt = differenz;
35
36
  if (controlResult < MINSTELLGROESSE)                //Begrenzung Stellgröße 
37
  {
38
    controlResult = MINSTELLGROESSE;
39
  }                          
40
  if (controlResult > MAXSTELLGROESSE) 
41
  {
42
    controlResult = MAXSTELLGROESSE;
43
  }
44
45
  return controlResult;
46
}

So einmal der Code

von Michael R. (mexman) Benutzerseite


Lesenswert?

>
> Ist es denn richtig, dass wenn ich den Lichtsensor zu halte die Regelung
> die maximal mögliche Stellgröße anlegen müsste - also 254 in meinem
> Fall?!


Richtig.

Gruss

Michael

von Di P. (drpepper) Benutzerseite


Lesenswert?

In der Reglergleichung teilst du Kd durch TA und nicht wie Ki durch 
taInSek.

Auf den ersten Blick sollte das zumindest das gleiche sein.

Außerdem solltest du mal das Ergebnis deines float-cast überprüfen und 
ggf. über eine alternative (hochskalierunge, Festkomma) nachdenken.

von loverboy (Gast)


Lesenswert?

kann es sein, dass du dich bei "BEGRENZUGIANTEIL" (für I-Anteil) 
verschrieben hast?
Rechtschreibmäßig vermisse ich da nämlich ein "N". Sonst klappen alle 
deine vergleich nicht, aber wahrscheinlich würde da auch dein Compiler 
meckern...
--> In dem fall: einfach ignorieren, was ich geschrieben habe ;)

von Max (Gast)


Lesenswert?

Also viel hin und ehr. Viele Versuche. Aber alles schlägt fehl. Ich bin 
echt am verzweifeln. Das Ding schwingt periodisch. Aber will nicht 
aufhören. Zu mindest bei der Helligkeit, wie ich es betreiben möchte. 
Verstehe auch nicht, dass es bis zu 190 (0 - 254) nicht schwingt.

kann mir jemand erklären, wie ich noch Einfluss auf meine "unbekannte" 
Regelstrecke mit einem Regler nehmen kann. Wie bedämpfe ich zum Beispiel 
den Lichtsensor.

LG Max

von BlabLa (Gast)


Angehängte Dateien:

Lesenswert?

Zum glätten eignet sich immer ein P-T1-Glied, womit du das Sensorsignal 
glättest. für K kannst du 1 annehmen, da du ja keine 
verstärkung/dämpfung haben willst.
Ich habs mal just for fun mal per hand eben mal ausgerechnet, hoffe du 
kannst meine schrift lesen.
Die obere Differenzengleichung sollte eigentlich genügen.
T ist die Abtastzeit und mit T1 müsstest du ein wenig rumspielen oder 
gegebenfalls mal durch simulieren.

Gruß
Blabla

ich hoffe das ich mich nicht verrechnet habe g

von BlabLa (Gast)


Lesenswert?

Was du noch machen könntest wäre das du zum Beispiel die 
Übertragungsfunktion der Regelstrecke bestimmst.

Dafür nimmst du die Sprungantwort des Systems auf und bestimmst ihre 
Parameter nach dem Verfahren wie im Link beschrieben.

Mit der Übertragungsfunktion der Regelstrecke und dem P-T1 Glied des 
Sensors könntest du dann anschliessend Die Reglerparameter nach einem 
Verfahren deiner Wahl bestimmen.

http://techni.tachemie.uni-leipzig.de/reg/rs_tn.html

von Anja (Gast)


Lesenswert?

BlabLa schrieb:
> BEGRENZUGIANTEIL

Vermutlich hatte ich doch recht mit dem zu kleinen I-Anteil (Ich meinte 
damit nicht die Regelzeitkonstante sondern den Betrag der auf den 
Ausgang wirkt).

BEGRENZUGIANTEIL muß die Möglichkeit haben bis nach 254 zu laufen.

Eine Willkürliche Begrenzung des I-Anteils als Anti-Windup ist 
normalerweise Unsinnig.
Besser ist ein Einfrieren des I-Anteils wenn der Regler an die 
Begrenzung (0 oder 254 läuft).
Damit das einfacher berechenbar ist wird auch nicht die Fehlersumme als 
I-Anteil gespeichert sondern die Summe aller  "KI  taInSek  esum"

Wenn Du das ganze analog aufbaust begrenzt Du ja auch nicht die 
Eingangsfehlersumme, sondern den Ausgang (an der Versorgungsspannung).

Gruß Anja

von Max (Gast)


Lesenswert?

Boar Leute ihr seit die Besten! ;-) Ich werde das mal ausprobieren. Hab 
jetzt 1 - 2 Tage Pause gemacht. Sonst hätte ich die Hardware aus dem 
Fenster geschmissen! ;-)

von Max (Gast)


Lesenswert?

@BlaBla

Du bist der Killer! ;-) War die richtige Lösung mit dem PT1 Glied. In 
Kombination mit dem PID Regler super Ergebnis. Anbei die Source. ggf. 
braucht das ja noch jemand! ;-)
1
uint16_t readLightSensor(uint8_t *channel)
2
{
3
    static uint8_t i = 0;
4
  static uint32_t result = 0;
5
  
6
  // Den ADC aktivieren und Teilungsfaktor auf 64 stellen
7
  ADCSRA = INITADC;
8
9
  // Kanal des Multiplexers waehlen
10
  // Interne Referenzspannung verwenden (also 2,56 V)
11
  ADMUX = REFVOLTAGE;
12
  
13
  // Den ADC initialisieren und einen sog. Dummyreadout machen
14
  ADCSRA |= (1<<ADSC);
15
  while(ADCSRA & (1<<ADSC));
16
  
17
  for(uint8_t i = 0; i < ADC_CIRCLES; i++)
18
  {
19
    ADCSRA |= (1<<ADSC);
20
    // Auf Ergebnis warten...
21
    while(ADCSRA & (1<<ADSC));
22
  
23
    result += ADCW;  
24
  }
25
  
26
  result /= ADC_CIRCLES;
27
28
  return (uint16_t) result;
29
}
30
31
uint16_t pt1GliedADC(uint8_t *channel)
32
{
33
  static float e = 0; // Ausgang
34
  float temp;
35
  float inputADC = readLightSensor(channel);  
36
37
  temp = ADC_T_T1 * (ADC_K * inputADC - e); //Rekursionsgleichung
38
  e =  e + temp;
39
40
  return (uint16_t) e;
41
}

von Max (Gast)


Lesenswert?

Ok ich will mal das Thema nochmal aufgreifen. Die Regelung funktioniert 
für einen festen Sollwert (sollLuxWert = 500). Soweit so gut. Wenn ich 
jetzt den sollLuxWert auf 50 Lux ändere, dann steuert er bei zu 
gehaltenden Lichtsensor nicht auf die geforderten 254. Dies liegt daran 
das esum in den Begrenzer läuft und Kp z.B. zu klein ist. Vergrößere ich 
die Grenzen, dann dann schwingt es bei großen Luxwerten extrem.

HILFE! :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.