home
erste Version am 29.11.2016
letzte Änderung am 03.12.2016

Temperatur- und Helligkeits-Logger


Ziel soll eine Akku-betriebene Schaltung sein, mit der Temperatur und Helligkeit von einem ATmega328 protokolliert werden können.
Die gesammelten Daten sollen regelmäßig per WLAN an ein Python-Script übermittelt und von diesem in einer Datenbank gespeichert werden.
Weiterhin sollte es möglich sein, mindestens zwei Sensor-Paare mit einem ATmega abzufragen bzw. deren Daten zu protokollieren.
Die dafür geplanten Komponenten sind:
- zur Entwicklung erstmal ein Arduino UNO, final ein ATmega328
- für die WLAN-Kommunikation ein ESP8266
- für Datum/Uhrzeit und als lokaler Zwischenspeicher ein RTC+EEPROM-Modul
- als Temperatur-Sensor ein DS18B20
- als Helligkeits-Sensor ein LDR vom Typ GL5528
- für den Fall, dass die 4KB des EEPROMs nicht reichen sollten, noch ein SD-Card-Modul mit einer 16GB-Card



Inhaltsverzeichnis

Offene Punkte
   Stromverbrauch / Abschaltbarkeit
   Zwischenspeicher
   temperaturabhängige Tiefschlaf-Dauer
Test-Aufbau
Erste Daten von der Schaltung
Datenbank-Design
Schaltplan
erster Tag auf Lochraster
eine kleine Änderung
die erste Einheit ist fertig
Minusgrade am Außen-Sensor
Visualisierung der Daten
zusätzliche Prüfungen und Erweiterungen
USB-Powerbank als Stromversorgung
LoggerView 1.0
LoggerView Performance
eine nicht existente Stunde
LoggerView ist quasi fertig
der Bau weiterer Schaltungen
eine kleine Korrektur



Offene Punkte

Die folgenden Aspekte sind vorab noch zu klären.

Stromverbrauch / Abschaltbarkeit

Der ATmega soll so oft wie möglich im Tiefschlaf-Modus laufen. Während dieser Zeiten sollen alle anderen Komponenten ebenfalls quasi abgeschaltet sein - mit dem Ziel, möglichst wenig Strom zu verbrauchen.

Ein nur bei Bedarf Strom verbrauchendes WLAN-Modul samt Software habe ich schon.
Für das RTC+EEPROM-Modul wäre noch zu testen, ob es über HIGH/LOW an einem ATmega-Pin ein/aus-geschaltet werden kann. Hier steht, dass ein ATmega-Pin bis zu 40 mA liefern kann. In einer Amazon-Kundenrezension zu dem Modul wird ein Stromverbrauch von 4mA (ohne die LED) genannt - was auch zu den Werten aus den Datenblättern der beiden Chips (DS3231 und AT24C32) passt.
Die beiden Sensoren (DS18B20 und GL5528) sollten diesbezüglich irrelevant sein.

Noch unbekannt ist (mir), ob ein Analog-In-Pin unmittelbar nach einer Tiefschlaf-Phase (bei der auch der ADC abgeschaltet wird) direkt korrekte Werte liefert. Mein Rollladen-Monitor zeigt seit einem Jahr nämlich konstant 5.0V Akku-Spannung an...und das erscheint mir höchst verdächtig.
Ein kurzer Test hat ergeben, dass der analogRead() nach einer Tiefschlaf-Phase (mit ADCSRA=0) Unsinn liefert. Wird aber der Inhalt des ADCSRA-Registers vor dem Tiefschlaf zwischengespeichert und nach dem Tiefschlaf bzw. vor dem analogRead() wiederhergestellt, kommen hingegen valide Werte an.

Zwischenspeicher

Das EEPROM AT24C32 bietet vier Kilobyte Speicherplatz. Bei einer Messung pro Minute wären das 4096/(60*24)=2.84 Byte pro Messwert - wenn die gesammelten Daten nur einmal am Tag per WLAN weggesichert werden sollen.
Ein Temperatur-Wert in maximaler Auflösung belegt zwei Byte bzw. 12 Bit (siehe "Figure 4" in DS18B20.pdf).
Ein Helligkeits-Wert via ATmega-Analog-In kann zwischen 0 und 1023 liegen - also 10 Bit.
In Summe 12+10=22 Bit bzw. drei Byte pro Messwert-Paar.

Vier Kilobyte reichen also nicht für einen ganzen Tag. Aber der ATmega hat ja auch noch ein Kilobyte EEPROM-Speicher.
Fünf Kilobyte würden für 5120/3=1706 Werte-Paare reichen, 60*24=1440 werden gebraucht.
Es blieben 1706-1440=266 Minuten Luft, in denen das WLAN temporär nicht erreichbar sein könnte.
Bei zwei Sensor-Paaren müsste zwangsläufig alle 12 Stunden weggesichert werden.

Wobei sich die Frage stellt, wie die Daten organisiert werden können.
Vielleicht alle 60 Minuten ein eigener Block mit Datum+Uhrzeit.
Also etwa:
Jahr(0-63) Monat(1-12) Tag(1-31) Stunde(0-23) Minute(0-59) Sekunde(0-59)
<3 Byte Wert 0>
<3 Byte Wert 1>
<3 Byte Wert n>
<3 Byte Wert 59>
6 Bit + 4 Bit + 5 Bit + 5 Bit + 6 Bit + 6 Bit = 32 Bit = 4 Byte
4 Byte + 60*3 Byte = 184 Byte für eine Stunde Daten von einem Sensor-Paar.

Die 6 Bit Jahres-Information wäre gut bis 2063.

In das EEPROM des ATmega passen 1024/184 = 5 Stunden, in das externe passen 4096/184 = 22 Stunden.

Die 104 (1024-(5*184)) ungenutzten Byte im EEPROM des ATmega könnten dazu genutzt werden, die Verwaltungs-Daten der Blöcke persistent zu speichern und damit durch einen Batterie-Wechsel höchstens ein bis zwei Minuten zu verlieren.


temperaturabhängige Tiefschlaf-Dauer

Bei meiner Rollladen-Steuerung habe ich die Erfahrung gemacht, dass die Dauer einer Tiefschlaf-Phase temperaturabhängig ist.
Laut Log-File hat sich zwischen 2015.12.02 und 2016.11.28 folgende Werte-Verteilung für die Tiefschlaf-Dauer [in Millisekunden] ergeben:
Millisekunden Anzahl
8330 25
8340 156
8350 87
8360 54
8370 34
8380 7

Also 50 Millisekunden temperaturabhängiges Delta bei einer Tiefschlaf-Phase von 8.3 Sekunden.
Nicht sehr viel...aber über einen Tag summiert sich so ein Fehler. Und die Rollladen-Steuerung steht im Wohnzimmer, in dem die Temperatur höchstens zwischen +19°C und +35°C schwankt.
Folglich sollte regelmäßig mit der Uhr synchronisiert werden.

Soll etwa alle 4.1 Sekunden ein Werte-Paar von den Sensoren geholt werden, müsste 14 mal pro Minute für 4.1 Sekunden gewartet werden. Das Ergebnis wären 15 Messwerte, die zu einem minütlichen Mittelwert verdichtet werden müssten...der dann im EEPROM abgelegt würde.
Würde alle fünf Minuten mit der Uhr synchronisiert werden, ergäben sich folgende Zeiten:
Minute
Sek.
Werte
4,1 Sek.
4,2 Sek.
1 60 14
57,4 58,8
2 120 14
114,8 117,6
3 180 14
172,2 176,4
4 240 14
229,6 235,2
5 300 14
287,0 294,0
Ist die Tiefschlaf-Phase 4.1 Sekunden lang, hätte ich nach fünf Minuten bereits 13 Sekunden Abweichung.
So geht das also eher nicht.

Entweder muss sich das Programm an eine sehr viel genauer passende Tiefschlaf-Dauer rantasten, indem mehrere unterschiedlich lange Zeiten gemäß folgender Tabelle geschlafen wird....
WDP3
WDP2
WDP1
WDP0
Dauer
0 0 0 0 16 ms
0 0 0 1 32 ms
0 0 1 0 64 ms
0 0 1 1 0.125 s
0 1 0 0 0.25 s
0 1 0 1 0.5 s
0 1 1 0 1.0 s
0 1 1 1 2.0 s
1 0 0 0 4.0 s
1 0 0 1 8.0 s
...oder es muss ganz brutal (und Strom-verschwendend) nach jeder Minute mit der RTC synchronisiert werden.
Wobei das sogar den Vorteil hätte, dass das externe EEPROM dann sowieso unter Strom wäre und man die drei Byte Messwert-Tupel direkt festschreiben könnte - ohne die knappen zwei Kilobyte RAM damit belasten zu müssen.

Andererseits: ATmega und RTC+EEPROM ziehen im aktiven Zustand (laut Datenblatt) zusammen etwa 20mA.
Wenn man jede Minute zwei Sekunden lang 20mA verbrät, sind das pro Tag bereits 24*60*2=2880 Sekunden oder 48 Minuten. Da wird ein Akku-Satz mit 1900mAh keine 120 Tage durchhalten.

Das Rantasten könnte folgendermaßen ablaufen:
- Restzeit bis zur vollen Minute von der RTC holen
- Restzeit umrechnen nach Anzahl von 0.25 Sekunden Tiefschlaf-Phasen, bis die neue Minute gerade begonnen hat
- ggf. Kontrolle, ob die neue Minute gemäß RTC tatsächlich schon begonnen hat
Damit sollte sich die Zeit mit relevantem Stromverbrauch im Millisekunden-Bereich abspielen.
Eine spezielle delay()-Funktion, die intern mit SLEEP_MODE_PWR_DOWN arbeitet, wäre hier vielleicht ganz hilfreich.

Eigentlich ist es nicht so wichtig, dass der erste Messwert in der Sekunde Null einer Minute geholt wird.
Es langt völlig, wenn erster und letzter Messwert irgendwo innerhalb der Minute liegen.
Schließlich soll die RTC möglichst nicht jede Minute eingeschaltet werden müssen. Idealerweise nur einmal pro Stunde, wenn ohnehin mit dem EEPROM kommuniziert werden muss.

Außerdem sollte es reichen, den Temperatur-Sensor nur einmal pro Minute abzufragen. Beim Helligkeits-Sensor ist es hingegen durchaus nützlich, die Helligkeit pro Minute aus dem Mittelwert mehrerer Helligkeitswerte der jeweiligen Minute zu bilden. Nicht so sehr für Tageslicht- bzw. Outdoor-Messungen - aber bei Indoor-Messungen wird dadurch auch ein nur kurz eingeschaltetes Licht detektierbar.

Genug überlegt... die Erkenntnisse beim Bau des Programms folgen auf der nächsten Seite.