mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PID Regler verbessern


Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Ich habe einen PD-Regler programmiert.
Er dient dazu, einen kleinen Dauermagneten unter einer Spule in der 
Schwebe zu halten.
'+----------------------------------------------------------------------------+'
'| Titel             :     Endarbeit: "Schwebender Magnet"                    |'
'+----------------------------------------------------------------------------+'
'| Funktion          :     Der Magnet schwebt unter einer Spule.              |'
'| Anschlüsse        :     PB1=PWM; PC0=ADC; PD2=RC5; PB0=LED                 |'
'+----------------------------------------------------------------------------+'
'| Name              :     Weinberg Denny                                     |'
'| E-Mail Adresse    :     Denny_Weinberg@hotmail.com                         |'
'+----------------------------------------------------------------------------+'


'|---------------------------------Controller---------------------------------|'
$regfile = "m8def.dat"                                      'ATmega8
$crystal = 14745600                                         'Quarzfrequenz (Extern); Standart: 14745600
$baud = 230400                                              'Funktionierende Baudrate; Standart: 230400

$hwstack = 100
$swstack = 100
$framesize = 100                                            'Freier Speicherplatz für Variablen...


'|---------------------------------Variablen----------------------------------|'
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten

Dim Istwert As Integer                                      'Analoge Spannung des Hallsensors
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
Dim Lastistewert As Integer                                 'Istwert der letzten Messung
Dim Delta As Integer                                        'Die Veränderung der Spannung des Hallsensors während eines Zyklus
Dim Kp As Integer                                           'Die Dämpfung des Magneten
Dim Ki As Integer
Dim Kd As Integer
Dim P As Integer
Dim I As Integer
Dim D As Integer
Dim Sollwert As Integer

Dim Rs232nummer As Byte                                     'ASCII-Code die seriell ankommen
Dim Zeichen As String * 5                                   'Seriell ankommende Zeichen
Dim Anfangsbuchstabe As String * 1                          'Hilfsbuchstabe bei Änderungen
Dim Endwert As String * 4                                   'Der wirkliche Wert der benötigt wird
Dim Zeichengroesse As Byte                                  'Hilfsvariable um das erste Zeichen herauszufiltern

Dim Impulslaenge As Word
Dim Rc5bitnummer As Byte
Dim Tempdaten As Word
Dim Befehl As Byte
Dim Empfangsfehler As Byte
Dim Wiederholen_erlaubt As Bit
Dim Letzter_befehl As Byte
Dim Rc5timervorgabe As Byte
Dim Interruptvektor As Bit


'|--------------------------------Konfiguration-------------------------------|'
Declare Sub Rc5()
Declare Sub Regelung_berechnen()                            'Unterprogramm um die Variablen zu Regelung_Berechnen
Declare Sub Regelung_auswerten()                            'Unterprogramm um die berechneten Werte auszuwerten
Declare Sub Rc5_berechnen()                                 'Unterprogramm, um den RC5-Code zu berechnen
Declare Sub Rc5_auswerten()                                 'Unterprogramm, um den RC5-Code auszuwerten

Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler

Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation

On Urxc Isr_rs232                                           'Interrupt der seriellen schnittstelle
Enable Urxc                                                 'Interrupt der seriellen schnittstelle einschalten

Config Timer0 = Timer , Prescale = 8
On Ovf0 Isr_timer0
Enable Timer0

Rc5timervorgabe = 26                                        'Impulslänge bei RC5 1,778ms --> 8000 Überlaufe / Sekunde
Timer0 = Rc5timervorgabe

Config Int0 = Rising                                        'Externer Interrupt; Steigende Flanke

Reset Ddrd.2                                                'Ausgang des Infrarormodules
Set Portd.2                                                 'Pullup ein

On Int0 Isr_int0
Enable Int0

Enable Interrupts                                           'Interrupts einschalten


'|-----------------------------Eingänge und Ausgänge--------------------------|'
Set Ddrb.0                                                  'Freier Pin (LED)


'|--------------------------------Einstellungen-------------------------------|'
Set Eingeschaltet                                           'Einschalten

Kd = 255                                                    '255
Kp = 1
Sollwert = 120                                              '120

Set Portb.0                                                 'LED Einschalten

Set Wiederholen_erlaubt                                     'Damit man eine Taste gedrückt halten kann


'|--------------------------------Hauptprogramm-------------------------------|'
Do
    Call Rc5

    If Eingeschaltet = 1 Then
       Start Adc
          Istwert = Getadc(0)                               'Analoge Spannung des Hallsensors messen
       Stop Adc

       Call Rc5                                             'Sonst bekommt er nicht alle RC5-Codes mit

       Call Regelung_berechnen                              'Werte Berechnen

       Call Rc5

       Call Regelung_auswerten                              'Werte Auswerten (begrenzen)
    Else
       Pulsweite = 0
    End If

    Pwm1a = Pulsweite                                       'Spulenstrom regeln
Loop


'|--------------------------------Alles mit RC5-------------------------------|'
Sub Rc5()
    If Interruptvektor = 1 Then
       Call Rc5_berechnen

       If Rc5bitnummer = 14 Then
          Call Rc5_auswerten
       End If

       Impulslaenge = 0
       Interruptvektor = 0
    End If
End Sub


'|-------------------------------Werte Berechnen------------------------------|'
Sub Regelung_berechnen()
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt

    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255

    Delta = Istwert - Sollwert

    P = Delta * Kp

    'I

    Delta = Istwert - Lastistewert                          'Istwertsveränderung Berechnen
    D = Delta * Kd                                          'Dämpfung hinzurechnen

    Pulsweite = D + P                                       'Pulsweite Berechnen
End Sub


'|----------------------------------Auswerten---------------------------------|'
Sub Regelung_auswerten()
    If Istwert > 0 Then
       If Pulsweite > 255 Then Pulsweite = 255              'Begrenzungen der Pulsweite einhalten
       If Pulsweite < 0 Then Pulsweite = 0                  'Begrenzungen der Pulsweite einhalten

       Lastistewert = Istwert                               'LastIstewert setzen
    Else                                                    'Wenn der Magnet falsch rum hängt wird er umgedreht
       Pulsweite = 255
    End If
End Sub

'|----------------------------------Berechnen---------------------------------|'
Sub Rc5_berechnen()
    Select Case Impulslaenge
       Case Is > 1500:                                      '-> startimpuls, nach empgfangsfehler muss immer erst ein solcher kommen.
          Rc5bitnummer = 1
          Tempdaten = 1
          Empfangsfehler = 0
       Case 26 To 29:                                       '-> große Länge: vorher 0, jetzt 1 + 0
          If Empfangsfehler = 0 Then
             Shift Tempdaten , Left                         'hinzufügen einer 0
             Incr Tempdaten                                 'umwandeln in 1
             Shift Tempdaten , Left                         'hinzufügen einer 0
             Incr Rc5bitnummer                              'bei Kombination '10' fehlt ein Impuls
          End If
       Case 19 To 22:                                       '-> mittlere Länge: vorher 1, jetzt 1 + 0 oder vorher 0 jetzt 1
          If Empfangsfehler = 0 Then
             Shift Tempdaten , Left                         'hinzufügen einer 0
             Incr Tempdaten                                 'umwandeln in 1
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
                Shift Tempdaten , Left                      'hinzufügen einer 0
                Incr Rc5bitnummer                           'bei Kombination '10' fehlt ein Impuls
             End If
          End If
       Case 12 To 15:                                       '-> kleine Länge     --> gleicher Wert wie vorher
          If Empfangsfehler = 0 Then
             Shift Tempdaten , Left , 1                     'hinzufügen einer 0
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
                Incr Tempdaten                              'umwandeln in 1
             End If
          End If
       Case Is > 400:                                       'aber kleiner 1500, dann war's eine Pause zwischen Befehlen beim Dauerdrücken
          If Empfangsfehler = 1 Or Wiederholen_erlaubt = 1 Then
             Rc5bitnummer = 1
             Tempdaten = 1
             Empfangsfehler = 0
          End If
       Case Else
         Empfangsfehler = 1
    End Select
End Sub

'|----------------------------------Auswerten---------------------------------|'
Sub Rc5_auswerten()
    Befehl = Tempdaten And &B00111111                       'Überflüssige Bits herausfiltern
    If Befehl < 64 Then
       If Wiederholen_erlaubt = 1 Or Befehl <> Letzter_befehl Then
          Letzter_befehl = Befehl
          Select Case Befehl
             Case 3
                Sollwert = Sollwert + 10
             Case 6
                Sollwert = Sollwert - 10
             Case 9
                Toggle Eingeschaltet
          End Select

          Befehl = 0
       End If
    End If
End Sub


'|--------------------Interrupt der seriellen Schnittstelle-------------------|'
Isr_rs232:
    Rs232nummer = Inkey()                                   'ASCII-Code einlesen

    Select Case Rs232nummer
       Case 13                                              'RS232Nummer 13 ist das Enter, das gesendet wird, wenn alles gesendet ist
          Select Case Zeichen
             Case "EIA"
                 Print Eingeschaltet                        'Zurücksenden, ob das Gerät eingeschaltet ist
             Case "POS"
                 Print Istwert                              'Istwert zurücksenden
             Case "SOL"
                 Print Sollwert                             'Sollwert zurücksenden
             Case "AUS"
                 Reset Eingeschaltet                        'Ausschalten
             Case "EIN"
                 Set Eingeschaltet                          'Einschalten
             Case "PB0"
                 Toggle Portb.0                             'LED Umschalten
             Case "P0E"
                 Set Portb.0                                'PortB.0 Einschalten
             Case "P0A"
                 Reset Portb.0                              'PortB.0 Ausschalten
             Case "KP"
                 Print Kp
             Case "KI"
                 Print Ki
             Case "KD"
                 Print Kd
             Case Else
                 Zeichengroesse = Len(zeichen) - 1          'Zeichengröße, um den Endwert herauszufinden

                 Anfangsbuchstabe = Left(zeichen , 1)       'Anfangsbuchstabe rausschneiden
                 Endwert = Right(zeichen , Zeichengroesse)  'Endwert rausschneiden

                 Select Case Anfangsbuchstabe
                   Case "S"
                        Sollwert = Val(endwert)             'Es wurde der Sollwert gesendet
                   Case "KP"
                        Kp = Val(endwert)                   'Es wurde die Dämpfung gesendet
                   Case "KI"
                        Ki = Val(endwert)
                   Case "KD"
                        Kd = Val(endwert)
                 End Select
          End Select

          Zeichen = ""                                      'Zeichen zurücksetzen
       Case Else
          Zeichen = Zeichen + Chr(rs232nummer)              'Nächstes zeichen hinzusetzen
    End Select
Return                                                      'Ins Hauptprogramm zurückspringen


'|----------------------Interrupt des Timer0 (Überlauf)-----------------------|'
Isr_timer0:
   Timer0 = Rc5timervorgabe
   Incr Impulslaenge
   If Impulslaenge > 65000 Then                             'Überlauf von Impulslaenge verhindern (nach 65535 kommt 0),
                                                             'damit Start (Impulslaenge > 500) sicher erkannt wird
      Impulslaenge = 1501
   End If
Return

'|--------------------Interrupt des externen Pins PIND.2----------------------|'
Isr_int0:                                                   'RC5 Impuls erkannt
   Incr Rc5bitnummer
   Interruptvektor = 1
Return
'|----------------------------------The End-----------------------------------|'

Es geht hauptsächlich um den Sub "Regelung_berechnen".
Ich möchte jetzt noch einen I-Anteil ins Programm integrieren.

Könnt ihr mir bitte erklären, wie ich das mache und welche Auswirkungen 
das genau hat??

P.S.: Die Regelung funktioniert sehr gut, allerdings gibt es immer eine 
Regeldifferenz (Magnet schwebt nie an der Sollwertstelle) und die 
funktionierende Hubhöhe ist nicht gerade groß.

Mit freundlichen Grüßen.
Denny

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

hab ich gerade ein deja vu oder hast du das vor ein paar Tagen schonmal 
gepostet?

Zu deinen Fragen:

Denny schrieb:
> Ich möchte jetzt noch einen I-Anteil ins Programm integrieren.
> Könnt ihr mir bitte erklären, wie ich das mache und welche Auswirkungen
> das genau hat??

Die genauen Auswirkungen sind schwierig zu erklären und mit deinen 
Angaben nicht zu bestimmen - besonders, weil dein Regelkreis hochgradig 
nichtlinear ist.

Wie du das machst... naja, im kontinuierlichen w(t) = k_I * 
int(e(tau)*dtau,tau=0..t). Ein Mikrocontroller kann jetzt nicht mit 
kontinuierlicher Zeit rechnen, damit wird aus dem infinitesimal kleinen 
dtau ein T (Abtastperiode), die Funktion e(t) ist ohnehin nur zu 
bestimmten Zeiten e(kT) bekannt, das kann man kurz als e_k schreiben, 
und das Integral wird wieder zu einer Summe (aus der die Integration 
schließlich mal hergeleitet wurde. Zusammengefasst also w_k=k_I * 
summe(e(jT)*T,j=0..k) = k_I  T  summe(e_j,j=0..k).

Nun ist diese Summe etwas zu aufwändig, um sie bei jedem Schritt zu 
berechnen - also muss man sie vereinfachen. Das geht auch ganz toll, 
denn summe(e_j,j=0..k)=summe(e_j,j=0..k-1)+e_k oder auch kurz sum_k = 
sum_(k-1) + e_k.

Zusammengefasst: w_k = k_I  T  sum_k und sum_k = sum(k-1) + e_k

Denny schrieb:
> P.S.: Die Regelung funktioniert sehr gut, allerdings gibt es immer eine
> Regeldifferenz (Magnet schwebt nie an der Sollwertstelle)

Dagegen sollte ein I-Anteil helfen.

Denny schrieb:
> und die funktionierende Hubhöhe ist nicht gerade groß.

Das ist bei einem linearen Regler an einem nichtlinearen, instabilen 
System zu erwarten. Besser wird das nur mit einem anderem 
Regelverfahren...

MfG, Heiko

Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe.
Ich werde es heute versuchen.

Heiko schrieb:
> Das ist bei einem linearen Regler an einem nichtlinearen, instabilen
> System zu erwarten. Besser wird das nur mit einem anderem
> Regelverfahren...
Was meinst Du mit einem anderen Regelverfahren??

Danke schon Mal für die gute Hilfe!

Autor: Andi ... (xaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was meinst Du mit einem anderen Regelverfahren??

es gibt noch was anderes als dieses standard kinderkram pid zeugs...
kannst mal bei wiki unter nichtlinearen reglern suchen, wird aber 
wesentlich komplexer

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denny schrieb:
> Was meinst Du mit einem anderen Regelverfahren??

Es gibt auch noch andere Regler als PID-Regler. Manche davon sind besser 
für nichtlineare Systeme geeignet. Mit Details kenne ich mich aber nicht 
aus.

MfG, Heiko

Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mit dem I-Anteil funktioniert noch nicht so gut.
'+----------------------------------------------------------------------------+'
'| Titel               :     Endarbeit: "Schwebender Magnet"                  |'
'+----------------------------------------------------------------------------+'
'| Funktion            :     Der Magnet schwebt unter einer Spule.            |'
'| Anschlüsse          :     PB1=PWM; PC0=ADC; PD2=RC5; PB0=LED               |'
'+----------------------------------------------------------------------------+'
'| Name                :     Weinberg Denny                                   |'
'| E-Mail Adresse      :     Denny_Weinberg@hotmail.com                       |'
'+----------------------------------------------------------------------------+'

'+----------------------------------------------------------------------------+'
'| PID-Regler          :                                                      |'
'|                                                                            |'
'| RC5-Empfang         :                                                      |'
'|                                                                            |'
'| RS232-Schnittstelle :                                                      |'
'+----------------------------------------------------------------------------+'


'|---------------------------------Controller---------------------------------|'
$regfile = "m8def.dat"                                      'ATmega8
$crystal = 14745600                                         'Quarzfrequenz (Extern); Standart: 14745600
$baud = 230400                                              'Funktionierende Baudrate; Standart: 230400

$hwstack = 100
$swstack = 100
$framesize = 100                                            'Freier Speicherplatz für Variablen...


'|---------------------------------Variablen----------------------------------|'
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten

Dim Istwert As Integer                                      'Analoge Spannung des Hallsensors
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
Dim Lastistewert As Integer                                 'Istwert der letzten Messung
Dim Delta As Single                                         'Die Veränderung der Spannung des Hallsensors während eines Zyklus
Dim Kp As Single                                            'Die Dämpfung des Magneten
Dim Ki As Single
Dim Kd As Single
Dim P As Single
Dim I As Single
Dim D As Single
Dim Integrator As Integer
Dim Sollwert As Single

Dim Rs232nummer As Byte                                     'ASCII-Code die seriell ankommen
Dim Zeichen As String * 10                                  'Seriell ankommende Zeichen
Dim Anfangsbuchstabe As String * 2                          'Hilfsbuchstabe bei Änderungen
Dim Endwert As String * 8                                   'Der wirkliche Wert der benötigt wird
Dim Zeichengroesse As Byte                                  'Hilfsvariable um das erste Zeichen herauszufiltern

Dim Impulslaenge As Word
Dim Rc5bitnummer As Byte
Dim Tempdaten As Word
Dim Befehl As Byte
Dim Empfangsfehler As Byte
Dim Wiederholen_erlaubt As Bit
Dim Letzter_befehl As Byte
Dim Rc5timervorgabe As Byte
Dim Interruptvektor As Bit


'|--------------------------------Konfiguration-------------------------------|'
Declare Sub Rc5()
Declare Sub Regelung_berechnen()                            'Unterprogramm um die Variablen zu Regelung_Berechnen
Declare Sub Regelung_auswerten()                            'Unterprogramm um die berechneten Werte auszuwerten
Declare Sub Rc5_berechnen()                                 'Unterprogramm, um den RC5-Code zu berechnen
Declare Sub Rc5_auswerten()                                 'Unterprogramm, um den RC5-Code auszuwerten

Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler

Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation

On Urxc Isr_rs232                                           'Interrupt der seriellen schnittstelle
Enable Urxc                                                 'Interrupt der seriellen schnittstelle einschalten

Config Timer0 = Timer , Prescale = 8
On Ovf0 Isr_timer0
Enable Timer0

Rc5timervorgabe = 26                                        'Impulslänge bei RC5 1,778ms --> 8000 Überlaufe / Sekunde
Timer0 = Rc5timervorgabe

Config Int0 = Rising                                        'Externer Interrupt; Steigende Flanke

Reset Ddrd.2                                                'Ausgang des Infrarormodules
Set Portd.2                                                 'Pullup ein

On Int0 Isr_int0
Enable Int0

Enable Interrupts                                           'Interrupts einschalten


'|-----------------------------Eingänge und Ausgänge--------------------------|'
Set Ddrb.0                                                  'Freier Pin (LED)


'|--------------------------------Einstellungen-------------------------------|'
Set Eingeschaltet                                           'Einschalten

Kd = 255                                                    '255
Ki = 0.7
Kp = 1
Sollwert = 120                                              '120

Set Portb.0                                                 'LED Einschalten

Set Wiederholen_erlaubt                                     'Damit man eine Taste gedrückt halten kann


'|--------------------------------Hauptprogramm-------------------------------|'
Do
    Call Rc5

    If Eingeschaltet = 1 Then
       Start Adc
          Istwert = Getadc(0)                               'Analoge Spannung des Hallsensors messen
       Stop Adc

       Call Rc5                                             'Sonst bekommt er nicht alle RC5-Codes mit

       Call Regelung_berechnen                              'Werte Berechnen

       Call Rc5

       Call Regelung_auswerten                              'Werte Auswerten (begrenzen)
    Else
       Pulsweite = 0
    End If

    Pwm1a = Pulsweite                                       'Spulenstrom regeln
Loop


'|--------------------------------Alles mit RC5-------------------------------|'
Sub Rc5()
    If Interruptvektor = 1 Then
       Call Rc5_berechnen

       If Rc5bitnummer = 14 Then
          Call Rc5_auswerten
       End If

       Impulslaenge = 0
       Interruptvektor = 0
    End If
End Sub


'|-------------------------------Werte Berechnen------------------------------|'
Sub Regelung_berechnen()
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt

    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255

    Delta = Istwert - Sollwert
    P = Delta * Kp

    I = Delta * 0.005
    I = I * Ki
    If Pulsweite <= 1 Then
    Else
       If Pulsweite < 1023 Then Integrator = Integrator + I
    End If

    Incr Integrator
    If Integrator < -1023 Then Integrator = -1023           'Begrenzung der Ausgangsgröße
    If Integrator > 1023 Then Integrator = 1023
    If Ki < 0.01 Then Integrator = 0

    Delta = Istwert - Lastistewert                          'Istwertsveränderung Berechnen
    D = Delta * Kd                                          'Dämpfung hinzurechnen

    Pulsweite = D + P                                       'Pulsweite Berechnen
    Pulsweite = Pulsweite + Integrator
End Sub


'|----------------------------------Auswerten---------------------------------|'
Sub Regelung_auswerten()
    If Istwert > 0 Then
       If Pulsweite > 255 Then Pulsweite = 255              'Begrenzungen der Pulsweite einhalten
       If Pulsweite < 0 Then Pulsweite = 0                  'Begrenzungen der Pulsweite einhalten

       Lastistewert = Istwert                               'LastIstewert setzen
    Else                                                    'Wenn der Magnet falsch rum hängt wird er umgedreht
       Pulsweite = 255
    End If
End Sub

'|----------------------------------Berechnen---------------------------------|'
Sub Rc5_berechnen()
    Select Case Impulslaenge
       Case Is > 1500:                                      '-> startimpuls, nach empgfangsfehler muss immer erst ein solcher kommen.
          Rc5bitnummer = 1
          Tempdaten = 1
          Empfangsfehler = 0
       Case 26 To 29:                                       '-> große Länge: vorher 0, jetzt 1 + 0
          If Empfangsfehler = 0 Then
             Shift Tempdaten , Left                         'hinzufügen einer 0
             Incr Tempdaten                                 'umwandeln in 1
             Shift Tempdaten , Left                         'hinzufügen einer 0
             Incr Rc5bitnummer                              'bei Kombination '10' fehlt ein Impuls
          End If
       Case 19 To 22:                                       '-> mittlere Länge: vorher 1, jetzt 1 + 0 oder vorher 0 jetzt 1
          If Empfangsfehler = 0 Then
             Shift Tempdaten , Left                         'hinzufügen einer 0
             Incr Tempdaten                                 'umwandeln in 1
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
                Shift Tempdaten , Left                      'hinzufügen einer 0
                Incr Rc5bitnummer                           'bei Kombination '10' fehlt ein Impuls
             End If
          End If
       Case 12 To 15:                                       '-> kleine Länge     --> gleicher Wert wie vorher
          If Empfangsfehler = 0 Then
             Shift Tempdaten , Left , 1                     'hinzufügen einer 0
             If Tempdaten.1 = 1 Then                        'vorher gab es eine 1
                Incr Tempdaten                              'umwandeln in 1
             End If
          End If
       Case Is > 400:                                       'aber kleiner 1500, dann war's eine Pause zwischen Befehlen beim Dauerdrücken
          If Empfangsfehler = 1 Or Wiederholen_erlaubt = 1 Then
             Rc5bitnummer = 1
             Tempdaten = 1
             Empfangsfehler = 0
          End If
       Case Else
         Empfangsfehler = 1
    End Select
End Sub

'|----------------------------------Auswerten---------------------------------|'
Sub Rc5_auswerten()
    Befehl = Tempdaten And &B00111111                       'Überflüssige Bits herausfiltern
    If Befehl < 64 Then
       If Wiederholen_erlaubt = 1 Or Befehl <> Letzter_befehl Then
          Letzter_befehl = Befehl
          Select Case Befehl
             Case 3
                Sollwert = Sollwert + 10
             Case 6
                Sollwert = Sollwert - 10
             Case 9
                Toggle Eingeschaltet
          End Select

          Befehl = 0
       End If
    End If
End Sub


'|--------------------Interrupt der seriellen Schnittstelle-------------------|'
Isr_rs232:
    Rs232nummer = Inkey()                                   'ASCII-Code einlesen

    Select Case Rs232nummer
       Case 13                                              'RS232Nummer 13 ist das Enter, das gesendet wird, wenn alles gesendet ist
          Select Case Zeichen
             Case "EIA"
                 Print Eingeschaltet                        'Zurücksenden, ob das Gerät eingeschaltet ist
             Case "POS"
                 Print Istwert                              'Istwert zurücksenden
             Case "SOL"
                 Print Sollwert                             'Sollwert zurücksenden
             Case "AUS"
                 Reset Eingeschaltet                        'Ausschalten
             Case "EIN"
                 Set Eingeschaltet                          'Einschalten
             Case "PB0"
                 Toggle Portb.0                             'LED Umschalten
             Case "P0E"
                 Set Portb.0                                'PortB.0 Einschalten
             Case "P0A"
                 Reset Portb.0                              'PortB.0 Ausschalten
             Case "KP"
                 Print Kp
             Case "KI"
                 Print Ki
             Case "KD"
                 Print Kd
             Case Else
                 Zeichengroesse = Len(zeichen) - 2          'Zeichengröße, um den Endwert herauszufinden

                 Anfangsbuchstabe = Left(zeichen , 2)       'Anfangsbuchstabe rausschneiden
                 Endwert = Right(zeichen , Zeichengroesse)  'Endwert rausschneiden

                 Select Case Anfangsbuchstabe
                   Case "SO"
                        Sollwert = Val(endwert)             'Es wurde der Sollwert gesendet
                   Case "KP"
                        Kp = Val(endwert)                   'Es wurde die Dämpfung gesendet
                   Case "KI"
                        Ki = Val(endwert)
                   Case "KD"
                        Kd = Val(endwert)
                 End Select
          End Select

          Zeichen = ""                                      'Zeichen zurücksetzen
       Case Else
          Zeichen = Zeichen + Chr(rs232nummer)              'Nächstes zeichen hinzusetzen
    End Select
Return                                                      'Ins Hauptprogramm zurückspringen


'|----------------------Interrupt des Timer0 (Überlauf)-----------------------|'
Isr_timer0:
   Timer0 = Rc5timervorgabe
   Incr Impulslaenge
   If Impulslaenge > 65000 Then                             'Überlauf von Impulslaenge verhindern (nach 65535 kommt 0),
                                                             'damit Start (Impulslaenge > 500) sicher erkannt wird
      Impulslaenge = 1501
   End If
Return

'|--------------------Interrupt des externen Pins PIND.2----------------------|'
Isr_int0:                                                   'RC5 Impuls erkannt
   Incr Rc5bitnummer
   Interruptvektor = 1
Return
'|----------------------------------The End-----------------------------------|'

Für die Zeit habe ich einfach mal 0.005 genommen und Ki ist 0.7.
Zuerst schwingt der Magnet sehr stark und dann nach einigen Sekunden 
schwebt er an seiner Position.
Manchmal fängt er wieder heftig an zu schwingen, kriegt sich aber wieder 
ein.
Der Sollwert ist 120 und die Schwebeposition ist ungefähr 130.
Was soll ich für Werte eingeben, dass es besser funktioniert??

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die bleibende Regelabweichung spricht nicht grade für den Regler ... vor 
allem wenn er einen I-Anteil enthalten soll. Die Schwingneigung deutet 
auf zu geringe Dämpfung hin. Mach auch Kr mal kleiner.

Gruß!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Edit: Ich meinte Kp.

Autor: Heiko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denny schrieb:
> Was soll ich für Werte eingeben, dass es besser funktioniert??

Weiß ich doch auch nicht. Kennst du die Systemparameter? Dann such dir 
ein Reglerentwurfsverfahren (Eigenwertvorgabe, Ziegler-Nichols, 
Kessler...) aus und mach.

Wenn nicht: Erstmal Systemparameter bestimmen...

MfG, Heiko

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo...

wenn es mit der Theorie nicht so hinhaut.... Faustregel.

1) I und D -Anteil zu null setzen..
    KI = 0 oder TI=9999999999
    KD = 0
2) KP langsam erhöhen bis man merkt das der Regler instabil wird.
   -> einfach mal schubsen...
      dabei stelle ich mir im Moment die Frage wie du die Postion 
bestimmst??
3) KP ca. 30% zurück stellen und den I-Anteil langsam erhöhen, bis
   das System ausreichend schnell ein den Bereich einschwingt den du dir
   vorstellst.

Den D-Anteil braucht man eigentlich nur wenn du schnelle Reaktionen 
brauchst,
aber in der Regel heizt du damit die Schwingneigung deines Reglers sehr 
an.

kleine Regel
P - gibt Power
I - gibt die PräzIsion
D - den SpeeD

;O)
Nicht sehr akademisch, aber vielleicht hilfts.
Gruss
Gary

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

Bewertung
0 lesenswert
nicht lesenswert
G. B. schrieb:
> KP langsam erhöhen bis man merkt das der Regler instabil wird.
Er ist die ganze Zeit instabil.
Ohne den Kd-Anteil geht es gar nicht.

G. B. schrieb:
> dabei stelle ich mir im Moment die Frage wie du die Postion
Die Position wird mit einem HAL815 gemessen.
Unten ist der Istwert 255 und oben (oder Magnet ganz weg) ist 0.

Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, dass ich nicht alles auf Anhieb versteh.
Ich bin noch ein Anfänger.

Mit den Werten:
Kp = 0.6
Kd = 100
Ki = 0.7 oder 0

Schwebt der Magnet sehr ruhig.
Allerdings ist der Istwert 200 bei einem Sollwert von 120.
Versteh ich nicht...

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur mal noch als Tip das Thema ist nicht ganz neu bzw. wird wegen des
Show-Effekts - denn man gerne mit nimmt - häufig gemacht.

Beitrag "Schwebende Kugel"

Zum Thema Einstellregeln... mein Tip war sehr pauschal und basiert
auf Erfahrung mit Antriebsregelungen. Die Anderen vor mir hatten aber
schon recht... genaue Angaben kann man nur mit einem Streckenmodel 
machen.

Dabei hilft dir aber auch das Web einfach mal nach "Regelung schwebender 
Magnet" eingeben.

Zu der Regelabweichung die du nun siehst, fällt mir im Moment nur 
folgendes ein:
a) Hast du Begrenzungen in deinem Regler überschritten - z.B. I-Anteil.
b) Hast du eine evtl. irgendwo in der Rechnung eine "Normierung", so das 
der
   Regler gar nicht die Differenz sieht.

Sorry wenn ich nun so pauschal bleibe, aber ich müsste mich selbst 
reinwühlen um dir mehr sagen zu können. Evtl. gibt es ja jemanden der 
das schon selber gemacht hat.

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ki = 0.7 oder 0

sorry das hab ich erst im Nachgang gelesen, nun ja wenn KI=0 das gleiche 
Ergebniss liefert wie KI=0.7 dann tippe ich schwer darauf das du dein
I-Anteil entweder überläuft oder gar nicht funktioniert.

dazu vielleicht einfach mal nach
http://www.rn-wissen.de/index.php/Regelungstechnik...
schauen

Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ich habe eben gemerkt, dass mein I-Anteil völlig falsch berechnet 
wird.
Ich probiere gerade das hin zu bekommen.

Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist irgendwie komisch:
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt

    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255

    Delta = Istwert - Sollwert
    P = Delta * Kp

    Esum = Esum + Delta
    If Esum > 255 Then Esum = 255
    If Esum < -255 Then Esum = -255
    I = Esum
    I = I * Ki

    Delta = Istwert - LetzterIstwert                          'Istwertsveränderung Berechnen
    D = Delta * Kd                                          'Dämpfung hinzurechnen

    Pulsweite = P + D
    Pulsweite = Pulsweite + I

Wenn ich Ki = 0 einstelle, Sollte der I-Anteil immer 0 sein.
Dann funktioniert aber die ganze Regelung nicht mehr.
Wenn ich jetzt aber anstatt "Pulsweite = Pulsweite + I" "Pulsweite = 
Pulsweite" schreibe, funktioniert alles.
Wie kann das sein!?

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Denny,

mit diesem Schnipsel kann ich leider auch nichts anfangen...
Vorschlag...
Implementiere den PID-Regler erst einmal in einer
eigenen Funktion und nimm den ganzen Normierungskram da raus.
Dann kannst du deinen Regler auch "offline" testen.
Die notwendigen Normierungen kannst du schlieslich vorher bzw.
nachher machen.
Wenn du dann noch Probleme mit dem Regler haben solltest, dann
poste nur diesen Code-Teil mit konkreter Testsequenz....
und nicht immer deinen ganzen Interpreter ;O) - den zwar
sterben für Bildschirmseiten keine Bäume, aber der Leser steht dafür
zwischen selbigen (Wald).

Viel Erfolg,
Gary

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Denny schrieb:
> Wenn ich jetzt aber anstatt "Pulsweite = Pulsweite + I" "Pulsweite =
> Pulsweite" schreibe, funktioniert alles.
> Wie kann das sein!?

mit dem was ich da lesen kann... nein

Autor: Denny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So jetzt habe ich mal alles rausgeschmissen.

'|---------------------------------Controller---------------------------------|'
$regfile = "m8def.dat"                                      'ATmega8
$crystal = 14745600                                         'Quarzfrequenz (Extern); Standart: 14745600
$baud = 230400                                              'Funktionierende Baudrate; Standart: 230400

$hwstack = 100
$swstack = 100
$framesize = 100                                            'Freier Speicherplatz für Variablen...


'|---------------------------------Variablen----------------------------------|'
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten

Dim Istwert As Integer                                      'Analoge Spannung des Hallsensors
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
Dim Letzteristwert As Integer                               'Istwert der letzten Messung
Dim Delta As Integer                                        'Die Veränderung der Spannung des Hallsensors während eines Zyklus
Dim Esum As Integer
Dim Kp As Single                                            'Die Dämpfung des Magneten
Dim Ki As Single
Dim Kd As Integer
Dim P As Single
Dim I As Single
Dim D As Integer
Dim Sollwert As Integer


'|--------------------------------Konfiguration-------------------------------|'
Declare Sub Regelung_berechnen()                            'Unterprogramm um die Variablen zu Regelung_Berechnen
Declare Sub Regelung_auswerten()                            'Unterprogramm um die berechneten Werte auszuwerten

Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler

Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation


'|--------------------------------Einstellungen-------------------------------|'
Set Eingeschaltet                                           'Einschalten

Kd = 255                                                    '255
Ki = 0
Kp = 1
Sollwert = 120                                              '120


'|--------------------------------Hauptprogramm-------------------------------|'
Do
    If Eingeschaltet = 1 Then
       Start Adc
          Istwert = Getadc(0)                               'Analoge Spannung des Hallsensors messen
       Stop Adc

       Call Regelung_berechnen                              'Werte Berechnen

       Call Regelung_auswerten                              'Werte Auswerten (begrenzen)
    Else
       Pulsweite = 0
    End If

    Pwm1a = Pulsweite                                       'Spulenstrom regeln
Loop


'|-----------------------------------Regelung---------------------------------|'
Sub Regelung_berechnen()
    Istwert = Istwert - 512                                 'Weil der Sensor die halbe Spannung in einer Richtung angibt
    Shift Istwert , Right , 1                               'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255

    Delta = Istwert - Sollwert                              'Proportionalanteil
    P = Delta * Kp

    Esum = Esum + Delta                                     'Integralanteil
    If Esum > 1023 Then Esum = 1023
    If Esum < -1023 Then Esum = -1023
    I = Esum * Ki
    'If I < 0.01 Then I = 0

    Delta = Istwert - Letzteristwert                        'Differenzialanteil
    D = Delta * Kd

    Pulsweite = P + D
    Pulsweite = Pulsweite + I
End Sub


'|----------------------------------Auswerten---------------------------------|'
Sub Regelung_auswerten()
    If Istwert > 0 Then
       If Pulsweite > 255 Then Pulsweite = 255              'Begrenzungen der Pulsweite einhalten
       If Pulsweite < 0 Then Pulsweite = 0                  'Begrenzungen der Pulsweite einhalten

       Letzteristwert = Istwert                             'LetzterIstwert setzen
    Else                                                    'Wenn der Magnet falsch rum hängt wird er umgedreht
       Pulsweite = 255
    End If
End Sub

Wie man sehen kann ist Ki auf 0 eingestellt.
Normalerweise müsste der Magnet jetzt schweben, wenn auch an der 
falschen Position.
Es tut sich aber gar nichts.
Wenn ich nun schreibe Pulsweite = Pulsweite + 0 anstatt Pulsweite = 
Pulsweite + I (I-Faktor sollte jetzt 0 sein) funktioniert alles.

Das ist doch nicht normal!
Was mache ich falsch??

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Danny...
funktioniert, funktioniert nicht... ist ja schön, aber
was kommt den da an Zahlen rein und raus?
Generier dir doch einfach mal nen Sprung als Testsignal.. und vergiss 
deine Hardware erst einmal.

Auserdem berechnest du den D-Anteil falsch.. es müsste sinngemäß so 
lauten
D = ( (Delta - Delta_alt)/TA) * KD
wenn du die Abtastzeit in KD ziehst
D = (Delta - Delta_alt) * KD

Gruss,
Gary

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe die Ta mal aus dem Spiel gelassen, damit ich nicht noch mit 
Kommazahlen arbeiten muss.
Sie ist ja eh konstant.
Desshalb ist mein Kd auch so groß.

Den I-Anteil habe ich mittlerweile aufgegeben...
Es geht ja auch so.

Autor: G. B. (garyb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein D-Anteil war aber auch kein D-Anteil.. was du hast sind zwei 
P-Regler
parallel geschalten.

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm
Komischerweise funktioniert es aber.
Ich schau mir es in den nächsten Tagen mal an...

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

Bewertung
0 lesenswert
nicht lesenswert
Gast2 schrieb:
> Hm
> Komischerweise funktioniert es aber.

Das heißt nicht viel.

Testen kann immer nur das Vorhandensein eines Fehlers nachweisen, nie 
dessen Fehlen. Wenn etwas scheinbar so funktioniert wie vorgesehen, kann 
das auch eine glückliche Fügung sein.

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe den Code nun angepasst.
Sub Regelung_berechnen()
    'Weil der Sensor die halbe Spannung in einer Richtung angibt
    Istwert = Istwert - 512
    'Der Wert geht bis 512, die Pulsweitemodulation arbeitet aber bis 255
    '--> Wert durch 2 teilen
    Shift Istwert , Right , 1

    'Proportionalanteil ausrechnen
    Regeldifferenz = Istwert - Sollwert
    P = Regeldifferenz * Kp

    'Differenzialanteil ausrechnen
    'Es wurde auf Ta verzichtet
    D = Regeldifferenz - Regeldifferenz_alt
    D = D * Kd

    'Alte Regeldifferenz speichern
    Regeldifferenz_alt = Regeldifferenz

    'Anteile zusammenrechnen
    Stellgroesse = P + D
End Sub
Das Ergebnis ist genau das gleiche.

Ich verstehe das mit dem I-Anteil nicht ganz.
Ich habe bereits viel versucht, komme aber nicht an das gewünschte 
Ergebnis.
Könnte ihr den I-Anteil bitte in diesen Codeschnipsel einbauen??

Vielen Dank!
Denny

Autor: gary (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wir sind doch hier in einem Do-It-Yourself-Forum und nicht bei 
Make-It-For-Me :O)

Beitrag "PID-Regler mit anti-Windup"

Gruss,
Gary

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
'|---------------------------PD-Regelung: berechnen---------------------------|'
Sub Regelung_berechnen()
    'Weil der Sensor die halbe Spannung in einer Richtung angibt
    Istwert = Istwert - 512
    'Der Wert geht bis 512, die Pulsweitemodulation arbeitet aber bis 255
    '--> Wert durch 2 teilen
    Shift Istwert , Right , 1

    'Proportionalanteil ausrechnen
    Regeldifferenz = Istwert - Sollwert
    P = Kp * Regeldifferenz

    'Regelungsdifferenzen addieren
    Regelungsdifferenzsumme = Regelungsdifferenzsumme + Regeldifferenz
    If Regelungsdifferenzsumme > 30000 Then
       Regelungsdifferenzsumme = 30000
    Elseif Regelungsdifferenzsumme < -30000 Then
       Regelungsdifferenzsumme = -30000
    End If
    I = Ki * Regelungsdifferenzsumme
    I = I / 500

    'Differenzialanteil ausrechnen
    'Es wurde auf Ta verzichtet
    D = Regeldifferenz - Regeldifferenz_alt
    D = Kd * D

    'Alte Regeldifferenz speichern
    Regeldifferenz_alt = Regeldifferenz

    'Anteile zusammenrechnen
    Stellgroesse = P + D
    Stellgroesse = Stellgroesse + I
End Sub
Leider schwebt der Magnet immer noch nicht an der Sollwertstelle.

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

Bewertung
0 lesenswert
nicht lesenswert
Warum

    I = I / 500

Du hast ein Ki. Wenn du einen Faktor brauchst, dann sollte der dort 
drinn mit enthalten sein.

Die 30000 für den Antiwindup: Hast du die empirisch ermittelt?

Generell: Wenn du eine Möglichkeit hast, der Regelung zuzusehen, dann 
solltest du die nutzen. Ideal wäre ein LCD, auf dem man sich die Werte 
für P, D und I ausgeben lassen kann. In deinem Fall ist natürlich der I 
Wert interessant. Wenn die Regelung funktioniert, müsste I im Laufe der 
Zeit immer kleiner werden, bis 0 erreicht wird (das zeigt an, dass die 
Sollposition erreicht ist)

Auch sollte man im Auge haben, ob es physikalisch überhaupt möglich ist, 
die Sollposition zu erreichen. Wenn dein Hubmagnet nicht in der Lage ist 
den schwebenden Magneten in seiner aktuellen Position noch höher zu 
heben, dann versagt die beste Regelung. Sprich: Mehr als Vollgas 
(Vollstrom) kann der Hubmagnet nicht geben. Reicht das nicht aus, den 
schebenden Magneten gegen die Schwerkraft noch weiter zu heben, dann 
kann sich deine Regelung brausen gehen. In dem Fall müsste man im I Wert 
erkennen, dass er sich nie aus seiner Anti-Windup Position herausbewegt, 
sprich ständig 30000 liefert.

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kd: 255
Kp: 1
Ki: 5

Jetzt schwebt der Magnet bei einem Sollwert von 80 so um den Wert 125.

I bleibt die ganze Zeit konstant auf 37.
Fällt euch da irgendwas auf??

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

Bewertung
0 lesenswert
nicht lesenswert
Gast2 schrieb:
> Kd: 255
> Kp: 1
> Ki: 5
>
> Jetzt schwebt der Magnet bei einem Sollwert von 80 so um den Wert 125.
>
> I bleibt die ganze Zeit konstant auf 37.
> Fällt euch da irgendwas auf??

Was macht Stellgroesse ?
Was machen P und D

Wenn I die ganze Zeit auf 37 bleibt, dann sollte doch Stellgroesse 
eigentlich immer größer und größer werden, wenn sich P und D nicht 
verändern (D sollte sowie so 0 sein, weil es ja keine Differenz gibt)

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P = ungefähr 50
D = 0 (manchmal -255 oder 255)
I = 37

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

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Wenn I die ganze Zeit auf 37 bleibt, dann sollte doch Stellgroesse
> eigentlich immer größer und größer werden,

Denkfehler von mir.

Aber wenn I bei 37 bleibt bedeutet das ja letztendlich, dass 
Regeldifferenz zu 0 geworden ist.

Wekche Datentypen hast du eigentlich? Kann sich eine Regeldifferenz von 
125-80 überhaupt dahingehend auswirken, dass Regeldifferenzsumme noch 
größer wird?

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Regeldifferenz ist immer so ungefähr 50...

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

Bewertung
0 lesenswert
nicht lesenswert
Gast2 schrieb:
> Die Regeldifferenz ist immer so ungefähr 50...


Das müsste sich dann aber hier
    Regelungsdifferenzsumme = Regelungsdifferenzsumme + Regeldifferenz
    If Regelungsdifferenzsumme > 30000 Then
       Regelungsdifferenzsumme = 30000
    Elseif Regelungsdifferenzsumme < -30000 Then
       Regelungsdifferenzsumme = -30000
    End If
    I = Ki * Regelungsdifferenzsumme
    I = I / 500
so auswirken, dass Regelungsdifferenzsumme immer größer wird und als 
folge davon I ebenfalls größer wird.

Jetzt gilt es herauszufinden, warum dem nicht so ist :-)

Die Datentypen von Regelungsdifferenzsumme und I sind zunächst 
interessant, um die Eigenschaften der Variablen zu kennen.

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe Ki (unnötig denk ich gerade) und I jetzt als Long definiert.
Es scheint jetzt zu funktionierten.
Ki = 5
Sollwert = 80
Istwert = 90 bis 100 ungefähr.

Bei Sollwert = 150 ist der Istwert 150! yeah :-)

Also funktioniert es jetzt nur wenn der Magnet etwas mehr unten Schwebt.
Wenn er höher Schwebt, fängt er an zu zittern und erreicht den Sollwert 
nicht ganz.

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

Bewertung
0 lesenswert
nicht lesenswert
Gast2 schrieb:
> Ich habe Ki (unnötig denk ich gerade) und I jetzt als Long definiert.
> Es scheint jetzt zu funktionierten.
> Ki = 5
> Sollwert = 80
> Istwert = 90 bis 100 ungefähr.
>
> Bei Sollwert = 150 ist der Istwert 150! yeah :-)
>
> Also funktioniert es jetzt nur wenn der Magnet etwas mehr unten Schwebt.
> Wenn er höher Schwebt, fängt er an zu zittern und erreicht den Sollwert
> nicht ganz.

Schau dir wieder die Regelabweichungswerte an. Jetzt könnte es sein, 
dass du schon in die Begrenzung kommst. Eventuell hilft hier spielen mit 
den Werten für Kp und Ki

Auch durch die Division durch 500 verlierst du was.

Wenn da alles Ganzzahlen sind, dann läufst du auch in folgendes Problem:
 1/3 + 1/3 + 1/3 -> 0 !!!

Hier könnte es helfen, alle Werte mal 10 (*) zu nehmen, damit 1 
Kommastelle bis zur Addition erhalten bleibt und die erst nach der 
Summation der Einzelglieder abzuschneiden.

(*) oder mal 2 oder 4 oder 8. Auf jeden Fall eine 2-er Potenz. Dann 
dividiert es sich schneller.

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe nicht ganz was das mit Kommastellen zu tun hat...

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

Bewertung
0 lesenswert
nicht lesenswert
Gast2 schrieb:
> Ich verstehe nicht ganz was das mit Kommastellen zu tun hat...


    I = Ki * Regelungsdifferenzsumme
    I = I / 500

Ki war 5
Du dividierst durch 500

Nehmen wir einfasch mal an, Regelungsdifferenzsumme wäre 99

   I = 5 * 99     = 495
   I = I / 500    = 495 / 500 = 0


rein mathematisch ist aber 99 * 5 / 500 = 0.99 also nahezu 1

-> Obwohl eine Regeldifferenz von 99 Einheiten besteht, wird der I Wert 
mit 0 errechnet und damit diese Regeldifferenz nicht mehr ausgeglichen.

Autor: Gast2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verstehe.
Ich werde es anpassen.

Ich habe in der Zwischenzeit einige Messungen gemacht und eine 
Excelkennlinie angefertigt.
Sinnlos oder sinnvoll darüber kann man streiten - jedenfalls geht das 
sehr einfach mit VisualBasic und RS232.

http://www4.pic-upload.de/10.03.10/vqt57ab45pk7.png

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.