Petromax 150 elektrisch
Vorgeschichte
Im Outdoorbereich ist Licht ein zentrales Thema. Aus meiner Militärzeit kenne ich Benzinvergaserlampen, die sehr hell und lange Zeit leuchten. Für den Gartensitzplatz wollte ich auch so etwas. Also erwarb ich eine Petromax 500. Betrieben wird diese allerdings mit Petroleum, was mir mehr zusagte da hier kein lästiger Benzingeruch entsteht. Die Lampe wurde anfangs häufig benutzt. Mit der Zeit zeigten sich diverse Probleme mit der Technik. Um zu verstehen wo das Problem liegt, muss man etwas über das Funktionsprinzip wissen. Die Lampe hat einen Glühstrumpf wie man es von den Butangaslampen vom Camping her kennt. Dort verdampft Flüssiggas und gelangt in denGlühstrumpf wo bei der Verbrennung Licht erzeugt wird. Damit das mit Petrolium funktioniert, muss dazu vorgängig der Verdampfer in Form einer Röhrenschlaufe kurz oberhalb des Glühstrumpfes vorgewärmt werden. Dazu füllt man die kleine Wanne unterhalb mit Spiritus und entzündet sie. Ist die Schale leer gebrannt und die Schlaufe heiss genug, öffnet man das Ventil vom Tank und der zuvor mittels Druckpumpe unter Druck gesetzte gefüllte Petroliumbehälter befördert das Petrolium zum Verdampfer und von da gelangt es weiter in den Glühstrumpf. Das erzeugte Gas verbrennt und der Strumpf leuchtet hell auf. Leider machte diese Lampe immer wieder Probleme. Öfters brannte das Gasgemisch ausserhalb des Strumpfes wobei kaum Licht, dafür Russ und unerwünschte Abgase entstanden. Die Luftpumpe war ineffizient. Beim Pumpen wurde der Glühstrumpf bei ruppigen Pumpstössen manchmal beschädigt und musste ersetzt werden. Also wurde die Lampe kurzerhand elektrifiziert. Der Boden des Tanks wurde aufgesägt, die innenliegenden Teile wie Pumpenrohr soweit als möglich gekürzt und ein 12V Blei-Gel Akkus eingebaut. Ein passender Halter wurde mittels eines 3D-Druckers erstellt. Flugs noch einen Schalter und eine Ladebuchse anstelle von Pumpe und Druckanzeige eingebaut und fertig.
Eine Petromax 150 Messing elektrifizieren
Petromax Lampen lassen sich eigentlich nicht dimmen, elektrische jedoch schon. Was lag da näher als eine weitere Petromax auf elektrisch umzurüsten. Ins Auge stach mir die 150er aus Messing mit vergoldetem Schirm (Trompetengold). Der Händler konnte mir einen Rabatt gewähren, da ich die Lampe auf Elektrik umbaute und er darum keine Modifikationen machen musste. Wie das gemacht wurde ist im folgenden auf dieser Seite dokumentiert.
Spezifikationen
Energieversorgung
Jedes batteriebetriebene Projekt braucht den richtigen Akku. Doch welchen? Es kamen drei Akkutypen zur Auswahl;
LiPo
- + sehr hoehe Energiedichte
- + sehr leicht
- + in vielen Grössen verfügbar
- - benötigt spezielle Ladeelektronik
- - ungeeignet für tiefe Temperaturen
- - benötigt humane Überwachung beim Laden
- - bedingt geeignet für den unbeaufsichtigten Verbleib im Gerät
LiFePo
- + hohe Energiedichte
- + leicht
- + einfache Ladeelektronik
- - nur in wenigen Grössen verfügbar
- - Grössen meist unpassend
NiMh
- + robust
- + einfachste Ladetechnik möglich
- + grosser Temperaturbereich
- - weniger Energiegehalt zu anderen Technologien
- * Grössen meist in Standardformen AA / AAA etc.
Funktionen
Akku laden
Die Ladeelektronik soll direkt in der Lampe eingebaut werden. Zum Laden wird lediglich ein ausreichend dimensioniertes Netzteil benötigt. Vorgesehen ist ein 24V Netzteil welches ca. 1A Strom liefern kann.
Akku-Ladestatus
Zur Anzeige von Akkuspannung und Ladestatus erhält die Lampe eine RGB-LED. Gemessen wird die Spannung des Akkus. Bei Anschluss des Ladegeräts zeigt die Farbe Blau ein Laden an, Weiss bedeutet Akku voll. Beim Gebrauch der Lampe wechselt die Anzeige von Grün nach Orange zu Rot. Sinkt die Akkuspannung unter das im Programm festgelegte Limit, schaltet sich die Lampe aus.
EIN/AUS – Helligkeit
Die Lampe sollte mittels eines einzigen Tasters bedient werden können. Man findet diese Funktion auch an Lichtdimmern für den Haushaltoder bei LED Nachtischlampen.
Elektronik
Controller Board
Die Schaltung ist auf minimalen Stromverbrauch ausgelegt. 12 Zellen NiMh Eneloop versorgen die gesamte Schaltung. Die Lampe selber benötigt 12V und hat dabei einen Strom von ca. 300mA. Da die Gesamtspannung bei voll geladenem Akku 16.2 (12 x 1.35V) beträgt, regelt die Elektronik die Impulslänge entsprechend herunter. Die dazu nötigen Eckwerte sind in der Software abgebildet.
Ladestrom und Verpolungsschutz
Die Ladeelektronik ist ausgelegt für ein 24V Netzteil mit mindestens 12W Leistung. Die Schaltung wird durch D1 gegen Verpolung geschützt. IC2 ist ein klassischer LM317 in Konstantstromschaltung. Der Strom wird durch R5 und R6 definiert. In Serie geschalten ergeben ihre 4Ω einen maximalen Strom von rund 300mA (1.25V / 4Ω = 0.32A) R1 und R10 bilden einen Spannungsteiler dessen Mittelpunkt zu einem ADC-Eingang des Prozessors führt. Damit wird detektiert, ob ein stromführendes Ladegerät angesteckt ist.
Ladeschalter
Der Prozessor schaltet den Ladestrom über T3 und Q1 zum Akku durch. R2 und R3 sorgen dafür, dass beide MOSFETs ohne Signal vom Prozessor gesperrt bleiben. Aufgrund der hohen Ladespannung (>5V) kann Q1 nicht direkt durch den Prozessor gesteuert werden. Diode D3 sorgt dafür,das kein Strom vom Akku über die im MOSFET Q1 vorhandene rückwärts gerichtete Diode zur Stromregelung fliesst. Denn damit würde der Spannungsteiler R1 / R10 aktiv und der Prozessor würde fälschlicherweise ein aktives Ladegerät detektieren.
Lampe schalten
MOSFET Transistor T2 schaltet die Lampe ein und aus.R4 sorgt für eine Sperrung von T2 wenn vom Prozessor kein aktiver Pegel anliegt.
Stromversorgung Prozessor und Status-LED
Die Spannung vom Akku wird mittels IC3 auf 5V reguliert. R8 und R9 bilden einen Spannungsteiler, dessen Wert an einen ADC-Eingang des Prozessors geführt wird. Er ermittelt damit die aktuelle Spannung des Akkus.
Digitale Status-LED
Zur Überwachung des Akkuszustandes und dessen Ladung wird eine digitale RGB-LED vom Typ WS2812 verwendet. In der Regel wird diese LED in programierbaren Lichterketten eingesetzt, doch natürlich lassen sich solche Typen auch einzeln einsetzen. Die LED hat je einen Versorgungspin für LED und Logik. Diese wurden der Einfachheit halber zusammengefasst. Das hat sich als nachteilig erwiesen, weil die Logik auch im Standbymodus der Lampe Strom verbraucht. Die Schaltung wurde daher so angepasst, dass die LED direkt aus einem Port des Prozessor versorgt wird. Weil in der Dunkelheit die Leuchtkraft der LED sowieso reduziert werden muss, kann der Strom unterhalb der 40mA Limite für diesen Pin gehalten werden.
Hardware
Erste Versuche auf dem Steckbrett
Ein Steckbrett (engl. Breadboard) eignet sich ideal um erste Versuche mit einer Schaltung zu machen. Es gibt sie in diversen Grössen. Änderungen sind jederzeit möglich, nichts ist fix. Ein Nachteil heute ist die Verwendung von Bauteilen in SMD Dimensionen. Sie lassensich wegen ihrer Bauform nicht in das Board einstecken. Abhilfe schaffen hier Adapterplatinen die es für fast alle SMD-Bauformen gibt. Alternativ kann man auch selbst eines fertigen.
Prozessor Interfacing
Wer ATMEL Prozessoren direkt programmieren möchte, benötigt nebst passenden Programmer natürlich Verbindung zum Prozessor. Bei Verwendungvon DIL-Gehäusen bietet sich ein solcher DIL-Messadapter an. Es können die normalen WireWrap Steckverbinder (M-F) verwendet werden. Um das Programmerkabel zu fixieren, wird es über das Steckbrett mit dem Prozessor verbunden. Die unbenutzten Pins am Adapter eignen sich hervorragend um Messungen mit dem Oszilloskop oder Voltmeter durchzuführen.
Funktionstest
Das Steckbrett eignet sich bestens zu debuggen von Schaltung und Software. Zusätzliche Messpunkte können einfach eingesteckt werden. Kein Löten ist notwendig. Einziger Nachteil bei etwas grösseren Schaltungen ist die Anzahl an Kabeln welche gerne die Sicht auf das Wesentliche behindern.
Fertige Platine
Obere Seite: zu sehen sind der Prozessorsockel und die Anschlüsse für Akku, Taster, LED, Akku, Ladekabel.
Untere Seite: Dies ist die erste Version. Im Bild die riesigen Dioden, die aus einem ausgeschlachteten DELL-Server stammen. Der MOSFET für die Lampe war noch unterdimensioniert und brannte mehrmals durch. Der MOSFET zum Laden des Akkus wurde ebenfalls durch einen robusteren Typ ersetzt.
LED Halter
Das ist die RGB-LED auf der Adapterplatine. Sie zeigt Akku und Ladezustand an. Sie sitzt da, wo ursprünglich die Druckanzeige war. Mehr Details im Abschnitt über den Umbau der Lampe.
Controller Halter
Der Halter für die Elektronik ist im 3D Druck entstanden. Er wird in den Montagering eingeklebt, der auch den ausgefrästen Deckelboden aufnimmt.
Software
Allgemein
Der verwendete Prozessor ist ein Atmel Tiny 861. Die folgenden Funktionen der Hardware werden verwendet:
- - ADC zum Messen der Akkuspannung und Prüfen des Vorhandeseins eines angeschlossenen Ladegeräts
- - PWM zum Regeln der Helligkeit der Lampe
- - WATCHDOG zum Energiemanagement
- - Interne Interrupts (TIMER0)
- - Externe Interrupts (INT0) für den Taster
Dazu kommen Bibliotheken zur Steuerung angeschlossener Peripherie (NEOPIXEL).
Funktionen
Status: Lampe inaktiv.
Der Watchdog weckt den Prozessor alle 8 Sekunden. Dieser prüft ob das Laderät angeschlossen ist. Wenn nicht, wird der Watchdog neugesetzt und der Prozessor in den Schlafmodus versetzt.
Wird ein Ladegerät erkannt bleibt der Prozessor wach und es wird weiter zur Hauptroutine gesprungen => Lampe aktiv
Status: Lampe aktiv
Die Hauptroutine besteht aus zwei Modulen.
Das erste Modul kümmert sich um Ladung des Akkus und den maximalen Strom der Lampe. Es wird alle 100ms durch einen Timerinterruptgetriggert. Weil der Akku voll geladen eine höhere Spannung hat als die Lampe verkraften kann, reduziert die Software das maximale PWM Verhältnis. Die in der Software angegebenen Werte wurden messtechnisch ermittelt. Dieses Modul steuert ebenfalls die Anzeigeder LED und zeigt den aktuellen Ladestatus respektive Akkustatus an.
Das zweite Modul wird alle 10ms durch einen Timerinterrupt getriggert. Hier wird der Taster ausgewertet um die Lampe heller oder dunkler zu machen oder Lampe ganz auszuschalten.
controller.bas
1 $regfile = „attiny861.dat“
2 $crystal = 16000000
3 $hwstack = 32
4 $swstack = 64
5 $framesize = 64
6
7 CONFIG SUBMODE = NEW
8 CONST USELCD = 0
9
10 CONST true = 1
11 CONST false = 0
12
13 ‚Voltage per digit x voltage-divider factor
14 CONST ChargeDividerFactor = 0.00107 * 23.0
15 CONST AccuDividerFactor = 0.00107 * 23.0
16
17 CONST up = 1
18 CONST down = 0
19 CONST ein = 1
20 CONST aus = 0
21 CONST pushed = 0
22
23 ‚Accu / Charge Levels in Volt
24 CONST AccuGreen = 13.0
25 CONST AccuOrange = 12.0
26 CONST AccuRed = 11.00
27 CONST AccuChargeLimit = 17.00
28 CONST MinDCLevel = 14.0
29 CONST MinLightBrightness = 25
30 CONST LightChangeDirDelayTime = 100 ‚1 Sec.
31
32 ‚NeoPixel Color Index
33 CONST NPblack = 0
34 CONST NPred = 1
35 CONST NPgreen = 2
36 CONST NPblue = 3
37 CONST NPwhite = 4
38 CONST NPdarkred = 5
39 CONST NPdarkgreen = 6
40 CONST NPdarkblue = 7
41 CONST NPdarkwhite = 8
42 CONST NPorange = 9
43 CONST NPdarkorange = 10
44
45 NeoPixelPower ALIAS PORTA.6
46 LightPWM ALIAS OCR1A
47 Lamp Alias PORTB.1
48 ChargeEnable ALIAS PORTB.4
49 StatusLED ALIAS PORTA.7
50 Switch ALIAS PINB.6
51 SwitchPullup ALIAS PORTB.6
52 ‚DebugPin ALIAS PORTA.4
53 ‚DebugPin2 ALIAS PORTA.5
54
55 DIM ResetOrigin AS Byte
56
57 DIM AccuVoltage AS Single
58 DIM ChargeVoltage AS Single
59 DIM DoCharge as Byte
60 DIM ChargerDetected as Byte
61 DIM CheckInterval as Byte
62 DIM v0 AS Long
63 DIM v1 AS Long
64 DIM i AS Byte
65
66 DIM Event10ms AS Byte
67 DIM Event100ms AS Byte
68 DIM Event100msCntr AS Byte
69
70 DIM SwitchCntr AS Byte
71 DIM LightBrightness AS Byte
72 DIM LightChangeDir AS Byte
73 DIM LightOn AS Byte
74 DIM StoredLightBrightness AS ERAM Byte
75 DIM MaxLightBrightness AS Byte
76 DIM LightChangeDirDelay AS Byte
77
78 DIM NP_red AS Byte
79 DIM NP_green AS Byte
80 DIM NP_blue AS Byte
81 DIM NPindex AS Byte
82
83 ’store sub code in separate files
84 $INCLUDE sub_adc.inc
85 $INCLUDE sub_watchdog.inc
86 $INCLUDE sub_neopixel.inc
87 $INCLUDE sub_lcd.inc
88
89 ’save source of reset
90 ResetOrigin = Peek(0)
91 MCUSR = 0
92
93 CONFIG NeoPixelPower = OUTPUT : NeoPixelPower = aus
94 CONFIG Lamp = OUTPUT
95 CONFIG ChargeEnable = OUTPUT : ChargeEnable = false
96 CONFIG StatusLED = OUTPUT
97 CONFIG Switch = INPUT : SwitchPullup = 1
98 ‚CONFIG DebugPin = OUTPUT : DebugPin = false
99 ‚CONFIG DebugPin2 = OUTPUT : DebugPin2 = false
100
101 LightChangeDir = up
102
103 ‚Unused Pins / set Pullup
104 ‚SET PORTA.4 ‚DebugPin / comment out when in use
105 ‚SET PORTA.5 ‚DebugPin2 / comment out when in use
106 ‚SET PORTB.0
107 ‚SET PORTB.2
108 ‚SET PORTB.3
109
110 ‚Init INT0 interrupts
111 MCUCR.ISC00 = 0
112 MCUCR.ISC01 = 0
113 GIMSK.INT0 = 1
114 On INT0 isrINT0 NoSave
115
116 ‚Init Timer0 (10ms cycle)
117 CONFIG TIMER0 = TIMER , PRESCALE = 1024
118 START TIMER0
119 ON OVF0 isrTimer0_Overflow NoSave
120 ENABLE OVF0
121
122 ‚Init PWM Timer1
123 Set Pllcsr.plle
124 Waitus 100
125 While Pllcsr.plock = 0
126 Wend
127 Set Pllcsr.pcke
128 TCCR1A = &B10000010
129 TCCR1B = &B00001000
130 LightPWM = 0
131
132 ‚Watchdog
133 InitWatchdog
134
135 ‚Init ADC
136 InitADC
137
138 ENABLE INTERRUPTS
139
140 ‚Do one dummy reading on each channel because this is the first ADC reading at all
141 ReadChargeVoltage
142 ReadAccuVoltage
143 ‚then get actual values
144 CheckVoltages
145
146 ‚Init LCD for debugging
147 #IF USELCD
148 Init_LCD
149 Write_LCD
150 #ENDIF
151
152 ‚Is watchdog source of reset?
153 If ResetOrigin.WDRF = true Then
154 ‚ brief check if charger is plugged in
155 If ChargeVoltage < MinDCLevel Then
156 ‚No, then sleep further
157 GIMSK.INT0 = 1 ‚activate wakeup interrupt
158 ’stop all loads
159 STOP ADC
160 NeoPixelPower = aus
161 Config POWERMODE = Powerdown
162 ‚*********************
163 ‚*** SLEEPING ZONE ***
164 ‚*********************
165 ‚Switch pressed? Wake up again
166 ‚do some inits again
167 InitADC
168 RESET Watchdog
169 End If
170 End If
171
172 ‚Restore the last used Brightness
173 LightBrightness = StoredLightBrightness
174 MaxLightBrightness = 255
175
176 ‚Put Power to the NeoPixel
177 NeoPixelPower = ein
178
179 ‚MAIN
180 Do
181 ‚all 100 ms
182 If Event100ms = true Then
183 Event100ms = false
184 ‚count intervals
185 INCR CheckInterval
186 Select Case CheckInterval
187 ‚every 5 seconds, the charging is disabled to have valid voltages
188 Case 50
189 ChargeEnable = false
190 ’now measure exact voltages
191 Case Is > 50
192 CheckVoltages
193 If AccuVoltage > 15.5 Then
194 MaxLightBrightness = 148 ‚58%
195 ElseIf AccuVoltage > 15.0 Then
196 MaxLightBrightness = 153 ‚60%
197 ElseIf AccuVoltage > 14.5 Then
198 MaxLightBrightness = 166 ‚65%
199 ElseIf AccuVoltage > 14.0 Then
200 MaxLightBrightness = 178 ‚70%
201 ElseIf AccuVoltage > 13.5 Then
202 MaxLightBrightness = 215 ‚85%
203 Else
204 MaxLightBrightness = 255
205 End If
206 If LightBrightness > MaxLightBrightness Then
207 LightBrightness = MaxLightBrightness
208 End If
209 CheckInterval = 0
210 ‚if no measure is running, do powermanagement and set led color
211 Case Else
212 If ChargerDetected = true Then
213 If DoCharge = true Then
214 SetPixelColor NPdarkblue
215 ChargeEnable = true
216 Else
217 SetPixelColor NPdarkwhite
218 ChargeEnable = false
219 End If
220 Else
221 If LightOn = true Then
222 Select Case AccuVoltage
223 Case Is > AccuGreen
224 SetPixelColor NPdarkgreen
225 Case Is > AccuOrange
226 SetPixelColor NPdarkorange
227 Case Is > AccuRed
228 SetPixelColor NPdarkred
229 Case Else
230 LightOn = false
231 End Select
232 Else
233 SetPixelColor NPblack
234 End If
235 End If
236 End Select
237
238 ’send color to neopixel
239 WritePixel
240
241 ‚If LCD is attached lets display some data
242 #IF USELCD
243 Write_LCD2
244 #ENDIF
245
246 ‚do not forget to reset watchdog timer
247 If ChargerDetected = true Then
248 Reset Watchdog
249 Else
250 If LightOn = true Then
251 Reset Watchdog
252 End If
253 End If
254 End If
255
256 ‚all 10 ms
257 If Event10ms = true Then
258 Event10ms = false
259 If Switch = pushed Then
260 If SwitchCntr < 25 Then INCR SwitchCntr
261 If SwitchCntr > 20 Then
262 If LightChangeDir = up Then
263 If LightBrightness < MaxLightBrightness Then
264 INCR LightBrightness
265 Else
266 INCR LightChangeDirDelay
267 If LightChangeDirDelay > LightChangeDirDelayTime Then
268 LightChangeDir = down
269 LightChangeDirDelay = 0
270 End If
271 End If
272 Else
273 If LightBrightness > MinLightBrightness Then
274 DECR LightBrightness
275 Else
276 INCR LightChangeDirDelay
277 If LightChangeDirDelay > LightChangeDirDelayTime Then
278 LightChangeDir = up
279 LightChangeDirDelay = 0
280 End If
281 End If
282 End If
283 End If
284 Else
285 If SwitchCntr > 20 Then
286 If LightChangeDir = up Then
287 LightChangeDir = down
288 Else
289 LightChangeDir = up
290 End If
291 End If
292 If SwitchCntr > 3 and SwitchCntr < 20 Then
293 If LightOn = false then
294 LightOn = true
295 Else
296 StoredLightBrightness = LightBrightness
297 LightOn = false
298 End If
299 End If
300 SwitchCntr = 0
301 LightChangeDirDelay = 0
302 End If
303
304 ’set light on/off as needed
305 If LightOn = true Then
306 LightPWM = LightBrightness
307 Else
308 LightPWM = aus
309 End If
310 End If
311 Loop
312
313 ‚ISRs
314 isrTimer0_Overflow:
315 $ASM
316 PUSH R16
317 PUSH R23
318 IN R24,SREG
319 PUSH R24
320 $END ASM
321 ’set 10ms interval
322 TIMER0 = 98
323 Event10ms = true
324 INCR Event100msCntr
325 If Event100msCntr > 10 Then
326 Event100msCntr = 1
327 Event100ms = true
328 End If
329 $ASM
330 POP R24
331 OUT SREG , R24
332 POP R23
333 POP R16
334 $END ASM
335
336 Return
337
338 isrINT0:
339 ‚Clear INT0 Interrupt to detect pushed switch
340 $ASM
341 PUSH R23
342 IN R24,SREG
343 PUSH R24
344 IN R23,GIMSK
345 ANDI R23,$BF
346 OUT GIMSK , R23
347 POP R24
348 OUT SREG , R24
349 POP R23
350 $END ASM
351 Return
sub_watchdoc.inc
1 ‚******************************
2 ‚* SUBS / FUNCTIONS / BLOCKS *
3 ‚******************************
4
5 SUB InitWatchdog
6 ‚Set Timeout period 250msec
7 WDTCR.WDP0 = 1
8 WDTCR.WDP1 = 0
9 WDTCR.WDP2 = 0
10 WDTCR.WDP3 = 1
11 ‚Enable Watchdog
12 WDTCR.WDIE = 0
13 WDTCR.WDCE = 1
14 WDTCR.WDE = 1
15 END SUB
16
17 SUB DisableWatchdog
18 LOCAL B AS Byte
19 B = WDTCR
20 B.WDCE = 1
21 B.WDE = 1
22 WDTCR = B
23 B.WDCE = 0
24 B.WDE = 0
25 WDTCR = B
26 END SUB
sub_adc.inc
1 ‚******************************
2 ‚* SUBS / FUNCTIONS / BLOCKS *
3 ‚******************************
4 SUB InitADC
5 CONFIG ADC = SINGLE , PRESCALER = 128 , REFERENCE = INTERNAL_1.1
6 START ADC
7 END SUB
8
9 SUB ReadAccuVoltage()
10 v0 = GetADC(0)
11 AccuVoltage = v0 * AccuDividerFactor
12 END SUB
13
14 SUB ReadChargeVoltage()
15 v1 = GetADC(1)
16 ChargeVoltage = v1 * ChargeDividerFactor
17 END SUB
18
19 SUB CheckVoltages
20 ReadAccuVoltage
21 ReadChargeVoltage
22 If ChargeVoltage > MinDCLevel Then
23 ChargerDetected = true
24 Else
25 ChargerDetected = false
26 End If
27 If AccuVoltage < AccuChargeLimit Then
28 DoCharge = true
29 Else
30 DoCharge = false
31 End If
32 END SUB
sub_neopixel.inc
1 ‚******************************
2 ‚* SUBS / FUNCTIONS / BLOCKS *
3 ‚******************************
4 Sub Setpixelcolor(byval Color As Byte)
5 Npindex = Color * 3
6 Np_red = Lookup(npindex , Npcolors)
7 Incr Npindex
8 Np_green = Lookup(npindex , Npcolors)
9 Incr Npindex
10 Np_blue = Lookup(npindex , Npcolors)
11 End Sub
12
13 Sub Writepixel()
14 ‚ Write NEOPIXEL
15 $asm
16 .def Pinhi = R18
17 .def Pinlo = R19
18 .def Data = R20
19 .def Bitcounter = R22
20
21 PUSH r18
22 PUSH r19
23 PUSH r20
24 PUSH r22
25
26 LDI BitCounter, 8
27 IN PinLo, PortA
28 ANDI PinLo, &b01111111
29 IN PinHi, PORTA
30 ORI PinHi, &b10000000
31
32 ‚*** GREEN
33 LDS Data, {NP_green}
34 Startgreen:
35 Out PortA , Pinhi
36 LSL Data
37 BRCS NotLowGreen
38 Out PortA , Pinlo
39 Notlowgreen:
40 DEC BitCounter
41 BRNE Bit0To6green
42 ‚Bit7green:
43 LDI BitCounter, &h8
44 RJMP ExitGreen
45
46 Bit0to6green:
47 RJMP +1
48 RJMP +1
49 RJMP +1
50 RJMP +1
51 NOP
52 Out PortA , Pinlo
53 CLZ
54 RJMP StartGreen
55
56 Exitgreen:
57 Out PortA , Pinlo
58 RJMP +1
59 RJMP +1
60 RJMP +1
61 NOP
62
63 ‚*** RED
64 LDS Data, {NP_red}
65 Startred:
66 Out PortA , Pinhi
67 LSL Data
68 BRCS NotLowRed
69 Out PortA , Pinlo
70 Notlowred:
71 DEC BitCounter
72 BRNE Bit0To6red
73 ‚Bit7Red:
74 LDI BitCounter, &h8
75 RJMP ExitRed
76
77 Bit0to6red:
78 RJMP +1
79 RJMP +1
80 RJMP +1
81 RJMP +1
82 NOP
83 Out PortA , Pinlo
84 CLZ
85 RJMP StartRed
86
87 Exitred:
88 Out PortA , Pinlo
89 RJMP +1
90 RJMP +1
91 RJMP +1
92 NOP
93
94 ‚*** BLUE
95 LDS Data, {NP_blue}
96 Startblue:
97 Out PortA , Pinhi
98 LSL Data
99 BRCS NotLowBlue
100 Out PortA , Pinlo
101 Notlowblue:
102 DEC BitCounter
103 BRNE Bit0To6blue
104 ‚Bit7Blue:
105 LDI BitCounter, &h8
106 RJMP ExitBlue
107
108 Bit0to6blue:
109 RJMP +1
110 RJMP +1
111 RJMP +1
112 RJMP +1
113 NOP
114 Out PortA , Pinlo
115 CLZ
116 RJMP StartBlue
117
118 Exitblue:
119 Out PortA , Pinlo
120 ‚****
121 POP r22
122 POP r20
123 POP r19
124 POP r18
125 $end Asm
126 End Sub
127
128 ‚****************************
129 ‚* DATAs *
130 ‚****************************
131 NPcolors:
132 DATA 0 , 0 , 0 ‚black
133 DATA &hFF , 0 , 0 ‚red
134 DATA 0 , &hFF , 0 ‚green
135 DATA 0 , 0 , &hFF ‚blue
136 DATA &hFF , &hFF , &hFF ‚white
137 DATA &h20 , 0 , 0 ‚darkred
138 DATA 0 , &h20 , 0 ‚darkgreen
139 DATA 0 , 0 , &h20 ‚darkblue
140 DATA &h20 , &h20 , &h20 ‚darkwhite
141 DATA &hFF , &hA5 , 0 ‚orange
142 DATA &h20 , &h17 , 0 ‚darkorange
sub_lcd.inc (für die Fehlersuche)
1 SUB Init_LCD
2 waitms 100
3 Open „coma.7:19200,8,n,1“ For Output As #1
4 Print #1 , Chr(&h11)
5 waitms 20
6 Print #1 , “ „
7 Print #1 , “ „
8 END SUB
9
10 SUB Write_LCD
11 DISABLE INTERRUPTS
12 Print #1 , Chr(&h80)
13 waitms 1
14 Print #1 , “ A:“;
15 Print #1 , FUSING(AccuVoltage , „#.#“);
16 ‚ Print #1 , Chr(13)
17 ‚ If ChargerDetected = true Then
18 ‚ Print #1 , “ C:“;
19 ‚ Else
20 ‚ Print #1 , “ c:“;
21 ‚ End If
22 ‚ Print #1 , FUSING(ChargeVoltage , „#.#“);
23 ENABLE INTERRUPTS
24 END SUB
25
26 SUB Write_LCD2
27 DISABLE INTERRUPTS
28 Print #1 , Chr(&h80)
29 Print #1 , „-A:“;
30 Print #1 , FUSING(AccuVoltage , „#.#“);
31 ‚Print #1 , Chr(13)
32 ‚If ChargerDetected = true Then
33 ‚ Print #1 , „-C:“;
34 ‚Else
35 ‚ Print #1 , „-c:“;
36 ‚End If
37 ‚Print #1 , FUSING(ChargeVoltage , „#.#“);
38 ENABLE INTERRUPTS
39 END SUB