1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
/*
* Bewegungsmelder.asm
*
* Created: 12.01.2015 13:13:40
* Author: Erich
*/
.INCLUDE "tn24def.inc"
; auf internen 128kHz-Oszillator stellen!
.EQU statusBits, 25 ; 0: hell, 1: akku voll, 2: akku nicht leer
.EQU hellBit, 0
.EQU akkuVollBit, 1
.EQU akkuNLeerBit, 2
.EQU hellSpannung, 0x80 ; Schwellwert, ab dem es hell ist
.EQU akkuVollSpannung, 0xb9 ; Schwellwert, ab dem der Akku voll ist (= 14,4V)
.EQU akkuLeerSpannung, 0x99 ; Schwellwert, ab dem der Akku leer ist (= 12,0V)
.EQU zaehlerschritte, 0xffff - 0x2d00 ; 90s?
rjmp RESET
reti
reti
reti
reti
reti
reti
reti
rjmp TIMER1_OVERFLOW ; Timer1 ist übergelaufen
reti
reti
reti
reti
rjmp ADC_INTERRUPT ; ADC-Conversion Interrupt
reti
reti
reti
RESET:
ldi r16,lo8(RAMEND) ; Stackpointer initialisieren
out SPL,r16
sbi DIDR0,ADC0D ; digitalen Eingang an ADC0 (Phototransistor) deaktivieren
sbi DIDR0,ADC1D ; digitalen Eingang an ADC1 (Akkuspannung) deaktivieren
ldi r16,0x00
out ADMUX,r16 ; VCC als Spannungsreferenz und ADC0 zur Single-Ended-Messung wählen
ldi r16,0x10
out ADCSRB,r16 ; linksbündige Ergebnisse, (free-running Mode wählen - wenn Auto-Trigger "an" wäre)
ldi r16,0xc8
out ADCSRA,r16 ; ADC an, Wandlung starten, Auto-Tigger aus, (Interrupt-Flag), ADC-Interrupt an, Vorteiler = 2 (=> 64kHz)
ldi r16,0x06
out PRR,r16 ; Clocks: Timer/Counter 1 an, Timer/Counter 0 aus, USI aus, ADC an ... zum Stromsparen
ldi r16,0x00
out WDTCSR,r16 ; Watchdog aus
ldi r16,0x05
out TCCR1B,r16 ; Timer/Counter 1: Vorteiler auf 1024
ldi r16,0x01
out TIMSK1,r16 ; Timer/Counter 1: Overflow-Interrupt an
ldi r16,0x04
out PORTA,r16 ; LED2 aus, (3x n.d.), LED1 aus, Akku ein, kein Pull-up an PORTA1 (Akkuspannung) & PORTA0 (Phototransistor)
ldi r16,0x04
out PORTB,r16 ; Pull-up an PORTB2 (Bewegungsmelder-Signal), Licht aus, Laden aus
ldi r16,0x8c
out DDRA,r16 ; Ausgänge: PORTA7 (LED2), PORTA3 (LED1), PORTA2 (Akkuschalter)
ldi r16,0x03
out DDRB,r16 ; Ausgänge: PORTB1 (Licht), PORTB0 (Ladeschalter)
sei ; Interrupts an
MAINLOOP:
sbrs statusBits,akkuNLeerBit ; Akku leer?
cbi PORTA,2 ; JA! -> Akku abklemmen
sbrc statusBits,akkuNLeerBit ; Akku leer?
sbi PORTA,2 ; nein -> Akku an
sbrs statusBits,akkuNLeerBit
sbi PORTA,3
sbrc statusBits,akkuNLeerBit
cbi PORTA,3
sbrs statusBits,akkuVollBit ; Akku voll?
rjmp AKKU_NICHT_VOLL ; nein!
sbi PORTA,7 ; LED2 an
sbi PORTB,0 ; Akkuladeschaltung deaktivieren
rjmp BEWEGUNG_AUSWERTEN
AKKU_NICHT_VOLL:
cbi PORTA,7 ; LED2 aus
cbi PORTB,0 ; Akkuladeschaltung aktivieren
BEWEGUNG_AUSWERTEN:
sbic PINB,2 ; Signal am Bewegungsmelder?
rjmp MAINLOOP ; nein!
sbrc statusBits,hellBit ; ist es hell?
rjmp MAINLOOP ; ja!
ldi r16,hi8(zaehlerschritte)
ldi r17,lo8(zaehlerschritte)
out TCNT1H,r16
out TCNT1L,r17 ; Timer/Counter 1 resetten
sbi PORTB,1 ; Licht an!
; sbi PORTA,3 ; LED1 an
rjmp MAINLOOP
ADC_INTERRUPT:
push r16 ; r16 und SREG pushen
in r16,SREG
push r16
in r16,ADCH ; Spannungswert holen
sbis ADMUX,MUX0
rjmp ADC_PHOTO
ADC_AKKU: ; Akkuspannung wurde gemessen
cbi ADMUX,MUX0 ; als nächstes Phototransistor messen
cbr statusBits,((1<<akkuNLeerBit) | (1<<akkuVollBit))
cpi r16,akkuLeerSpannung
brcs ADC_ENDE ; r16 <= akkuLeerSpannung?
sbr statusBits,(1<<akkuNLeerBit); nein!
cpi r16,akkuVollSpannung
brcs ADC_ENDE ; r16 <= akkuVollSpannung?
sbr statusBits,(1<<akkuVollBit) ; nein!
rjmp ADC_ENDE
ADC_PHOTO: ; Phototransistorspannung wurde gemessen
sbi ADMUX,MUX0 ; als nächstes Akkuspannung messen
sbr statusBits,(1<<hellBit)
cpi r16,hellSpannung
brcs ADC_ENDE ; r16 <= hellSpannung?
cbr statusBits,(1<<hellBit) ; nein!
ADC_ENDE:
pop r16 ; SREG und r16 popen
out SREG,r16
pop r16
sbi ADCSRA,ADSC ; nächste Wandlung starten
reti ; ADC_INTERRUPT
TIMER1_OVERFLOW:
cbi PORTB,1 ; Licht aus!
; cbi PORTA,3 ; LED1 aus
reti ; TIMER1_OVERFLOW
|