mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PI-Regler (PIC) Problem mit Abtastzeit und Totzeit


Autor: Michael (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich versuche eine Regelung für eine Laserdiode zu entwickeln, bei der 
die optische Leistung geregelt wird (siehe Anhang).
Bei Temperaturschwankungen (Störgrösse) ändert sich die optische 
Leistung. Der Sollwert (w) wird über eine Spannung vorgegeben. Der 
Istwert wird über die integrierte Monitordiode gemessen und über einen 
Transimpedanzwandler ebenfalls als Spannungssignal eingelesen (x).

Der Regelalgorithmus wird über einen Timer mit Interrupt alle 1024us 
aufgerufen und der Stellwert über PWM ausgegeben, d.h. Ta=1024us. Mit 
einem Filter wird das PWM-Signal in eine DC-Spannung gewandelt.

Mithilfe der Sprungantwort (siehe Anhang) habe ich bereits versucht nach 
Ziegler/Nichols & co geeignete Parameter zu erhalten.
(Streckenparameter Ts=1.4ms, Tt=1.12ms, Kps=0.263, Kpr=2.93, Tn=5.43ms, 
Kir*Ta=0.05). Die Sprungantwort wurde direkt am PIC-Eingang gemessen 
(r(x),rückgeführtes Signal, offener Regelkreis, alle Zeitglieder 
enthalten)

#Problem 1
Beim Einschalten schwingt der Kreis zu stark oder die Anregelzeit ist zu 
lang (sollte ca. 5ms betragen).

#Problem 2
Beim Auftreten der Störgrösse (Temperaturzu- bzw. abnahme) funktioniert 
zwar die Regelung, aber nur bis zu einer gewissen Grenze (die PWM-Grenze 
von 964int ist dabei noch nicht erreicht. Das bedeutet, dass die 
Leistung bei Temperaturänderung ab einem gewissen Punkt nicht nicht mehr 
nachgeregelt wird). Das kann ich mir nicht erklären, da die Leistung 
durch den PI-Regler über das PWM-Signal komplett ausgeregelt werden 
sollte.

#Problem 3
Ich befürchte das die Regelbarkeit des Kreises schlecht ist, da die 
Abtastzeit im Verhältnis zu den Streckenparametern zu gross ist. Leider 
weiss ich nicht, wo ich den Code noch optimieren kann. Die meiste Zeit 
wird für die beiden Multiplikationen beansprucht (gemessene Zeit für 
einen Durchlauf 896us, wobei die Routine alle 1024us aufgerufen wird).

Weder mit den Parametern nach Ziegler/Nichols noch nach Prinzip der 
Stabilitätsgrenze oder Herumprobieren haben geholfen. Auch im Forum habe 
ich noch keine Lösung gefunden.

Vielleicht kann mir jemand ein paar Tipps geben?

Besten Dank.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:
> Ich befürchte das die Regelbarkeit des Kreises schlecht ist, da die
> Abtastzeit im Verhältnis zu den Streckenparametern zu gross ist. Leider
> weiss ich nicht, wo ich den Code noch optimieren kann. Die meiste Zeit
> wird für die beiden Multiplikationen beansprucht (gemessene Zeit für
> einen Durchlauf 896us, wobei die Routine alle 1024us aufgerufen wird).

Wenn ich jetzt mein über 20 Jahre altes RT Wisen versuche auszupacken, 
dann meine ich mich zu erinnern, daß deine Abtastzeit zumindest so 4-5 
mal kleiner sein sollte als deine relevanten Zeitkonstanten. Da die im 
Bereich einer Millisekunde liegen wäre eine Abtastzeit von 200µs 
angebracht.
Du schreibst von viel zeit für Multiplikation, was multiplizierst Du 
denn?

Fliesskomma?
In C?

Du solltest auf jeden Fall zu Festkomma oder integerberechnung 
übergehen, das müsste ohne zu große Probleme machbar sein, deine 
Regelgröße und dein Istwert kommen ja auch mit 8/10/16 Bit Genauigkeit 
als Integer rein.

Viel Erfolg

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier am Anfang deiner ISR hast du zb schon mal 2 Stellen, an denen du 
locker Zeit sparen kannst
void pi_sample_isr(void)
{
  output_toggle(PIN_A5);          //Test um Ta zu messen
  set_adc_channel( 1 );          //ADC-Kanal 1 auswählen
  delay_us( 10 );            //Delay für Setup               
  w = read_adc( );          //Einlesen der Spannung am Pin7 (AN0)     
  set_adc_channel( 0 );          //ADC-Kanal 0 auswählen             
  delay_us( 10 );            //Delay für Setup      
  x  = read_adc( );          //Einlesen der Spannung am Pin6 (AN1)
  e=w-x;

du musst zb nicht die Soll-Spannung bei jedem ISR Aufruf erneut 
bestimmen. Im Vergleich zum Rest ändert sich die ja so gut wie nie. Es 
reicht völlig, wenn das die Hauptschleife macht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach die Division durch 8192 erst nachdem du die Einzelterme 
zusammengezählt hast



  a/8192 + b/8192  ->  ( a + b ) / 8192

mathematisch ist das äquivalent. Aber in C mit Integer Arithmetik macht 
es unter Umständen einen großen Unterschied.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Infos.

Die Sollwertabfrage habe ich jetzt in der Hauptschleife und die Division 
nur am Ende durchgeführt. Jetzt benötigt ein Durchlauf der ISR noch 
768us. Dieser Wert variiert noch, da die zu verarbeitenden Grössen sich 
auch ändern. Deshalb darf der nächste Interrupt erst erfolgen wenn der 
vorherige abgeschlossen wurde, d.h. das Interrupt-Flag gelöscht wurde. 
Nur so bleibt die Abtastzeit konstant. Somit bleibt in meinem Fall die 
Abtastzeit (Zählerüberlauf) weiterhin auf 1024us, da der nächste 
kleinere Teiler 1:4 (=512us@8MHz) ist. Also benötige ich eine 
Durchlaufzeit <512us.



@U.R. Schmitt
Um Zeit zu sparen, habe ich bereits die Multiplikation der 
Reglergleichung als Integer programmiert, sonst dauert das noch länger.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Überleg welche deiner Variablen unbedingt long bzw. int32 sein müssen. 
Welche Operationen werden in welcher Bitbreite durchgeführt?

Wozu den Prozessor durch eine 32 Bit Multiplikation durchjagen, wenn es 
16 Bit auch tun, weil das Ergebnis sowieso nicht größer als 16 Bit 
werden kann.

(Ich habs jetzt nicht analysiert, aber das erscheint mir augenfällig)

zb

signed long w=0;
signed long x=0;
signed int32 e=0;


w kommt vom ADC, x ebenfalls.
Müssen das wirklich long sein?

  e=w-x;

  if(e>964)
    e=964;
  if(e<-964)
    e=-964;

e ist die Differenz von w und x (bei dir jetzt gerechnet als long 
Subtraktion). Braucht es für e wirklich 32 Bit? Kann w - x überhaupt 
groß genug werden um einen int zu sprengen?

Und so gehst du deine komplette Berechnung durch. Nimm Worst Case 
Zahlenwerte an und sieh nach wie gross die Ergebnisse werden.

Ich denke du kannst auf die Art mindestens 30%, wenn nicht mehr, der 
Laufzeit deiner ISR einsparen. Achte vor allen Dingen darauf, dass du 
Multiplikationen in der Bitbreite runterbringst, das bringt am meisten.

Du bist dir hoffentlich bewusst, dass

    a >> 13

und
    a / 8192

nicht dasselbe machen, wenn a eine negative Zahl ist?

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

die Geschichte mit den Datentypen ist schon ziemlich heikel wenn man 
nicht aufpasst. Ich bin da auch schon öfter in die Falle getappt.

Also ich hab mir das folgendermassen gedacht:
w=x=signed long, da ADC mit 10bit arbeitet
(bei CCS-Compiler: long=int16=16 bit)

e kann auch negativ werden, deshalb signed
e=w-x deshalb w,x auch signed

Pwert=Kpr*e: da ich eine float Berechnung vermeiden möchte, aber 
Kpr=2.93 ist, muss ich 2.93 umwandeln:
293  2^13   2400256      24002 (die letzten beiden Stellen streichen)
---* ---- = ------- -->  -----
100  2^13   819200       8192

also muss ich e mit 24002 multiplizieren und wenn e=964max dann brauche 
ich int32 (32bit). Darum müssen doch auch alle anderen Variablen vom 
gleichen Datentyp sein? Sonst erhält man ein falsches Ergebnis (hab ich 
mit dem Simulator getestet).

Alternativ könnte ich auch Pwert=Kpr*(int32)e rechnen (cast), aber das 
bringt wohl auch keinen Vorteil?

##############################################################

Schiebeoperation bei negativen Zahlen:

Da bin ich gestern auch schon darüber gestolpert. Ich glaube ich kann 
das so abfangen:

  y=Pwert+Isum;

  if(y&0x80000000)
  {
    y>>=13;
    y|=0xFFF80000;
  }
  else
  {
    y>>=13;
  }

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann caste es doch zum shiften in unsigned!

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> Dann caste es doch zum shiften in unsigned!

Sorry das war wohl Blödsinn.
@ Karl Heinz:
Warum ist
    a >> 13

und
    a / 8192

nicht das selbe? Meine C Kenntnisse sind in den letzten Jahren etwas 
eingerostet, aber macht >> nicht bei signed Variablen ein arithmetischen 
Shift, also zieht bei negativen Zahlen Einsen nach?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:

> nicht das selbe? Meine C Kenntnisse sind in den letzten Jahren etwas
> eingerostet, aber macht >> nicht bei signed Variablen ein arithmetischen
> Shift, also zieht bei negativen Zahlen Einsen nach?

Was >> bei signed Werten macht, ist überhaupt nicht definiert. Damit 
fängt es schon mal an :-)

Und selbst wenn es das von dir vorgeschlagene tut (was sehr 
wahrscheinlich ist), kommt immer noch nicht dasselbe raus.
Probiers einfach aus:

-9 / 4    ergibt -2     das sollte soweit klar sein

-9 ist binär

    00001001    +9
    11110110    invertiert
    11110111    2-er Komplement

Binär ist also -9 gleich 0b11110111
das jetzt um 2 Stellen nach rechts geschoben   0b11111101
Das ist welche Zahl

   11111101    Muster
   00000010    invertiert
   00000011    2-er Komplement

0b11 ist 3, d.h. 0b11111101  war -3

Huch  -9 / 4 ergibt -3? Das .... stimmt wohl nicht ganz

Division schneiden konzeptionell Kommastellen ab, runden also zur 0 hin. 
Shift Operationen 'runden' aber immer zur nächst kleineren Zahl. Daher 
kommt bei negativen Zahlen was anderes raus

   -2.3   in Richtung 0 gerundet  ist nun mal -2
   -2.3   zur nächst kleineren Zahl gerundet ergibt aber -3

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:

> 293  2^13   2400256      24002 (die letzten beiden Stellen streichen)
> ---* ---- = ------- -->  -----
> 100  2^13   819200       8192

Hast du mal in der Simulation ausprobiert, was passiert wenn du anstelle 
von *24002 / 8192 einfach *24 / 8 rechnest?

Du hast es hier ja mit einem PI Regler zu tun. Seine Aufgabe ist es ein 
e auf 0 zu bringen. Und ob er da jetzt mit einem Stellwert um 1 oder 2 
größer oder kleiner gegensteuert, spielt doch bei großen Fehlern nicht 
so sehr die große Rolle.

Ich könnte mir auch einen Hybrid-Ansatz vorstellen. Bei großen 
Fehlerwerten e rechnet der PI Regler zwar schnell aber etwas ungenauer 
(*24/8) und wenn e kleiner wird (vorzugsweise dann, wenn die Berechnung 
dann wieder komplett in 16 Bit passt) wird sukzessive wieder in Richtung 
*24002/8192 zurückgeschaltet.

> ich int32 (32bit). Darum müssen doch auch alle anderen Variablen vom
> gleichen Datentyp sein?

Dazu muss e immer noch nicht 32 Bit sein.
Du kannst e ja als 16 Bit berechnen und nur zur Multiplikation auf 32 
Bit hochcasten.

> Sonst erhält man ein falsches Ergebnis (hab ich
> mit dem Simulator getestet).

Logisch. Wenn du mathematisch ein 32 Bit Ergebnis erhältst aber nur mit 
16 Bit multiplizerst, hast du einen Überlauf und damit ein falsches 
Ergebnis

> Alternativ könnte ich auch Pwert=Kpr*(int32)e rechnen (cast), aber das
> bringt wohl auch keinen Vorteil?

Ein bischen was würde es schon bringen. Die vorhergehende Subtraktion 
ist dann nicht mehr 32 Bit sondern nur noch 16 Bit


Aber über so einen Hybrid Ansatz: ungenau aber schnell bei großen 
Fehlern und bei kleinem Fehler sukzessive auf genauere Berechnung 
umschalten. Ich denke das könnte in der Laufzeit schon einiges bringen.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Division schneiden konzeptionell Kommastellen ab, runden also zur 0 hin.
> Shift Operationen 'runden' aber immer zur nächst kleineren Zahl.

Mist das hab ich Blödmann übersehen.
Dürfte aber bei dem Algorithmus nicht ins Gewicht fallen.
Aber das das Verhalten von '>>' bei negativen Zahlen nicht spezifiziert 
ist wusste ich nicht (mehr?)
Programmiere in den letzten 5 Jahren praktisch ausschliesslich in Java, 
dort ist es spezifiziert und es gibt sogar ein arithmetisches und ein 
binäres SHR, wobei ich mir nie merken kann welches jetzt welches ist.
Aber in den Anwendungen die ich machen muss ist Bitschieberei eher die 
Aussahme :-)

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Hast du mal in der Simulation ausprobiert, was passiert wenn du anstelle
> von *24002 / 8192 einfach *24 / 8 rechnest?

Es ist eh ziemlich unsinnig die Parameter mit einer Genauigkeit von 13 
Bit rechnen zu wollen. Er hat sie wenn ich das recht sehe grafisch 
bestimmt, also nicht genauer als sagen wir 2%, das wären 6 Bit. Seine 
Messwerte sind mit einem 10 Bit Wandler, wobei die Genauigkeit auch 
nicht mehr als 8 Bit sein dürften.
Und am wichtigsten. Seine Abtastzeit ist so groß wie die wesentlichen 
Zeitkonstanten der Regelstrecke, das bedeutet, wenn er einen Stellwert 
anlegt, ist der im Extramfall bis zum nächsten Abtasten schon komplett 
falsch, weil das System inzwischen seinen Ausgangswert schon um relativ 
die Hälfte geändert hat.
Also sollte es vollkommen reichen mit 8Bit zu Rechnen.
Egal wie aber er sollte mit der Abtastfrequenz auf zumindest 0,25 ms 
runterkommen.
Gruß

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
U.R. Schmitt schrieb:
> reichen mit 8Bit zu Rechnen.

Sorry meine natürlich mit 8 Bit Werten. Daraus folgt die Ergebnisse in 
16 Bit.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, vielleicht reichen 8 bit für den ADC auch aus. Ich werde das mal 
testen. Die Berechnung muss auf jedenfall kürzer werden.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe versucht, das Ganze mit 8bit zu realisieren, aber da ergibt 
sich für mich ein Problem:

w-Wert einlesen (w=unsigned int=8bit,ADC=8bit), Wertebereich: 0..0xFF 
o.k.
x-Wert einlesen (x=unsigned int=8bit,ADC=8bit), Wertebereich: 0..0xFF 
o.k.
e=w-x?
Wenn ich auch negative Werte zulassen möchte(muss), welchen Datentyp 
nehme ich dann für e?

e=signed int --> Wertebereich -127..+128, dann kann |w-x| nur <128 sein

e=signed long(16bit) -->Wertebereich -32768<=e<=32767 <-- würde das mit 
einem cast funktionieren? Wenn ja wie?
e=(???)w-(???)x;


Die Berechnung der P-,I- und D-Anteile habe ich vereinfacht und komplett 
auf "rationale Beiwerte" verzichtet, d.h.:
...
Pwert=e<<2; //Pwert=4*e, 2 bit schieben nach links
if(e<0)
  Pwert|=0x0003; //2 bit rechts jetzt 0 --> mit 1 maskieren
Iwert=e>>1; //Iwert=0.5*e, 1 bit schieben nach rechts
if(e<0)
  Iwert|=0x8000; //MSB mit 1 maskieren
...
usw.

Das geht auf jeden Fall schneller und ich kann jetzt die ISR konstant 
nach 256us aufrufen. Nachteilig ist, dass ich so nur Werte von 2^x 
verwenden kann.
Die Berechnung wie vorgeschlagen hat irgendwie nicht richtig 
funktioniert, ich weiss nicht warum aber der uP hat nicht das 
ausgegeben, was ich erwartet habe (entweder maximale Leistung oder 0).

Noch eine regelungstechnische Frage:
Die aufgenommene Sprungantwort der Laserdiode entspricht ja der 
optischen Antwort auf den Eingangssprung--> deshalb die kurzen 
Streckenzeiten ~1ms.
Aber: Die Diode ist in einem Gehäuse eingebaut und dieses erwärmt sich 
durch den Betrieb der Laserdiode - nur eben viel langsamer. Und durch 
die Erwärmung nimmt die optische Leistung (=Istgrösse) bei konstantem 
Strom ab.
Muss man da nicht quasi eine Störsprungantwort aufnehmen? Diese hätte 
nämlich deutlich grössere Zeitkonstanten.
Dann wäre e=w-x (w=konstant, x=f(z), Stichwort Festwertregler)
Irgendwie hab ich da gerade das Problem mit dem Ei und der Henne... :-)

Vielen Dank.

Gruss Michael

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:
> Hallo,
>
> ich habe versucht, das Ganze mit 8bit zu realisieren, aber da ergibt
> sich für mich ein Problem:
>
> w-Wert einlesen (w=unsigned int=8bit,ADC=8bit), Wertebereich: 0..0xFF
> o.k.
> x-Wert einlesen (x=unsigned int=8bit,ADC=8bit), Wertebereich: 0..0xFF
> o.k.
> e=w-x?
> Wenn ich auch negative Werte zulassen möchte(muss), welchen Datentyp
> nehme ich dann für e?

Falsche Fragestellung

Ist mir auch früher schon mal aufgefallen, dass du anscheinend der 
Ansicht bist, dass der Datentyp des Ergebnisses sich irgendwie auf die 
Berechnung auswirkt.
Dem ist nicht so!

zuerst musst du dich fragen:
wenn ich
  w - x
rechne, wie mach ich das, dass ich das richtige Ergebnis bekomme, selbst 
wenn w und x uint8_t sind.

Dazu musst du beide Werte zunächst nach int16_t bringen.

   (int16_t)w - int16_t(x)

welchen Wertebereich kann das haben?

Das Ergebnis kann von -255 bis +255 gehen (w gleich 255, x gleich 0; 
bzw. umgekehrt). Und damit ist als Datentyp für e ein int8_t schon aus 
dem Rennen.
e muss ein int16_t sein.

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
....ZA
Ist mir auch früher schon mal aufgefallen, dass du anscheinend der
Ansicht bist, dass der Datentyp des Ergebnisses sich irgendwie auf die
Berechnung auswirkt.
Dem ist nicht so!
....ZE

Vielleicht konnte ich mich nicht richtig verständlich machen. Meiner 
Meinung nach wird eine Berechnung in int als Ergebnis ebenfals int 
haben, also 8 bit. Dieses Ergebnis möchte ich einer Variablen vom typ 
long (16bit) zuweisen, wegen der negativen Werte. Und das geht so nicht, 
da das High-Byte des Ergebnisses mit 0 gefüllt ist. Also muss ich wie Du 
gerade schriebst einen cast anwenden, der das 8bit Ergebnis auf 16bit 
wandelt.
Ist das soweit richtig?

Ich habe es mittlerweile so gemacht, das ich w<x abgefragt habe und das 
Ergebnis mit 0xFF00 maskiert habe. Funktioniert auch. Aber Deine 
Variante ist sicher eleganter.

(int16_t)w - int16_t(x) <-- ist die Schreibweise wirklich so?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael schrieb:

> Vielleicht konnte ich mich nicht richtig verständlich machen. Meiner
> Meinung nach wird eine Berechnung in int als Ergebnis ebenfals int
> haben, also 8 bit.

Du scheinst einen seltsamen Compiler zu benutzen.

int hat 8 Bit
long hat 16 Bit

mit long in 16 Bit kann ich noch leben, aber ein int mit 8 Bit ist vom 
C-Standard her überhaupt nicht gedeckt. int hat mindestens 16 Bit.
Ausser natürlich dein Compiler kocht sein eigenes Nicht-Standard 
Süppchen.

> da das High-Byte des Ergebnisses mit 0 gefüllt ist. Also muss ich wie Du
> gerade schriebst einen cast anwenden, der das 8bit Ergebnis auf 16bit
> wandelt.
> Ist das soweit richtig?

No.
Du darfst schon gar kein 8-Bit Ergebnis haben. Denn 8 Bit reichen nicht 
um jedes mögliche Ergebnis aufnehmen zu können. Es ist völlig wurscht ob 
du dann im Nachhinein das Ergebnis von 8 auf 16 Bit aufbläst. Da ist das 
Kind schon in den Brunnen gefallen. Die Berechnung selber darf nicht in 
8 Bit gemacht werden.

>
> Ich habe es mittlerweile so gemacht, das ich w<x abgefragt habe und das
> Ergebnis mit 0xFF00 maskiert habe. Funktioniert auch.

Glaub ich nicht.
nagative Zahlen funktionieren anders. Stichwort 2-er Komplement.

> (int16_t)w - int16_t(x) <-- ist die Schreibweise wirklich so?

Schreibfehler

  (int16_t)w - (int16_t)x

Ein Cast reicht auch. Der andere Teilnehmer an der Operation wird dann 
vom Compiler implizit auf int16_t gecastet.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Michael:
Vieleicht postest Du deinen jetzigen Code nochmal als Anhang mit rein.

Autor: Michael (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier nochmal der C-code. Es läuft zwar aber irgendwie passt da was noch 
nicht. Ich bin noch am Testen und melde mich morgen nochmal.

Besten Dank

Gruss Michael

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da hat sich noch ein Fehler eingeschlichen..
y=(unsigned int)Pwert+Isum; //falsch

y=Pwert+Isum; //richtig

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert die Regelung jetzt besser?
Gib mal ein bischen Feedback.
Gruß

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der momentane Stand ist so, dass sich ein stabiler Wert der 
Laserleistung einstellt. Die Schwankungen (springen) des Istwertes sind 
durch Verwendung des 8bit ADC auch geringer geworden.
Aber das Regelverhalten bei Auftreten der Störgrösse (Temperatur) ist 
immer noch unbefriedigend. D.h. Wird die Laserdiode von aussen erwärmt, 
so nimmt die Laserleistung erst ab und dann steigt sie über den Sollwert 
hinaus (bis zu 20% je nach Temperatur). Beim Kühlen entsprechend 
umgekehrt. Also der Regler arbeitet schon, aber erstens langsam und 
zweitens viel zu starke Gegenkopplung.

Als Einstellmöglichkeit habe ich die Verstärkung des rückgeführten 
Istwertes(Monitorstrom), und die Parameter des Reglers Kpr und Kir (und 
den Sollwert).

e=(w-x) x: Verstärkung des Monitorsignals (stromproportionale Spannung, 
x=Umon=Rv*Imon; w=Usoll)

Ist Rv zu klein, so ist auch das ausgegebene Stellsignal zu klein und 
die Leistung nimmt bei Erwärmung ab, obwohl das PWM-Signal grösser wird.
(PWM-Signal nimmt zu wenig zu)

Ist Rv zu gross so ist so ist das ausgegebene Stellsignal zu gross und 
die Leistung steigt bei Erwärmung an, das PWM Signal wird ebenfalls 
grösser.
(PWM-Signal nimmt weiterhin zu, obwohl es kleiner werden müsste). Bei zu 
grossem Rv schwingt die Regelung.

Bei 100% Laserdiode (30mW) habe ich eine Sollspannung von 1.99V und eine 
Monitorspannung von 2.97V. Müssten nicht beide Signale so skaliert 
werden, dass sie gleich gross sind?

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn aber beide Signale gleich skaliert sind, sind ja beide auch gleich 
gross, da Laserstrom und Monitorstrom proportional sind. Das würde 
bedeuten, das bei einem P-Regler die Regelabweichung 0 wäre und das 
Stellsignal auch (y=Kpr*e). Aber das kann nicht sein, da der P-Regler 
eine bleibende Regelabweichung benötigt. Das System würde sonst nur 
schwingen.

Ein häufig diskutiertes Thema hier im Forum...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.