Hallo, hat jemand Erfahrung mit PID-Regler unter BASCOM AVR? Kann mir jemand einen Tip geben, wo ich suche soll oder gar ein Programmbespiel? Habe bis jetzt nur das Buch Büttner, digitale Regelungen gefunden
I am looking for some exampl of software for PID regulator on microcntroller AVR for motor or temperatur.
"AVR221: Discrete PID controller" http://atmel.com/dyn/products/app_notes.asp?family_id=607 http://www.roboternetz.de/wissen/index.php/Regelungstechnik
$regfile = "m8535.dat" ' -----[ Program Description ]-------------------------------------------------- ' ' This program implements an PID algorithm in BASCOM ' ' This File is partialy based on a program from ?????? and ' I do not intent to touch any of his rights !!! ' So for correct use of his copyrights please inform as marked below! ' ????????? ' ' ' -----[ Disclaimer ]----------------------------------------------------------- ' ' This example is offered on an "AS IS" basis, no warranty expressed or implied. ' The programers disclaim liability of any damages associated with the use of ' the hardware or software described herein. You use it on your own risk. ' I'm not able to provide any free support. ' ' Copyright (c) 2001 Mike Eitel all rights reserved ' ' -----[ Revision History ]----------------------------------------------------- ' ' 060529 - Version AVRPID Ver .95 Basic PID functionality Mike Eitel ' ' -----[ Aliases ]-------------------------------------------------------------- $sim ' Helps testing in a simulation ' -----[ Constant ]------------------------------------------------------------- ' -----[ Variables ]------------------------------------------------------------ Dim Auto_mode As Bit ' Regulator on ? Dim Manual_value As Single ' Output if not regulating Dim Sp As Single ' Setpoint Dim Pv As Single ' Process Value Dim Cv As Single ' PID output Dim First_execution As Byte ' First start recognition Dim Initial_error As Single ' Startup difference Dim A As Byte ' Tmp for random Dim B As Single ' Tmp for random ' -----[ Start of program ]----------------------------------------------------- ' -----[ Start of program ]----------------------------------------------------- ' -----[ Start of program ]----------------------------------------------------- Auto_mode = 1 ' Permanent running choosen First_execution = 0 ' Set permanent running algorithm Manual_value = 40 ' Output if not regulating = on Sp = 37 ' Value to aim to Cyclic: ' -----[ Start of endless running program ]------------------------------------- Waitms 50 ' PID must run deterministic ' time slices Gosub Regulator ' Call the PID allgorithm Gosub Object ' Call the simulated outer loop Goto Cyclic ' -----[ End of endless running program ]------------------------------------ ' -----[ End of endless running program ]------------------------------------ ' -----[ End of endless running program ]------------------------------------ ' ------------------------------------------------------------------------ --- ' -----------------------------[ Subroutines ]------------------------------- ' ------------------------------------------------------------------------ --- Object: ' -----[ Start of simulated regulation loop ]-------------------------------- Pv = Pv + Cv ' linear function used If Pv = Sp Then ' When PV=SP then make a A = Rnd(100) ' random SP jump Sp = 1 * A End If Return Regulator: ' -----[ Start of PID Regulator]--------------------------------------------- ' -----[ Constant ]---------------------------------------------------------- Const Kp = .85 ' Proportional factor Const Ki = .67 ' Integration factor Const Kd = .15 ' Derivation factor ' -----[ Variables ]--------------------------------------------------------- 'Dim Sp As Single ' Setpoint 'Dim Pv As Single ' Process Value 'Dim Cv As Single ' PID output ' 'Dim First_execution As Byte ' First start recognition 'Dim Initial_error As Single ' Startup difference Dim Last_pv As Single ' Last PV Dim Last_sp As Single ' Last SP Dim Sum_error As Single ' Summed error value Dim D_pv As Single ' Derrivated delta PV Dim Error As Single ' Difference between SP and PV Dim Pterm As Single ' Proportional calculated part Dim Iterm As Single ' Integrated calculated part Dim Dterm As Single ' Derivated calculated part ' -----[ Code ]-------------------------------------------------------------- If Auto_mode = 1 Then ' -------- Regulating modus Error = Sp - Pv Sum_error = Sum_error + Error Iterm = Ki * Sum_error ' Integrated CV part ' -------- First time startup If First_execution < 2 Then If First_execution = 0 Then Sum_error = Manual_value / Ki First_execution = 1 Initial_error = Error End If Pterm = 0 Dterm = 0 If Initial_error > 0 And Error < 0 Then First_execution = 2 Last_pv = Pv End If If Initial_error < 0 And Error > 0 Then First_execution = 2 Last_pv = Pv End If Last_sp = Sp ' -------- Normal calculation loop Else D_pv = Last_pv - Pv Last_pv = Pv Dterm = Kd * D_pv ' Derivated CV part If Sp = Last_sp Then ' -------- Normal loop when setpoint not changed Pterm = Kp * Error ' Proportional CV part ' -------- Loop when setpoint changed Else Pterm = 0 Dterm = 0 If Sp > Last_sp And Pv > Sp Then Last_sp = Sp Last_pv = Pv End If If Sp < Last_sp And Pv < Sp Then Last_sp = Sp Last_pv = Pv End If End If ' Enf of SP change seperation ' End If ' Enf of first time running seperation ' Cv = Pterm + Iterm ' Summing of the tree Cv = Cv + Dterm ' calculated terms ' -------- Forced modus Else ' When running in non regulationg modus Cv = Manual_value ' Set output to predefined value First_execution = 0 ' restart bumpless End If Return
Ich hab vor Kurzem einen PID Regler mit Atmega8 + L293 aufgebaut. Ich wollte damit einen DC-Motor mit selbst gebastelten Encoder regeln. Der Encoder besteht aus einer auf Overheadfolie bedruckten Codescheibe und einer Gabellichtschranke. Das Programm funktionier bisher ganz gut. Ich kann die Parameter Kp, Ki, und Kd verstellen und mir die Drehzahl via Uart/RS232 anzeigen lassen. Die Impulse werden mittels Interrupt an INT0 gezählt. Die Regelung erfolgt in 40ms Abstand mittels Timerinterrupt. Dummerweise habe ich nun aber keine Idee, wie der Regler abgeändert werden muss um eine Positionsregelung zu erhalten. Ich möchte sagen, dass sich der Motor z.B. 20 Umdrehungen nach rechts drehen und dort stoppen soll. Ich möchte gerne eine Linearführung damit antreiben bzw. so etwas wie eine Servomotorsteuerung aufbauen. Ich hab zwar immer wieder etwas mit Kaskadenregelung gelesen, aber wie das nun in Bascom gehen soll, ist mir noch nocht ganz klar. Wenn ich recht verstanden habe brauche ich quasi noch einen äußeren Regelkreis, der mir aus den Umdrehungen pro Sekunde noch irgendwie eine Position verrät und diese dann Regelt. Vielleicht hätte da jemand den Einen oder Anderen Codebrocken für mich? Mein PID Drehzahlregler:
1 | '------------------------------------------------------------------------------ |
2 | 'name : PID Drehzahlregelung |
3 | 'copyright : (c) 2009 by Türk Mario |
4 | 'purpose : Drehzahlregelung von DC-Motoren |
5 | ' |
6 | 'micro : Mega8 |
7 | '------------------------------------------------------------------------------ |
8 | $regfile = "m8def.dat" |
9 | $crystal = 8000000 |
10 | $hwstack = 32 |
11 | $swstack = 8 |
12 | $framesize = 24 |
13 | $baud = 38400 |
14 | |
15 | Config Pinb.0 = Output 'LED |
16 | Config Pinb.3 = Output 'PWM |
17 | Config Pinc.0 = Output 'Richtung |
18 | Config Pinc.1 = Output 'Richtung |
19 | Config Pind.2 = Input |
20 | Portd.2 = 1 'Pullup einschalten |
21 | Config Portd.0 = Input 'Uart Eingang |
22 | Portd.0 = 1 |
23 | |
24 | Dim E As Single |
25 | Dim Esum As Single |
26 | Dim Ealt As Single |
27 | Dim Kp As Single |
28 | Dim Ki As Single |
29 | Dim Kd As Single |
30 | Dim Ta As Single |
31 | Dim Proportionalteil As Single |
32 | Dim Integralteil As Single |
33 | Dim Differentialteil As Single |
34 | Dim Cv As Single |
35 | Dim Gv As Single |
36 | |
37 | Dim Flanken As Integer 'Gezählte Flanken |
38 | Dim Flankenperturn As Integer 'Anzahl der Flanken pro Umdrehung |
39 | Dim Umdrehungen As Single |
40 | Dim Solldrehzahl As Single |
41 | Dim Maxdrehzahl As Single |
42 | |
43 | Dim Befehl As String * 9 |
44 | Dim Bcount As Integer |
45 | Dim Ar(5) As String * 5 |
46 | |
47 | Kp = 30 |
48 | Ki = 8 |
49 | Kd = 0.2 |
50 | Ta = 0.04 |
51 | Solldrehzahl = 20 |
52 | Maxdrehzahl = 80 |
53 | Flankenperturn = 30 |
54 | |
55 | E = 0 |
56 | Esum = 0 |
57 | Ealt = 0 |
58 | |
59 | Config Int0 = Falling 'Fallende Flanke löst den Interupt aus |
60 | Enable Interrupts |
61 | Enable Int0 |
62 | On Int0 Encoder_zaehlen 'Encoder_zaehlen wird im Falle des Interrupts ausgelöst |
63 | |
64 | |
65 | Config Timer1 = Timer , Prescale = 256 'Timer1 führt alle 40ms die Regelung durch |
66 | On Timer1 Regler |
67 | Timer1 = 64285 ' 65535 - (8000000/256/Ta) Ta = 25 |
68 | Enable Timer1 |
69 | Start Timer1 |
70 | 'Timer 2 ist für die Motor PWM zuständig |
71 | Config Timer2 = Pwm , Compare Pwm = Clear Up , Pwm = On , Prescale = 64 |
72 | Ocr2 = 30 |
73 | 'Richtung Vorgeben: |
74 | Portc.0 = 1 |
75 | Portc.1 = 0 |
76 | 'Motor PWM Starten |
77 | Enable Timer2 |
78 | Start Timer2 |
79 | $sim |
80 | |
81 | Do 'Hauptprogramm |
82 | |
83 | Input "" , Befehl |
84 | Bcount = Split(befehl , Ar(1) , ": ") |
85 | If Ar(1) = "Kp" Then 'Einstell- und Infomöglichkeiten |
86 | Kp = Val(ar(2)) |
87 | End If |
88 | If Ar(1) = "Ki" Then |
89 | Ki = Val(ar(2)) |
90 | End If |
91 | If Ar(1) = "Kd" Then |
92 | Kd = Val(ar(2) ) |
93 | End If |
94 | If Ar(1) = "soll" Then |
95 | Solldrehzahl = Val(ar(2)) |
96 | End If |
97 | If Ar(1) = "max" Then |
98 | Maxdrehzahl = Val(ar(2)) |
99 | End If |
100 | If Ar(1) = "rps" Then |
101 | Print Umdrehungen |
102 | End If |
103 | If Ar(1) = "pid" Then |
104 | Print "Kp=" ; Kp |
105 | Print "Ki=" ; Ki |
106 | Print "Kd=" ; Kd |
107 | End If |
108 | If Ar(1) = "pwm" Then |
109 | Print Ocr2 |
110 | End If |
111 | Loop |
112 | |
113 | Encoder_zaehlen: 'Hier werden alle Flanken gezählt |
114 | Incr Flanken |
115 | Return |
116 | |
117 | |
118 | |
119 | Regler: 'Der PID Regler Algorithmus |
120 | Timer1 = 64285 |
121 | Umdrehungen = Flanken / Ta 'Ermittlung der Umdrehungen pro Sekunde |
122 | Umdrehungen = Umdrehungen / Flankenperturn |
123 | Flanken = 0 'Flankenzähler auf null setzen |
124 | |
125 | E = Solldrehzahl - Umdrehungen 'Regelabweichung berechnen |
126 | Esum = Esum + E 'Fehler aufsummieren |
127 | |
128 | Proportionalteil = Kp * E 'Proportionalglied berechnen |
129 | |
130 | Integralteil = Ki * Ta 'Integralglied berechnen |
131 | Integralteil = Integralteil * Esum |
132 | |
133 | Differentialteil = E - Ealt 'Differentialglied berechnen |
134 | Differentialteil = Differentialteil / Ta |
135 | Differentialteil = Differentialteil * Kd |
136 | |
137 | Cv = Proportionalteil + Integralteil 'Alle Gliede zusammenfassen |
138 | Cv = Cv + Differentialteil |
139 | |
140 | Gv = Maxdrehzahl / 255 'Übertragen auf PWM Duty Cycle |
141 | Gv = Gv * Cv |
142 | |
143 | If Gv < 0 Then Gv = 0 |
144 | If Gv > 255 Then Gv = 255 |
145 | Ocr2 = Gv 'Motor PWM wird entsprechend angepasst |
146 | |
147 | |
148 | |
149 | Ealt = E 'Regelfehler merken für den nächsten Durchlauf |
150 | |
151 | |
152 | Return |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.