Forum: Mikrocontroller und Digitale Elektronik Regelung eines unstabilen Systems


von Denny (Gast)


Lesenswert?

Hallo.
Ich habe eine Regelung programmiert, die einen Magneten schweben lässt.
Unter dem Magnet befindet sich ein HAL815.
Je tiefer der Magnet desto höher die Spannung (GetADC; 2,5...5V)

Meine Frage:
Was kann ich an der Regelung verbessern??
1
'+------------------------------------------------------------------------------+'
2
'| Titel             :     Endarbeit: "Schwebender Magnet"                      |'
3
'+------------------------------------------------------------------------------+'
4
'| Funktion          :     Der Magnet schwebt unter einer Spule.                |'
5
'| Anschlüsse        :     PB1=PWM, PC0=ADC                                     |'
6
'+------------------------------------------------------------------------------+'
7
'| Name              :     Weinberg Denny                                       |'
8
'| Copyright         :     Copyright © Denny 2009                               |'
9
'| E-Mail Adresse    :     Denny_Weinberg@hotmail.com                           |'
10
'+------------------------------------------------------------------------------+'
11
12
13
'|----------------------------------Controller----------------------------------|'
14
$regfile = "m8def.dat"                                      'ATmega8
15
$crystal = 3686400                                          'Quarzfrequenz (Extern)
16
$baud = 9600                                                'Funktionierende Baudrate
17
18
19
'|----------------------------------Variablen-----------------------------------|'
20
Dim Position As Integer                                     'Analoge Spannung des Hallsensors
21
Dim Pulsweite As Integer                                    'Die Pulsweite für den Spulenstrom
22
Dim Alteposition As Integer                                 'Position der letzten Messung
23
Dim Positionsveraenderung As Integer                        'Die Veränderung der Spannung des Hallsensors während eines Zyklus
24
25
Dim Daempfung As Integer                                    'Die Dämpfung des Magneten
26
27
Dim Sollwert As Integer                                     'Damit man die Position des Magneten verstellen kann
28
29
Dim Nummer As Byte                                          'ASCII-Code die seriell ankommen
30
Dim Zeichen As String * 5                                   'Seriell ankommende Zeichen
31
32
Dim Eingeschaltet As Bit                                    'Um alles auszuschalten
33
34
Dim Anfangsbuchstabe As String * 1                          'Hilfsbuchstabe bei Änderungen
35
Dim Endwert As String * 4                                   'Der wirkliche Wert der benötigt wird
36
37
Dim Zeichengroesse As Byte
38
39
40
'|---------------------------------Konfiguration--------------------------------|'
41
Declare Sub Berechnen()                                     'Unterprogramm um die Variablen zu berechnen
42
Declare Sub Auswerten()                                     'Unterprogramm um die berechneten Werte auszuwerten
43
44
Config Adc = Single , Prescaler = Auto , Reference = Avcc   'Analog-Digital-Wandler
45
Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down       'Pulsweitenmodulation
46
47
On Urxc Serialin                                            'Interrupt der seriellen schnittstelle
48
Enable Urxc                                                 'Interrupt der seriellen schnittstelle einschalten
49
50
Enable Interrupts                                           'Interrupts einschalten
51
52
53
'|------------------------------Eingänge und Ausgänge---------------------------|'
54
Config Portb.0 = Output                                     'Freier Pin (LED)
55
56
57
'|---------------------------------Einstellungen--------------------------------|'
58
Set Eingeschaltet                                           'Einschalten
59
60
Daempfung = 150                                             'Standartwert
61
62
Sollwert = 100
63
64
Portb.0 = 1                                                 'LED Einschalten
65
66
67
'|---------------------------------Hauptprogramm--------------------------------|'
68
Do
69
    If Eingeschaltet = 1 Then
70
          Start Adc
71
                   Position = Getadc(0)                     'Analoge Spannung des Hallsensors messen
72
          Stop Adc
73
          Toggle Portb.0                                    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
74
          Call Berechnen
75
76
          Call Auswerten
77
    Else
78
          Pulsweite = 0
79
    End If
80
81
    Compare1a = Pulsweite                                   'Spulenstrom regeln
82
Loop
83
84
85
'|--------------------------------Werte berechnen-------------------------------|'
86
Sub Berechnen()
87
          Position = Position - 512                         'Weil der Sensor die halbe Spannung in einer Richtung angibt
88
89
          Position = Position / 2                           'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255
90
91
          Pulsweite = Position - Sollwert
92
93
          Positionsveraenderung = Position - Alteposition   'Positionsveränderung berechnen
94
          Positionsveraenderung = Positionsveraenderung * Daempfung       'Dämpfung hinzurechnen
95
96
          Pulsweite = Pulsweite + Positionsveraenderung     'Pulsweite berechnen
97
98
          'Pulsweite = Pulsweite + Offset                    'Offset hinzurechnen
99
End Sub
100
101
102
'|-----------------------------------Auswerten----------------------------------|'
103
Sub Auswerten()
104
          If Position > 0 Then
105
                    If Pulsweite > 255 Then Pulsweite = 255 'Begrenzungen der Pulsweite einhalten
106
                    If Pulsweite < 0 Then Pulsweite = 0     'Begrenzungen der Pulsweite einhalten
107
108
                    Alteposition = Position                 'Alteposition setzen
109
          Else                                              'Wenn der Magnet falsch rum hängt wird er umgedreht
110
                    Pulsweite = 255
111
          End If
112
End Sub
113
114
115
'|---------------------Interrupt der seriellen Schnittstelle--------------------|'
116
Serialin:
117
      Nummer = Inkey()                                      'ASCII-Code einlesen
118
119
      Select Case Nummer
120
               Case 13                                      'Nummer 13 ist das Enter, das gesendet wird, wenn alles gesendet ist
121
                      Select Case Zeichen
122
                            Case "EiA"
123
                                Print Eingeschaltet         'Zurücksenden, ob das Gerât eingeschaltet ist
124
                            Case "OFF"
125
                                Print Sollwert
126
                            Case "DAE"
127
                                Print Daempfung             'Dämpfung zurücksenden
128
                            Case "Aus"
129
                                Reset Eingeschaltet         'Ausschalten
130
                            Case "Ein"
131
                                Set Eingeschaltet           'Einschalten
132
                            Case "PB0"
133
                                Toggle Portb.0              'PortB.0 Ein- /Ausschalten
134
                            Case Else
135
                                Zeichengroesse = Len(zeichen) - 1       'Zeichengröße, um den Endwert herauszufinden
136
137
                                Anfangsbuchstabe = Left(zeichen , 1)       'Anfangsbuchstabe rausschneiden
138
                                Endwert = Right(zeichen , Zeichengroesse)       'Endwert rausschneiden
139
140
                                Select Case Anfangsbuchstabe
141
                                     Case "O"
142
                                          Sollwert = Val(endwert)       'Es wurde das Offset gesenden
143
                                     Case "D"
144
                                          Daempfung = Val(endwert)       'Es wurde die Dämpfung gesenden
145
                                End Select
146
                      End Select
147
148
                      Zeichen = ""                          'Zeichen zurücksetzen
149
               Case Else
150
                      Zeichen = Zeichen + Chr(nummer)       'Nächstes zeichen hinzusetzen
151
      End Select
152
Return                                                      'Ins Hauptprogramm zurückspringen
153
'|------------------------------------The End-----------------------------------|'

Da sind noch viele Zusatzsachen drin.
Es geht hauptsächlich um das Unterprogramm "Berechnen".

Danke!
Denny

von Weingut P. (weinbauer)


Lesenswert?

Du must den ADC nicht dauernd ein und ausschalten, einmal einschalten 
reicht.

Denny schrieb:
> Position = Position / 2

geht eleganter mit shift Position , right , 1


ansonsten schau mal nach PID-Regler, z.B. hier:

http://www.avr-praxis.de/forum/showthread.php?t=22

oder da:

http://www.mikrocontroller.net/attachment/552/PID.doc

von Alex P. (drdatensalat)


Lesenswert?

Da hast du dir eines der kompliziertesten Probleme der Regelungstechnik 
herausgesucht!
Vor allem weil die 1.) Anziehungskraft des Magneten quadratisch(!) mit 
dem Abstand abnimmt - also extem nichtlinear ist und 2.) Der Magnet eine 
Induktivität darstellt die den Strom verzögert; dieser zählt aber für 
die Anziehungskraft.
Außerdem hätte ich statt eines Hallsensors (der ja hauptsächlich deinen 
Schwebemagneten misst) eine Lichtschranke zur Lagemessung erwartet.
Wie soll das überhaupt gehen?

Der vorgeschlagene PID-Regler ist auf jeden Fall die richtige Richtung.
Die benötigten PID-Koeffizienten musst du aber ausprobieren. Außerdem 
muss dein digitaler Regelkreis sehr(!) schnell sein (einschließlich der 
A/D-Wandlung des Signals vom Hallsensor).
Eigentlich würde man für so eine Aufgabe einen analogen Regelkreis (mit 
unterlagerten Regelkreisen) nehmen.

von Purzel H. (hacky)


Lesenswert?

Sehr schnell ? Was auch immer das bedeutet. Falls so ein System denn 
schwingen wuerde, was waere denn eine moegliche Resonanzfrequenz ? 1 kHz 
...bmmmmmmmmmm... eher nicht. 100 Hz ... baaaaaaaaa ... eher nicht 
allenfalls 10Hz. Dh ein kilosample sollte genuegen. Allerdings muss man 
die quadratische Kennlinie wegmachen.

von dr.schmock (Gast)


Lesenswert?

Anmerkung:
Der PID-Regler ist gut für stabile Systeme, z.B. zur Temperaturregelung.
Wenn dein System instabil ist (es hat einen I-Anteil), sollte der Regler 
keinen I-Anteil haben - sonst wird dein geregeltes System i.A. instabil.
D.h. wenn du den PID-Regler vom Link benutzt, dann I-Koeffizienten auf 0 
setzen. (wird also ein PD-Regler)

Ich denke, dass ein µC schnell genug sein kann, den Magneten zu regeln.

von dr.schmock (Gast)


Lesenswert?

..aber zu deiner eigentlichen Frage... was verbessern ? ...

dein Regler scheint ja der richtige Typ zu sein. Nun musst du eben 
rausbekommen, was die idealen Koeffizienten sind (welche Dämpfung, 
welche Schnelligkeit).
Das kann dir hier im Forum keiner sagen. Wenn du keine mathematische 
Beschreibung des Systems hast, musst du einfach probieren

von Tueftler (Gast)


Lesenswert?

Hm, was meinst du denn mit Dämpfung? Davon habe ich noch nichts gehört?
Ich dachte immer es gibt nur den P I und D Anteil. Oder willst du das 
System aktiv bedämpfen?

Grüße,
Tueftler

von lassativ (Gast)


Lesenswert?

..aber zu deiner eigentlichen Frage... was verbessern ? ...

so lange du standard mit T anstatt D schreibst...
... weigert sich der Magnet mit PID zu schweben.

von Thilo M. (Gast)


Lesenswert?

Tueftler schrieb:
> Oder willst du das
> System aktiv bedämpfen?

Kann z.B. so erfolgen:
1
ZK = 80;
2
TG = TG*(1-1/ZK)+T/ZK;
3
T = TG;

Wobei es sich hier um eine Temperaturregelung handelt.
Gedämpft wird der Istwert, also die gemessene Temperatur.

T = gemessene Temperatur und Variable zur Weiterverrechnung
TG = gedämpfter Temperaturwert (globale Variable, Wert muss erhalten 
bleiben)
ZK = Zeitkonstante, abhängig von der Abtastrate

von dr.schmock (Gast)


Lesenswert?

@ Tueftler:
hast schon recht.
Aber ich hatte mich auf den Quelltext bezogen, da heißt ein Faktor 
"Daempfung". Das kann man so machen, ist halt nicht wie aus dem 
Lehrbuch.

von Michael von Gersdorff (Gast)


Lesenswert?

Hallo Denny

Der beste Weg so eine schwierige Strecke zu regeln ist vermutlich ein 
Regler mit sogenanntem Beobachtersystem. Das bedeutet daß Du zunächt 
einen Strom zum Halten des Magneten erzeugst der dem Theoretischen Wert 
oder einer Näherung aus gemessenen Versuchen entspricht (Strom als 
Funktion der Magnetposition). Damit kann Dein Magnet zwar noch nicht auf 
Position gehalten werden aber der Strom ist schon einigermaßen korrekt 
und ändert sich je nach Position des Magneten. Zu diesem Strom addierst 
bzw. subtraierst Du noch einen Korrekturwert falls der Magnet nicht in 
der von Dir gewünschten Position schwebt. Als letzte Verbesserung machst 
Du den Korrekturwert selbst in einer Tabelle auch noch abhängig von der 
Position des Magnetes.
Solch ein Reglekreis ist einem PID Regler weit überlegen und hat nicht 
die Nachteile eines Integralanteils (Destabilisierung)
MfG
Michael

von Denny (Gast)


Lesenswert?

Der Magnet schwebt ja bereits mit den Berechnungen.
Allerdings habe ich diese Berechnungen selbst "erfunden".
Der Magnet Schwebt auch nicht an der Position des Sollwertes.
Aber wie soll ich das machen?

Irgendwie müsste ich schreiben: If Position > Sollwert Then... Else...

Ich bin noch auf der Schule und wir sehen gerade Regelungstechnik.
Aber wir sind noch ganz am Anfang.

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.