Pro-Mini-Tuning

Der Arduino Pro Mini ist ein sehr minimalistisches Arduino Board mit wenig Platzbedarf. Aus diesem Grund ist es ein idealer Kandidat für den Einsatz als Zielplatine in einem batteriebetriebenen System. In diesem Blogpost beschreibe ich, wie man den Stromverbrauch minimieren kann und einen neuen Bootloader brennen kann, der Flash-Speicher spart, Debugging ermöglicht und einen lästigen WDT-Fehler behebt.

Die originalen Boards wurden von Sparkfun entworfen und kommen heutzutage (als Klone) in 4 verschiedenen Versionen: Mit einem ATmega168P oder mit einem ATmega328P und mit 8 MHz oder 16 MHz, wobei sie im ersten Fall mit 3,3 Volt und im letzteren Fall mit 5 Volt betrieben werden.

Die Besonderheit des Pro Mini ist, dass es keinen USB-UART-Konverter besitzt, der normalerweise auf einem Arduino-Board integriert ist. Für den Einsatz in batteriebetriebenen Geräten ist das von Vorteil, da man dadurch Strom spart. Für die Entwicklung benötigt man allerdings einen externen Konverter.

Man bekommt solch einen USB-UART-Konverter günstig bei eBay oder Amazon. Man sollte sicherstellen, dass der Konverter einen Header mit Pins hat, die wie folgt angeordnet sind: DTR, RX, TX, Vcc, CTS, GND. Diese Pins stimmen mit dem Header des Pro Mini eins zu eins überein (wie im Bild). Zu beachten ist, dass der GND-Pin am Adapter der unterste Pin ist und auf dem Pro Mini Board der Pin neben dem untersten Pin mit GND beschriftet ist. Da die beiden unteren Pins auf dem Pro Mini Board aber beide miteinander verbunden sind, spielt dies jedoch keine Rolle.

Man kann natürlich Konverter mit anderen Pin-Belegungen verwenden, aber dann muss man individuelle Verbindungen herstellen. Eine Möglichkeit ist zum Beispiel, einen Buspiraten, wie hier beschrieben zu verwenden.

Egal welchen Konverter man benutzt, sollte man darauf achten, dass er einen DTR-Pin besitzt. Dieser wird genutzt, um ein Reset auf dem Pro Mini auszulösen, damit danach der Bootloader einen Upload starten kann. Wenn man keinen DTR-Pin am Konverter hat, muss man vor einem Upload selbst die Reset-Taste drücken. Am besten drückt man sie, während das Programm kompiliert, und lässt die Reset-Taste sofort los, wenn die Kompilierung abgeschlossen ist.

Eines sollte beachtet werden. Bei den Pro-Mini-Klonen aus China ist die Reihenfolge für die Pins des Headers oft umgekehrt, d.h. statt dass DTR der oberste Pin ist (im obigen Bild), ist es der unterste Pin. Aber auch wenn man den USB-UART-Adapter falsch herum anschließt, zerstört man dabei die Chips auf der Platine nicht. Sie funktionieren einfach nicht und die Power-LED leuchtet nicht auf.

Wer noch nie einen Pro Mini verwendet hat, sollte sich am besten mit dem Tutorial von Sparkfun mit dem Board vertraut machen. In der Arduino IDE muss man das richtige Board auswählen (im Menü Werkzeuge) und sobald man das Board ausgewählt hat, muss man noch einmal in das Menü zurückkehren, um den richtigen Prozessor auszuwählen. Danach gibt es keinen Unterschied mehr zur Programmierung eines Arduino Uno.

Nun, es gibt einen kleinen Unterschied, wenn man mit der 3,3 Volt/8 MHz-Version arbeitet. Die MCU läuft mit der halben Geschwindigkeit, aktualisiert den Millis-Zähler nur alle 2 ms und verbraucht deutlich weniger Strom als bei der 5 Volt/16 MHz-Version (oder einem Arduino Uno). Die 3,3-Volt-Version verbraucht rund 5 mA, die 5-Volt-Version verbraucht ca. 19 mA.

Reduktion des Stromverbrauchs

Wenn man ein System mit einer Batterie betreibt, sollte es sich die meiste Zeit im Ruhezustand (Power-Down-Modus) befinden, in dem der Stromverbrauch minimal ist. Wenn man das Datenblatt des ATmega328P konsultiert, sieht man, dass die MCU im Power-Down-Modus mit deaktivierter Brown-Out-Erkennung (BOD) und deaktiviertem Watchdog-Timer (WDT) 0,1 μA verbraucht. Dies entspricht 1 mAh pro Jahr (wenn man ein Jahr mit 10.000 Stunden approximiert). Dabei ist zu beachten, dass die Selbstentladung von Batterien viel höher ist! Selbst Li-SOCl2-Batterien, die eine sehr geringe Selbstentladungsrate von rund 1 %/Jahr aufweisen, würden bei einem 2600-mAh-Akku rund 26 mAh pro Jahr verlieren.

Zusätzlich zu den 0,1 μA, die die MCU am Leben erhalten, benötigt man vermutlich etwas Strom für Sensoren, die die MCU aufwecken sollen. Das kann zum Beispiel ein Beschleunigungssensor oder nur ein Vibrationsschalter (mit einem Pull-up-Widerstand) sein. Oder vielleicht eine Echtzeituhr. Ich benutze oft einen Vibrationsschalter, der im Normalzustand geschlossen ist und ein Pull-up-Widerstand von 10 MΩ besitzt. Der Schalter ist an einen Eingangspin angeschlossen ist, der als PIN-Change-Interrupt (PCI) -Eingang konfiguriert ist. Die 10 MΩ liegen außerhalb der Spezifikation, aber ich habe bisher keine Probleme damit gehabt. Bei 3,3 Volt verbraucht das System dann insgesamt 0,43 µA.

Um Strom zu sparen, kann man die LowPower-Bibliothek von rocketscream einsetzen (falls man ATtinys oder dem ATmega1284 (P) verwenden möchte, dann sollte man meinen Fork der Bibliothek verwenden). Die Hauptmethode dieser Bibliothek ist die powerDown-Methode. Ein typischer Aufruf sieht dabei wie folgt aus:

LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

Der Aufruf führt dazu, dass die MCU mit deaktiviertem Analog-Digitalwandler (ADC) und abgeschalteten Brown-Out-Check (BOD) in den Power-Down-Modus versetzt wird. Wenn man den ADC nicht deaktiviert (wofür es kaum einen Grund gibt), verbraucht dieser ungefähr 250 μA auf. BOD kann durch Fusebits deaktiviert oder aktiviert werden. Wenn BOD aktiviert ist, überprüft es ständig die Versorgungsspannung und erzwingt einen Reset, wenn die Versorgungsspannung unter ein konfiguriertes Niveau fällt. Dabei werden etwa 20 μA verbraucht. Da man diesen Test im Ruhezustand nicht benötigt, kann man bei den meisten MCUs BOD per Software mit dem Argument BOD_OFF deaktivieren.

Schließlich fragt man sich vielleicht, was das erste Argument SLEEP_FOREVER bewirkt und warum man nicht stattdessen den Stecker ziehen sollte. Es bedeutet einfach, dass die MCU nur durch einen externen Interrupt aufgeweckt werden kann, wie z.B. durch einen PCI, wie oben erwähnt, oder durch eine Eingabe an einem der externen Interrupt-Pins des ATmega328P.

Wenn man die MCU regelmäßig aufwecken möchte, kann man eines der folgenden Argumente verwenden: SLEEP_8S, SLEEP_4S, SLEEP_2S, SLEEP_1S, SLEEP_500MS, SLEEP_250MS, SLEEP_120MS, SLEEP_60MS, SLEEP_30MS, SLEEP_15MS. Wird beim Aufruf von powerDown eines dieser Argumente verwendet, wird der Watchdog-Timer (WDT) nach der angegebenen Zeit aktiviert. Wenn man das in einer Schleife tut, kann man beispielsweise alle 8 Sekunden aufwachen, etwas tun und dann wieder schlafen. Im Schlaf verbraucht die MCU etwa 5 μA für den Watchdog-Timer.

Diese Dinge wollen wir jetzt anhand des LowPower-Beispielprogramms powerDownWakePeriodic.ino im example-Ordner ausprobieren. Innerhalb des Programms wird die MCU alle 8 Sekunden aufweckt und dann sofort wieder schlafen gelegt. Wenn man jetzt den USB-UART-Adapter vom Board trennt, das Pro Mini-Board an eine externe Stromversorgung anschließt und den Strom misst, wie im Bild gezeigt, sollte man eine erhebliche Reduktion des Stromverbrauchs feststellen können.

Messung des Versorgungsstroms eines Pro Mini

Während man vielleicht erwarten würde, 5 μA zu sehen (da WDT aktiviert ist), sieht man aber tatsächlich etwas um 3-5 mA. Der Grund dafür ist, dass die Power-LED (die man wirklich nicht benötigt, wenn man den Pro Mini in einem batteriebetriebenen Gerät verwendet) den größten Teil des Stroms verbraucht.

Stromfresser entfernen

Wenn man also wirklich Energie sparen will, dann muss man die Power-LED oder alternativ den 10 kΩ oder 1 kΩ Serienwiderstand für die LED entfernen. Im Bild unten ist die Position der LED (rot) und des Widerstands (grün) für verschiedene Versionen der Platine markiert. Es gibt aber auch noch völlig andere Versionen. Um herauszubekommen, welches die Power-LED ist, kann man einfach das Board mit Strom versorgen und dann schauen, welche LED dauerhaft leuchtet.

Position der Power-LED (rot), des Serienwiderstands (grün), des Spannungsreglers (gelb) und der eingebauten LED (blau)

Man kann die LED entfernen, indem man eines der Pads erhitze und die LED oder den Widerstand mit einer Pinzette anhebt. Es gibt andere Möglichkeiten, wie zum Beispiel viel Lot aufzutragen, sodass beide Pads erhitzt werden. Hier hilft nur Probieren. Nach dem Entfernen der Power-LED (oder des Serienwiderstands) sollten nur noch ca. 20-40 μA fließen. Das meiste davon wird durch den Spannungsregler verursacht, das kleine IC mit 5 Pins (gelb umrandet).

Ich entferne auch immer den Spannungsregler, um wirklich in den Nano-Ampere-Bereich zu kommen. Wenn man wirklich einen Regler verwenden möchte, z. B. weil man eine 9-Volt-Zelle einsetzen will, um das Board mit Strom zu versorgen, dann sollte man einen Regler mit einem niedrigen Ruhestrom verwenden, wie z.B. einen HT75xx-1 oder einen MCP1702. Ersterer hat den Vorteil, dass er auch funktioniert, wenn die Eingangsspannung unter das garantierte Spannungsniveau fällt, während letzterer in diesem Fall beginnt, viel Strom zu ziehen. In jedem Fall haben beide Regler im Normalfall einen Ruhestrom von etwa 2 μA.

Nach dem Entfernen des Spannungsreglers und dem Ausführen der Beispielskizze powerDownWakePeriodic.ino sollte die Stromaufnahme auf 5 μA sinken, was dem vom Watchdog-Timer benötigten Strom entspricht. Wenn man das Beispielprogramm powerDownWakeExternalInterrupt.ino ausführt, bei der man den digitalen Pin 2 an Vcc anschließt oder die Zeile attachInterrupt(0, wakeUp, LOW) auskommentiert, sollte der Stromverbrauch auf 0,1 μA sinken. „Sollte“ heißt aber nicht, dass das tatsächlich so ist. Vor kurzem habe ich ein Pro Mini bekommen, das nach allen Modifikationen immer noch 360 μA zieht. Ich habe keine Ahnung, warum.

EDIT: Mittlerweile weiß ich, was mit dem Pro Mini los war. Es gibt wohl ATmega328P-Fälschungen. Diese zeichnen sich dadurch aus, dass ihr Power-Down-Mode-Strom viel zu hoch ist. Außerdem funktioniert HV-Programmierung bei ihnen nicht. Und sie scheinen eine bestimmte Byte-Folge im Boot-Segment des Chips zu besitzen.

Schließlich ist da noch die System-LED, die mit dem digitalen Pin 13 verbunden ist. Wenn man Pin 13 als Ausgang verwenden will, dann sollte man auch diese LED (blau umrandet) oder den Serienwiderstand in der Nähe entfernen.

Optiboot-Bootloader

Der mit dem Pro Mini gelieferte Bootloader stammt aus der Steinzeit der Arduino-Ära. Es hat eine Größe von 2 kB (anstelle von 512 Bytes, was ausreicht) und er hat einen Fehler, der dazu führt, dass man den Watchdog-Timer nicht nutzen kann. Wenn die MCU neu gestartet wird, während der Watchdog-Timer aktiviert ist, wird die Watchdog-Zeitverzögerung nach dem Reset auf 15 Millisekunden festgelegt. Der ursprüngliche Bootloader deaktiviert den Watchdog-Timer nicht und so wird die MCU während des Bootens neu gestartet. Und das passiert unendlich oft. Der einzige Ausweg besteht dann darin, die Stromversorgung zu trennen und die MCU erneut zu starten.

Mittlerweile gibt es den optiboot Bootloader, der auch der Standard-Bootloader auf dem Arduino Uno ist. Dieser Bootloader hat nicht das WDT-Problem und verwendet nur 512 Bytes Flash-Speicher. Noch besser, die neueste Version 8.0 (die noch nicht Teil der Arduino-Distribution ist) unterstützt das Schreiben im Flash-Speicher, was hilfreich ist, wenn man debuggen möchte, wie ich in meinem Tutorial zum Debuggen mit einem gdb-stub beschrieben habe. Es gibt also drei gute Gründe, auf die neueste Version von optiboot umzusteigen.

Zuerst muss man das optiboot Github-Repository herunterladen oder klonen. Dann (nach dem Entpacken der heruntergeladenen Zip-Datei) muss man in das Verzeichnis wechseln, das die Quelldateien für den Bootloader enthält. Wenn man die ZIP-Datei heruntergeladen hat, ist es

cd optiboot-master/optiboot/bootloaders/optiboot/

Falls man geklont hat, heißt das Top-Level-Verzeichnis optiboot statt optiboot-master. Dieses Verzeichnis enthält bereits eine kompilierte Version für den Uno oder den Pro Mini 16MHz namens optiboot_atmega328.hex. Diese Datei sollte im dritten Schritt an den Ort kopiert werden, an dem sich die optiboot-Bootloader der Arduino-Installation befinden. Das wäre

  • macOS: ~/Library/Arduino15/packages/arduino/hardware/avr/1.8.3/bootloaders/optiboot
  • Linux: ~/.arduino15/packages/arduino/hardware/avr/1.8.3/bootloaders/optiboot
  • Windows: C:BenutzerNAMEAppDataLocalArduino15packagesarduinohardwareavr1.8.3bootloadersoptiboot

Das Verzeichnis enthält höchstwahrscheinlich eine Datei mit dem gleichen Namen, die man aber überschreiben kann.

Viertens kann man jetzt eine Version für die 8-MHz-Version des Pro Mini generieren (im obigen Ordner):

Make atmega328_pro8 BAUD_RATE=57600

Dadurch wird die Datei optiboot_atmega328_pro_8MHz.hex generiert. Als fünften Schritt kopiert man diese Datei in das gleiche Verzeichnis der Arduino-Installation.

Im sechsten Schritt muss man die boards.txt Datei erweitern, die sich im Verzeichnis 1.8.3 befindet (siehe die obigen Verzeichnispfade). Dazu lädt man die Datei in einen (reinen) Texteditor, sucht nach der Zeile ## Arduino Pro oder Pro Mini (5V, 16 MHz) mit ATmega328P und setzt dann den folgenden Text davor:

## Arduino Pro oder Pro Mini (5V, 16 MHz, Optiboot) mit ATmega328P
## --------------------------------------------------
pro.menu.cpu.16MHzatmega328opti=ATmega328P (5V, 16 MHz, optiboot)

pro.menu.cpu.16MHzatmega328opti.upload.maximum_size=32256
pro.menu.cpu.16MHzatmega328opti.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328opti.upload.speed=115200

pro.menu.cpu.16MHzatmega328opti.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328opti.bootloader.high_fuses=0xDE
pro.menu.cpu.16MHzatmega328opti.bootloader.extended_fuses=0xFD
pro.menu.cpu.16MHzatmega328opti.bootloader.file=optiboot/atmega328_optiboot.hex

pro.menu.cpu.16MHzatmega328opti.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328opti.build.f_cpu = 16000000L

## Arduino Pro oder Pro Mini (3,3 V, 8 MHz, Optiboot) mit ATmega328P
## ---------------------------------------------------
pro.menu.cpu.8MHzatmega328opti=ATmega328P (3,3 V, 8 MHz, Optiboot)

pro.menu.cpu.8MHzatmega328opti.upload.maximum_size=32256
pro.menu.cpu.8MHzatmega328opti.upload.maximum_data_size=2048
pro.menu.cpu.8MHzatmega328opti.upload.speed=57600

pro.menu.cpu.8MHzatmega328opti.bootloader.low_fuses=0xFF
pro.menu.cpu.8MHzatmega328opti.bootloader.high_fuses=0xDE
pro.menu.cpu.8MHzatmega328opti.bootloader.extended_fuses=0xFD
pro.menu.cpu.8MHzatmega328opti.bootloader.file=optiboot/optiboot_atmega328_pro_8MHz.hex

pro.menu.cpu.8MHzatmega328opti.build.mcu=atmega328p
pro.menu.cpu.8MHzatmega328opti.build.f_cpu = 8000000L

Dies erweitert den nutzbaren Flash-Speicher von 30720 auf 32256 Bytes, stellt die richtige Kommunikationsgeschwindigkeit ein, setzt die richtigen Fuse-Bits und verweist auf die richtigen Bootloader-Dateien für die neuen Optionen. Wenn man nun die Arduino IDE neu startet, werden man feststellen, dass es neue Optionen gibt, wenn Sie das Board Arduino Pro oder Pro Mini im Menü Werkzeuge ausgewählt hat.

Im siebten Schritt muss man den neuen Bootloader auf das Pro Mini Board brennen. Auf meinem Mac mache ich das normalerweise manuell mit AVRFuses. Man muss erst den Bootloader brennen und dann noch die Fuse-Bits für die Größe des Bootloaders anpassen. Angeschlossen werden muss der Programmer an den Pro Mini wie im folgenden Bild gezeigt.

Anschluss des Pro Mini an einen ISP-Programmer

Wenn man dies mit der Arduino IDE machen möchte, geht man wie folgt vor:

  1. Das richtige Board wählen, das ist entweder Pro Mini Atmega328P (3,3V, 8 MHz, Optiboot) oder (5V, 16 MHz, Optiboot).
  2. Einen ISP-Programmierer an den Computer anschließen und den seriellen Anschluss sowie den Typ des ISP-Programmers im Menü Werkzeuge einstellen (man kann auch einen Uno als ISP-Programmer verwenden, wie hier beschrieben).
  3. Ein Programmerkabel an den Pro Mini anschließen. Mann muss entweder ein eigenes Programmierkabel bauen oder einzelne Jumper-Kabel verwenden (siehe obiges Bild).
  4. Nun wählt man im Menü Werkzeuge die Option Bootloader brennen aus und wartet.
  5. Die eingebaute LED sollte nach Abschluss des Brennens dreimal schnell blinken und dann pausieren.

Danach sollte man in der Lage sein, das Blink-Programm über den USB-UART-Adapter hochzuladen. Außerdem kann man jetzt debuggen (wie in meinem Tutorial beschrieben) man kann größere Programme hochladen und der WDT-Fehler ist behoben.

Views: 187

Kategorien: Boards, Hack, Low-Power, Tutorial

2 Comments

  1. Hallo Herr Nebel,

    funktioniert das auch mit einem 168 Pro mini 5V 18MHZ ??
    Muss man nur in der Textdatei alle 328 gegen 168 tauschen?
    Ansonsten sind die ja kompatibel

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

Copyright © 2024 Arduino-Bastelecke

Thema von Anders NorenHoch ↑