Für einen aktuellen Geocache, der eine Hommage an das bekannte Tetris-Spiel ist, wollte ich, dass die Leute ein einfaches physisches Puzzle lösen (wie im Bild oben gezeigt). Als Belohnung erhält man den Code, mit dem man eine Box öffnen kann. Was muss man also tun, um so etwas zu realisieren? Und wie stellt man sicher, dass die Batterien für die nächsten 20 Jahre nicht gewechselt werden müssen?

Puzzle-Lösungen

Bevor wir uns mit der Frage beschäftigen, wie wir mögliche Lösungen erkennen können, müssen wir bestimmen, wie viele Lösungen es überhaupt gibt. Im besten Fall gibt es eine eindeutige Lösung, die wir dann mithilfe von Sensoren erkennen können. Für das oben gezeigte Puzzle ist die Lösung leider nicht eindeutig.

Ich habe ein kleines Python-Skript geschrieben, das alle Möglichkeiten durchsucht, wenn ein Teil bereits platziert ist. In all diesen Fällen gab es jedoch keine eindeutige Lösung. Zwei Teile zu platzieren, hat jedoch geholfen. Die im linken Bild gezeigte Kombination führt zu einer eindeutigen Lösung. Wobei das nur stimmt, wenn man davon ausgeht, dass die roten Puzzleteile eine bestimmte Seite nach oben haben. Im Bild sieht man auch die LED oben am Puzzle-Brett, die verwendet wird, um den Code zu blinken, den man braucht, um die Box zu öffnen.

Das einzige verbleibende Problem besteht also darin, die Anwesenheit jedes Puzzle-Teils wahrzunehmen (und das auf eine Weise, die so energieeffizient wie möglich ist).

Wahrnehmen von Puzzle-Teilen

Müssen wir jede Art von Stück einzeln wahrnehmen oder reicht es aus, festzustellen, dass alle Teile auf dem Brett sind? Die erste Alternative könnte mit RFID umgesetzt werden. Dies wäre jedoch kompliziert und teuer. Ich bin mir nicht einmal sicher, ob es Lösungen gibt, die auf dieser räumlichen Skala funktionieren. Die zweite Alternative scheint in Ordnung zu sein, wenn zufällige Konfigurationen von auf dem Brett liegenden Teilen eine sehr geringe Wahrscheinlichkeit haben, als Lösung wahrgenommen zu werden. Eine Idee könnte also sein, dass man versucht, das Vorhandensein eines Teils an bestimmten Positionen zu testen, wobei alle Teile flach auf dem Puzzle-Brett liegen müssen. Da das Holz selbst nicht wahrgenommen werden kann (mit jedem mir bekannten Sensor), muss man etwas in die Puzzleteile integrieren, z.B. einen kleinen Magneten. Diese können dann z.B. mit Reedschaltern oder Hall-Sensoren erfasst werden.

Ich habe kleine Neodym-Magnete in die Puzzle-Teile gesteckt und Sugru benutzt, um sie zu fixieren. Ich habe dann die Unterseite der Stücke grau lackiert, damit man weiß, welche Seite der Puzzle-Teile nach oben zeigen sollen. Diese Magnete können dann mit Hall-Sensoren erfasst werden, Sensoren, die das Magnetfeld messen. Da die Magnete nicht sehr stark sein können und weil sie den Sensoren nicht beliebig nahe kommen können, ist es nicht möglich, digitale Hall-Sensoren zu verwenden, die auf starke Änderungen des Magnetfeldes angewiesen sind. Also entschied ich mich für einen relativ günstigen analogen Hall-Sensor, den SS49E. Diesen Sensor kann man mit 2,7 bis 5 Volt betreiben, er benötigt grob einen Versorgungsstrom von 5 mA und die Empfindlichkeit liegt bei ca. 1,0-3,2 mV/Gs.

Ich habe einige Experimente durchgeführt und herausgefunden, dass die Magnete in den Puzzle-Teilen durch das Holz des Puzzle-Bretts hindurch wahrgenommen werden können. Also legte ich alle Teile auf das Brett, benutzte Magnete von der anderen Seite und markierte die Stellen, platzierte die Sensoren an den markierten Stellen und fixierte sie (wieder) mit Sugru. Jetzt müssen wir nur noch die Sensoren an eine MCU anschließen und ein Arduino-Programm schreiben.

Board-Auswahl und -Anpassung

Welches Board sollte man verwenden oder sollte man ein eigenes entwerfen? Eines der Hauptkriterien ist dabei, wie viele Pins benötigt werden. Man könnte alle Versorgungspins der Sensoren miteinander verbinden und dann vom gemeinsamen Vcc-Pin der Platine beziehen. Dann braucht man 7 Analog-Digital-Wandler-Pins. Wenn wir jeden Sensor einzeln über einen Datenausgangspin mit Spannung versorgen wollen, benötigen wir zusätzlich 7 Ausgangspins. Ein Arduino Pro Mini würde den Job auf jeden Fall erledigen und er hat auch den richtigen Formfaktor. Darüber hinaus gibt es eine 3,3-Volt-Version mit 8 MHz und das Board hat keinen USB-Anschluss, sodass man zur Programmierung einen zusätzlichen USB-UART-Adapter benötigt. Warum ist das alles ein Vorteil? Man spart etwas Geld, etwas Platz und vor allen Dingen Energie (weil keine Energie durch einen USB-Konverter verschwendet wird, den man im operativen Betrieb nicht braucht).

Beim Betrieb eines Pro Mini Boards mit 5 Volt bei 16 MHz benötigt das Board laut einem Experiment von Andreas Rohner 21,85 mA. Wenn wir den von den Sensoren benötigten Versorgungsstrom hinzufügen, sind wir bei 57 mA. Etwas, das mit einer Batterie nicht geleistet werden kann. Aber es geht besser.

In dem oben erwähnten Experiment zeigte Andreas Rohner auch, dass das Entfernen des Spannungsreglers und der Power-LED den Stromverbrauch erheblich reduziert. Als er die MCU dann bei ausgeschaltetem Watchdog-Timer (WDT) in den Power-Down-Modus versetzte, reduzierte er den Stromverbrauch auf 20 μA. Das hat mich tatsächlich überrascht, denn im Datenblatt des ATmega328P steht, dass die MCU nur 100 nA zieht, wenn der WDT deaktiviert ist. Und wenn man sich den Schaltplan des Pro Mini Boards anschaut, gibt es keine Möglichkeit, dass 20 μA irgendwo verschwendet werden. Tatsächlich erhält man die im Datenblatt versprochenen 100 nA, wenn man die Brown-Out-Erkennung deaktiviert.

Wer daran interessiert ist, auch ein solches Board zu modifizieren und einen neuen, modernen Bootloader auf den Pro Mini zu brennen, sollte sich die detaillierte Anleitung in einem Tutorial zum Tunen eines Pro Mini anschauen.

Low-Power-Design

100 nA ist also die untere Grenze dessen, was wir erreichen können, wenn sich die MCU im Power-Down-Modus befindet. Wir werden versuchen, so gut wie möglich in diesem Bereich zu bleiben.

Wecksensor

Wir brauchen etwas, um die MCU aufzuwecken. Mein Lieblingssensor dafür ist der SQ-SEN-200 Vibrationssensor. In Deutschland ist er relativ teuer, aber mein chinesischer Lieblingshändler hatte sie etwas günstiger (derzeit scheinen sie aber überall ausverkauft zu sein). Diese Sensoren sind extrem empfindlich. Wenn man eine Platine sehr, sehr vorsichtig anhebt, ohne zu schütteln, wird der Sensor aktiviert, d.h. ein Schalter wird geöffnet. Man benötigt also einen Pull-up-Widerstand, der an einen digitalen Pin angeschlossen ist, und kann dann einen Pin-Change-Interrupt auslösen lassen. Der Pull-up-Widerstand kann in diesem Fall einen ziemlich hohen Wert haben. Ich benutze 5 MΩ. Bei einer Versorgungsspannung von 3,6 Volt bedeutet dies, dass von diesem Pull-up etwa 720 nA gezogen werden, was bei ausgeschalteter MCU insgesamt 820 nA ergibt. Reicht das aus, um einen Interrupt auszulösen? Streng genommen liegt es außerhalb der Spezifikation, aber es funktioniert wunderbar. Die Spezifikation besagt, dass der maximale Eingangsleckstrom für jeden digitalen Eingangspin 1 μA beträgt, was dann bedeute würde, dass nur 720nA gezogen werden und der Pegel am Eingangspin 0V beträgt. Aber das ist nicht das, was passiert. Der 1 μA Leckstrom ist extrem pessimistisch. Ich habe mit meinem Multimeter Siglent SDM3045X ein paar tausendmal einen digitalen Eingang mit und ohne 5 MΩ Pull-up gemessen und nie einen Messwert mit mehr als 10 nA erreicht. Es kann sein, dass dieser Eingangspin in einer Umgebung mit viel EMI Probleme verursachen kann. Außerdem ist er wahrscheinlich nicht für hochfrequentes Schalten geeignet, aber für die Erkennung einer Änderung des Vibrationssensors ist es gut genug.

Verbinden der Sensoren

Wenn alle sieben Hall-Sensoren gleichzeitig mit Strom versorgt werden, werden 35 mA verbraucht. Es besteht jedoch keine Notwendigkeit, sie alle gleichzeitig mit Strom zu versorgen. Tatsächlich kann man alle Ausgangsleitungen miteinander verbinden und sie an einen analogen Eingangspin der MCU anschließen. Wenn man dann einen der Sensoren einschaltet, indem man Strom zuführt, erhält man nur den Messwert von diesem aktivierten Sensor und es gibt keine Interferenzen mit den anderen Sensoren. So kann man gleichzeitig Strom und Verkabelung sparen!

Rechts sieht man die Verbindungen des Boards zur Außenwelt. Oben geht das schwarz-rote Kabel zum Akku. Rechts oben sieht man den Vibrationssensor. In der Mitte befindet sich der Pull-up-Widerstand. Der rechte Stecker hat zwei Kabel für die LED und eines für den analogen Eingang. Der untere Stecker hat ein schwarzes Kabel als gemeinsame GND-Leitung für alle Sensoren und die restlichen Kabel gehen zu den Versorgungspins der Sensoren.

Auslesen der Sensoren

Wenn man die Werte der Sensoren auslesen möchte, kann man jeden einzelnen Sensor einschalten, den Sensorwert auslesen und dann wieder ausschalten. Diese Schleife benötigt 440 μs und während dieser Zeit zieht das Board 4 mA für die Platine und 5 mA für den Sensor, d.h. 9 mA für 0,44 ms. Die zusätzliche Verarbeitung dauert 100 μs. D.h. rund 4 mA für 0,1 ms. Zwischen zwei Messungen kann man die MCU ausschalten und den Watchdog-Timer verwenden, um die MCU wieder aufzuwecken. Tatsächlich wird das gesamte Timing im Programm vom Watchdog-Timer durchgeführt und das gesamte Warten erfolgt im Power-Down-Modus. Alle Timer und alle Peripheriegeräte sind ausgeschaltet.

Wie viel Zeit kann man jetzt schlafen, bevor man den Zustand des Boards erneut überprüfen muss? Ich habe das davon abhängig gemacht, wie viele Puzzle-Teile bereits auf dem Puzzle-Brett liegen. Am Anfang ist das Schlafintervall 8 Sekunden lang. Fehlt nur noch ein Puzzle-Teil, wird jede Viertelsekunde geprüft. Dies bedeutet, dass, wenn das Puzzle-Brett durch Bewegen aktiviert wird, es die meiste Zeit für 8 Sekunden schläft und dann eine Messung durchführt:

(8000 ms x 5,1 μA + 0,1 ms x 4000 μA + 0,44 ms x 9000 μA)/8000,54 ms = 5,64 μA

Wird jede Viertelsekunde gemessen, erhöht sich das auf etwa 18 μA, was immer noch ziemlich niedrig ist. Wenn man konservativ den Durchschnitt dieser beiden Werte nimmt, bedeutet dies, dass das Board, wenn es aktiv ist, im Durchschnitt nicht mehr als 12 μA zieht. Vergleicht man das mit dem einfachen Setup, wobei die MCU in ihrer unveränderten Konfiguration und alle Hall-Sensoren für die ganze Zeit mit Strom zu versorgen sind: 40 mA. Dies ist ein Faktor von 3000 und macht den Unterschied aus, ob ein System 20 Jahre lang oder 3 Tage lang mit einer Batterie betrieben werden.

Blinken des Ergebnisses

Sobald alle Teile an Ort und Stelle sind, blinkt eine super-helle LED das Ergebnis. Die LED zieht 4 mA. Sie ist für 1/4 Sekunde für einen Impuls eingeschaltet, mit ungefähr 100 Impulsen pro Lösungsanzeige (mit Wiederholungen des Ergebnisses). Insgesamt benötigt dies also 100 mAs oder 28 μAh.

Unterm Strich

Schauen wir uns nun an, wie viel Energie insgesamt verbraucht wird. Hier unterscheiden wir zwischen der Energie, die während des Schlafens verbraucht wird, und der Energie, die notwendig ist, um das Rätsel zu lösen. Ersteres wird als Entladung pro Jahr berechnet (vorausgesetzt, es passiert nichts). Für letzteres gehen wir davon aus, dass das Rätsel in 60 Minuten gelöst ist und dann weitere 30 Minuten im Warten verbracht werden, bevor die MCU in den Tiefschlaf gehen.

Die Selbstentladungsrate der Li-SOCl2 Batterien beträgt weniger als 1 % pro Jahr. In unserem Fall mit einem 2600 mAh Akku bedeutet dies 26 mAh (oder weniger). Die MCU und der Pull-up-Widerstand am Vibrationssensor ziehen weniger als 1 μA, das sind etwa 10 mAh pro Jahr, was insgesamt zu 36 mAh/Jahr führt. Nehmen wir eine Lebensdauer des Cache von 20 Jahren (sehr optimistisch) an, so würden wir nicht mehr als 720 mAh verbrauchen. Bei einem 2600 mAh Li-SOCl2 Akku, von dem wir konservativ annehmen, dass man 2/3 der Kapazität nutzen kann, haben wir noch 1000 mAh für Besuche übrig.

Unter der Annahme, dass das Lösen des Rätsels 1 Stunde dauert (was extrem auf der sicheren Seite ist), führt der Besuch die zu folgendem Stromverbrauch (wobei wir eine halbe Stunde „Abkühlzeit“ und Blinken des Ergebnisses hinzufügen):

12 μAh + 3 μAh + 28 μAh = 43 μAh

Dies bedeutet, dass wir in den nächsten 20 Jahren mehr als 20.000 Besuche bewältigen können. Mit anderen Worten ist es wahrscheinlicher, dass ein mechanisches, Umwelt- oder Vandalismusproblem der begrenzende Faktor für die Lebensdauer des Cache sein wird.

Auswildern

Sobald alle Ideen ausprobiert wurden und das Arduino-Programm zu funktionieren scheint, ist es an der Zeit, die endgültige Version zu bauen, die hoffentlich robust genug ist, um ein paar Jahre in freier Wildbahn zu überleben. Hierbei sind die Benutzer (Geocacher) und der Designer (ich selbst) meist das Problem. Nachdem ich einige Jahre in der Informatik gearbeitet habe (aber nicht in HMI), ist es immer noch interessant zu sehen, dass selbst eine Ein-Bit-Schnittstelle (ein Taster) manchmal falsch interpretiert werden kann.

Im Falle des Puzzles war (bisher) nicht die menschliche Schnittstelle das Problem, sondern meine Entscheidungen, welche Komponenten verwendet werden sollten. Nachdem ich alles zusammengebaut und -gelötet hatte, machte ich den „letzten“ Test. Dabei ergaben sich zwei Probleme. Manchmal wurde ein Puzzle-Teil nicht erkannt, weil es bei der Positionierung auf dem Puzzle-Brett ein paar Millimeter Spiel gab. Und das machte einen großen Unterschied in dem, was die Sensormesswerte ergaben. Zweitens schienen die Sensormesswerte für alle Puzzle-Teile zufällig zu variieren.

Das erste Problem habe ich durch die Verwendung von Magneten mit 8 mm Durchmesser anstelle von 5 mm gelöst. Das zweite Problem wurde durch die weißen Stecker verursacht, die im Bild oben zu sehen sind. Sie saßen nicht fest und führten aus diesem Grund zu unterschiedlichen elektrischen Widerständen, wenn sie leicht bewegt wurden. Bei den analogen Signalen (den Hall-Sensor-Messungen) gab es dadurch erhebliche Unterschiede.

Ich verwende deshalb jetzt DuPont Stecker, die sehr fest sitzen. Und seitdem läuft auch alles rund. Unten ist ein Foto des endgültigen Systems zu sehen, bevor ich die Box geschlossen habe. Man beachte, dass ich erneut Sugru verwendet habe, um den Akku und die Leiterplatte auf die Box zu kleben. Das Coole an Sugru ist, dass es zuverlässig an fast allem haftet, dauerhaft klebt und nicht leitend ist.

Verdrahtung der Puzzle-Box

In Aktion

Und wie sieht es aus, wenn die Puzzle-Box in Aktion ist? Es ist nicht wirklich spektakulär. Aber die Geocacher, die bereits damit gespielt haben, mögen es. Hier ist es …