Vor einiger Zeit habe ich mir zwei DIY-Sensoren von technikkram.net bestellt. Technikkram schickt alle Teile, nur löten muss man noch. Obwohl ich im Löten nicht sonderlich geübt bin, hat der Aufbau und die Inbetriebnahme nach dem zusätzlichen Einstellen der Sendefrequenz funktioniert.
Kein Betrieb mit Akkus möglich
Für den Betrieb meiner Homematic-Sensoren verwende ich ausschliesslich wiederaufladbare eneloop-Akkus. Leider hat der technikkram-Sensor nach wenigen Tagen mit den Akkus den Betrieb eingestellt, wohingegen der Sensor mit Alkaline-Batterien mehr als ein halbes Jahr ohne Problem gelaufen ist und wohl auch noch wesentlich länger gelaufen wäre.
Schaut man sich die Entladekurve der eneloops an, wird auch sofort klar, warum das so ist: Die Spannung eines einzelnen, voll-geladenen Akkus fällt sehr schnell von 1,45 V ab, um sich dann auf ca. 1,2 V für längere Zeit zu stabilisieren. Bei zwei Zellen in Serie ergibt das eine Spannung von 2,4 V. Der Arduino Mini Pro kommt standardmässig mit einer Brown-Out-Detection daher, welche bei 2,7 V eingestellt ist. Die BOD soll ein instabiles Verhalten bei zu geringer Versorgungsspannung verhindern und schaltet den Pro Mini bei Unterschreitung einfach ab, was mit den eneloops innerhalb weniger Tage passiert. Alkaline-Batterie hingegen starten mit einer höheren Spannung als die NiMH und bleiben auch sehr lange über 1,35 V, so dass die BOD erst viel später zuschlägt.
Lösung: Brown-Out-Detection (BOD) einstellen
Glücklicherweise kann man die BOD-Spannung konfigurieren (Schwellen: 4,3 V - 2,7 V - 1,8 V - off). Die BOD und noch andere Einstellungen werden mittels sogenannter Fuses (Sicherungen) gesetzt. Das geht leider nicht über das normalerweise für die Programmierung verwendete serielle Interface, sondern nur über einen Programmer. Ich verwende einen sehr günstigen (ca. 3 US-$) USB ISP AVR Programmer, den man z.B. hier bestellen kann. Es ist zu beachten, dass der Programmer auch 3,3 V beherrscht und nicht nur 5V, da der Arduino Pro Mini ebenfalls in der 3,3V-Ausgabe auf dem Sensor sitzt. Die Spannung des Programmers kann meist über einen Jumper eingestellt werden.
ISP-Programmer anschliessen
Da ich den Arduino Pro Mini schon eingelötet hatte und zu faul war, die Stiftleiste auf dem Board nachträglich aufzulöten, habe ich es "fliegend" mit einem Breadboard und E-Z Hooks gemacht. Eine gute Dokumentation der Verkabelung ist hier zu finden.
Fuses auslesen
Fuses auslesen und neu setzen geht einfach mit avrdude. Man kann das Tool herunterladen, oder wie bei Ubuntu direkt über den Packagemanager Apt installieren.
$> sudo apt install avrdude libusb-1.0-0
Als nächstes sollten die Batterien entfernt und der Programmer an den USB-Port angeschlossen werden. Man kann nun die korrekte Funktionsweise mit avrdude überprüfen:
$> avrdude -v -p m328p -c usbasp avrdude: Version 6.3 Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/ Copyright (c) 2007-2014 Joerg Wunsch System wide configuration file is "/etc/avrdude.conf" User configuration file is "/home/alison/.avrduderc" User configuration file does not exist or is not a regular file, skipping Using Port : usb Using Programmer : usbasp AVR Part : ATmega328P Chip Erase delay : 9000 us PAGEL : PD7 BS2 : PC2 RESET disposition : dedicated RETRY pulse : SCK serial program mode : yes parallel program mode : yes Timeout : 200 StabDelay : 100 CmdexeDelay : 25 SyncLoops : 32 ByteDelay : 0 PollIndex : 3 PollValue : 0x53 Memory Detail : Block Poll Page Polled Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- --------- eeprom 65 20 4 0 no 1024 4 0 3600 3600 0xff 0xff flash 65 6 128 0 yes 32768 128 256 4500 4500 0xff 0xff lfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00 hfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00 efuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00 lock 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00 calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00 signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00 Programmer Type : usbasp Description : USBasp, http://www.fischl.de/usbasp/ avrdude: auto set sck period (because given equals null) avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f (probably m328p) avrdude: safemode: hfuse reads as DA avrdude: safemode: efuse reads as FD avrdude: safemode: hfuse reads as DA avrdude: safemode: efuse reads as FD avrdude: safemode: Fuses OK (E:FD, H:DA, L:FF) avrdude done. Thank you.
Wenn obiger Output erscheint, hat die Kommunikation mit dem Arduino funktioniert. Wichtig ist die vorletzte Zeile mit der Ausgabe der Fuses, E für Extended, H für High, L für Low. Wenn man noch nicht an den Fuses geschraubt hat, kann man direkt zu "Fuses einstellen" springen. Ansonsten muss ruft man den Engbedded Atmel AVR® Fuse Calculator auf, wählt als "AVR part name" den "ATmega328P" aus und gibt die ausgelesenen Fuses unter "Current Settings" ein. Danach kann man unter "Feature configuration" das Brown Out Detection level auf 1.8V setzen und bekommt unten die korrekte Fuse-Configuration für den avrdude angezeigt.
Fuses einstellen
Um die neu berechneten Fuses auf den Pro Mini zu übertragen, wird avrdude mit den Fuse-Werten aus dem Fuse Calculator aufgerufen. Wer bisher keine Anpassungen an den Fuses vorgenommen hat, kann die Kommandozeile unverändert übernehmen.
$> avrdude -p m328p -c usbasp -U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0xfe:m avrdude: warning: cannot set sck period. please check for usbasp firmware update. avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f (probably m328p) avrdude: reading input file "0xff" avrdude: writing lfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of lfuse written avrdude: verifying lfuse memory against 0xff: avrdude: load data lfuse data from input file 0xff: avrdude: input file 0xff contains 1 bytes avrdude: reading on-chip lfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of lfuse verified avrdude: reading input file "0xda" avrdude: writing hfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of hfuse written avrdude: verifying hfuse memory against 0xda: avrdude: load data hfuse data from input file 0xda: avrdude: input file 0xda contains 1 bytes avrdude: reading on-chip hfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of hfuse verified avrdude: reading input file "0xfe" avrdude: writing efuse (1 bytes): Writing | ################################################## | 100% 0.01s avrdude: 1 bytes of efuse written avrdude: verifying efuse memory against 0xfe: avrdude: load data efuse data from input file 0xfe: avrdude: input file 0xfe contains 1 bytes avrdude: reading on-chip efuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of efuse verified avrdude: safemode: Fuses OK (E:FE, H:DA, L:FF) avrdude done. Thank you.
Das wars. Bei mir läuft der technikkram-Sensor nun seit einigen Wochen mit eneloops.
Tiefentladung verhindern
Die eneloops haben eine Entladeschluss-Spannung von 1,0 V. Werden sie unter diese Schwelle entladen, nehmen sie Schaden. Durch die Verschiebung der BOD auf 1,8 V würden der Pro Mini rechnerisch bei nur 0,9V pro Zelle ausschalten, also unterhalb der Entladeschluss-Spannung. Die BOD von 1,8 V nützt uns also nichts. Daher kann man die BOD ganz ausschalten:
$> avrdude -p m328p -c usbasp -U lfuse:w:0xff:m -U hfuse:w:0xda:m -U efuse:w:0xff:m
und die Abschaltung des Arduino bei zu geringer im Programm erledigen. Dafür muss im Programm (HM-WDS40-TH-I-BME280.ino) die function loop
um die Abschaltung ergänzt werden, so dass sie wie folgt aussieht:
void loop() { bool worked = hal.runready(); bool poll = sdev.pollRadio(); if ( worked == false && poll == false ) { // deep discharge protection if( hal.battery.critical() ) { // halt the arduino hal.activity.sleepForever(hal); } hal.activity.savePower<Sleep<>>(hal); } }
Zusätzlich sollte natürlich auch die kritische Batteriespannung konfiguriert werden. Der Prozessor des Pro Mini (ATmega328P) kann die eigene Versorgungsspannung messen in dem sie, einfach gesagt, gegen eine Referenzspannung verglichen wird (zum Nachlesen z.B. hier). Diese Referenzspannung ist jedoch sehr ungenau (+/- 10%), was dazu führt, dass Vcc ebenfalls ungenau gemessen wird. Konfiguriere ich bei meinen Sensoren 2,1V als kritische Spannung, schaltet der Arduino erst bei 2,02 oder 2,03 V ab. Das kann bei anderen Boards durchaus verschieden sein.
Die kritische Batteriespannung wird hiermit auf 2.1 V gesetzt: battery.critical(21)
:
class Hal : public BaseHal { public: void init (const HMID& id) { BaseHal::init(id); // measure battery every 1h battery.init(seconds2ticks(60UL * 60), sysclock); battery.low(23); battery.critical(21); } bool runready () { return sysclock.runready() || BaseHal::runready(); } } hal;
Sollte der Arduino jedoch zu früh abschalten, dann kann man diesen Wert noch nach unten korrigiren.
Kompilieren und Hochladen auf den Arduino Pro Mini nicht vergessen!