Forum: Mikrocontroller und Digitale Elektronik PI-Regelung bleibt hängen...


von Stefan G. (Gast)


Lesenswert?

Hallo,
ich bin nachwievor dabei meinen PI Regler zu programmieren. So richtig 
funktioniert´s jedoch leider immer noch nicht, und ich frage mich ob es 
an meinen aus der Sprungantwort der Strecke errechneten Parametern 
liegt, oder ob noch ein Fehler im Programm steckt.Nochmal kurz zur 
Problematik:
ich möchte einen konstanten Luftstrom regeln. Ich gebe also einen 
Sollfluss vor (bzw. eine Sollspannung die einem Sollfluss entspricht). 
Abhängig davon verändere ich die Pulsbreite, mit der ich mein Ventil 
ansteuere. Am Flussensor messe ich den Ist-Fluss bzw. die Ist-Spannung. 
Egal was für einen Sollwert ich für meinen Luftfluss einstelle, der 
Ist-Wert pendelt sich immer bei ca. 3,3 Volt ein.
Da ich leider alleine davor sitze und keinen anderen Ansprechpartner 
habe, stelle ich die Frage nochmal hier ins Forum, mit der Bitte sich 
mal den in der ISR befindlichen Regelalgorithmus anzusehen. Vielleicht 
seht ihr ja einen Fehler.

#include <mega323.h>

// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>


#define ADC_VREF_TYPE 0x00
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSR|=0x40;
// Wait for the AD conversion to complete
while ((ADCSR & 0x10)==0);
ADCSR|=0x10;
return ADCW;
}

float v_ist;
float e_k;    // Regeldifferenz
float e_k_alt;
float k_p = 1.446;  // Verstärkungsfaktor
float t_i = 0.007343;  // Verzugszeit
float t_0 = 0.017708;  // Abtastzeit
float u_k;        // Stellgröße
float u_k_alt;
int v_soll;
int stell;


// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
  // aktuelle Spannung berechnen:
  v_ist = (5.0/1023)*read_adc(0);

  // Regelabweichung e_k berechnen:
   e_k = v_soll - v_ist;

    // Stellgröße u_k berechnen:
     u_k = u_k_alt + k_p*(e_k*(1+t_0/t_i)-e_k_alt);

      // Stellgrößenbegrenzung:
       if (u_k > 5.0) u_k = 5.0;
       else if (u_k < 0.0) u_k = 0.0;

       // Stellgröße in entsprechenden PWM Wert umrechnen:
       stell = (int) (u_k*255/5.0);

       // Pulsbreite setzen:
       OCR0 = stell;

       u_k_alt = u_k;
       e_k_alt = e_k;
}


void main(void)
{


// Input/Output Ports initialization
// Port A initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In 
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T 
State7=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func0=In Func1=In Func2=In Func3=Out Func4=In Func5=In Func6=In 
Func7=In
// State0=T State1=T State2=T State3=1 State4=T State5=T State6=T 
State7=T
PORTB=0x08;
DDRB=0x08;

// Port C initialization
// Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out 
Func7=Out
// State0=1 State1=1 State2=1 State3=1 State4=1 State5=1 State6=1 
State7=1
PORTC=0xFF;
DDRC=0xFF;

// Port D initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In 
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T 
State7=T
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 460,800 kHz
// Mode: Phase correct PWM top=FFh
// OC0 output: Non-Inverted PWM
TCCR0=0x62;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: TCCR2=0x07: 3600 Hz  -> t_0 = 1/(3600/255) = 70.83 ms
//    TCCR2=0x06; 14400 Hz -> t_0 = 1/(14400/255) = 17,708 ms
//    TCCR2=0x05; 28800 Hz -> t_0 = 1/(28800/255) = 8,85 ms
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
GICR|=0x00;
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 115200
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 115,200 kHz
// ADC Voltage Reference: AREF pin
ADMUX=ADC_VREF_TYPE;
ADCSR=0x85;

// Global enable interrupts
#asm("sei")


// Sollspannung über Terminal einlesen:
v_soll = (int) getchar()-48;

// Timer loslaufen lassen:
TCCR2=0x06;
}

von Stefan G. (Gast)


Lesenswert?

eine Idee kam mir da noch gerade:
könnte es Probleme geben, daß die Abarbeitung der Befehle so lange 
dauert, daß zwischendurch bereits wieder ein Interrupt aufgerufen wird? 
Obwohl doch eigentlich alle Interrupts während der Abarbeitung gesperrt 
sind, oder? Was würde denn in so einem Fall passieren?
Und wie könnte man die Zeit herausfinden, die die Ausführung der ISR 
braucht? Ich habe schonmal in den AVRStudio Debugger nachgesehen und 
wollte anhand der Anzahl der Maschinenbefehle zurückrechnen, jedoch sehe 
ich in dem Wirrwarr garnicht wo nun meine ISR anfängt und wo sie wieder 
aufhört.

Nochmal zu meiner Hard/ Software:

ATmega323
AVRStudio

Gruß,
Stefan

von Sascha Rother (Gast)


Lesenswert?

Hallo Stefan!

Ich sehe gerade, dass du v_soll einen int-Wert zuweist, der über die 
Konsole reinkommt. In deiner ISR rechnest du aber mit einem 
float-Bereich von 0-5V. Ich bin nicht 100% sicher, aber das passt glaube 
ich nicht ganz zusammen und muss als erstes korrigiert werden.
Dann würde ich folgendermaßen vorgehen:

Als erstes würde ich die Regelroutine komplett auskommentieren und 
zunächst mal den Sollwert, den du über die Konsole sendest als 
Stellgröße für die PWM benutzen, D.h. du setzt OCR0=v_soll*255/5.0. So 
kannst du zunächst testen, ob 1. deine Konsolensteuerung funktioniert 
und 2. die PWM am Ventil das macht, was sie soll. Mit den eingegeben 
Werten müsste sich das Ventil dann von 0-100% steuern lassen. Wenn das 
funktioniert, hast du deine I/O-Ebene getestet.

Erst jetzt würde ich dann die Regelung mit hinzu nehmen, wobei du 
zunächst nur eine P-Regelung realisierst:

u_k = u_k_alt + k_p*e_k

Gib z.B. 2,5 als v_soll ein, die Regelung müsste sich dann auf einen 
Wert einstellen. Falls das System schwingen sollte, ist dein k_p zu 
groß. Ist das System bei diesem Wert stabil, wähle als v_soll z.B. 4. 
Das Ventil muss dann auf jeden Fall weiter öffnen. Reißt das Ventil ganz 
auf, so ist k_p zu groß. Läßt sich kaum eine Änderung am Ventil 
feststellen, ist dein k_p zu klein.

Erst wenn du diese Schritte hinter dir hast, und das Ventil reagiert 
einigermaßen auf dein v_soll, würde ich den I-Anteil dazu nehmen.

Halte mich ruhig auf dem Laufenden, mich interessiert es sehr.

Gruß, Sascha

von Sascha Rother (Gast)


Lesenswert?

Moment, statt u_k = u_k_alt + k_p*e_k muss es

u_k = k_p*e_k

heißen, sonst würdest du bei jedem Aufruf der ISR den alten Wert 
hinzuaddieren. Langsam frage ich mich, ob deine PI-Realisierung 
überhaupt stimmt...

von Stefan G. (Gast)


Lesenswert?

Hallo Sascha,
das mit int und float habe ich erstmal behoben, ich dachte das würde 
nichts ausmachen, aber ist vielleicht doch besser. Ich denke auch, daß 
der Summand u_k_alt bei der PI Realisierung falsch ist. Ich habe ihn nun 
weggelassen, da ich auch in RT Büchern nichts derartiges gefunden habe. 
Du schriebst, ich sollte erstmal testen ob/ wie die I/O Ebene funzt. Das 
habe ich gemacht und bin auf folgendes Problem gestoßen: Beim 
kontinuierlichen Erhöhen der Pulsbreite (von 0 angefangen) tut sich sehr 
lange garnichts. Bei einer Pulsbreite von ca. 58% "springt" das Ventil 
plötzlich auf (zwischen 58 und 60%). Für ein Proportionalventil ist das 
natürlich ein sehr merkwürdiges Verhalten, da könnte ich ja gleich ein 
herkömmliches Schaltventil nehmen. Ich werde mich deshalb morgen nochmal 
mit dem Hersteller in Verbindung setzen, da ich so gerde keinen Sinn 
sehe weiter rumzuexperimentieren. Ich werde dich auf dem laufenden 
halten.
Bis dann,
Stefan

von Harald Hermenau (Gast)


Lesenswert?

Ohne auf die Theorie rückgreifen zu wollen,
würde ich vorschlagen, den Regelalgorithmus
wie folgt zu gestalten:
Da durch den timer-Interrupt mit einer konstanten
Abtastzeit gearbeitet wird, braucht diese im
Regelalgorithmus nicht mehr berücksichtigt werden.
Im Endeffekt berücksichtigt der Faktor ki das Verhältnis
von Regelzeitkonstante und Abtastzeit.

  e_k = v_soll - v_ist;

// für PI Regler in P-Regler und I-Regler trennen
// P-Regler
  u_p = e_k * kp;  // Regelabweichung * Proportionalfaktor

// I-Regler
  u_i = u_i + e_k * ki;  // Regelabweichung * Nachstellzeit

  u_k = u_i + u_p;

Eine andere Sache sind die Datenformate. Bei 8Bit
Prozessoren auf jeden Fall auf Fließkomma verzichten.
Das kostet nur zuviel Rechenzeit. Das ist wahrscheinlich
der Grund warum der PI Regler nicht funktioniert.
Am sinnvollsten ist es, alle Größen auf 8Bit bzw.
16Bit Werte zu normieren um dadurch nur mit ganzen Zahlen
rechnen zu können.
Die meiste Arbeit besteht jetzt im normieren und begrenzen
der Zahlenwerte.

von Stefan G. (Gast)


Lesenswert?

Hallo Harald,
danke für deine Tipps, ich werde mich jetzt mal ranmachen und meinen 
Code etwas modifizieren. Die Problematik mit den floats ist mir auch 
schon aufgefallen, wußte jedoch noch nicht genau wie ich das so gut 
umrechnen soll, da ja die Regelparameter ki und kp nunmal kommabehaftete 
Zahlen sind...

Bei deiner Gleichung für den I-Regler: entspricht das u_i nach dem 
Gleichheitszeichen dem u_i_alt (also dem aus dem vorherigen Durchlauf)? 
Dann würde es also lauten
   u_i = u_i_alt + e_k * ki  ?

Gruß,
Stefan

von Stefan G. (Gast)


Lesenswert?

Hallo,
ich habe jetzt nochmal so einiges an meinem Programm gemacht:
1) erstmal nur einen P-Regler realisiert
2) von float auf int umgestellt
3) 10 bit PWM (und nachwievor 10 bit ADC).
Gedacht habe ich mir das nun wie folgt:
Zuerst wird der Sollwert eingelesen. Das mache ich, indem ich einen 
String über den Terminal einlese. 1023 entspricht dabei einer 
Flussmessersollspannung von 5 Volt.
Dann starte ich den Timer, wenn der überläuft wird regelmäßig die 
Spannung meines Flussmessers A/D gewandelt, ich habe dann einen Wert 
zwischen 0 und 1023. Nun kann ich die Regelabweichung e_k errechnen. Mit 
diesem Wert wird dann direkt (noch mit dem Faktor k_p) die Pulsbreite 
gesteuert. Bei der größtmöglichen Regelabweichung wird dann 1023 in das 
OCR1A Register geschrieben, was dann einer Pulsbreite von 100% 
entspräche. Soweit die Theorie.
So wie ich mir das gedacht habe, funktioniert das jedoch leider noch 
nicht. Immerhin bekomme ich schonmal unterschiedliche Ist-Werte für 
verschiedene Sollwerte, aber immernoch eine ziemliche Regelabweichung.
Ich habe da auch schon zwei mögliche Fehlerquellen im Kopf, weiß jedoch 
noch nicht genau wie ich sie beheben könnte.
A) Ich bin mir, da ich jetzt auch nicht mehr mit floats, sondern 
"normierten" ints rechne nicht mehr sicher wie ich den Faktor k_p 
gewichten / bestimmen soll.
B) Wenn das Ventil geschlossen ist, es also keinen Fluss gibt, gibt mir 
der Flussmesser eine Spannung von 1 Volt (und nicht 0 Volt!!!) aus. Das 
müßte ja eigentlich meinen ganzen Regelalgorithmus ziemlich 
durcheinander bringen. Ich weiß nur nicht genau, wie ich diesen "offset" 
ausgleichen könnte. Habt ihr eine Idee?
Ich hänge unten nochmal meinen Programmcode an.
Vielen dank im voraus,
Stefan

#include <mega323.h>

// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>


#define ADC_VREF_TYPE 0x00
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSR|=0x40;
// Wait for the AD conversion to complete
while ((ADCSR & 0x10)==0);
ADCSR|=0x10;
return ADCW;
}

int v_ist;
int e_k;    // Regeldifferenz
int e_k_alt;
int k_p =296;     // entspricht 1.446 (ermittelt aus Sprungantwort) 
Verstärkungsfaktor normiert
      // 1023*1,446/5 Volt = 296
int u_p;        // Stellgröße
int u_p_alt;
int v_soll;
int stell;
char wert[4];


// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{


  // aktuelle Spannung einlesen (Wert zwischen 0 und   1023):
  v_ist = read_adc(0);


  // Regelabweichung e_k berechnen:
   e_k = v_soll - v_ist;

   // P-Regler
    u_p = e_k * k_p;


      // Stellgrößenbegrenzung:
       if (u_p > 1023) u_p = 1023;
       else if (u_p < 0) u_p = 0;

       // Stellgröße in entsprechenden PWM Wert umrechnen:
       stell = u_p;

       // Pulsbreite setzen:
       OCR1A = stell;

       u_p_alt = u_p;
       e_k_alt = e_k;
}


void main(void)
{


// Input/Output Ports initialization
// Port A initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In 
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T 
State7=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In 
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T 
State7=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func0=Out Func1=Out Func2=Out Func3=Out Func4=Out Func5=Out Func6=Out 
Func7=Out
// State0=1 State1=1 State2=1 State3=1 State4=1 State5=1 State6=1 
State7=1
PORTC=0xFF;
DDRC=0xFF;

/// Port D initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=Out Func6=In 
Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=0 State6=T 
State7=T
PORTD=0x00;
DDRD=0x20;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value:
// TCCR1B=0x04: 4.400 kHz/ 2046 = 7 Hz
// TCCR1B=0x01: 3686.400 kHz/2046 = 1800 Hz
// Mode: Ph. correct PWM top=03FFh
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x83;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;


// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: TCCR2=0x07: 3600 Hz  -> t_0 = 1/(3600/255) = 70.83 ms
//    TCCR2=0x06; 14400 Hz -> t_0 = 1/(14400/255) = 17,708 ms
//    TCCR2=0x05; 28800 Hz -> t_0 = 1/(28800/255) = 8,85 ms
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
GICR|=0x00;
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 115200
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 115,200 kHz
// ADC Voltage Reference: AREF pin
ADMUX=ADC_VREF_TYPE;
ADCSR=0x85;

// Global enable interrupts
#asm("sei")


// Sollspannung (10 bit integer zwischen 0 und 1023) über Terminal 
einlesen:
gets(wert,4);

// Array in int umrechnen:
v_soll = atoi(wert);

// Timer 2 loslaufen lassen:
TCCR2=0x06;
}

von Stefan G. (Gast)


Lesenswert?

Also, ein Fehler ist mir gerade noch aufgefallen: Beim P-Regler muß in 
die Berechnung der Stellgröße auf jedem Fall auch die vorherige 
Stellgröße mit hinzuaddiert werden:

u_p = u_p_alt + e_k * k_p;

Ansonsten würde ja sobald die Regelabweichung verschwindet auch die 
Stellgröße zu Null werden, sprich das Ventil ganz geschlossen werden.
Nun bleibt nur noch die Frage wie ich mein k_p richtig wähle, das 
Verhalten meines Regelkreises kommt mir noch etwas spanisch vor. Das mag 
aber auch an der Charakteristik des Proportionalventils liegen, da 
dieses sich nur innerhalb eines sehr kleinen Fensters (Pulsbreite 
zwischen 55% und 60%) regt. Außerhalb dieses Bereichs ist es entweder 
ganz auf, oder ganz zu.
Stefan

von Sascha (Gast)


Lesenswert?

Das mit dem u_p_alt wird nicht funktionieren. Stell dir vor, u_p_alt 
wäre 50%, dann hättest du nach zwei Aufrufen der Reglerroutine eine 
Stellgröße von 100% und dein Ventil wäre voll auf und käme auch nicht 
wieder runter. Was du brauchst ist ein Offset, den du nach den 
Berechnungen einfach hinzuaddierst. u_p_0 könnte z.B. 512 (50%) sein.

//Offset
u_p_0=512;

// Stellgröße in entsprechenden PWM Wert umrechnen:
stell = u_p + u_p_0;

Das Problem mit dem Ventil ist natürlich das größte im Moment. Wenn es 
wirklich nur zwischen auf und zu zu steuern ist, sind alle deine 
Bemühungen mit einem Regler umsonst. Das Ganze kann nur funktionieren, 
wenn dein Stellglied einigermaßen linear arbeitet, und nicht so 
schaltend wie zur Zeit.

von edi (Gast)


Lesenswert?

hi,

das war am 23-05-2003 schon klar...

ed

von Stefan G. (Gast)


Angehängte Dateien:

Lesenswert?

@ edi: Nur zur Info: das Ventil daß ich derzeit verwende ist ein 
Proportionalventil. So super linear zwischen 0 Volt und 24 Volt arbeiten 
die aber leider nicht. Die öffnen sich erst ab einer relativ hohen 
Spannung, und dann geht´s ziemlich fix bis sie auf sind.

@ sascha: Danke für die Tipps, so richtig sehe ich jedoch nicht den 
Unterschied und das Problem. Meine Stellgröße ist ja begrenzt, kann also 
maximal 1023 groß werden. Und die Regelabweichung kann ja auch negativ 
werden, d.h. u_p müßte dann auch wieder kleiner werden können.
Ich habe es zumindest mal mit einem Offset probiert und kam aufs selbe 
Ergebnis: Der Sollwert von 1023 wird ohne Regelabweichung erreicht und 
gehalten. Wenn ich z.B. einen Sollwert von 512 eingeben, so bekomme ich 
folgendes merkwürdige Verhalten: die Ist-Spannung zittert zwischen 1023 
und ca. 230 hin- und her. Das Ergebnis ist natürlich absoluter Müll. Ich 
denke ja noch, daß ich einen Fehler in meinem Algorithmus habe...

Zur Linearität des Proportionalventils: Ich habe da mal so eine 
Kennlinie mit Excel (s. Anhang) aufgenommen: Ausgangsspannung des 
Flussmessers in Abhängigkeit von der Pulsbreite. Ich habe das alles mal 
bei unterschiedlichen PWM Frequenzen gemacht, das Ergebnis ist aber 
immer ziemlich ähnlich: es tut sich nur was in einem relativ kleinen 
Bereich. (die gelbe Linie interessiert nicht, da habe ich es mal mit 
einem normalen auf - zu - Ventil probiert).
Die Kennlinie des Proportionalventils ist halt nur in einem ziemlich 
kleinen Bereich linear. Kann ich vielleicht irgendwie meinen 
Regelalgorithmus an die Kennlinie anpassen?
Gruß,
Stefan

von Stefan G. (Gast)


Lesenswert?

Ach ja, mir viel gerade noch etwas ein zum Thema Offset u_p_0 oder alter 
Stellgröße u_p_alt:

Bei Verwendung eines Offsets hätte ich ja, wenn die Regelabweichung 
bereits 0 ist, immer noch eine Stellgröße.
D.h. das Ventil würde sich weiterhin bewegen, obwohl es ja eigentlich in 
seiner Position verharren müßte...
Stefan

von Sascha (Gast)


Lesenswert?

Du musst mit dem Offset den Arbeitspunkt in die Mitte deiner Kennlinie 
legen, da wo sie den linearen Verlauf hat. Ist dein Sollwert kleiner als 
der Arbeitspunkt, so bekommst du eine negative Regelabweichung und deine 
Stellgröße verkleinert sich. Sollwert zu groß -> Stellgröße größer. 
Versuche folgenden Code:

// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
    // aktuelle Spannung einlesen (Wert zwischen 0 und 1023):
    v_ist = read_adc(0);

    // Regelabweichung e_k berechnen:
    e_k = v_soll - v_ist;

    // P-Regler
    u_p = e_k * k_p + u_p_0;

    // Stellgrößenbegrenzung:
    if (u_p > 1023) u_p = 1023;
    else if (u_p < 0) u_p = 0;

    // Stellgröße in entsprechenden PWM Wert umrechnen:
    stell = u_p;

    // Pulsbreite setzen:
    OCR1A = stell;

    u_p_alt = u_p;
    e_k_alt = e_k;
}

Durch setzen von k_p=0 kannst du erstmal herausfinden, welchen Wert 
u_p_0 haben muss, damit du ca. 50% Durchfluss hast. Dann k_p wieder 
zurücksetzen.
Übrigens musst du deinen Timer 2 noch initialisieren (TCCR2)!

von Harald Hermenau (Gast)


Lesenswert?

Nochmals zum P-Regler.
Beim P-Regler DARF!!! der alte p-Wert nicht mit dazugerechnet werden 
(sonst haben wir ja den I-Regler!!).
Beim P-regler ist ja das Problem, das er den Sollwert nie erreicht, bzw. 
erst bei undendlich großer Verstärkung.
Beim I-regler braucht man sich den berechneten Wert z.B u_i_alt nicht zu 
merken. Den vorherigen Wert merkt sich schon der Kompiler.

Tschüß!

von Stefan G. (Gast)


Lesenswert?

@ sascha: Der Timer 2 wird ganz unten im Programmcode mit 0x07 
initialisiert. Danach müßte dann alle 70,83 ms ein Interrupt ausgelöst 
werden.

Ich habe dann mal k_p auf 0 gesetzt und probiet den richtigen Offset zu 
finden. Dabei trat jedoch das merkwürdige Phänomen auf, das die Spannung 
langsam immer geringer wurde, wenn ich also als Stellgröße nur u_p = 
u_p_0 = 470 hatte. Das konnte ich mir nicht erklären.
Ich habe nun erstmal u_p_0 auf 470 gelasen und k_p wieder auf 1 gesetzt. 
Nun klappt das alles schon besser. Zumindest die Spannung die mir mein 
Multimeter anzeigt kommt besser hin. Das was mir mein A/D Wandler auf 
dem Terminal ausgiebt wackelt immernoch ziemlich hin- und her.
Ich werde hier nochmal etwas rumtüfteln. Erstmal vielen Dank und 
wahrscheinlich bis später :-)
Stefan

von Stefan G. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
irgendwie habe ich das Gefühl, daß ich das Einlesen meiner aktuellen 
Spannung von der Regelroutine (also von der ISR) trennen muß, und 
kontinuierlich nebenher messen muss. Ich habe nämlich folgendes Problem 
(s. Excel File): Wenn ich mittlere Sollwerte (also mittleren Fluss) 
vorgebe, so wackelt mein Signal zwischen min und max hin und her. Etwas 
ähnliches ist auch an der Pulsbreite auf dem Oszi zu beobachten: Die 
Pulsbreite springt immer zwischen sehr geringen (~5%) und sehr hohen 
(~95%) hin und her. D.h. daß die Stellgröße permanent wackelt, und dies 
kann nur an der Regelabweichung e_k liegen. In e_k geht als variable 
Größe ja nur v_ist bzw. read_adc(0) vom A/D Wandler ein. Hier muß also 
denke ich die Fehlerquelle liegen, da sich e_k offenbar immer 
sprungartig ändert. Hat jemand eine Idee wie ich da etwas ändern kann?
Stefan

von Sascha (Gast)


Lesenswert?

Das Schwingen ist eigentlich ein typisches Anzeichen für ein zu großes 
k_p. Verkleinere es vielleicht auf ca. 75% vom jetztigen Wert und 
beobachte nochmal. Ist die x-Achse die Zeit in Sekunden? Wenn ja, ist 
das wahrscheinlich die Lösung. Dadurch nimmt natürlich die 
Regelgenauigkeit ab, aber das kompensiert man dann nachher mit dem 
I-Anteil (aber erst, wenn der P-Anteil stabil läuft).

von Stefan G. (Gast)


Lesenswert?

Hallo Sascha,
das mit dem k_p hatte ich auch schon gedacht, wußte jedoch bisher nicht 
wie ich den Wert kleiner als 1 machen soll, da ich ja nur mit Integer 
Werten arbeite.
Die X-Achse ist noch garnicht skaliert. Jedes mal wenn der Timer 2 
überläuft, wird ein Interrupt ausgelöst und ich lese das A/D Ergebnis. 
D.h. die Intervalle auf der X-Achse sind ca. 70 ms groß.
Stefan

von Sascha (Gast)


Lesenswert?

Wenn das Intervall 70ms ist, dann gibts scheinbar noch ein anderes 
Problem. Hast du mal überlegt, dein Messsignal über einen Tiefpass zu 
filtern?

von Stefan G. (Gast)


Lesenswert?

Ja, überlegt hatte ich das mal. Habe aber bisher nur einen Kondensator 
hinter meinem Flussmesser hängen, um die Ausgagnsspannung zu glätten. 
Man hat mir gesagt das würde reichen, ich kann aber auch nochmal einen 
"richtigen" Tiefpass probieren.
Stefan

von Gerhard (Gast)


Lesenswert?

Hallo Stefan ,

Versuch erstmal k_p durch 2 zu dividieren
und schau dir mal das Ergebnis an.
Müsste eigendlich deutlich besser laufen .

Gruss Gerhard

von Stefan G. (Gast)


Lesenswert?

Hallo,
wenn ich k_p durch 2 dividiere, bekomme ich unabhängig vom Sollwert den 
selben Ist-Wert raus. Ich bin mir auch nachwievor nicht sicher wie ich 
ein k_p von 1/2 in einen Regelalgorithmus einbinden soll, der nur mit 
Integer Werten arbeitet. Hier nochmal der Ausschnitt aus dem Programm 
(ich werde mich jetzt auch nochmal um die Sache mit dem Tiefpass 
kümmern).
Stefan

int v_ist;
int e_k;    // Regeldifferenz
int e_k_alt;
float k_p =1/2;    // 1.446 Verstärkungsfaktor
int u_p;        // Stellgröße
int u_p_alt;
int u_p_0=470;    // Offset
int v_soll;
int stell;
char wert[4];
char istwert[4];
int i;
int ad_summe;


// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
  // aktuelle Spannung einlesen (Wert zwischen 0 und 1023):
  v_ist = read_adc(0);

  // Regelabweichung e_k berechnen:
   e_k = v_soll - v_ist;

   // P-Regler
    u_p = e_k * k_p + u_p_0;


      // Stellgrößenbegrenzung:
       if (u_p > 1023) u_p = 1023;
       else if (u_p < 0) u_p = 0;

       // Stellgröße in entsprechenden PWM Wert umrechnen und 
Typeconversion nach int:
       stell = (int) u_p;

       // Pulsbreite setzen:
       OCR1A = stell;

       u_p_alt = u_p;
       e_k_alt = e_k;

  /******
  // Mittelung des A/D Ergebnis:
       for(i=1; i<=10; i++)
       {
         ad_summe += read_adc(0);
       }
       ad_summe/=10;
       itoa(ad_summe, istwert);
       ******/
       itoa(read_adc(0),istwert);
       puts(istwert);
}

von Sascha (Gast)


Lesenswert?

1.446 war doch auch kein Int-Wert, oder? Und den solltest du durch 2 
teilen, also k_p=0.7 oder so testen.

von Stefan G. (Gast)


Lesenswert?

Ja, 1.446 war kein Int-Wert, aber den hatte ich auch durch 1 ersetzt, 
als ich von meinem float Regelalgorithmus zu integern übergegangen bin. 
Wenn ich obiges Programm mit k_p = 0.7 betreibe, bekomme ich das selbe 
"zittern" der Ausgangsgröße. Das merkwürdige dabei ist ja, daß es 
wirklich mit konstanter Frequenz und (annähernd konstanter) Amplitude 
schwingt. Wenn ich beispielsweise 512 als Sollwert vorgebe, wechseln 
sich am Ausgang (Ist-Wert) die Werte ~215 (+-1) und ~1018 (+-1) konstant 
ab. Das sah man ja auch in der Excel Tabelle die ich gestern hier 
gepostet habe. Ob das durch einen simplen Tiefpaß zu beheben ist weiß 
ich ja nochnicht so ganz....ich bin aber dabei.
Stefan

von Sascha (Gast)


Lesenswert?

Hast Recht, hab mir mal die Tabelle angeschaut. Das Diagramm sieht ja so 
aus, als wenn es harmonische Schwingungen wären, aber das liegt nur an 
der Darstellung. Die Werte sehen so aus, als wenn noch irgendein 
systematischer Fehler drinsteckt. Es ist unmöglich, dass die gewandelten 
Werte dem korrekten Messsignal entsprechen, da sie ja wie du schon 
sagtest so springen. Hast du den AD-Wandler schon mal mit einer 
Gleichspannung getestet? Gibt es eigentlich ein DAtenblatt über den 
Durchflusssensor?

von Stefan G. (Gast)


Lesenswert?

Eben, es scheint mir auch so daß da noch ein systematischer Fehler 
drinsteckt. Den AD Wandler habe ich gerade nochmal mit einer 
Gleichspannung getestet. Das funktioniert einwandfrei.
Datenblätter vom Durchflussmesser habe ich ebenfalls. Was möchtest du 
denn wissen? Abhängig vom Durchfluss gibt das Teil am Ausgang 1 Volt 
(kein Fluss) oder 5 Volt (voller Fluss) aus.
Stefan

von Sascha (Gast)


Lesenswert?

Ich dachte, der Sensor gibt vielleicht ein frequenzproportionales Signal 
statt einer Gleichspannung raus. Wenn der Wandler funktioniert, hilft 
vielleicht ein Tiefpass.

von Stefan G. (Gast)


Lesenswert?

Hallo,
ich habe es nun nochmal mit einem Tiefpaßfilter probiert. Das hat jedoch 
nichts gebracht. Die Werte die mir mein A/D Wandler für die Ist-Spannung 
ausgibt, sehen genau gleich aus und schwanken immernoch so heftig. Es 
muß also nachwievor irgendein logischer Fehler im Programm sein. Die 
Frage ist nur welcher? Ich finde partout keinen Denkfehler im Programm, 
es ist ja eigentlich auch nicht so kompliziert...

von Gerhard (Gast)


Lesenswert?

Hallo Stefan ,

hab mir mal das Excel File angesehen und bin auch der Meinung
dass der Regler übersteuert d.h. er ist zu scharf eingestellt.

Ich kann zwar kein C , aber probier das mal um den Regler
zu "entschärfen".

e_k = v_soll - v_ist;

e_k = e_k / 2;

u_p = e_k + u_p_0;


Damit kannst du die Abweichung halbieren.

Gruss Gerhard

von Uwe (Gast)


Lesenswert?

Hallo Stefan!

Ohne das ich mich jetzt mit dem Prog. beschäftigt habe, setze doch Kp 
einfach mal auf 0, versorge den Eingang mit 1-5V und schaue dir die Ua 
im Bezug auf die Differenz Usoll zu Ue an.

Ich denke jedenfalls dein Kp ist zu hoch.

Wie wäre es eigentlich mal mit simulieren, da zeigen sich oft kleine 
aber böse Fehler.

MFG Uwe

von Stefan G. (Gast)


Lesenswert?

@ Gerhard: Wenn ich e_k = e_k / 2; setze, tut sich eigentlich nichts 
bzgl. des merkwürdigen Verhaltens. Es wackelt immernoch genauso hin und 
her. Das Problem muß also irgendwo anders liegen, ich vermute ja schon, 
daß der A/D Wandler irgendwie doch murks baut, obwohl er sonst normal 
funzt.´

@ Uwe: Wenn ich k_p auf 0 setze, geht ja keine Variable Größe mehr in 
meine Stellgröße ein. Ich bekomme also unabhängig vom Sollwert immer 
denselben Ist-Wert.
Wie meinst du das mit Simulieren? Mit Matlab? Da hätte ich jetzt keine 
Ahnung wie ich da rangehen sollte, und wüßte auch nicht wirklich was für 
Erkenntnisse ich daraus gewinnen sollte...
Stefan

von Gerhard (Gast)


Lesenswert?

Hallo Stefan,

hab mir nochmal das Excel File angeschaut.

Eigentlich kann man sagen dass der Regler
bei Sollwert 1000 schon halbwegs funktioniert.
Sieht auch bei Sollwert 200 nicht ganz so schlecht aus.

2 Vorschläge habe ich noch.

1.  e_k noch durch einen höheren Wert dividieren.
    z.B. 5 , 10 , 20 ...

2.  Ich weiß nicht wie exakt die Werte vom Durchflussmesser
    rüberkommen. Probier vielleicht mal den Mittelwert der
    letzten 5 od. 10 Messungen zu bilden und diesen für
    die Berechnungen herzunehmen. Etwaige Fehlmessungen
    bzw. Störungen würden dadurch entschärft.
Hoffe für dich dass das hilft.

Gruss Gerhard

von Stefan G. (Gast)


Lesenswert?

Hallo Gerhard,
genau die Sachen die du mir gerade nanntest habe ich schonmal probiert. 
Ohne Erfolg. Das "Wackeln" ist immer noch da, jedoch nicht mehr zwischen 
~200 und ~1000, sondern zwischen ~500 und ~1000. (bei einer 
Regelabweichung von e_k = e_k/8, einem k_p von 0,7 und einer Mittelung 
des A/D Ergebnisses über 10 Werte). Ich erkenne da absolut kein System.
STefan

von Uwe (Gast)


Lesenswert?

Hallo Stefan!
Ich habe mich mal mit deinem Probl. genauer beschäftigt und dazu dein 
Progr. betrachtet. Wenn das alles ist, was die PWM beeinflusst, kann es 
nicht gehen.
Wo ist der SOLLWERT im Ausgangswert? Der P,I,D-Anteil sind nur 
Abweichungen, davon!

Solltest du nicht drauf kommen schreibe ich es dir heute Nacht, es ist 
ganz einfach.

MFG Uwe

von Uwe (Gast)


Lesenswert?

Hallo Stefan!

Deine Geschichte ist mir nict aus dem Kopf gegangen und mir sind noch 
einige Dinge Eingefallen.

Ich denke dein Grundprobl.ist das "schnappen" deines Ventil's
in Verbindung mit den 70ms Tastzeit. Wie schnell jetzt der Sensor + 
Luftstrom reagieren ist natürlich auch so eine Sache.
jedenfalls ist dein Kp, auf den engen Stellbereich gesehen, viel zu 
klein. Andererseits passt ein hoher Kp nicht zu den 70 ms Abtstzeit(da 
könnte viel geschehen). Mein 2. Gedanke war eigentlich:

v_ist = ADC - Offset(1V)
e_k = (v_soll - v_ist) * Kp ;
u_p = v_soll + e_k

Dabei muss sich v_soll aber im Regelbereich deines Vent. befinden. Kp 
würde ich jetzt in Schritten von 5 erhöhen.
Wo ich kein gutes Gefühl habe sind die 70ms Abtastzeit.
Passt denn das zur Regelzeit deines Systems. Kannst du nicht mal die 
Zeit messen von Sensor 0->100% bei Vent.0->1

Übrigens ist es möglich das du dein Vent. stromgesteuert fahren musst? 
Das wird zb.im KFZ-Bereich oft so gemacht.

MFG Uwe

von edi (Gast)


Lesenswert?

hi Stefan,

wie sieht dein ventil aus? ist es motorgesteuert oder
pneumatisch?

dass es erst bei 58% 'aufmacht' ist alles andere als linear.
dokumentation?

ed

von Stefan G. (Gast)


Lesenswert?

@ edi: Bei dem Ventil handelt es sich um ein Magnetventil. Es hat also 
eine Spule, die von Strom durchflossen wird und somit einen Kolben 
bewegt. Daß das Ventil so spät erst aufmacht kommt mir halt auch sehr 
merkwürdig vor. Auch der Vertreter der Firma (Fluid Automation Systems) 
konnte mir nicht sagen, ob das normal ist. Etwas schwache Leistung, aber 
offenbar kennen die sich schlecht mit PWM aus. Er sagte mir nur, daß die 
Steuerspannung ca. zwischen 12 und 24 Volt liegt, insofern würde es ja 
passen, daß das Ventil erst noch geschlossen bleibt...

@ Uwe: Danke erstmal für deine zahlreichen Tipps. Ich habe Freitag nicht 
gearbeitet, daher antworte ich erst jetzt. Mit deinem Posting vom 20.06 
konnte ich nicht so viel anfangen. Was meinst du mit "Wenn das alles 
ist, was die PWM beeinflusst,..."?
Inwiefern meinst du daß die Abtastzeit ein Problem darstellt? Da fehlt 
mir etwas der theoretische Hintergrund. Die Abtastzeit kann ich ja noch 
über den Timer verändern. Und wie muß die Abtastzeit im Verhältnis zur 
"Ansprechzeit" meines Systems gewählt werden? Eine Sprungantwort habe 
ich ja schonmal aufgenommen. Das System reagiert wie ich fand sehr 
schnell. Am Ausgang (also am Flussensor) sieht man ebenfalls nahezu 
einen Sprung. Die Totzeit betrug 2,205 ms, die Zeitkonstante (also die 
Zeit die das System braucht um nach "Ablauf" der Totzeit auf Sollwert 5 
V zu kommen) betrug 0,513 ms. Ist deine Idee also, daß ich die 
Abtastzeit wesentlich verringern müßte? Muß die Abtastzeit ähnlich groß 
sein wie die Systemzeitkonstante?
Ich werde nun nochmal probieren einige von dir vorgeschlagene Änderungen 
in mein Programm mit zu übernehmen.

Das Vewntil könnte ich auch stromgesteuert antreiben. Da habe ich aber 
keine Ahnung wie ich eine Strom PWM hinbekommen soll. Mit Spannung 
sollte es zumindest auch funktionieren.
Bis dann,
Stefan

von Stefan G. (Gast)


Lesenswert?

@ Uwe: Mir fiel gerade noch etwas auf: Warum hast du in die Stellgröße 
direkt v_soll mit eingehen lassen? :

u_p = v_soll + e_k

von thkais (Gast)


Lesenswert?

Zu dem Ventil: So, wie Du das beschreibst, ist das kein 
Proportionalventil, sondern ein ganz ordinäres Magnetventil mit einer 
Nennspannung von 24 Volt. Die schalten bei 12V auch (manchmal).
Ein Proportionalventil ist häufig mit einer motorgetriebenen Spindel 
ausgestattet, es gibt auch rein magnetisch angetriebene. Die ersteren 
haben entweder ein Poti oder einen Impulsgeber als Rückmeldung, die 
letzteren eine komplizierte Elektronik. Zumeist kann man Prop.- Ventile 
daran erkennen, daß sie 1. Sauteuer sind und 2. drei Anschlüsse haben (2 
für Spannungsversorgung, einer für das Steuersignal (0-20mA od. 4-20 
mA).

von Stefan G. (Gast)


Lesenswert?

Bei dem Ventil handelt es sich jedoch definitiv um ein 
Proportionalventil. Vielleicht ist es ja hinüber, glaube ich aber 
eigentlich nicht. Es hat 2 Anschlüsse, steuerbar mit Strom, Spannung 
oder PWM. Sauteuer war es im Vergleich zu einem "normalen" Ventil 
ebenfalls: 130 Euro.
Stefan

von Stefan G. (Gast)


Lesenswert?

Ich habe gerade nochmal die Abtastzeit (also die Zeit nach der die 
Regelroutine wieder aufgerufen wird) verringert. Jedoch auch bei einer 
Zeit von 0,07ms ändert sich nichts an dem Verhalten: Auf dem Oszilloskop 
sieht man nachwievor, daß die Pulsbreite ständig zwischen zwei sehr 
unterschiedlichen Werten springt. Es wechseln sich fortlaufend 
Pulsbreiten von ca. 10% und dann wieder 90% ab.

von Uwe (Gast)


Lesenswert?

Hallo Stefan!
Du hast also eine Reaktionszeit über alles von ~2,7ms.
70us Abtastzeit? Das schafft doch der ADW garnicht,du hattest doch 
130Khz für'n ADC eingestellt? 2,7ms/0,07ms=~38 Werte zwischen Fluss min 
und max, du hast also eine max-Auflösung von 38 Werten. Dein System ist 
veflixt schnell! Das 10/90% Springen kommt bestimmt aus einer relativ 
grossen Wertänderung am Sensor wärend der Abtastzeit und dem schmalen 
Steurbereich deines Vent.Sehr heikle Sache für Ferndiagnose wenn man 
noch nicht einmal das System kennt.Eins kann ich dir aber jetzt schon 
sagen: Wenn das System so schnell bleibt kommst du um knallhartes ASM 
nicht drummherum. Eventuell könnte ein externer ADC das Probl. 
entschärfen. Ein anderer Kontroller wäre bei mir auf jedenfall schon in 
Verwendung. Sehe ich das richtig, du hast einen Takt von 3,68MHz?
Wenn ja, viel zu langsam, es sind ja noch andere Aufgaben zu erledigen! 
Wie schnell kann der Mega323? Maximal ausreitzen bis Übertakten! Die 
Tastzeit nicht vom Timer bestimmen lassen sondern vom ADC -immer wenn 
fertig Neustart und Daten verarbeiten.Mehr fällt mir momentan nicht ein.
Ach ja Sollwert, Das ist dein notwendiger Offset um die Reglung in den 
Arbeitsbereich zu bringen. Durch den
"gleitenden" Offset werden Regelabweichungen besser ausgeglichen. Dein 
schlimmstes Probl. ist und bleibt aber das sch... Vent. Ist das Ding 
einseitig federbelastet, oder sind das 2 Magneten die gegeneinander 
arbeiten? Alles Mist, sehen  und austesten muss man sowas!

Trotzdem viel Erfolg, Uwe

von Stefan G. (Gast)


Lesenswert?

Hallo,
ja, das ganze per Ferndiagnose zu machen ist allerdings ziemlich sche... 
. Aber leider habe ich hier keinen Fachkundigen vor Ort. Ich werde nun 
mal deine einzelnen Fragen der Reihe nach abarbeiten:

1) Wieso meinst du daß mein AD Wandler die 0,07 ms Abtastzeit nicht 
schafft? Die AD Wandlung erfolgt mit einer Frequenz von 115,2 kHz. Das 
heißt das alle (1/115200) Sekunden eine Wandlung vorgenommen wird, also 
alle 0,00868 ms, oder? Das müßte doch ausreichen...

2) Was genau ist ASM?

3) Ich glaube 4 MHz ist die maximale Taktfrequenz. Mit Übertakten kenne 
ich mich nicht richtig aus. Wieso meinst du ist das viel zu langsam? 
(naja, irgendwo hast du wahrscheinlich recht, ich muß nämlich noch jede 
Menge andere Aufgaben erledigen wie Temperaturregelung und eine 
Flussregelung für insgesamt 10 (!!!) Ventile)

4) Im Ventil befindet sich meines Wissens eine Spule, die den Kolben 
steuert. Ohne Spannungsversorgung ist das Ventil geschlossen.

Stefan

von Uwe (Gast)


Lesenswert?

Hallo Stefan!
Ich habe mir dein Probl. noch mal durch den Kopf gehen lassen und bin zu 
dem Schluss gekommen, mit einem P-Regler kommst du nicht ans Ziel. Was 
du brauchst ist ein I-Regler dessen Stellwert nur bewertet wird.
Die Schnelligkeit deines Systems, die beim P-Regler stört, kommt uns 
jetzt bei der Regelgeschwindigkeit entgegen. Wie meine ich das nun. 
Erstmal was grundsätzliches : der ausgebbare Stellwert bewegt sich im 
Bereich Wert(Vent.zu)-5% bis Wert(Vent. offen) +5% , die Tastzeit legst 
du auf den 3-4 Wert der Systemregelzeit, also ca.10ms. Der Wert  der 
Regelabweichung wird nur bewertet, und  als Stellwert ausgegeben. Also , 
Abweichung  <5 kein Stellwert; 5-10 = Stellwert 1; 11-20 = Stellwert 2 
und >20 = Stellwert 3. Die Werte sind jetzt natürlich frei festgelegt 
und bedürfen der Optimierung. Bei jedem Regeltakt wird deine PWM also um 
max. 3 verändert Das System wird dadurch mächtig ausgebremst und hat 
Zeit sich einzustellen.
Als kleiner Nebeneffekt entsteht ein Zeitgewinn für die anderen Aufgaben 
des Kontrollers. Durch die 10ms Tastzeit hast du hoffentlich ein noch 
genügend schnelles System (100 Stellwerte je Sekunde)

Ich hoffe du kannst mir irgendwie folgen, bin ein schlechter Erklärer, 
und bringst den Regler jetzt zum regeln.

<Wieso meinst du daß mein AD Wandler die 0,07 ms Abtastzeit <nicht 
schafft? Die AD Wandlung erfolgt mit einer Frequenz <von 115,2 kHz. Das 
heißt das alle (1/115200) Sekunden eine <Wandlung vorgenommen wird, also 
alle 0,00868 ms, oder? Das <müßte doch ausreichen

Das ist der Takt für den ADC, du musst aber 10 Bit Wanden, also 70us. 
Das ist übrigens genau das was im Datenblatt anderer Kontroller steht. 
Oder ist der Mega323 schneller?


MFG Uwe

von Wolfram (Gast)


Lesenswert?

Hallo Stefan

Ich verstehe nicht warum du eine so hohe samplingfrequenz nimmst (soweit 
ich weiss ist die maximale samplefrequenz 15khz) und innerhalb der muss 
deine Regelroutine durchlaufen werden.Ich glaube nicht dass dein Ventil 
schneller ist als eine typische PWM mit 4KHz.Als Samplefrequenz sollte 
500Hz vollkommen ausreichen.(oder was sollen da für Druckunterschiede 
geregelt werden?)
Zwischen dem Luftdrucksensor und dem ADC sollte ein Tiefpass sein der 
mindestens 40dB Daempfung bei 250 Hz hat(eigentlich sollte ueberhaupt 
keine Frequenzen oberhalb der halben Samplefreq durchgelassen werden 
weil dein Regler sonst auf
Frequenzen im falschen Frequenzbereich antwortet.(aliasingeffekte)
und muessen die Reglerwerte nicht auch an die Samplefrequenz
angeglichen werden?
Ist die Exceltabelle die oeffnung des Ventils bei reiner PWM oder in 
Verbindung mit dem Regler aufgenommen?
Du solltest eine Tabelle machen: eingangswerte 0..100% ausgangswerte 
entsprechende PWM Werte ueber die du linearisierst.

Ich hoffe das hilft ein bisschen

CU Wolfram

von Stefan G. (Gast)


Lesenswert?

Hallo Wolfram, erstmal danke für die Antwort.
Wie bastel ich mir denn einen Tiefpass mit 40 db Dämpfung bei einer 
frequenz von 250 Hz? Wie ein "normaler" Tiefpaß aussieht weiß ich, wie 
ich das mit den 40 dB mit einbeziehe weiß ich leider nicht.

Was genau meinst du mit "Reglerwerten" die an die Samplefrequenz 
angepaßt werden sollen?

Die Excel Tabelle ist übrigens die Öffnung des Ventils (bzw. der vom 
Flussmesser gemessene Durchfluss, der abhängig von der Ventilöffnung 
variiert) in abhängigkeit (nur) von der Pulsbreite. Eine Regelung ist 
dort nicht dabei, ich habe einfach die Pulsbreite von 0 angefangen 
kontinuierlich erhöht und mir angesehen was am Flussmesser ankommt.
Stefan

von Stefan G. (Gast)


Lesenswert?

@ Uwe: Danke für deine Tipps, ist gut möglich daß ich mit einem reinen 
P-Regler nicht weiterkomme. Jedoch sehe ich in deiner Beschreibung nicht 
genau wo denn nun eigentlich der I-Anteil steckt. So wie du das erklärt 
hast:

>Der Wert der Regelabweichung wird nur bewertet, und als
>Stellwert ausgegeben. Also , Abweichung <5 kein Stellwert; 5->10 = Stellwert 1; 
11-20 = Stellwert 2 und >20 = Stellwert 3.

würde ich das mit if und else Schleifen abprüfen, dann sehe ich jedoch 
nicht genau, wo da noch ein richtiger PI Regler hintersteckt.
Gruß,
Stefan

von Uwe (Gast)


Lesenswert?

Hallo Stefan!
Ich sagte ja, bin ein schlechter Erklärer.
Der I-Anteil entsteht durch das Aufsummieren der Stellwerte (sagen wir 
+3)bei jedem Zyklus zb.:
PWM=100->Zyklus->PWM=103->Zyklus->PWM=106 ....
und beim Überschwingen natürlich zurück. Durch die grosse Tastzeit 
sollte aber kein Überschwingen eintreten.
Habe mir übrigens deine Öffnungskurven noch einmal angeschaut und 
festgestellt das bei 110Hz der Stellvorgang recht gut ausschaut. ->Kann 
es möglich sein das das Vent.am besten mit Gleichspannung funktioniert? 
Hast du das mal getestet? Ich meine so ein Vent. ist ja auch nur eine 
Induktivität und die sind nicht gut auf NF zu sprechen.

Nicht locker lassen, das wird schon!

MFG Uwe

von edi (Gast)


Lesenswert?

Stefan,

schau mal hier
http://209.41.13.11/d/NEWS_S6_D.pdf

dein ventil ist ein hundsnormales magnetventil: entweder
auf... oder ...zu!

ich glaube du verlierst nur deine zeit.

ed

von Stefan G. (Gast)


Angehängte Dateien:

Lesenswert?

@ edi: Ich glaube mittlerweile daß Proportionalventile garnicht so 
proportional arbeiten wie es sich anhört... . Ich habe gerade nochmal 
ein anderes Proportionalventil eines anderen Herstellers (Bürkert) 
erhalten. Dessen Kennlinie sieht ziemlich ähnlich aus: der halbwegs 
lineare Teil befindet sich in einem sehr kleinen Fenster. Ich habe das 
Excel File mit der Kennlinie nochmal angehängt, guck dir das mal an. Daß 
beide Ventile einen Fehler haben ist ja eher unwahrscheinlich...
Gruß,
Stefan

ps: die Werte auf der x-Achse entsprechen übrigens der Pulsbreite meiner 
10 bit PWM: 1023 entspricht Pulsbreite von 100 %.

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.