1 | ; #####################################################################
|
2 | ; ### Lüfterregelung 1.0 07/2004 (c) Uwe Freese ###
|
3 | ; ### http://www.uwe-freese.de mail@uwe-freese.de ###
|
4 | ; ### ###
|
5 | ; ### You can use this program freely, but please always include ###
|
6 | ; ### this copyright information when you share it. ###
|
7 | ; ### ###
|
8 | ; ### Diese Software kann frei verwendet werden, aber bitte immer ###
|
9 | ; ### diesen Copyright-Hinweis hinzufügen, wenn es weitergegeben ###
|
10 | ; ### wird! ###
|
11 | ; #####################################################################
|
12 |
|
13 | .CSEG
|
14 | .ORG 0x00
|
15 |
|
16 | .include "2313def.inc"
|
17 |
|
18 | ; ------------------ Diese Werte dürfen geändert werden ------------------
|
19 |
|
20 | .equ MotorThrMIN = 40 ; min. Lüfterleistung x/255 (im Bereich 1..254)
|
21 | ; Muss kleiner als MotorThrMAX sein. So einstellen, dass der Motor bei dem Wert nicht stehenbleibt.
|
22 | .equ MotorThrMAX = 254 ; max. Lüfterleistung x/255 (im Bereich 1..254)
|
23 | .equ MotorThrSTART = 150 ; Lüfterleistung am Anfang x/255
|
24 | .equ anatest_every = 60 ; alle x Schleifendurchgänge nur Temperatur messen
|
25 | ; ein Schleifendurchgang dauert ca. 43,5 ms
|
26 | ; bei Wert von 150 also Messung alle 6,5 s
|
27 | ; damit dauert einmal komplett herunter (Maximal- zu Minimaldrehzahl) ca. 12,6 Min.
|
28 | ; damit dauert einmal komplett herauf (Minimal- zu Maximaldrehzahl) ca. 5 Min.
|
29 | ; Der Wert ist abhängig vom verwendeten Lüfter. Bei einem Lüfter mit hoher Luftleistung z.B. 200 nehmen.
|
30 | ; bei einem Lüfter mit niedriger Luftleistung (Papst 4412F/GL) niedrigen Wert nehmen (80).
|
31 | .equ STARTUPDELAY = 60 ; Wie lange am Anfang Motor komplett einschalten? (x * 50 ms)
|
32 |
|
33 | ; ------------------ Für die Regelung irrelevante Werte (dürfen geändert werden) ------------------
|
34 |
|
35 | .equ LEDBLINK_LOOPVAL = 7 ; in welchem Rythmus blinken (Taktverhältnis LEDBLINK_LOOPVAL/LEDBLINK_LOOPVALMAX)
|
36 | .equ LEDBLINK_LOOPVALMAX = 14 ; in welchem Rythmus blinken (Taktverhältnis LEDBLINK_LOOPVAL/LEDBLINK_LOOPVALMAX)
|
37 | .equ LEDBLINKQUICK_LOOPVAL = 2 ; in welchem Rythmus blinken (Taktverhältnis LEDBLINKQUICK_LOOPVAL/LEDBLINKQUICK_LOOPVALMAX)
|
38 | .equ LEDBLINKQUICK_LOOPVALMAX = 4 ; in welchem Rythmus blinken (Taktverhältnis LEDBLINKQUICK_LOOPVAL/LEDBLINKQUICK_LOOPVALMAX)
|
39 |
|
40 | ; ------------------ Folgende Werte möglichst nicht ändern ------------------
|
41 |
|
42 | ;Port B pins
|
43 | .equ AIN0 = 0
|
44 | .equ AIN1 = 1
|
45 | .equ MOTOR = 5
|
46 |
|
47 | ; Bargraph:
|
48 | ; 0-6 ist PortD Pin 0-6
|
49 | ; 7-8 ist PortB Pin 2-3
|
50 |
|
51 | ;Belegung PortD
|
52 | ; Pin 0 = LED 0 (Bargraph)
|
53 | ; Pin 1 = LED 1 (Bargraph)
|
54 | ; Pin 2 = LED 2 (Bargraph)
|
55 | ; Pin 3 = LED 3 (Bargraph)
|
56 | ; Pin 4 = LED 4 (Bargraph)
|
57 | ; Pin 5 = LED 5 (Bargraph)
|
58 | ; Pin 6 = LED 6 (Bargraph)
|
59 |
|
60 | ;Belegung PortB
|
61 | ; Pin 0 = AIN0
|
62 | ; Pin 1 = AIN1
|
63 | ; Pin 2 = LED 7 (Bargraph)
|
64 | ; Pin 3 = LED 8 (Bargraph)
|
65 | ; Pin 4 = LED 9 (Bargraph) (ROT)
|
66 | ; Pin 5 = Motor-Ausgang
|
67 | ; Pin 6 = Temperatur-Test Pin 0 (Standard = aus)
|
68 | ; Pin 7 = Temperatur-Test Pin 1 (Standard = ein)
|
69 |
|
70 | ; Temperatur-Test-Pins
|
71 | ; normale Einstellung ist: Pin 0 ein, Pin 1 aus
|
72 | ; durch Schalten von beiden Pins auf aus, kann überprüft werden, ob die Temperatur gerade "stark" fällt
|
73 | ; durch Schalten von beiden Pins auf ein, kann überprüft werden, ob die Temperatur gerade "stark" steigt
|
74 |
|
75 | ; Werte, ab denen die LEDs an sind
|
76 | .equ LED0_on_if_higher = 23
|
77 | .equ LED1_on_if_higher = 46
|
78 | .equ LED2_on_if_higher = 70
|
79 | .equ LED3_on_if_higher = 93
|
80 | .equ LED4_on_if_higher = 116
|
81 | .equ LED5_on_if_higher = 139
|
82 | .equ LED6_on_if_higher = 162
|
83 | .equ LED7_on_if_higher = 185
|
84 | .equ LED8_on_if_higher = 209
|
85 | .equ LED9_on_if_higher = 232
|
86 |
|
87 | .def temp = r16 ; allgemein verwendbare temp-Variable
|
88 | .def temp2 = r17 ; Level zur Anzeige von Geschwindigkeit für 10 LEDs (0..10)
|
89 | .def mydelay = r18
|
90 | .def startuploopcounter = r19
|
91 | .def motorloopcounter = r20 ; Motor-Schleifenzähler
|
92 | .def MotorThr = r21 ; momentaner Wert, bis zu dem Motor ein ist
|
93 | .def anatest_loop = r22
|
94 | .def history = r23 ; von den letzten 8 Messungen abspeichern, ob current_motor_thr
|
95 | ; erhöht (1) oder erniedrigt (0) wurde
|
96 | .def history_quick = r24 ; von den letzten 8 Messungen abspeichern, ob current_motor_thr
|
97 | ; schnell erhöht/erniedrigt (1) oder nur normal erhöht/erniedrigt wurde (0)
|
98 | .def LED_loop = r25
|
99 | .def LED0_on = r26
|
100 | .def LED9_on = r27
|
101 | .def ledblink_loopval_current = r28 ; für tatsächliches Blinkverhalten verwendet (abhängig von Temp-Differenz stark/schwach)
|
102 | .def ledblink_loopvalmax_current = r29 ; für tatsächliches Blinkverhalten verwendet (abhängig von Temp-Differenz stark/schwach)
|
103 |
|
104 | ; --------- Initialisierung ---------
|
105 |
|
106 | ; Stack initialisieren
|
107 | ldi temp, 0xB5; RAMEND == 0xDF
|
108 | out SPL, temp
|
109 |
|
110 | ; Watchdog einschalten
|
111 | ldi temp, 0b00001111
|
112 | out WDTCR, temp
|
113 |
|
114 | ; Rest
|
115 | ldi LED0_on,0
|
116 | ldi LED9_on,0
|
117 | ldi LED_loop, LEDBLINK_LOOPVALMAX
|
118 | ldi anatest_loop,1 ; gleich nach Start die erste Messung machen
|
119 |
|
120 |
|
121 | ldi temp,0b11111100 ; initialise port B as I/O, 6 OUT 2 IN
|
122 | out DDRB,temp
|
123 |
|
124 | ldi temp,0b00101111 ; key columns all low and
|
125 | out PORTB,temp ; active pull ups on rows enabled
|
126 |
|
127 | ldi temp,0b01111111 ; initialise port D as I/O, 7 OUT
|
128 | out DDRD,temp
|
129 |
|
130 | rcall RESET_HIGH_TEMP_DIFF_PINS
|
131 |
|
132 | ; damit der Motor anläuft 5 Sek. einschalten
|
133 | ldi temp,0b01111111 ; alle LEDs an PORT D
|
134 | out PORTD,temp
|
135 | sbi PORTB,2 ; LED an Port B
|
136 | sbi PORTB,3 ; LED an Port B
|
137 | sbi PORTB,4 ; LED an Port B
|
138 |
|
139 | ldi MotorThr,MotorThrMAX ; volle Drehzahl
|
140 | rcall STARTUPLOOP ; 3 sec Motor komplett einschalten
|
141 |
|
142 |
|
143 | ; history mit "normal höher" oder "normal niedriger" füllen, damit auch gleich PRO_ADJUST anspringen kann, wenn es stark unterschiedlich ist.
|
144 | ldi history_quick,0b00000000; clear history
|
145 | sbic ACSR,ACO ; skip next instruction if output is low
|
146 | rjmp INIT_HOEHER
|
147 | ldi history,0b00000000 ; clear history
|
148 | rjmp MOTOR_SLOWDOWN
|
149 |
|
150 | INIT_HOEHER:
|
151 | ldi history,0b11111111 ; clear history
|
152 |
|
153 | ; Motor langsam von Maximalwert auf Default stellen
|
154 | MOTOR_SLOWDOWN:
|
155 | subi MotorThr,3 ; mit 3-facher Geschwindigkeit herunterregeln (ergibt etwa 2-3 Sek für's Herunterregeln)
|
156 | rcall BARGRAPH
|
157 | rcall MOTORLOOP
|
158 | cpi MotorThr,MotorThrSTART ; schon auf Defaultwert?
|
159 | brlo MAINLOOP ; dann nicht verringern
|
160 | rjmp MOTOR_SLOWDOWN
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 | MAINLOOP:
|
171 |
|
172 | ; --------- Spannung vergleichen ---------
|
173 | rcall MOTORLOOP
|
174 | rcall LEDBLINK
|
175 |
|
176 | ; nur von Zeit zu Zeit einen anatest machen
|
177 | dec anatest_loop
|
178 | cpi anatest_loop,0
|
179 | brne MAINLOOP
|
180 |
|
181 | ldi anatest_loop,anatest_every
|
182 | lsl history ; Platz in History schaffen (Bit 0 auf 0)
|
183 | lsl history_quick ; Platz in History schaffen (Bit 0 auf 0)
|
184 | ldi ledblink_loopval_current, LEDBLINK_LOOPVAL ; Blinkwerte auf Standard
|
185 | ldi ledblink_loopvalmax_current, LEDBLINK_LOOPVALMAX ; Blinkwerte auf Standard
|
186 |
|
187 | sbic ACSR,ACO ; skip next instruction if output is low
|
188 | rjmp HOEHER
|
189 |
|
190 | ; Ist-Temperatur stark höher -> MotorThr um 5 erhöhen
|
191 | ; Ist-Temperatur normal höher -> MotorThr um 1 erhöhen
|
192 | ; Ist-Temperatur stark niedriger -> MotorThr um 2 verringern
|
193 | ; Ist-Temperatur normal niedriger -> MotorThr um 1 verringern
|
194 |
|
195 | NIEDRIGER:
|
196 | ; Auswertung, ob "stark fallend"
|
197 | ; Wenn Temperatur fallend, dann hat Temp.fühler höheren Widerstand. Spannung an AIN2 ist dann höher.
|
198 | ; Jetzt also Spannung an AIN1 auch höher machen, um zu sehen, ob sie dann an AIN2 immer noch höher ist.
|
199 | ; Spannung an AIN1 wird erhöht, in dem Temp 0 auch EINgeschaltet wird.
|
200 | sbi PORTB, 6
|
201 | rcall MY_DELAY ; ca 1 ms warten, damit die Spannung sich anpasst, falls Kapazitäten
|
202 | rcall MY_DELAY
|
203 | rcall MY_DELAY
|
204 | rcall MY_DELAY
|
205 | rcall MY_DELAY
|
206 |
|
207 | sbic ACSR,ACO ; skip next instruction if output is high
|
208 | rjmp NIEDRIGER_NORMAL
|
209 |
|
210 | NIEDRIGER_STARK:
|
211 | sbr history_quick,1 ; setze Bit 0 auf 1 in history_quick
|
212 | ldi ledblink_loopval_current, LEDBLINKQUICK_LOOPVAL ; Blinkwerte auf schnell-blinkend
|
213 | ldi ledblink_loopvalmax_current, LEDBLINKQUICK_LOOPVALMAX ; Blinkwerte auf schnell-blinkend
|
214 | rcall DEC_MOTORTHR
|
215 | NIEDRIGER_NORMAL:
|
216 | rcall DEC_MOTORTHR
|
217 | rjmp HISTORY ; und springe dann zu HISTORY
|
218 |
|
219 | HOEHER:
|
220 | sbr history,1 ; setze Bit 0 auf 1 in history
|
221 | ; Auswertung, ob "stark steigend"
|
222 | ; Wenn Temperatur steigend, dann hat Temp.fühler niedrigeren Widerstand. Spannung an AIN2 ist dann niedriger.
|
223 | ; Jetzt also Spannung an AIN1 auch niedriger machen, um zu sehen, ob sie an AIN2 dann immer noch niedriger ist.
|
224 | ; Spannung an AIN1 wird erniedrigt, in dem Temp 1 auch AUSgeschaltet wird.
|
225 | cbi PORTB, 7
|
226 | rcall MY_DELAY ; ca 1 ms warten, damit die Spannung sich anpasst, falls Kapazitäten
|
227 | rcall MY_DELAY
|
228 | rcall MY_DELAY
|
229 | rcall MY_DELAY
|
230 | rcall MY_DELAY
|
231 |
|
232 | sbis ACSR,ACO ; skip next instruction if output is low
|
233 | rjmp HOEHER_NORMAL
|
234 |
|
235 | HOEHER_STARK:
|
236 | sbr history_quick,1 ; setze Bit 0 auf 1 in history_quick
|
237 | ldi ledblink_loopval_current, LEDBLINKQUICK_LOOPVAL ; Blinkwerte auf schnell-blinkend
|
238 | ldi ledblink_loopvalmax_current, LEDBLINKQUICK_LOOPVALMAX ; Blinkwerte auf schnell-blinkend
|
239 | rcall INC_MOTORTHR
|
240 | rcall INC_MOTORTHR
|
241 | rcall INC_MOTORTHR
|
242 | rcall INC_MOTORTHR
|
243 | HOEHER_NORMAL:
|
244 | rcall INC_MOTORTHR
|
245 |
|
246 | ; --------- History-Auswertung ---------
|
247 |
|
248 | HISTORY:
|
249 | ; zunächst HighTempDiff-Pins wieder auf Normalzustand
|
250 | rcall RESET_HIGH_TEMP_DIFF_PINS
|
251 |
|
252 | ldi LED0_on,0 ; LED 0 Blinkmodus AUS (default)
|
253 | ldi LED9_on,0 ; LED 10 Blinkmodus AUS (default)
|
254 |
|
255 | mov temp,history
|
256 | andi temp,0b01111111 ; letzte 7 Bits betrachten
|
257 | cpi temp,0b01111111 ; wenn alle 6 Bits EIN
|
258 | breq LEVEL_HOCH
|
259 | rjmp LEVEL_WEITER
|
260 |
|
261 | LEVEL_HOCH:
|
262 | ldi LED9_on,1 ; LED 10 EIN
|
263 | rjmp HISTORY_END
|
264 |
|
265 | LEVEL_WEITER:
|
266 | mov temp,history
|
267 | andi temp,0b01111111 ; letzte 7 Bits betrachten
|
268 | cpi temp,0b00000000 ; wenn alle 6 Bits AUS
|
269 | breq LEVEL_RUNTER
|
270 | rjmp HISTORY_END
|
271 | LEVEL_RUNTER:
|
272 | ldi LED0_on,1 ; LED 0 EIN
|
273 |
|
274 | HISTORY_END:
|
275 | rcall BARGRAPH
|
276 | rjmp MAINLOOP
|
277 |
|
278 | ; ---------- ENDE -----------
|
279 |
|
280 |
|
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 | ; --------- Bargraph-Anzeige ---------
|
287 |
|
288 | BARGRAPH:
|
289 | ; Anzahl LEDs = (MotorThr - MotorThrMIN) / 20
|
290 | ; dadurch max = (254 - 25) / 24 = 9,6
|
291 | ; dadurch min = (25 - 25) / 24 = 0
|
292 | BARGRAPH_LEDCHECK0:
|
293 | ; Test, ob LED0 gerade blinkt (dann nichts ändern)
|
294 | cpi LED0_on,0
|
295 | brne BARGRAPH_LEDCHECK1
|
296 | ; normaler Check (wie bei anderen LEDs)
|
297 | cbi PORTD,0
|
298 | cpi MotorThr,LED0_on_if_higher
|
299 | brlo BARGRAPH_LEDCHECK1
|
300 | sbi PORTD,0
|
301 | BARGRAPH_LEDCHECK1:
|
302 | cbi PORTD,1
|
303 | cpi MotorThr,LED1_on_if_higher
|
304 | brlo BARGRAPH_LEDCHECK2
|
305 | sbi PORTD,1
|
306 | BARGRAPH_LEDCHECK2:
|
307 | cbi PORTD,2
|
308 | cpi MotorThr,LED2_on_if_higher
|
309 | brlo BARGRAPH_LEDCHECK3
|
310 | sbi PORTD,2
|
311 | BARGRAPH_LEDCHECK3:
|
312 | cbi PORTD,3
|
313 | cpi MotorThr,LED3_on_if_higher
|
314 | brlo BARGRAPH_LEDCHECK4
|
315 | sbi PORTD,3
|
316 | BARGRAPH_LEDCHECK4:
|
317 | cbi PORTD,4
|
318 | cpi MotorThr,LED4_on_if_higher
|
319 | brlo BARGRAPH_LEDCHECK5
|
320 | sbi PORTD,4
|
321 | BARGRAPH_LEDCHECK5:
|
322 | cbi PORTD,5
|
323 | cpi MotorThr,LED5_on_if_higher
|
324 | brlo BARGRAPH_LEDCHECK6
|
325 | sbi PORTD,5
|
326 | BARGRAPH_LEDCHECK6:
|
327 | cbi PORTD,6
|
328 | cpi MotorThr,LED6_on_if_higher
|
329 | brlo BARGRAPH_LEDCHECK7
|
330 | sbi PORTD,6
|
331 | BARGRAPH_LEDCHECK7:
|
332 | cbi PORTB,2
|
333 | cpi MotorThr,LED7_on_if_higher
|
334 | brlo BARGRAPH_LEDCHECK8
|
335 | sbi PORTB,2
|
336 | BARGRAPH_LEDCHECK8:
|
337 | cbi PORTB,3
|
338 | cpi MotorThr,LED8_on_if_higher
|
339 | brlo BARGRAPH_LEDCHECK9
|
340 | sbi PORTB,3
|
341 | BARGRAPH_LEDCHECK9:
|
342 | ; Test, ob LED9 gerade blinkt (dann nichts ändern)
|
343 | cpi LED9_on,0
|
344 | brne BARGRAPH_LEDCHECK10
|
345 | ; normaler Check (wie bei anderen LEDs)
|
346 | cbi PORTB,4
|
347 | cpi MotorThr,LED9_on_if_higher
|
348 | brlo BARGRAPH_LEDCHECK10
|
349 | sbi PORTB,4
|
350 | BARGRAPH_LEDCHECK10:
|
351 | ret
|
352 |
|
353 |
|
354 |
|
355 | ; MotorThr erhöhen
|
356 | INC_MOTORTHR:
|
357 | cpi MotorThr,MotorThrMAX ; wenn schon Maximalwert
|
358 | breq INC_MOTORTHR_RET ; dann nicht erhöhen
|
359 | inc MotorThr ; sonst erhöhe Wert
|
360 | INC_MOTORTHR_RET:
|
361 | ret
|
362 |
|
363 | ; MotorThr verringern
|
364 | DEC_MOTORTHR:
|
365 | cpi MotorThr,MotorThrMIN ; wenn schon Minimalwert
|
366 | breq DEC_MOTORTHR_RET ; dann nicht verringern
|
367 | dec MotorThr ; sonst verkleinere Wert
|
368 | DEC_MOTORTHR_RET:
|
369 | ret
|
370 |
|
371 | ; TempDiff-Pins auf Standard setzen
|
372 | RESET_HIGH_TEMP_DIFF_PINS:
|
373 | cbi PORTB, 6
|
374 | sbi PORTB, 7
|
375 | ret
|
376 |
|
377 |
|
378 |
|
379 | MOTORLOOP: ; Dauer ca. 90 ms
|
380 | ;von current_motor_thr bis 0 runterzählen
|
381 | mov motorloopcounter,MotorThr
|
382 | sbi PORTB,MOTOR ; Motor ein
|
383 | MOTORLOOP_EIN:
|
384 | rcall MY_DELAY
|
385 | dec motorloopcounter
|
386 | brne MOTORLOOP_EIN
|
387 |
|
388 | cbi PORTB,MOTOR ; Motor aus
|
389 |
|
390 | ; von (255-current_motor_thr) bis 0 runterzählen und Motor aus
|
391 | ldi motorloopcounter,255
|
392 | sub motorloopcounter,MotorThr
|
393 | MOTORLOOP_AUS:
|
394 | rcall MY_DELAY
|
395 | dec motorloopcounter
|
396 | brne MOTORLOOP_AUS
|
397 |
|
398 | ret
|
399 |
|
400 |
|
401 |
|
402 |
|
403 |
|
404 | LEDBLINK:
|
405 | ; Schleifenzähler immer modulo 256 zählen
|
406 | dec LED_loop
|
407 | brne LED0BLINK ; ist = 0?
|
408 |
|
409 | ; LED_loop zurücksetzen. Dabei high_temp_diff beachten.
|
410 | mov LED_loop, ledblink_loopvalmax_current
|
411 |
|
412 | LED0BLINK:
|
413 | cpi LED0_on,0 ; Test, ob Blinken (LED 0 für "Temperatur runter") überhaupt erwünscht
|
414 | breq LED9BLINK
|
415 |
|
416 | ; LED einschalten?
|
417 | cp LED_loop, ledblink_loopval_current
|
418 | brlo LED0_EIN
|
419 |
|
420 | LED0_AUS:
|
421 | cbi PORTD,0
|
422 | rjmp LED9BLINK
|
423 | LED0_EIN:
|
424 | sbi PORTD,0
|
425 |
|
426 | LED9BLINK:
|
427 | cpi LED9_on,0 ; Test, ob Blinken (LED 9 für "Temperatur rauf") überhaupt erwünscht
|
428 | breq LEDBLINK_ENDE
|
429 |
|
430 | ; LED einschalten?
|
431 | cp LED_loop, ledblink_loopval_current
|
432 | brlo LED9_EIN
|
433 |
|
434 | LED9_AUS:
|
435 | cbi PORTB,4
|
436 | rjmp LEDBLINK_ENDE
|
437 | LED9_EIN:
|
438 | sbi PORTB,4
|
439 |
|
440 | LEDBLINK_ENDE:
|
441 | ret
|
442 |
|
443 |
|
444 |
|
445 |
|
446 |
|
447 | MY_DELAY: ; Dauer: 193,25 us
|
448 | wdr ; Watchdog zurücksetzen
|
449 | ldi mydelay,255
|
450 | MY_DELAY_LOOP:
|
451 | dec mydelay
|
452 | brne MY_DELAY_LOOP
|
453 |
|
454 | ret
|
455 |
|
456 | STARTUPLOOP:
|
457 | ldi startuploopcounter,STARTUPDELAY
|
458 | STARTUPLOOP_INNER:
|
459 | rcall MOTORLOOP
|
460 | dec startuploopcounter
|
461 | brne STARTUPLOOP_INNER
|
462 |
|
463 | ret
|