home Inhaltsverzeichnis
erste Version am 24.12.2017
letzte Änderung am 07.01.2018
LED-Streifen als Nachtlicht - Seite 4
Logging über WLAN
Der Taster ist verbaut und zieht, wenn betätigt, D12 auf Masse.
Das Neu-Einmessen funktioniert zwar, dessen Einleitung stellt sich
jedoch äußert schwierig dar. Weil... Taster drücken und gleichzeitig
die 12V anschließen grenzt an fortgeschrittene Akrobatik. Ein
Schalter oder eine Jumper-Brücke wäre schlauer gewesen.
Und das Sensor-Gehäuse ist immer noch nicht an die Wand geschraubt,
weil es neue Probleme gibt:
Der ESP-01-WLAN-Adapter läuft mit Standard-Firmware und muss somit
über AT-Befehle gesteuert werden. Daher kommt es zu Änderungen des
Laufzeitverhaltens. Schließlich muss der ATmega328 vor jeder
Kommunikation sicherstellen, dass der ESP-01 im WLAN eingebucht ist
und die Verbindung zum SocketServer steht. Das dauert normalerweise
unter einer Sekunde (wenn die Einbuchung im WLAN noch steht).
Manchmal aber auch deutlich länger.
Daher kommt es gelegentlich zu sehr sonderbaren Effekten und das
wiederum macht quasi sämtliche Messwerte unbrauchbar.
Nicht tragisch, aber ganz speziell verwunderlich ist der Umstand,
dass die LEDs jede Nacht pünktlich 36 bis 38 Sekunden nach 03:10 Uhr
eingeschaltet werden. Nun ist 03:10 Uhr genau die Zeit, zu der der
WLAN-Router seinen Reboot fährt. Folglich stirbt die
WLAN-Verbindung. Eigentlich sollte das kein Grund für den ATmega328
sein, aufzuwachen. Aber wer weiß, was die AT-Firmware in so einem
Fall macht..... 30 Sekunden lang viel Strom ziehen
wahrscheinlich.... und der LF50CV war ja nicht dafür dimensioniert,
zusätzlich einen 3,3V-Regler plus ESP-01 zu versorgen.
Für stabiles Laufzeitverhalten hilft eigentlich nur, sämtliche
Funktionen mit variabler Laufzeit auf den ESP8266 auszulagern.
Aus diesem Grund starte ich bereits jetzt mit dem angedachten
Folgeprojekt. Also dem "WLAN-Syslog-Adapter" alias Logging-Device.
So. Nun ist Feierabend mit den AT-Befehlen. Das Logging-Device hängt
am Nachtlicht und erstmal sieht alles gut aus.
Die erste Nacht mit dem Logging-Device verlief ohne Auffälligkeiten.
Auch wurden die LEDs um 03:10 Uhr nicht eingeschaltet.
Nun gibt es zwei mögliche Folge-Aufgaben.
Entweder baue ich das Logging-Device jetzt so um, dass der ATmega328
darüber auch Parameter beim SocketServer anfragen und empfangen
kann. Damit ließe sich sowas wie "Helligkeitswert, ab dem die LEDs
ausgeschaltet bleiben", "Nachleucht-Dauer" und die "Parameter für
die Funktion <PWM-Wert zu Helligkeit>" anpassen, ohne den
ATmega328 neu flashen zu müssen.
Oder ich überdenke nochmal den Algorithmus, mit dem die
LED-Helligkeit an eine veränderte Gesamt-Helligkeit angepasst wird.
Das läuft nämlich doch irgendwie nicht immer ganz so, wie ich mir
das vorgestellt habe.
Helligkeits-Anpassung
Wenn Bewegung erkannt wurde und die Helligkeit(1) kleiner/gleich 45
ist, werden die LEDs eingeschaltet.
Die Berechnung ihres PWM-Wertes erfolgt mittels: min(255,
map(helligkeit, 0, 45, 3, 255))
Nach Einschalten der LEDs kann nur noch die Gesamt-Helligkeit
aus Fremdlicht- und LED-Helligkeit gemessen werden.
Es existiert ein Array, in dem jedem der 256 möglichen PWM-Werte ein
Helligkeitswert(2) zugeordnet wird, der von den LEDs ohne Fremdlicht
erreicht wird.
Damit ergeben sich folgende (exemplarisch herausgegriffene) Werte:
Helligkeit(1) |
PWM-Wert |
Helligkeit(2) |
0 |
3 |
5
|
1 |
8 |
17
|
2 |
14 |
31
|
3 |
19 |
45
|
10 |
59 |
152
|
20 |
115 |
300
|
30 |
171 |
447
|
40 |
227 |
591
|
44 |
249 |
644
|
45 |
255 |
659
|
50 |
255 |
659
|
Bem.: Helligkeit(2) wurde zwischenzeitlich neu erfasst und passt
nicht mehr ganz zur zweiten Messreihe in der dortigen Spalte
"dunkel".
Wenn nun nachträglich Fremdlicht hinzukommt, ändert sich
Helligkeit(2).
Der derzeitige Algorithmus verwendet das Array Helligkeit(2) bzw.
<Helligkeit zu PWM-Wert ohne Fremdlicht>, um eine
Helligkeits-Differenz in die entsprechende PWM-Wert-Differenz
umzuwandeln. Implementiert ist es folgendermaßen:
/* -------------------------------------------------------------------
* Liefert zum PWM-Wert "pwm" den PWM-Wert, bei dem die resultierende
* Helligkeit um den Wert von "lum_delta" verändert ist.
* "lum_delta" ist zu berechnen aus neuer_Wert - alter_Wert.
* Also etwa:
* neu(400) - alt(300) = 100 = positiv = heller geworden
* neu(300) - alt(400) = -100 = negativ = dunkler geworden
*/
int recalcPwm2(unsigned char pwm, int lum_delta) {
int fnd, idx=pwm;
fnd=led_lum_g[pwm]+lum_delta;
if(lum_delta<0) { // es ist dunkler geworden
while(idx>3 && led_lum_g[idx]>fnd) {
idx--;
}
} else { // es ist heller geworden
while(idx<255 && led_lum_g[idx]<fnd) {
idx++;
}
}
return(idx);
}
Die Funktion liefert immerhin schon mal neue PWM-Werte, die zu neuen Gesamt-Helligkeiten führen, die gemäß Helligkeits-Differenz in die richtige Richtung gehen.
Das Ergebnis ist allerdings weit davon entfernt, der Helligkeit zu entsprechen, die sich ergeben hätte, wenn die LEDs erst nach der Helligkeits-Änderung eingeschaltet worden wären.
Hier zwei entsprechende Blöcke aus dem Log:
2017.12.28 18:22:38 Info: last_lum_g=25 2017.12.28 18:22:39 Info: runWithLight() 2017.12.28 18:22:39 Info: cur_sec=0 led_val=143 last_lum_g=405 cur_lum=401 2017.12.28 18:22:39 Info: last_lum_g=405 cur_lum=398 led_val=143 led_val2=140 2017.12.28 18:22:39 Info: last_lum_g=396 cur_lum=390 led_val=140 led_val2=138 2017.12.28 18:22:40 Info: last_lum_g=391 cur_lum=385 led_val=138 led_val2=136 2017.12.28 18:22:44 Info: last_lum_g=383 cur_lum=368 led_val=136 led_val2=130 2017.12.28 18:22:44 Info: cur_sec=1 led_val=130 last_lum_g=340 cur_lum=342 2017.12.28 18:22:45 Info: cur_sec=2 led_val=130 last_lum_g=340 cur_lum=341 [...] 2017.12.28 18:23:29 Info: last_lum_g=2 2017.12.28 18:23:29 Info: runWithLight() 2017.12.28 18:23:29 Info: cur_sec=0 led_val=14 last_lum_g=33 cur_lum=34 2017.12.28 18:23:35 Info: cur_sec=1 led_val=14 last_lum_g=33 cur_lum=35 2017.12.28 18:23:36 Info: cur_sec=2 led_val=14 last_lum_g=33 cur_lum=35
|
Um 18:22:38 wurde Bewegung erkannt. Bevor die LEDs eingeschaltet wurden, betrug die Helligkeit 25 (Treppenlicht war an).
Nach Einschalten der LEDs mit PWM-Wert 143 betrug die Gesamt-Helligkeit 405. Um 18:22:39 wurde das Treppenlicht ausgeschaltet.
Die Gesamt-Helligkeit hat sich um 7 (von 405 auf 398) geändert. Dadurch wurden die LEDs auf den PWM-Wert 140 runtergedreht.
Fünf Sekunden später war die Helligkeit bei 368 und dem PWM-Wert 130 angekommen.
Wobei diese fünf Sekunden nicht bedeuten müssen, dass es tatsächlich erst fünf Sekunden später passiert ist.
Die Zeitangabe stammt vom SocketServer und zeigt an, wann die Meldung dort angekommen ist. Vielleicht sollte ich noch den Wert von millis() in die Meldung aufnehmen.
Kurz danach um 18:23:29 wurde wieder Bewegung erkannt. Diesmal war das Treppenlicht nicht mehr an. Die Helligkeit betrug 2.
Nach Einschalten der LEDs mit PWM-Wert 14 betrug die Gesamt-Helligkeit 33.
Also zwei sehr unterschiedliche Helligkeiten für den identischen Zustand (Treppenlicht ist aus). Helligkeit auf 398 statt 34 und PWM-Wert von 140 statt 14.
Irgendwo in meinem Algorithmus fehlt mir auch die inverse Funktion zu dem min(255, map(helligkeit, 0, 45, 3, 255))
.
Also sowas wie map(pwm_wert, 3, 255, 0, 45)
.
Für pwm_wert=143 liefert der invers_map()=25.
Laut Array gilt: pwm=155 val=406; der invers_map() liefert für 155: 27
Und: pwm=152 val=398; dafür liefert invers_map(): 26
Und für den Wert nach fünf Sekunden: pwm=141 val=369; invers_map()=24
Ich will da aber nicht 24 sondern 2 sehen!
Vielleicht ziehe ich das Delta ja an der falschen Seite ab.
Laut Array gilt: pwm=11 val=25
Also wäre bereits mit dem PWM-Wert 11 die Fremdlicht-Helligkeit von 25 erreicht.
405-368=37
Laut Array gilt: pwm=16 val=37
Der invers_map() liefert zu 16 die 2.
Leider muss der Test von diesem Algorithmus noch etwas warten....
Jetzt stehen erstmal die Weihnachts- und Sylvester-Besuche bei der Sippschaft an.
So...2018...nun gehts weiter...und gleich stellt sich die Frage, was denn passieren soll, wenn die Fremdlicht-Helligkeit zu- statt abnimmt.
Einfach den bisherigen PWM-Wert beizubehalten, wird nicht funktionieren. Bei obigen Daten wird das erste Helligkeits-Delta mit dem Wert 405-398=7 gemeldet, was zum PWM-Wert 3 führen würde.
Und wenn dann kein Erhöhen des PWM-Wertes vorgesehen wäre, bliebe es dabei.
Jetzt habe ich spaßeshalber mal die Daten beider Messreihen in Libre Office Calc reingepasted und daraus jeweils ein Diagramm erstellen lassen.
Dass die Helligkeits-Werte der zweiten Messung derart parallel zueinander verlaufen, hatte ich tatsächlich nicht erwartet.
Hätte ich mir das mal früher auf diese Weise angesehen..... dann hätte ich mir den ganzen Heckmeck ab neuer Ansatz sparen können.
Jedenfalls ist diese Erkenntnis ja wohl nur so zu deuten, dass mein allererster Ansatz prinzipiell valide war und der Fehler durch was anderes entstanden sein muss.
Wie schön. Absolute Werte sind mir sowieso sehr viel lieber. Bei Delta-Werten würden sich die prinzip-bedingten Rundungsfehler nach ein paar Iterationen voraussichtlich in den merkbaren Bereich aufsummieren.
zurück auf Los
Nun berechne ich die Fremdlicht-Helligkeit bei eingeschalteten LEDs also wieder aus <aktuell gemessene Helligkeit> minus <gespeicherte LED-Helligkeit gemäß PWM-Wert>.
Der map(helligkeit, 0, 45, 3, 255)
liefert folgende PWM-Werte:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
0 | 3 | 8 | 14 | 19 | 25 | 31 | 36 | 42 | 47 | 53 | 59 | 64 | 70 | 75 | 81 | 87 |
16 | 92 | 98 | 103 | 109 | 115 | 120 | 126 | 131 | 137 | 143 | 148 | 154 | 159 | 165 | 171 | 176 |
32 | 182 | 187 | 193 | 199 | 204 | 210 | 215 | 221 | 227 | 232 | 238 | 243 | 249 | 255 |
Dies ist der derzeitige Inhalt des Arrays, das die Helligkeits-Werte ohne Fremdlicht zu einem PWM-Wert angibt:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
0 | 1 | 2 | 3 | 5 | 7 | 9 | 11 | 14 | 17 | 20 | 23 | 25 | 26 | 29 | 31 | 35 |
16 | 37 | 40 | 42 | 45 | 48 | 51 | 53 | 56 | 58 | 61 | 63 | 66 | 70 | 72 | 75 | 77 |
32 | 79 | 82 | 85 | 88 | 91 | 93 | 95 | 98 | 101 | 104 | 107 | 109 | 111 | 114 | 117 | 120 |
48 | 123 | 125 | 128 | 130 | 133 | 136 | 138 | 141 | 143 | 147 | 149 | 152 | 154 | 156 | 160 | 163 |
64 | 165 | 168 | 170 | 173 | 175 | 179 | 181 | 183 | 186 | 189 | 192 | 194 | 197 | 200 | 202 | 205 |
80 | 208 | 210 | 213 | 215 | 218 | 221 | 223 | 226 | 228 | 232 | 234 | 237 | 240 | 241 | 245 | 248 |
96 | 250 | 253 | 255 | 258 | 261 | 263 | 266 | 269 | 271 | 274 | 277 | 280 | 281 | 284 | 287 | 290 |
112 | 293 | 295 | 298 | 300 | 303 | 306 | 308 | 311 | 314 | 317 | 318 | 321 | 324 | 328 | 330 | 332 |
128 | 334 | 337 | 340 | 343 | 346 | 348 | 351 | 353 | 355 | 358 | 361 | 364 | 367 | 369 | 371 | 374 |
144 | 377 | 379 | 382 | 385 | 388 | 390 | 392 | 394 | 398 | 401 | 403 | 406 | 408 | 411 | 413 | 416 |
160 | 418 | 422 | 424 | 427 | 428 | 431 | 434 | 437 | 439 | 442 | 445 | 447 | 449 | 452 | 455 | 458 |
176 | 461 | 463 | 465 | 468 | 471 | 473 | 476 | 479 | 481 | 484 | 486 | 488 | 491 | 494 | 496 | 499 |
192 | 501 | 504 | 506 | 509 | 511 | 515 | 518 | 520 | 522 | 525 | 527 | 530 | 532 | 534 | 536 | 539 |
208 | 542 | 544 | 546 | 549 | 552 | 554 | 556 | 559 | 563 | 565 | 568 | 570 | 572 | 575 | 578 | 580 |
224 | 583 | 585 | 588 | 591 | 593 | 595 | 597 | 600 | 603 | 605 | 607 | 610 | 613 | 615 | 617 | 620 |
240 | 623 | 625 | 627 | 630 | 632 | 635 | 637 | 640 | 642 | 644 | 647 | 650 | 652 | 654 | 656 | 659 |
Nun habe ich folgende Einträge im Log:
2018.01.04 18:26:52 Info: millis=609309 last_lum_g=21 2018.01.04 18:26:53 Info: runWithLight() 2018.01.04 18:26:53 Info: millis=609396 cur_sec=0 led_val=120 last_lum_g=318 cur_lum=323 2018.01.04 18:26:56 Info: millis=609680 last_lum_g=318 cur_lum=325 cur_lum_noLED=11 led_val=120 led_val2=64 (unmotiviert) 2018.01.04 18:26:58 Info: millis=610096 last_lum_g=185 cur_lum=179 cur_lum_noLED=14 led_val=64 led_val2=81 (unmotiviert) 2018.01.04 18:26:59 Info: millis=615954 cur_sec=1 led_val=81 last_lum_g=223 cur_lum=223 [...] 2018.01.04 18:27:09 Info: millis=625924 cur_sec=11 led_val=81 last_lum_g=223 cur_lum=222 2018.01.04 18:27:10 Info: millis=626933 cur_sec=0 led_val=81 last_lum_g=223 cur_lum=224 2018.01.04 18:27:19 Info: millis=636168 last_lum_g=223 cur_lum=200 cur_lum_noLED=0 led_val=81 led_val2=3 (Treppenlicht ausgeschaltet) 2018.01.04 18:27:20 Info: millis=636461 cur_sec=1 led_val=3 last_lum_g=6 cur_lum=6 [...] 2018.01.04 18:27:38 Info: millis=654425 cur_sec=3 led_val=3 last_lum_g=6 cur_lum=6 2018.01.04 18:27:38 Info: millis=654826 last_lum_g=6 cur_lum=32 cur_lum_noLED=27 led_val=3 led_val2=154 (Treppenlicht eingeschaltet) 2018.01.04 18:27:38 Info: millis=655361 cur_sec=4 led_val=154 last_lum_g=410 cur_lum=413 [...] 2018.01.04 18:27:42 Info: millis=658551 cur_sec=0 led_val=154 last_lum_g=410 cur_lum=405 2018.01.04 18:27:44 Info: millis=660771 last_lum_g=410 cur_lum=404 cur_lum_noLED=1 led_val=154 led_val2=8 (unmotiviert) 2018.01.04 18:27:52 Info: millis=668443 cur_sec=1 led_val=8 last_lum_g=44 cur_lum=42 [...] 2018.01.04 18:28:20 Info: millis=696419 cur_sec=29 led_val=8 last_lum_g=44 cur_lum=41 2018.01.04 18:28:21 Info: deepSleep()
|
Vor der ersten Bewegungserkennung war das Treppenlicht eingeschaltet.
Bei last_lum_g=21 liefert der map() led_val=120. Das Einschalten der LEDs mit 120 führt zu einer neuen Helligkeit last_lum_g=318. Es gilt array[120]=314. Somit hätte es zu 314+21=335 führen sollen.
Dann (0,284 Sekunden später) stieg die Helligkeit auf 325, wodurch ein removeLedLum(120, 325) ausgeführt wurde und das Ergebnis 11 (325-array[120] = 325-314 = 11) geliefert hat.
Die Helligkeit 11 führt zum PWM-Wert 64. Und das wiederum zur Helligkeit 185.
Ohne Fremdlicht gilt array[64]=165. Also ein Delta von 20 (185-165=20). Das passt somit zur Treppenlicht-Helligkeit, auch wenn die 11 deutlich von 21 abweicht...
Um 18:26:58 sank die Helligkeit von 185 auf 179. Daher removeLedLum(64, 179) = 14 (179-array[64] = 179-165 = 14).
14 ergibt laut map() 81.
81 führt zur Helligkeit 223. Ohne Fremdlicht gilt array[81]=210. 223-210=13. Passt eher nicht zu 21.
Soweit....so unschön.
Um 18:27:19 habe ich das Treppenlicht ausgeschaltet. Dadurch sank die Helligkeit auf 200. removeLedLum(81, 200) = 0 (200-array[81] = 200-210 = -10).
Zur Helligkeit 0 liefert der map() den PWM-Wert 3, was zur Helligkeit 6 führt.
Um 18:27:38 habe ich das Treppenlicht wieder eingeschaltet. Die Helligkeit stieg von 6 auf 32. removeLedLum(3, 32) = 27 (32-array[3] = 32-5 = 27).
Zu 27 liefert der map() 154. 154 führt zur Helligkeit 410.
Um 18:27:44 wurde stattdessen (unmotiviert) 404 gemeldet. removeLedLum(154, 404) = 1 (404-array[154] = 404-403 = 1).
Zu 1 liefert der map() 8. 8 führt zur Helligkeit 44. Ohne Fremdlicht ergibt array[8]=17. 44-17=27 ... und das passt nicht ganz zur 21 des Treppenlichts.
Fazit: durchaus schlüssig....aber trotzdem verfluchter Mist.
Vielleicht sollte ich den Wert des Mindest-Deltas von derzeit 5 auf 15 ändern.
Damit würde auf das Ein- oder Ausschalten des Treppenlichts noch sicher reagiert werden, nicht aber auf kleine Messfehler.
Zumindest wären damit die obigen drei unmotivierten Helligkeits-Änderungen nicht verarbeitet worden.
Wahrscheinlich wäre es jedoch effektiver, wenn zwischen PWM-Wert-Änderung und Helligkeits-Messung etwas länger gewartet würde. Derzeit sind es nur zehn Millisekunden.
Beide Änderungen haben nicht zum gewünschten Ergebnis geführt. Irgendwie scheint sich mir die Gesamt-Helligkeit nach einer PWM-Wert-Änderung erst nach mehreren Sekunden stabilisiert zu haben...!?
Deshalb bin ich nun schon zum zweiten mal auf die Idee der schrittweisen Annäherung zurückgekommen. Und zwar diesmal so:
- wenn die Soll-Helligkeit gemäß PWM-Wert nicht zur gemessenen Gesamt-Helligkeit passt
- die Soll-Helligkeit errechnet sich aus:
- Fremdlicht-Helligkeit = <gemessene Gesamt-Helligkeit@(LEDs ein)> minus <LED-Helligkeit gemäß PWM-Wert>
- PWM-Wert2 = calcLuminosity(Fremdlicht-Helligkeit)
- Soll-Helligkeit = <LED-Helligkeit gemäß PWM-Wert2> plus Fremdlicht-Helligkeit
- einen Schritt (5% der Abweichung) in die entspr. Richtung nachregeln
Dieser Algorithmus liefert das bisher beste Ergebnis. Nachdem ich den delay() zwischen den einzelnen Nachregel-Schritten von 100 auf 10 Millisekunden geändert hatte, passt sich die LED-Helligkeit nun auch hinreichend schnell an eine veränderte Fremdlicht-Helligkeit an.
Ich werde das mal ein oder zwei Tage mit dieser Firmware-Version laufen lassen und beobachten.
Derweil fange ich schon mal an, das Nachtlicht für die Treppe in den Keller zu bauen....bzw. da erstmal Strom hinzubringen.
Die Fortsetzung bekommt eine eigene Seite.