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.