Zum Hauptinhalt Zur Navigation

DIY Katzentracker: Wir stalken unsere Freigängerkatzen

Nachdem unser Kater tagelang verschwunden war, kam mir die Idee für einen selbst gebauten Tracker - er ist klein, leicht, günstig und funktioniert ohne Mobilfunk .
/ Thomas Ell
265 Kommentare News folgen (öffnet im neuen Fenster)
Kater Leopold hat meinen Tracker getestet. (Bild: Thomas Ell)
Kater Leopold hat meinen Tracker getestet. Bild: Thomas Ell

Letztes Jahr haben wir zwei Katzenkinder aus dem Tierheim geholt: eine sehr scheue Katze (Ada Lovelace) und einen sehr scheuen Kater (James Babbage). Offenbar hatten beide sehr schwere erste Lebenswochen hinter sich. Nachdem sie an unser Haus gewöhnt waren, sollten sie zu Freigängern erzogen werden. Doch gleich beim ersten Versuch verschwand unser Kater und blieb über Tage verschollen.

Gerade als ich ihn als vermisst gemeldet hatte, tauchte er wieder auf, und seither kam er jeden Mittag und Abend bei uns vorbei und schlief nachts drinnen. Es interessierte mich sehr, wo er eigentlich den ganzen Tag so war. Und als IoT-Entwickler begann ich darüber nachzudenken, wie ich das mit den Mitteln der modernen Computerelektronik herausfinden könnte.

Meine Lösung können alle Menschen nachbauen, die schon Erfahrungen mit der Programmierung von C++-Programmen mithilfe der Arduino IDE für kleine Mikrocontroller gesammelt haben und auch gerne wissen wollen, was ihre Freigängerkatze den ganzen Tag lang macht.

Klein, leicht, günstig, ohne Mobilfunk

Bei meinen ersten Recherchen stieß ich auf die Seite von Mr. Lee. Er hat sich offensichtlich schon länger mit der gleichen Problematik beschäftigt und bietet fertige Lösungen an(öffnet im neuen Fenster) .

So eine Catcam(öffnet im neuen Fenster) wäre vielleicht eine Lösung gewesen - oder ein Livetracker, wie ich sie selbst schon (öffnet im neuen Fenster) mehrmals entwickelt habe(öffnet im neuen Fenster) . Aber die Catcam ermittelt keine GPS-Koordinaten und ich bin mir nicht sicher, ob die Bilder immer erzählen, wo sie tatsächlich aufgenommen wurden. Hier ist noch eine andere Idee für einen Katzentracker mit Lorawan .

Lorawan Anwendungsbeispiele
Lorawan Anwendungsbeispiele (02:41)

Eine Mobilfunklösung war mir zu teuer und aufwendig, wegen des notwendigen Vertrages und weil sie sicher auch einen höheren Stromverbrauch hätte. Auch sollte ein Verlust des Gerätes finanziell verschmerzbar sein.

Daher waren meine Anforderungen:

  • sehr klein
  • sehr leicht
  • sehr günstig
  • extrem geringer Stromverbrauch, um den Akku möglichst klein halten zu können
  • kein Mobilfunk notwendig
  • GPS-Koordinaten müssen irgendwo aufgezeichnet werden.

Ich startete also wieder ein eigenes Projekt. Eine Warnung vorneweg:

Ich übernehme keine Garantie für die im Artikel beschriebene Vorgehensweise. Es gibt eine gewisse Wahrscheinlichkeit dafür, dass die Katze mit dem für die Anbringung des Trackers notwendigen Halsband oder Geschirr irgendwo draußen im Gelände hängenbleibt und sich dabei womöglich sogar verletzt. Das sollte beim Nachbau und Ausprobieren des Trackers berücksichtigt werden. Möglicherweise ist es besser, sich im Notfall automatisch öffnende Katzenhalsbänder statt eines Geschirrs zu verwenden. Ich habe ein Geschirr verwendet, da ich davon ausgegangen bin, dass dieses sich am Katzenkörper nicht verdrehen kann, was für die Position des Trackers an der Katze wichtig ist. Mit der im Artikelende erwähnten Modifikation könnte aber auch ein Halsband funktionieren. Sich selbst öffnende Geschirre scheint es nicht zu geben.

Was für das Projekt benötigt wird

Mein Katzentracker wird mit der Arduino IDE programmiert. Achtung: Dieses Projekt funktioniert so noch nicht mit der Arduino IDE 2.0, es muss eine ältere Version verwendet werden. Ich nutze dafür die Version 1.8.13(öffnet im neuen Fenster) - ich habe beide Versionen auf meinem PC installiert.

Wer zum ersten Mal mit der Arduino IDE für den ESP32 programmiert, sei auf dieses Tutorial (öffnet im neuen Fenster) verwiesen.

Für den Zugriff auf Dateien auf dem ESP32 muss der ESP32 Filesystem Uploader installiert werden(öffnet im neuen Fenster) .

Für das Projekt wird benötigt:

Bauteile für den Katzentracker
Bauteil Bezugsmöglichkeit
1 Mikrocontroller LILYGO® TTGO MINI 32 V2.0 ESP32(öffnet im neuen Fenster)
1 GPS-Empfänger Beitian Kleinstes Mini Dual GLONASS + GPS BN-180(öffnet im neuen Fenster)
1 Akku EREMIT 3.7V 250mAh LiPo Akku 502030(öffnet im neuen Fenster)
Verbindungskabel Ist beim Beitian dabei.
Lötstation So etwas habt ihr hoffentlich schon zu Hause.
Elektronik-Seitenschneider Auf keinen Fall die üblicherweise im Haushalt befindlichen klobigen Teile - ich benutze nur die von Knipex.
Katzengeschirr Trixie Katzengeschirr mit Leine, L 1,20 m(öffnet im neuen Fenster)

Einen passenden Mikrocontroller finden

Erste Experimente mit Mikrocontrollern habe ich vor einigen Jahren mit einem Adafruit Trinket(öffnet im neuen Fenster) gemacht. Er ist zwar sehr klein, aber auch in vielerlei Weise sehr beschränkt. Schon wenn ich die eine oder andere Bibliothek verwendete, blieb manchmal kaum Speicher für mein eigenes Programm. So bin ich über den ESP8266 zum ESP32 gekommen und bei diesem seit ein paar Jahren hängengeblieben.

Den ESP32-Chipsatz haben viele Hersteller als Grundlage für ihre eigenen Varianten von Mikrocontrollern verwendet. Viele meiner Programme(öffnet im neuen Fenster) laufen auf dem TTGO-T-Display von Lilygo. Dieser Mikrocontroller hat ein eingebautes Display, das die Anzahl der Möglichkeiten mit so einem Mikrocontroller noch einmal vervielfacht, aber für einen Katzentracker zu viel Strom verbraucht und zu groß ist. Die gleiche Firma bietet aber auch den TTGO MINI 32 V2.0(öffnet im neuen Fenster) an, der kein Display hat und noch einmal ein Stückchen kleiner ist.

Dieser Mikrocontroller hat auch einen Anschluss für einen Lipo-Akku plus zugehörigem Laderegler, der mit von mir gemessenen ungefähr 7 Milliampere (mA) offensichtlich auch keinen zu hohen Eigenverbrauch hat. Übrigens sind Mikrocontroller mit niedrigem Stromverbrauch beim Einsatz eines Akkus im Deep Sleep keine Selbstverständlichkeit. Zwar kommt der ESP32 tatsächlich mit einigen wenigen Mikroampere aus, aber in Verbindung mit einer externen Stromversorgung benötigt er fast immer eine Ladeschaltung, die oft ungünstig ausgelegt ist und dazu führt, dass diese Mikrocontroller trotz Deep Sleep deutlich mehr Strom verbrauchen.

Bei meinen bisherigen Arbeiten mit dem ESP32 hatte ich mich noch nicht damit beschäftigt, wie man die beim Tracken entstehenden Massendaten am besten speichert. Ich hatte zwar schon einmal etwas von einem EEPROM im ESP32-Chipsatz gelesen, aber noch keinerlei Experimente damit unternommen. Nach etwas Recherche fand ich heraus, dass es gar kein EEPROM im klassischen Sinne im ESP32 gibt und stattdessen zusätzlicher Flash-Speicher verwendet wird. Davon gibt es im TTGO MINI 32 V2.0 4 MByte.

Deep Sleep

Durch die geringe Größe vieler Mikrocontroller fallen einem schnell Anwendungen ein, bei denen der Mikrocontroller mobil oder draußen eingesetzt wird. Spätestens, wenn man die Anwendung fertig entwickelt hat und erste Versuche abseits der Stromversorgung durch den heimischen Computer macht, wird klar, dass auch Mikrocontroller Strom verbrauchen, und es entsteht die Frage nach einer mobilen Stromversorgung(öffnet im neuen Fenster) . Schnell stellt man dann fest, dass selbst große Akkus das Gerät nicht monatelang mit Strom versorgen können. In dieser Situation fängt man dann üblicherweise an, sich damit auseinanderzusetzen, wie man eventuell Strom sparen kann.

So ist es für viele Anwendungen gar nicht erforderlich, dass sie rund um die Uhr laufen. Beispielsweise würde es beim regelmäßigen Loggen einer Temperatur völlig reichen, wenn man dies einmal pro Stunde macht. Und selbst wenn es jede Minute wäre, so könnte man in 5 Sekunden die Messung vornehmen und dann den Mikrocontroller für die restlichen 55 Sekunden ausschalten. Nur, wer schaltet ihn dann wieder ein?

Für derartige Anwendungsfälle gibt es beim ESP32 den Deep-Sleep-Modus. Ohne hier ins Detail zu gehen, kann man sich das so vorstellen, dass nahezu alle Komponenten im ESP32 abgeschaltet werden, zum Beispiel auch der Mikroprozessor selbst, und nur eine extrem wenig Strom verbrauchende Uhr eingeschaltet bleibt. Diese weckt nach einer einstellbaren Zeit den ESP32 wieder auf.

Das Problem dabei sind oft die angeschlossenen Ladecontroller oder der Akku selbst. Denn obwohl der ESP32 in diesem Modus nahezu keine Energie mehr verbraucht, verbrauchen sie dann immer noch etwas Strom. Beim MINI 32 sind das 7 mA und damit kann man einiges anfangen.

Stromverbrauch, Akku und das Trackingverfahren

Wenn der Tracker sehr klein ist, dafür aber der Akku groß, habe ich nichts gewonnen. Für den Katzentracker habe ich darum einen sehr kleinen Akku mit nur 250 Milliamperestunden (mAh) verwendet. Beim Bestellen des oben angegebenen Akkus muss man darauf achten, den richtigen Steckertyp anzugeben. Es muss ein JST-GH-1.25-mm-Anschluss sein.

Der Stromverbrauch setzt sich aus dem Wechsel zwischen Deep Sleep und aktiver Phase zusammen. Im Deep Sleep verbraucht die gesamte Anwendung nur 7 mA, aber in der aktiven Phase über 100 mA, wobei ein großer Anteil durch den GPS-Empfänger verursacht wird. Die Messungen habe ich mit einem USB-Spannungs- und Strommessgerät von FNIRSI durchgeführt, das ich aktuell nicht mehr auf Banggood finde. Es gibt aber offenbar einen Nachfolger: FNIRSI-FNB5B(öffnet im neuen Fenster) .

Bei dem verwendeten 250-mAh-Akku könnte der Tracker im Deep Sleep über 35 Stunden betrieben werden. Aber das ist natürlich unrealistisch, denn zumindest hin und wieder muss die Position ermittelt werden und das kostet dann richtig Strom. Für eine erste grobe Abschätzung nehme ich an, dass der Tracker alle 5 Minuten die GPS-Position ermitteln soll und dann 1 Minute benötigt, um die aktuelle GPS-Position zu ermitteln, im Flash-Speicher abzulegen und wieder schlafen zu gehen.

Im praktischen Betrieb ist es aber ungewiss, ob die Position tatsächlich in dieser Zeit gefunden wird. Manchmal dauert es nur Sekunden und ein anderes Mal Minuten. Im Beispiel teilen sich die 250 mAh wie folgt auf:

250 mAh = (7 mA * 0.084 h + 110 mA * 0.017 h)

Nach h umgestellt und ausgerechnet gibt das etwa 100 Wiederholungen. 100 * 6 Min, also etwa 10 Stunden Betrieb!

Länger bleiben die Katzen bei uns normalerweise nicht weg. Das passt also.

Trackingverfahren

Wie schon beschrieben, habe ich auf Livetracking verzichtet. Denn sonst müsste ich nicht nur über GPS eine Position ermitteln, sondern auch noch eine Mobilfunkverbindung aufbauen und die gefundenen Koordinaten per SMS, E-Mail oder direkt an einen Server versenden. Der Aufwand wäre relativ hoch, da ich mir einen zusätzlichen Mobilfunkvertrag besorgen müsste, der registriert und mit Geld versorgt sein will.

Beim Einsatz eines Servers (Raspberry?) müsste ich mich um dessen Installation kümmern. Dazu kommt, dass während des Aufbaus der Mobilfunkverbindung und des Versendens viel Strom verbraucht wird.

Wenn die Daten aber nicht direkt versendet werden, müssen sie bis zu dem Zeitpunkt, an dem ich sie mir ansehen will, irgendwo gespeichert werden. Zu diesem Zweck wäre es möglich, an den ESP32 einen Slot für eine Micro-SD-Karte anzulöten und mit entsprechenden Bibliotheken anzusprechen. Es geht aber einfacher. Der TTGO MINI 32 V2.0 hat 4 MByte Flash-Speicher und es sollte doch irgendwie möglich sein, diese zu verwenden.

SPIFFS

Würde man selbst versuchen, auf den Flash-Speicher zuzugreifen, wäre das mit sehr viel Programmieraufwand verbunden. Darum habe ich die SPI-Flash-File-Storage-Bibliothek ( SPIFFS(öffnet im neuen Fenster) ) verwendet. Sie realisiert ein einfaches Dateisystem ohne Verzeichnisse, was den Zugriff auf den Flash-Speicher wesentlich vereinfacht. Für meine Programmierung bekomme ich mit SPIFFS Befehle wie:

  • format
  • open
  • print
  • flush
  • close

So spare ich Gewicht, Größe und Kosten sowie das Anbringen und Anlöten eines Micro-SD-Kartenslots. Allerdings entsteht dadurch das Problem, an diese Dateien heranzukommen. Schließlich kann ich jetzt nicht einfach die Micro-SD-Karte entnehmen, in einen Kartenleser stecken und am PC auslesen.

Daten mit dem FSBrowser flashen

Um die vom Tracker erzeugten Dateien ansehen zu können, muss der MINI 32 mit einem Webbrowser geflasht werden. Ein solcher gehört standardmäßig zum ESP32-Paket und nennt sich FSBrowser. Er ist zu finden unter Datei -ᐳ Beispiele -ᐳ WebServer -ᐳ FSBrowser. In der Datei FSBrowser.ino müssten folgende zwei Zeilen angepasst werden:

        const char* ssid = "wifi-ssid"; const char* password = "wifi-password";

Für wifi-ssid und wifi-password werden die passenden Werte vom eigenen WLAN eingesetzt. Der so veränderte FSBrowser wird am besten als neues eigenes Projekt abgespeichert.

Der Nachteil ist, dass anschließend der Tracker wieder neu auf dem ESP32 geflasht werden muss. Theoretisch ist es möglich, den Tracker und den Webbrowser gemeinsam auf den MINI 32 zu bringen. Aber das würde den Rahmen dieses Tutorials sprengen. Wir flashen zwischen Tracken und Tracks ansehen immer hin und her.

Für mich ist diese Lösung okay, da ich aus dem Tracken meiner Katzen keine Alltagsbeschäftigung machen wollte und mich daher der gelegentliche Aufwand nicht stört.

Im FSBrowser (Zeile: #define FORMAT_FILESYSTEM false ) gibt es die Möglichkeit, den Flash-Speicher zu löschen. Das ist nur am Anfang und natürlich dann nötig, wenn der Speicherplatz ausgeht. Anschließend sollten unbedingt mit ESP32 Sketch Data Upload die für den FSBrowser wichtigen Dateien in den Flash Speicher geladen werden. Dafür wird der ESP32 Filesystem Uploader verwendet, sonst funktioniert später im Webbrowser beim Aufruf von http://esp32fs.local/edit(öffnet im neuen Fenster) die Anzeige der Dateien nicht.

GPS-Empfänger

Wie schon erwähnt, kann der MINI 32 im Deep Sleep mit 7 mA auskommen. Da aber der GPS-Empfänger mit dem MINI 32 verbunden ist und auch von diesem seinen Strom bekommt, bleiben immer noch ca. 60 mA übrig.

Das würde vielleicht rechnerisch für knapp vier Stunden reichen, wenn der Akku aber schon älter ist und/oder das Suchen nach Satelliten lange dauert, möglicherweise auch keine zwei Stunden. Es wäre also sehr sinnvoll, den GPS-Empfänger immer dann abschalten zu können, wenn der MINI 32 im Deep Sleep ist. Leider ist das bei vielen GPS-Empfängern nicht allein durch ein Stückchen Programmcode möglich. In diesem Fall kann ich einen Transistor an einen der GPIOs löten und mit diesem den GPS-Empfänger ein- oder ausschalten.

Zum Glück ist das aber für den von mir eingesetzten GPS-Empfänger nicht nötig. Er lässt sich durch das Senden einer geheimnisvollen Serie an Bytes durch Software abschalten. Und damit er auch wieder aufwacht, muss ich einfach nur ein paar Zeichen auf die serielle Schnittstelle schreiben.

Dateiformat

Theoretisch kann ich die Zahlenwerte der Koordinaten einfach in eine Datei in den Flash-Speicher schreiben. Doch das pure Zahlenmaterial ist für Menschen sehr schwer zu interpretieren und es wäre wesentlich einfacher zu verstehen, wenn die Koordinaten auf einer schicken Landkarte dargestellt würden. Damit der Tracker massentauglich ist, habe ich als Dateiformat eine einfache Variante des GPX-Formats(öffnet im neuen Fenster) verwendet, die von Google Maps verwendbar ist. Dieses Format verwendet einen definierten Anfang:

        

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="Babbagetracker" version="1.0">

und einen definierten Abschluss:

        

</gpx>

Wenn diese nicht vorhanden sind, kann die Datei von Google Maps und wohl auch den meisten anderen Kartenprogrammen nicht gelesen werden.

Zwischen diesen beiden Einträgen kann ich nun in beliebiger Menge Koordinaten im folgenden Format schreiben:

        

<wpt lat="xx.xxxxxxx" lon="y.yyyyyyy">
<ele>zzz.zzzzzzz</ele>
<time>2022-10-12T20:31:22Z</time>
</wpt>

Normalerweise haben Geräte zum Tracken einen Start- und Stopp-Taster, mit dem bestimmt wird, wann das Tracken beginnt und wann es wieder endet. Damit ist es solchen Geräten möglich, den Anfang und auch das Ende in einer Datei entsprechend zu schreiben. Der MINI 32 hat leider keine einzige Taste, die ich für so einen Zweck verwenden könnte. Natürlich könnte ich eine anlöten, aber ich wollte es ja so minimalistisch wie möglich haben.

Wenn ich wenigstens eine einzige winzige Möglichkeit hätte, ihm etwas mitzuteilen, wenn ich ihm nur ein einziges Bit mitteilen könnte, dann wäre es möglich, ihn immer genau dann einfach eine Datei beenden und eine neue Datei anfangen zu lassen! Diese Möglichkeit gibt es tatsächlich und es ist der Reset-Taster.

Das hat damit zu tun, wie das Programm grundsätzlich arbeitet. Denn im Gegensatz zu den normalen Programmen, die für Arduino-kompatible Mikrocontroller geschrieben werden, wird bei Deep-Sleep-Programmen eher keine Loop-Schleife verwendet. Jedes Mal, wenn der Mikrocontroller aus dem Tiefschlaf aufwacht, wird der gesamte Programmcode von Neuem durchlaufen. Gerade so, als ob er eingeschaltet oder ein Reset durchgeführt wird.

Würde mein Programm allerdings nach jedem Aufwachen eine neue Datei anlegen, wäre das auch nicht in meinem Sinn. Der Trick ist es, festzustellen, ob der MINI 32 tatsächlich resettet wurde oder ob er stattdessen aus dem Tiefschlaf aufgewacht ist. Dies ist mit dieser Anweisung möglich:

        

if (esp_sleep_get_wakeup_cause () == 4)

Wenn die Funktion esp_sleep_get_wakeup_cause () den Wert 4 zurückgibt, kommt der MINI 32 aus dem Tiefschlaf. Im Programmcode öffne ich mit dem Attribut FILE_APPEND nun die schon existierende Datei und schreibe einfach eine weitere Koordinate mit writePosition () hinein.

Kurze Anleitung zur Verwendung der Daten in Google Maps

Wer bei Google Maps angemeldet ist, kann links oben bei den drei Strichen ein Menü aufrufen und die Option Meine Orte wählen. Dort den Punkt Karten auswählen und dann KARTE ERSTELLEN. Es öffnet sich ein neues Fenster bzw. Tab mit einem kleinen weißen Bereich links oben. Dort kann der Track über Unbenannte Ebene -ᐳ Importieren geladen werden.

Anleitung zur Verkabelung

Beim Beitian BN-180 von Banggood sind zwei passende Verbindungskabel dabei. Besonders praktisch ist dabei der schon an einem Ende montierte Stecker. Dieser lässt sich direkt an den Empfänger stöpseln und so habe ich nur noch die Aufgabe, das andere Ende an den MINI 32 anzulöten.

Dazu schneide ich mit einem Seitenschneider das Meiste des Kabels ab, schneide vorsichtig die einzelnen Adern frei und isoliere sie ab. Das kann man mit einem passenden Abisoliergerät machen oder aber mit dem Seitenschneider. Mangels Abisoliergerät habe ich den Seitenschneider verwendet. Achtung: Dabei muss man extrem vorsichtig vorgehen!

Mit der einen Hand den Draht bzw. die einzelne Ader halten. Mit der anderen Hand den Seitenschneider. Den Seitenschneider etwa 2 mm von der Schnittkante mit seinen beiden Klingen ansetzen. Ganz vorsichtig einen Zehntelmillimeter in die Isolierung drücken. Wieder loslassen. Den Draht zwei-, dreimal um etwa 45 Grad drehen und dabei jedes Mal wieder ein bisschen eindrücken. Jetzt den eingestellten Winkel des Seitenschneiders halten, also weder noch mehr zudrücken noch loslassen, und die beiden Hände bei gehaltener Ader und Seitenschneider auseinanderziehen.

Mit viel Glück sind 2 mm Isolierung abgezogen. Wahrscheinlicher ist, dass dabei auch die einzelnen Litzendrähtchen mit abgeschnitten wurden. Daher ist es vielleicht besser, den Draht erst einmal nicht zu kürzen und mit dem dadurch noch genügend langen Draht zu üben.

Nun die einzelnen Litzen ein bisschen miteinander verdrillen und mit etwas Lötzinn verzinnen. Jetzt können wir das dem Beitian beiliegende Klebepad in die Mitte der Seite mit dem TTGO-Schild kleben, darauf den GPS-Empfänger wie im Foto gezeigt kleben, die verzinnten Adern um die Kante des MINI32 biegen, in die in der Tabelle genannten Anschlüsse stecken und mit dem Lötkolben und etwas Lötzinn verlöten.

Die richtigen Anschlüsse
Beitian BN-180 Lilygo MINI 32
GND GND
TX 17
RX 16
VCC 5V

Anwendung

Vor dem ersten Mal ändern wir im Code die Zeile

        

#define FORMAT_FILESYSTEM false

in

        

#define FORMAT_FILESYSTEM true

und kompilieren und flashen damit den MINI 32. Direkt danach nehmen wir die Änderung zurück und flashen den MINI 32 wieder mit der nicht den Flash-Speicher formatierenden Version. Jetzt rufen wir die Funktion Werkzeuge-ᐳ ESP32 Sketch Data Upload auf. Damit werden vier für den späteren Betrieb des FSBrowsers notwendige Dateien in das Filesystem kopiert.

Nach diesen Vorbereitungen können wir den MINI 32 mit dem Tracker flashen und der Katze umhängen.

Idealerweise machen wir nach dem Abnehmen des Trackers von der Katze noch einen Reset, denn dann wird ja eine neue Datei angelegt und an die alte Datei das korrekte Ende angehängt. Wenn wir anschließend mit dem FSBrowser die vorletzte angelegte Datei herunterladen und mit einem GPX-Programm ansehen, sollte das funktionieren, da sie ein korrektes Dateiende bekommen hat.

Der Tracker wird ausprobiert

Es ist so weit, eine unserer Katzen muss den Tracker testen. Mittlerweile haben wir uns mit Leopold und Ron noch zwei andere jungen Katzen von privat geholt. Denn leider wurde Babbage von einem Auto überfahren und Ada sollte nicht alleine bleiben. Leopold wurde von mir für den Test auserkoren, da er mit dem kleinen Katzengeschirr aus der Tierhandlung gut zurechtkam. Bevor es ernst wurde, haben wir ihm das Geschirr ein paarmal ohne Tracker angezogen und ihn dafür mit Katzengoodies belohnt.

Als Gehäuse für den Tracker habe ich die Plastikschachtel einer Packung Laktasetabletten gewählt. Da passt der Tracker ohne Mühe hinein und muss noch nicht einmal fixiert werden. Das Gehäuse habe ich anschließend mit medizinischem Klebeband am Geschirr befestigt.

Anschließend habe ich mich mit einer Tasse Kaffee in der wunderbar warmen Oktobersonne auf den Balkon gesetzt und Leo dabei beobachtet, wie er seinen üblichen Gepflogenheiten im Garten nachging. Also: Ada Lovelace jagen und von ihr gejagt werden, irgendwelchen für Katzen interessanten Gerüchen nachgehen, mit Leo spielen oder Insekten fangen.

Dabei ist mir einmal aufgefallen, wie er durch einen für ihn anscheinend normalerweise durchgängigen Schlitz zwischen Hauswand und Schuppen wollte und mit dem mittlerweile zur Seite gerutschten Tracker hängenblieb. Es ist nichts passiert, er war nur irritiert und hat sich einfach wieder zurückbegeben.

Leider ist er gar nicht aus unserem Garten entwichen und in die Nachbargärten vorgedrungen. So konnten die mit dem Tracker erfassten Positionen auch keine Überraschungen offenbaren. Einige der erfassten Positionen befanden bei der Betrachtung in Google Maps trotzdem beim Nachbarn, was auf eine mangelhafte Genauigkeit schließen lässt.

Dafür könnte es mindestens zwei Gründe geben. Zum einen war durch den zur Seite gerutschten Tracker die Lage des GPS-Empfängers nicht mehr ideal, denn dieser sollte immer mit seiner Antenne nach oben zeigen. Zum anderen stehen bei uns im Garten hohe Bäume und die Katzen halten sich auch meistens am Rand in Gebüschnähe oder im Gebüsch auf. Beides ist nicht ideal für den Empfang von GPS-Signalen.

Fazit

Mir hat das zur Seite rutschende Gehäuse gar nicht gefallen. Bei einer Neukonstruktion würde ich den GPS-Empfänger durch ein wesentlich verlängertes Verbindungskabel viel weiter vom Mikrocontroller und Akku entfernen. So könnte dieser oben am Kopf sitzen und der Rest unten am Hals. Dadurch würde das Ganze wahrscheinlich weniger leicht zur Seite rutschen und der GPS-Empfänger immer optimal nach oben zeigen. Damit könnte Leo wahrscheinlich leichter durch enge Schlitze kommen und der Empfang der GPS-Signale deutlich verbessert werden.

Sowohl der Mikrocontroller als auch der GPS-Empfänger haben eine Reihe von LEDs für die Anzeige verschiedener Zustände. Selbstverständlich verbrauchen auch diese einiges an Strom. Ich habe sie bei der Entwicklung des Katzentrackers aber gut zur Fehlersuche und Funktionskontrolle verwenden können. Theoretisch könnte man sie mit einem feinen Lötkolben ablöten, aber das war für meine Zwecke nicht unbedingt erforderlich und ich habe mich auch nicht getraut, es durchzuführen.

Beispieldatei

        

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="Babbagetracker" version="1.0">
  <wpt lat="44.1493277" lon="7.5617761">
  <ele>1871.0000000</ele>
  <time>2022-10-12T20:30:01Z</time>
  </wpt>
</gpx>

Man mag nicht glauben, wie viele Kurven die durch diesen Ort bestimmte Straße hat.

Formel zum Stromverbrauch und Programmcode

Hier noch eine Formel zum Herumspielen:

Hier die Formel als Programm für den Löser des HP-42S :

    

00 { 72-Byte Prgm }
01 LBL "STROM"
02 MVAR "BD"
03 MVAR "GK"
04 MVAR "DD"
05 MVAR "PD"
06 MVAR "DS"
07 MVAR "PS"
08 RCL "DD"
09 RCL "PD"
10 +
11 RCL "GK"
12 ×
13 RCL "DS"
14 RCL "DD"
15 ×
16 RCL "PS"
17 RCL "PD"
18 ×
19 +
20 ÷
21 RCL "BD"
22 -
23 END

BD = Betriebsdauer in Stunden
GK = Gesamtkapazität
DD = Deepsleepdauer
PD = Positionssuchdauer
DS = DeepsleepStrom
PS = Positionssuchdauer

Programmcode

        

#include <TinyGPS++.h>
#include <HardwareSerial.h>
#include "FS.h"
#include "SPIFFS.h"

#define uS_TO_S_FACTOR 1000
#define WAKEUPDELAY 60000

#define CHECKDELAY 5000
#define GOSLEEPDELAY 2000
#define BLINKDELAY 100

#define LED_BUILTIN 22

static const int RXPin = 17, TXPin = 16;
static const uint32_t GPSBaud = 9600;

boolean serial = false;
boolean written = false;
long lastCheckDelay = millis();
long lastGoSleepDelay = millis();
long lastBlinkDelay = millis();

String dateStr;
String timeStr;
String gpsLatStr;
String gpsLngStr;
String gpsAltiStr;

File file;
String lastFileName = "";
long charsProcessed = 0;

int blinkCnt = 0;
boolean blinkStatus = true;

TinyGPSPlus gps;
HardwareSerial serialGPS(2);

void setup() {
  Serial.begin(115200);

  pinMode(LED_BUILTIN, OUTPUT);

  Serial.println();
  Serial.println("DeepSleep BabbageTracker für Golem - von Thomas Ell");

  if (!SPIFFS.begin(true)) {
    Serial.println("SPIFFS lässt sich nicht initialisieren!");
    return;
  }

  unsigned int totalBytes = SPIFFS.totalBytes();
  unsigned int usedBytes = SPIFFS.usedBytes();

  Serial.print("Verfügbarer Speicherplatz : ");
  Serial.print(totalBytes);
  Serial.println(" byte");
  Serial.print("Schon benutzt             : ");
  Serial.print(usedBytes);
  Serial.println(" byte");
  Serial.println();

  // Letzte Datei im Dateisystem ermitteln
  File root = SPIFFS.open("/");
  file = root.openNextFile(FILE_READ);
  while (file) {
    lastFileName = file.name();
    file = root.openNextFile(FILE_READ);
  }
  file.close();

  Serial.print("Aktuelle Datei: ");
  Serial.println(lastFileName);
  Serial.println();

  serialGPS.begin(GPSBaud, SERIAL_8N1, RXPin, TXPin);
  serialGPS.write("Wake up!");
}

void loop() {

  // Auf das Ende der Initialsierung des GPS Empfängers warten
  if (serialGPS.available()) {
    gps.encode(serialGPS.read());
    if (!serial) {
      Serial.println ("GPS Signal da!");
      serial = true;
      blinkCnt = 2;
    }
  }

  // Auf eine gültige Position warten
  if (millis() - lastCheckDelay > CHECKDELAY) {
    if (serial && gps.location.isValid()) {
      getData();

      if (esp_sleep_get_wakeup_cause() == 4) {
        Serial.println ("Aufgewacht aus Deep sleep.");
        file = SPIFFS.open("/" + lastFileName, FILE_APPEND);
      } else {
        Serial.println ("Aufgewacht durch Reset.");
        file = SPIFFS.open("/" + lastFileName, FILE_APPEND);
        writeClosure ();
        file.close ();
        String fileName = "/" + dateStr + "T" + timeStr + ".gpx";
        file = SPIFFS.open(fileName, FILE_WRITE);
        writeHeader ();
      }
      Serial.println (timeStr + ": " + gpsLatStr + ", " + gpsLngStr);

      writePosition ();

      file.flush();
      file.close();
      written = true;
      blinkCnt = 5;
      lastGoSleepDelay = millis();
    }
    lastCheckDelay = millis();
  }

  // Nach erfolgreichem Wegschrieben einer Position noch auf das Ende des Blinkens warten
  if (written) {
    if (millis() - lastGoSleepDelay > GOSLEEPDELAY) {
      Serial.println ("Gehe schlafen.");
      goSleep();
    }
  }

  // Blinken realisieren
  if (millis() - lastBlinkDelay > BLINKDELAY) {
    if (blinkCnt > 0) {
      if (blinkStatus) {
        blinkStatus = false;
        digitalWrite(LED_BUILTIN, HIGH);
      } else {
        blinkStatus = true;
        digitalWrite(LED_BUILTIN, LOW);
        blinkCnt--;
      }
    }
    lastBlinkDelay = millis();
  }

}

void writeHeader () {
  file.print("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n");
  file.print("<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"Babaggetracker\" version=\"1.0\">\r\n");
}

void writePosition () {
  file.print("<wpt lat=\"" + gpsLatStr + "\" lon=\"" + gpsLngStr + "\">\r\n");
  file.print("  <ele>" + gpsAltiStr + "</ele>\r\n");
  file.print("  <time>" + dateStr + "T" + timeStr + "Z</time>\r\n");
  file.print("</wpt>\r\n");
}

void writeClosure () {
  file.print("</gpx>\r\n");
}

void goSleep () {
  byte cmd[] = {0xB5, 0x62, 0x06, 0x57, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x4B, 0x43, 0x42, 0x86, 0x46};
  for (int i = 0; i < sizeof(cmd); i++) {
    serialGPS.write(cmd[i]);
  }
  esp_sleep_enable_timer_wakeup(WAKEUPDELAY * uS_TO_S_FACTOR);
  esp_deep_sleep_start();
}

void getData () {
  int help;
  dateStr = "";
  help = gps.date.year();
  if (help < 10) {
    dateStr = dateStr + "0" + (String) help;
  } else {
    dateStr = dateStr + (String) help;
  }
  dateStr = dateStr + "-";
  help = gps.date.month();
  if (help < 10) {
    dateStr = dateStr + "0" + (String) help;
  } else {
    dateStr = dateStr + (String) help;
  }
  dateStr = dateStr + "-";
  help = gps.date.day();
  if (help < 10) {
    dateStr = dateStr + "0" + (String) help;
  } else {
    dateStr = dateStr + (String) help;
  }

  timeStr = "";
  help = gps.time.hour();
  if (help < 10) {
    timeStr = timeStr + "0" + (String) help;
  } else {
    timeStr = timeStr + (String) help;
  }
  timeStr = timeStr + ":";
  help = gps.time.minute();
  if (help < 10) {
    timeStr = timeStr + "0" + (String) help;
  } else {
    timeStr = timeStr + (String) help;
  }
  timeStr = timeStr + ":";
  help = gps.time.second();
  if (help < 10) {
    timeStr = timeStr + "0" + (String) help;
  } else {
    timeStr = timeStr + (String) help;
  }
  gpsLatStr = formatDouble (gps.location.lat(), 7);
  gpsLngStr = formatDouble (gps.location.lng(), 7);
  gpsAltiStr = formatDouble (gps.altitude.meters(), 7);
}

String formatDouble (double value, int decimals) {
  String valueStr = String (value, decimals);
  int pointPos = valueStr.indexOf (".");
  if (decimals == 0) {
    valueStr = valueStr.substring (0, pointPos);
  } else {
    valueStr = valueStr.substring (0, pointPos + decimals + 1);
  }
  return valueStr;
}

Thomas Ell interessiert sich für Fotografie, 3D-Drucker, Roboter, technische Gadgets und Technik allgemein. Er kann mit Delphi, Lazarus, ArduinoIDE, Visual Studio und Eclipse in Object Pascal, C++, VB.NET, Java, Javascript und Maschinensprache programmieren. Er hat ein Blog, Steinlaus.de(öffnet im neuen Fenster) .


Relevante Themen