1 | '+----------------------------------------------------------------------------+'
|
2 | '| Titel : Endarbeit: "Schwebender Magnet" |'
|
3 | '+----------------------------------------------------------------------------+'
|
4 | '| Funktion : Der Magnet schwebt unter einer Spule. |'
|
5 | '| Anschlüsse : PB1=PWM; PC0=ADC; PD2=RC5; PB0=LED |'
|
6 | '+----------------------------------------------------------------------------+'
|
7 | '| Name : Weinberg Denny |'
|
8 | '| E-Mail Adresse : Denny_Weinberg@hotmail.com |'
|
9 | '+----------------------------------------------------------------------------+'
|
10 |
|
11 | '+----------------------------------------------------------------------------+'
|
12 | '| PID-Regler : |'
|
13 | '| |'
|
14 | '| RC5-Empfang : |'
|
15 | '| |'
|
16 | '| RS232-Schnittstelle : |'
|
17 | '+----------------------------------------------------------------------------+'
|
18 |
|
19 |
|
20 | '|---------------------------------Controller---------------------------------|'
|
21 | $regfile = "m8def.dat" 'ATmega8
|
22 | $crystal = 14745600 'Quarzfrequenz (Extern); Standart: 14745600
|
23 | $baud = 230400 'Funktionierende Baudrate; Standart: 230400
|
24 |
|
25 | $hwstack = 100
|
26 | $swstack = 100
|
27 | $framesize = 100 'Freier Speicherplatz für Variablen...
|
28 |
|
29 |
|
30 | '|---------------------------------Variablen----------------------------------|'
|
31 | Dim Eingeschaltet As Bit 'Um alles auszuschalten
|
32 |
|
33 | Dim Istwert As Integer 'Analoge Spannung des Hallsensors
|
34 | Dim Pulsweite As Integer 'Die Pulsweite für den Spulenstrom
|
35 | Dim Lastistewert As Integer 'Istwert der letzten Messung
|
36 | Dim Delta As Single 'Die Veränderung der Spannung des Hallsensors während eines Zyklus
|
37 | Dim Kp As Single 'Die Dämpfung des Magneten
|
38 | Dim Ki As Single
|
39 | Dim Kd As Single
|
40 | Dim P As Single
|
41 | Dim I As Single
|
42 | Dim D As Single
|
43 | Dim Integrator As Integer
|
44 | Dim Sollwert As Single
|
45 |
|
46 | Dim Rs232nummer As Byte 'ASCII-Code die seriell ankommen
|
47 | Dim Zeichen As String * 10 'Seriell ankommende Zeichen
|
48 | Dim Anfangsbuchstabe As String * 2 'Hilfsbuchstabe bei Änderungen
|
49 | Dim Endwert As String * 8 'Der wirkliche Wert der benötigt wird
|
50 | Dim Zeichengroesse As Byte 'Hilfsvariable um das erste Zeichen herauszufiltern
|
51 |
|
52 | Dim Impulslaenge As Word
|
53 | Dim Rc5bitnummer As Byte
|
54 | Dim Tempdaten As Word
|
55 | Dim Befehl As Byte
|
56 | Dim Empfangsfehler As Byte
|
57 | Dim Wiederholen_erlaubt As Bit
|
58 | Dim Letzter_befehl As Byte
|
59 | Dim Rc5timervorgabe As Byte
|
60 | Dim Interruptvektor As Bit
|
61 |
|
62 |
|
63 | '|--------------------------------Konfiguration-------------------------------|'
|
64 | Declare Sub Rc5()
|
65 | Declare Sub Regelung_berechnen() 'Unterprogramm um die Variablen zu Regelung_Berechnen
|
66 | Declare Sub Regelung_auswerten() 'Unterprogramm um die berechneten Werte auszuwerten
|
67 | Declare Sub Rc5_berechnen() 'Unterprogramm, um den RC5-Code zu berechnen
|
68 | Declare Sub Rc5_auswerten() 'Unterprogramm, um den RC5-Code auszuwerten
|
69 |
|
70 | Config Adc = Single , Prescaler = Auto , Reference = Avcc 'Analog-Digital-Wandler
|
71 |
|
72 | Config Timer1 = Pwm , Pwm = 8 , Prescale = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down 'Pulsweitenmodulation
|
73 |
|
74 | On Urxc Isr_rs232 'Interrupt der seriellen schnittstelle
|
75 | Enable Urxc 'Interrupt der seriellen schnittstelle einschalten
|
76 |
|
77 | Config Timer0 = Timer , Prescale = 8
|
78 | On Ovf0 Isr_timer0
|
79 | Enable Timer0
|
80 |
|
81 | Rc5timervorgabe = 26 'Impulslänge bei RC5 1,778ms --> 8000 Überlaufe / Sekunde
|
82 | Timer0 = Rc5timervorgabe
|
83 |
|
84 | Config Int0 = Rising 'Externer Interrupt; Steigende Flanke
|
85 |
|
86 | Reset Ddrd.2 'Ausgang des Infrarormodules
|
87 | Set Portd.2 'Pullup ein
|
88 |
|
89 | On Int0 Isr_int0
|
90 | Enable Int0
|
91 |
|
92 | Enable Interrupts 'Interrupts einschalten
|
93 |
|
94 |
|
95 | '|-----------------------------Eingänge und Ausgänge--------------------------|'
|
96 | Set Ddrb.0 'Freier Pin (LED)
|
97 |
|
98 |
|
99 | '|--------------------------------Einstellungen-------------------------------|'
|
100 | Set Eingeschaltet 'Einschalten
|
101 |
|
102 | Kd = 255 '255
|
103 | Ki = 0.7
|
104 | Kp = 1
|
105 | Sollwert = 120 '120
|
106 |
|
107 | Set Portb.0 'LED Einschalten
|
108 |
|
109 | Set Wiederholen_erlaubt 'Damit man eine Taste gedrückt halten kann
|
110 |
|
111 |
|
112 | '|--------------------------------Hauptprogramm-------------------------------|'
|
113 | Do
|
114 | Call Rc5
|
115 |
|
116 | If Eingeschaltet = 1 Then
|
117 | Start Adc
|
118 | Istwert = Getadc(0) 'Analoge Spannung des Hallsensors messen
|
119 | Stop Adc
|
120 |
|
121 | Call Rc5 'Sonst bekommt er nicht alle RC5-Codes mit
|
122 |
|
123 | Call Regelung_berechnen 'Werte Berechnen
|
124 |
|
125 | Call Rc5
|
126 |
|
127 | Call Regelung_auswerten 'Werte Auswerten (begrenzen)
|
128 | Else
|
129 | Pulsweite = 0
|
130 | End If
|
131 |
|
132 | Pwm1a = Pulsweite 'Spulenstrom regeln
|
133 | Loop
|
134 |
|
135 |
|
136 | '|--------------------------------Alles mit RC5-------------------------------|'
|
137 | Sub Rc5()
|
138 | If Interruptvektor = 1 Then
|
139 | Call Rc5_berechnen
|
140 |
|
141 | If Rc5bitnummer = 14 Then
|
142 | Call Rc5_auswerten
|
143 | End If
|
144 |
|
145 | Impulslaenge = 0
|
146 | Interruptvektor = 0
|
147 | End If
|
148 | End Sub
|
149 |
|
150 |
|
151 | '|-------------------------------Werte Berechnen------------------------------|'
|
152 | Sub Regelung_berechnen()
|
153 | Istwert = Istwert - 512 'Weil der Sensor die halbe Spannung in einer Richtung angibt
|
154 |
|
155 | Shift Istwert , Right , 1 'Word-->Byte = /4 und Hallsensor = halbe Spannung = *2 => /2 =>0...255
|
156 |
|
157 | Delta = Istwert - Sollwert
|
158 | P = Delta * Kp
|
159 |
|
160 | I = Delta * 0.005
|
161 | I = I * Ki
|
162 | If Pulsweite <= 1 Then
|
163 | Else
|
164 | If Pulsweite < 1023 Then Integrator = Integrator + I
|
165 | End If
|
166 |
|
167 | Incr Integrator
|
168 | If Integrator < -1023 Then Integrator = -1023 'Begrenzung der Ausgangsgröße
|
169 | If Integrator > 1023 Then Integrator = 1023
|
170 | If Ki < 0.01 Then Integrator = 0
|
171 |
|
172 | Delta = Istwert - Lastistewert 'Istwertsveränderung Berechnen
|
173 | D = Delta * Kd 'Dämpfung hinzurechnen
|
174 |
|
175 | Pulsweite = D + P 'Pulsweite Berechnen
|
176 | Pulsweite = Pulsweite + Integrator
|
177 | End Sub
|
178 |
|
179 |
|
180 | '|----------------------------------Auswerten---------------------------------|'
|
181 | Sub Regelung_auswerten()
|
182 | If Istwert > 0 Then
|
183 | If Pulsweite > 255 Then Pulsweite = 255 'Begrenzungen der Pulsweite einhalten
|
184 | If Pulsweite < 0 Then Pulsweite = 0 'Begrenzungen der Pulsweite einhalten
|
185 |
|
186 | Lastistewert = Istwert 'LastIstewert setzen
|
187 | Else 'Wenn der Magnet falsch rum hängt wird er umgedreht
|
188 | Pulsweite = 255
|
189 | End If
|
190 | End Sub
|
191 |
|
192 | '|----------------------------------Berechnen---------------------------------|'
|
193 | Sub Rc5_berechnen()
|
194 | Select Case Impulslaenge
|
195 | Case Is > 1500: '-> startimpuls, nach empgfangsfehler muss immer erst ein solcher kommen.
|
196 | Rc5bitnummer = 1
|
197 | Tempdaten = 1
|
198 | Empfangsfehler = 0
|
199 | Case 26 To 29: '-> große Länge: vorher 0, jetzt 1 + 0
|
200 | If Empfangsfehler = 0 Then
|
201 | Shift Tempdaten , Left 'hinzufügen einer 0
|
202 | Incr Tempdaten 'umwandeln in 1
|
203 | Shift Tempdaten , Left 'hinzufügen einer 0
|
204 | Incr Rc5bitnummer 'bei Kombination '10' fehlt ein Impuls
|
205 | End If
|
206 | Case 19 To 22: '-> mittlere Länge: vorher 1, jetzt 1 + 0 oder vorher 0 jetzt 1
|
207 | If Empfangsfehler = 0 Then
|
208 | Shift Tempdaten , Left 'hinzufügen einer 0
|
209 | Incr Tempdaten 'umwandeln in 1
|
210 | If Tempdaten.1 = 1 Then 'vorher gab es eine 1
|
211 | Shift Tempdaten , Left 'hinzufügen einer 0
|
212 | Incr Rc5bitnummer 'bei Kombination '10' fehlt ein Impuls
|
213 | End If
|
214 | End If
|
215 | Case 12 To 15: '-> kleine Länge --> gleicher Wert wie vorher
|
216 | If Empfangsfehler = 0 Then
|
217 | Shift Tempdaten , Left , 1 'hinzufügen einer 0
|
218 | If Tempdaten.1 = 1 Then 'vorher gab es eine 1
|
219 | Incr Tempdaten 'umwandeln in 1
|
220 | End If
|
221 | End If
|
222 | Case Is > 400: 'aber kleiner 1500, dann war's eine Pause zwischen Befehlen beim Dauerdrücken
|
223 | If Empfangsfehler = 1 Or Wiederholen_erlaubt = 1 Then
|
224 | Rc5bitnummer = 1
|
225 | Tempdaten = 1
|
226 | Empfangsfehler = 0
|
227 | End If
|
228 | Case Else
|
229 | Empfangsfehler = 1
|
230 | End Select
|
231 | End Sub
|
232 |
|
233 | '|----------------------------------Auswerten---------------------------------|'
|
234 | Sub Rc5_auswerten()
|
235 | Befehl = Tempdaten And &B00111111 'Überflüssige Bits herausfiltern
|
236 | If Befehl < 64 Then
|
237 | If Wiederholen_erlaubt = 1 Or Befehl <> Letzter_befehl Then
|
238 | Letzter_befehl = Befehl
|
239 | Select Case Befehl
|
240 | Case 3
|
241 | Sollwert = Sollwert + 10
|
242 | Case 6
|
243 | Sollwert = Sollwert - 10
|
244 | Case 9
|
245 | Toggle Eingeschaltet
|
246 | End Select
|
247 |
|
248 | Befehl = 0
|
249 | End If
|
250 | End If
|
251 | End Sub
|
252 |
|
253 |
|
254 | '|--------------------Interrupt der seriellen Schnittstelle-------------------|'
|
255 | Isr_rs232:
|
256 | Rs232nummer = Inkey() 'ASCII-Code einlesen
|
257 |
|
258 | Select Case Rs232nummer
|
259 | Case 13 'RS232Nummer 13 ist das Enter, das gesendet wird, wenn alles gesendet ist
|
260 | Select Case Zeichen
|
261 | Case "EIA"
|
262 | Print Eingeschaltet 'Zurücksenden, ob das Gerät eingeschaltet ist
|
263 | Case "POS"
|
264 | Print Istwert 'Istwert zurücksenden
|
265 | Case "SOL"
|
266 | Print Sollwert 'Sollwert zurücksenden
|
267 | Case "AUS"
|
268 | Reset Eingeschaltet 'Ausschalten
|
269 | Case "EIN"
|
270 | Set Eingeschaltet 'Einschalten
|
271 | Case "PB0"
|
272 | Toggle Portb.0 'LED Umschalten
|
273 | Case "P0E"
|
274 | Set Portb.0 'PortB.0 Einschalten
|
275 | Case "P0A"
|
276 | Reset Portb.0 'PortB.0 Ausschalten
|
277 | Case "KP"
|
278 | Print Kp
|
279 | Case "KI"
|
280 | Print Ki
|
281 | Case "KD"
|
282 | Print Kd
|
283 | Case Else
|
284 | Zeichengroesse = Len(zeichen) - 2 'Zeichengröße, um den Endwert herauszufinden
|
285 |
|
286 | Anfangsbuchstabe = Left(zeichen , 2) 'Anfangsbuchstabe rausschneiden
|
287 | Endwert = Right(zeichen , Zeichengroesse) 'Endwert rausschneiden
|
288 |
|
289 | Select Case Anfangsbuchstabe
|
290 | Case "SO"
|
291 | Sollwert = Val(endwert) 'Es wurde der Sollwert gesendet
|
292 | Case "KP"
|
293 | Kp = Val(endwert) 'Es wurde die Dämpfung gesendet
|
294 | Case "KI"
|
295 | Ki = Val(endwert)
|
296 | Case "KD"
|
297 | Kd = Val(endwert)
|
298 | End Select
|
299 | End Select
|
300 |
|
301 | Zeichen = "" 'Zeichen zurücksetzen
|
302 | Case Else
|
303 | Zeichen = Zeichen + Chr(rs232nummer) 'Nächstes zeichen hinzusetzen
|
304 | End Select
|
305 | Return 'Ins Hauptprogramm zurückspringen
|
306 |
|
307 |
|
308 | '|----------------------Interrupt des Timer0 (Überlauf)-----------------------|'
|
309 | Isr_timer0:
|
310 | Timer0 = Rc5timervorgabe
|
311 | Incr Impulslaenge
|
312 | If Impulslaenge > 65000 Then 'Überlauf von Impulslaenge verhindern (nach 65535 kommt 0),
|
313 | 'damit Start (Impulslaenge > 500) sicher erkannt wird
|
314 | Impulslaenge = 1501
|
315 | End If
|
316 | Return
|
317 |
|
318 | '|--------------------Interrupt des externen Pins PIND.2----------------------|'
|
319 | Isr_int0: 'RC5 Impuls erkannt
|
320 | Incr Rc5bitnummer
|
321 | Interruptvektor = 1
|
322 | Return
|
323 | '|----------------------------------The End-----------------------------------|'
|