Algorithmen gegen Rezo

In der c’t 13, bzw auf ‘heise.de’ wurde ein Kommentar mit der Überschrift ‘Facebook & Co. brauchen eine öffentlich-rechtliche Organisation’ veröffentlicht.

Im Kommentar leitet der Autor aufgrund Rezos enormer Wirkung in der Öffentlichkeit ab, dass wir eine Änderung in der Bewertung von Beiträgen durch Algorithmen benötigen.

Da ich persönlich Rezos Beitrag ziemlich gut fand, erstaunt es mich, dass sein Beitrag zu einem solchen Ansinnen führt. Eher hätte ich den Vorschlag des Autors VOR Rezos Beitrag sinnvoll gefunden. Rezo hat doch gerade gezeigt, dass es möglich ist, auch für ein ehrbares Anliegen Aufmerksamkeit zu erreichen.

Vielleicht liegt der Grund für Rezos Erfolg auch schlicht darin, dass die schon jetzt vorhandenen Algorithmen besser arbeiten, als es sich der Autor vorstellen mag. Denn ich halte Googles Algorithmen durchaus dazu in der Lage, leeres Geschwätz von gehaltvollem Text zu unterscheiden.

Meiner Meinung nach hat Rezos Erfolg aber mit den aktuellen Algorithmen wenig zu tun, ich denke eher, dass er einfach den Nerv einer großen Masse von Menschen getroffen hat, die bewusst oder unbewusst im Laufe der Jahre gemerkt haben, dass sie von vielen Politikern nur noch mehr oder weniger rhetorisch geschickt mit leeren Worthülsen abgefertigt werden. Unsere Politiker haben gelernt, dass sich mit Show mehr als mit Argumenten erreichen lässt und sich damit ihr eigenes Grab geschaufelt. Das ist es, was Rezo vermutlich mit ‘Die Zerstörung der CDU’ gemeint hat. Rezo hat keine Show gemacht. Er hat die Sprache der Jugend bzw. des Netzes verwendet, um zu argumentieren! Es waren keine Algorithmen, die Rezo nach oben gebracht haben, sondern schlicht sein Beitrag selbst. Ich denke nicht, dass man irgendetwas machen sollte, um die Sichtbarkeit von Beiträgen, wie den von Rezo, in irgendeiner Weise beeinflussen zu können.

Der Autor leitet seinen Vorschlag aus den für den öffentlichen Rundfunk geltenden Mechanismen ab. Dabei zeigt er auf, wie im Nationalsozialismus der Rundfunk dafür missbraucht wurde, die Meinung von Bevölkerungsgruppen gezielt zu beeinflussen. Nach dem zweiten Weltkrieg wurde darum der öffentlich-rechtliche Rundfunk dezentral von den Landesmedienanstalten gesteuert. Der Autor vergleicht den Rundfunk mit dem Internet und möchte auf dieses eine ähnliche menschliche Kontrolle ausüben! Das finde ich völlig falsch!

Schon das physikalische Prinzip des Rundfunks ist ein völlig anderes, als es uns mit dem auf einem Netzwerk basierenden Internet heutzutage zur Verfügung steht. Damals wurden die Bürger tatsächlich zentral von Antennenmasten mit Wellen bestrahlt. Heute kann sich jeder völlig frei die Informationen aus dem Internet picken, die ihn persönlich interessieren.

Viel entscheidender ist aber, dass, zumindest bei uns und zur Zeit noch, jeder Mensch selbst ‘Rundfunk’ betreiben kann! Jeder kann selbst etwas veröffentlichen und damit argumentativ gegen Unwahrheiten, Halbwissen und Schwachsinn vorgehen. Das ist ein sehr hohes Gut und darf auf keinen Fall verändert werden.

Was auch immer der Autor für einen Mechanismus in den Algorithmen implantieren möchte, er will dass dies von irgendwelchen menschlichen Gremien gesteuert wird und würde damit eine weitere Schlüsselstelle installieren, die zur Zensur missbraucht werden kann.

Selbst wenn eine derartige Maßnahme etabliert und auch funktionieren würde, so stellt sich die Frage, was dadurch erreicht wird? Die dann ganz oben erscheinenden Beiträge würden eine große Masse an Menschen gar nicht mehr interessieren!

Wir müssen akzeptieren, dass eine breite Masse halt nichts Intelligentes sehen möchte. Die, bei denen das anders ist, sollten in der Lage sein, die für sie wichtigen Informationen gezielt zu finden! Und noch viel besser, die vermeintlich ‘bösen’ Algorithmen sorgen ja schon jetzt dafür, dass sie, zumindest in meinem Fall, mir Dinge zeigen, die mich interessieren! Das ist doch eigentlich eine gute Sache. Schwachsinn bekommen nur die angezeigt, die ihn offensichtlich sehen wollen. 🙂 Ich muss jetzt nur lernen, dass ich mich in den vielen interessanten Dingen nicht verliere.

Der Kommentar macht auf mich den Eindruck, als ob er Annegret Kramp-Karrenbauer mit ihrer Idee ‘Die Regulierung von Meinungsäußerungen vor Wahlen’ unterstützen möchte.

Lasst das Internet in Ruhe! Es ist ein Spiegel der Gesellschaft. Wenn Ihr möchtet, dass dort andere Dinge zu finden sind, als dass das zur Zeit der Fall ist, dann ändert die Gesellschaft!

 

Zero SR/F versus Lightning Strike

Erst einmal die entscheidenden Fakten:

Bildquelle: Zero Motorcycles

Zero SR/F

  • Reichweite: 259 km (innerorts)
  • Leistung: 110 PS
  • Drehmoment: 190 Nm
  • Gewicht: 220 kg oder 226 kg

 

Bildquelle: Lightning Motorcycles

Lightning Motorcycle Strike

  • Reichweite: 169 bis 241 km
  • Leistung: 91 PS
  • Drehmoment: 244 Nm
  • Gewicht: 206 kg mit 10 kWh-Akku und 211 kg mit 15 kWh-Akku

Mal abseits der anderen möglichen Anwendungszwecke eines Motorrades, geht es uns großen Jungs doch nur darum, wer wirklich das schnellste und vor allem das am meisten absurd brutalst schnell beschleunigende Motorrad hat. Alles andere ist eh ein Fall fürs Auto. Und so wie es aussieht, haben die Knalltüten-Motorräder da jetzt ausgedient!

Wer will noch eine BMW S 1000 RR mit lächerlichen 113 Nm, oder eine KTM 1290 Super Duke mit bescheidenen 141 Nm ?

Wenn es 244 Newtonmeter gibt! Und die ab ‘Standgas’!

Selbst die ‘kleine’ Zero SR/F hat davon noch 190 Newtonmeter zu bieten! Ernsthaft: Wer will da noch ein Moped mit einem Explosionsmotor? Das macht im Motorradquartett keinen Stich mehr und am Stammtisch versteckt man sich mit so etwas am besten hinter einem großen Mass Bier. Außerdem stinkt es! Und ist umweltschädlich! Ihh Bäh!

Wer jetzt also für derartige Vergleichskämpfe gerüstet sein will, der sucht sich gleich etwas Schönes bei den Elektronenraketen heraus. Und da kommen die beiden im Titel genannten Mopeds gerade recht. Aber welches ist nun das Bessere?

Die Reichweite interessiert hier auch nicht besonders. Allerdings wirkt sie sich auf das Gewicht aus. Weniger Reichweite bedeutet meist auch kleineren Akku und da der sauschwer ist, wirkt sich das natürlich auf das Leistungsgewicht aus. Wir wollen darum den leichtesten Akku. 🙂

Da stehen sich dann 220 kg (Zero) gegen 206 kg (Lightning) gegenüber. Oder 190 gegen 241 Newtonmeter. Noch Fragen?

Ja, eine: Wer ist in der Lage diese gewaltige Kraft auf den Boden zu bringen, ohne das sich der Hinterradreifen als endloser Klebe-Kaugummi auf dem Asphalt breit macht? Oder der Fahrer selbst im vierten Gang, oder so, noch einen Wheelie mit anschließender Variation eines doppelten Rittbergers macht?

Richtig: Die Antriebsschlupfregelung. Aber wer will denn noch selbst fahren?

🙂

Mai Thi Nguyen-Kim im Thalia in Darmstadt

Seit ein paar Monaten bin ich ein großer Fan von Dr. Mai Thi Nguyen-Kim. Sie ist eine promovierte Chemikerin und als solche hätte ich mich normalerweise Null für sie interessiert. Sie taucht allerdings in der Videoübersicht von Terra X Lesch & Co auf und das ist für mich eine echte Empfehlung, denn ich bin auch ein großer Fan von Professor Harald Lesch. Eines der ersten Videos, welches ich von ihr gesehen habe, ist:

Dort legt sie sich mit Prof. Karin Michels von der Uniklinik Freiburg auf wissenschaftlich gesicherte Weise an, die mir sehr imponiert hat.

Sie betreibt in Verbindung mit funk mehrere Youtube-Kanäle. Der ursprünglich unter ‘schönschlau’ betitelte Kanal läuft jetzt unter der Bezeichnung ‘maiLab‘.

Der ältere, aber der, meiner Meinung nach, weniger formalisierte und damit nettere, Kanal von ihr ist ‘The Secret Life Of Scientists‘.

Und auch auf ‘Terra X Lesch & Co‘ ist sie mit einzelnen Videos vertreten.

Nach dem Kokosöl-Video sah ich mir ihre Videos über CRISPR an, da mich dieses Thema auch sehr interessiert.

Nach ihrer Promotion entschied sie sich dafür, vermutlich schweren Herzens, Wissenschaftsjournalistin zu werden. Keine schlechte Entscheidung, wie ihre unzähligen Videos beweisen. Außer Lesch kenne ich niemanden, der Wissen bzw. Wissenschaft so anschaulich aufbereitet, wie Mai Thi. Man möchte ihr am liebsten ständig Fragen hinwerfen, die sie doch bitte sofort auf ihre Art aufbereitet, erklärt und beantwortet. 🙂

Wenn man heutzutage hört und sieht, wie scheinbar gebildete Menschen Schwachsinn verzapfen, kann es einem schlecht werden. Da ist es unbedingt erforderlich, dass wieder mehr wissenschaftliche Methodik in unser aller Bewusstsein dringt.

Denn leider wird manchmal unter dem Deckmantel der Wissenschaft falsches Wissen vermittelt. Da es aber ‘Wissenschaftler’ oder andere, scheinbar gebildete Leute (zum Beispiel Ärzte) gesagt haben, oder weil es in einem Magazin oder auf einer Webseite mit Hinweis auf eine wissenschaftliche Studie geschrieben wurde, glauben die Menschen es. Das ist dann natürlich fatal! Diese Menschen sind ja auch wieder Meinungsverbreiter und schnell wird das falsche Wissen in der Öffentlichkeit weiter verbreitet.

Es anschließend wieder aus den Köpfen heraus zu bekommen und durch die Wahrheit zu ersetzen, ist sehr schwierig. Passiert dies fortwährend und leider ist das schon längst so, erodiert im Laufe der Zeit auch der Glaube an die Wissenschaft. Dann passiert es, dass ein Teil der Öffentlichkeit gegenüber wissenschaftlich fundierten Aussagen skeptisch wird und schon lebt die flache Erde wieder. Wir müssen darum alles tun, dass wissenschaftliche Studien nicht für die Verbreitung von falschem Wissen verwendet werden und wir alle mehr davon verstehen, was wissenschaftliches Arbeiten eigentlich bedeutet.

So wie ich Mai Thi verstanden habe, ist dies der wesentliche Grund für ihre Entscheidung Wissenschaftsjournalistin zu werden und mit ihren Mitteln darauf hinzuarbeiten, dass wir alle in die Lage versetzt werden, kritischer mit dem umzugehen, was wir alltäglich im Internet und auch sonst so vorgesetzt bekommen. Und im Idealfall Unsinn erkennen und nicht jedem dummen Hype hinterherrennen.

Ein anderer gedanklicher Ansatz sich mit Wissenschaft zu beschäftigen, ist die Idee, alles um uns herum als Moleküle zu betrachten. So hat man eine Art Lego-Baustein, mit dem man nahezu alles bauen, aber auch erklären kann. Ich denke, dieser gedankliche Ansatz hat Mai Thi zu ihrem Buch ‘Komisch, alles chemisch!’ bewogen, welches zur Zeit auf Platz 2 der Spiegel Bestseller im Bereich Sachbuch ist.

Als ich auf Instagram davon erfuhr, dass Mai Thi demnächst in Darmstadt im Thalia eine Lesung hält, wollte ich auf jeden Fall hin, um sie einmal persönlich zu sehen. Das war gestern Abend.

Ich war noch nie vorher in meinem Leben auf einer Lesung und darum sehr gespannt, wie das abläuft. Die Lesung sollte um 18:00 Uhr beginnen und darum war ich schon um 17:00 Uhr da, damit ich ja nichts verpasse und mir vielleicht einen guten Platz organisieren kann. Gleich nach meiner Ankunft im Thalia kaufte ich mir Mai This Buch und vergewisserte mich bei der Verkäuferin, dass ich es auch signieren lassen kann.

Im hinteren Bereich vom Thalia, da wo auch die Fachliteratur zu finden ist, waren einige Reihen Stühle aufgestellt und ein paar wenige junge Leute saßen schon da. Die meisten Stühle waren aber noch unbesetzt und ich entschloss mich, erst einmal in den Bücherregalen zu stöbern.

Mit einem Buch über agile Methoden suchte ich mir dann einen Platz in der dritten Stuhlreihe in der Mitte, so dass ich eine optimale Position für Fotos oder Filme hatte.

Während ich las, kamen immer mehr Menschen und setzen sich auf die Stühle. Es wurden so viele, dass das Personal vom Thalia noch viele Stühle holen musste. Und irgendwann saßen sogar ein paar Leute neben mir auf dem Boden zwischen den Stühlen. Neben mir saß eine junge Chemikerin und unterhielt sich lautstark mit ihren Bekannten. Nach der Lesung wollte sie ins Cafe Chaos gehen.

Um etwa 17:30 Uhr kam Mai Thi vorbei, lächelte freundlich und prüfte das Mikrofon. Dann verschwand sie wieder.

Einmal erschien ein älterer Herr mit asiatischen Gesichtszügen und suchte nach einem unbesetzten Stuhl. Aber nicht er wollte da sitzen, sondern er führte anschließend eine ältere Frau mit langen grauen Haaren zu dem Platz. Ich vermute, dass waren Mai This Eltern. Später habe ich mich nur gewundert, dass der Herr wieder verschwunden war, zumindest konnte ich ihn nirgends mehr sehen.

Insgesamt eine nette Stimmung und ich wollte gerne noch einmal so jung sein und noch einmal studieren.

Pünktlich um kurz nach 18:00 Uhr kam schließlich Mai Thi. Sie war genau so, wie man sie von ihren Videos her kannte. Scheinbar entspannt, freundlich und ohne sich auch nur einmal zu verhaspeln, zeigte sie am Anfang ein paar von in ihrer Kindheit gemalten Bildern, die mit Text versehen waren und zeigten, dass sie schon damals Autorin werden wollte. Und schon hatte sie uns in ihren Bann gezogen.

Die Lesung selbst war eine Mischung aus scheinbar freiem Erzählen, aufgelockert mit kurzen Passagen, die sie direkt aus ihrem Buch vorlas. Am Ende bekam sie von einem jungen Mann, ich denke es ist ihr Ehemann gewesen, eine Ukulele gebracht, mit dem sie ein kurzes Lied über Chemie präsentierte. Ich habe es für Euch aufgenommen und auf Youtube gestellt:

Anschließend konnte man sein persönliches Exemplar von ihrem Buch von ihr signieren lassen. Dazu reihte ich mich schnell in eine gerade entstehende Menschenschlange ein und wartete geduldig darauf, bis ich an die Reihe kam. Vor mir kam eine junge Frau dran und brachte Mai Thi ein Cookie mit, welches Mai Thi ein charmantes Lächeln entlockte. Dies war offensichtlich eine Reminiszenz an Mai This Keksemojis, die sie manchmal für richtige Antworten in ihren Kommentaren vergibt.

Nun bin ich stolzer Besitzer von meinem ersten Buch mit persönlicher Signierung der Autorin! Und Mai Thi hat sich ihren Kindheitswunsch mehr als erfolgreich verwirklicht. Bitte unterstützt sie auf ihrer Mission, den Menschen wieder mehr Neugier auf die Funktionsweise dieser Welt zu vermitteln und sie mit echten wissenschaftlichen Methoden zu stillen!

 

Michelstadt Mi1

  • Am Karfreitag habe ich den Mi1 gefahren und habe davon einen Film erstellt. Ihr findet ihn hier:

Im letzten Winter traf ich in ‘Röders Hütte’ in der Nähe von Reichelsheim einen Mountainbiker, der mir von einer tollen neuen Strecke mit vielen und langen Trails bei Michelstadt erzählte. Das hatte ich mir gemerkt und jetzt war der Zeitpunkt gekommen, die Strecke einmal auszuprobieren. Die Strecke ist die neue Geo-Naturparkstrecke Mi1, die am 19.5.2019 offiziell eröffnet wird. Im Film sind nur die Trails zu sehen.

Die Trails sind möglicherweise nichts für Hardcore-Downhiller, aber vermutlich gerade darum für sehr viele Mountainbiker geeignet. Die Strecke ist ehrlich, es sind keine gemeine Stellen enthalten. Wer ab und zu Teilstücke zu Fuß geht, kann sie sich auch als Anfänger einmal ansehen (aber macht Platz für Biker, die gerade runter kommen) und für die Versierteren unter uns, gibt es viele kleine und größere Schanzen für Sprünge oder Drops. Ich selbst bin eher so der Durchschnittsbiker, darum erwartet nicht zu viel Speed im Film. 🙂

Fast 30 Minuten Trails! Hammer!

Gefahren mit Ghost AMR Lector 9500: https://www.bike-magazin.de/mountainb…

Gefilmt mit GoPro Hero 6, dem Vorgänger der Hero 7: https://amzn.to/2vm9lbm

Mein Artikel über die GoPro Hero 6: https://tinkerpete.wordpress.com/2018…

 

Meine Garmin Watch Faces

Für einige Smartwatches der Firma Garmin ist es möglich ein eigenes ‘Watch Face’ zu erstellen. Dabei handelt es sich um ein – im klassischen Sinne – Ziffernblatt. Das heißt, es ist möglich ein völlig eigenes Ziffernblatt zu programmieren und anschließend auf die Smartwatch zu laden.

Connect-IQ

Sieht man im Internet auf der Garmin Seite Connect-IQ nach, finden sich bereits Tausende von Watch Faces, die man einfach auf seine Garmin Smartwatch laden kann. Normalerweise macht man das aber über ‘Garmin Connect’, das ist die zu jeder Garmin Smart Watch gehörende App. Dort gibt es einen Menüpunkt, mit dem man ein Watch Face komfortabel auswählen und auf der Smartwatch installieren kann. Auf der Smartwatch selbst kann man mehrere, schon installierte Watch Faces über den Menüpunkt ‘Displaydesign’ auswählen und aktivieren.

Eine Zeit lang macht es richtig Spaß die verschiedenen Watch Faces auszuprobieren. Es gibt so viele Verschiedene! Teilweise sind die nicht nur unterschiedlich gestaltet, sondern haben völlig neue und interessante Funktionen. Es gibt zum Beispiel eine, die eine miniaturisierte Weltkarte darstellt und darauf den Sonnenverlauf zeigt. Oder eine, die eine grafische Balkendarstellung der Herzfrequenzzonen zeigt. Und selbstverständlich kann man zwischen unzähligen Analog- und Digital-Watchfaces auswählen.

Wer gerne etwas Persönlicheres haben möchte, kann sich mit Hilfe der ‘Garmin Face It’-App aus einem mit dem Smartphone aufgenommenen Foto ein individuelles Watch Face machen!

Eigene Watch Faces

Wem das alles nicht genügt und etwas programmieren kann, der kann einfach sein eigenes Watchface programmieren. Über die Weihnachtszeit bekam ich Mega-Lust mir mein ganz eigenes Watchface zu erstellen. Selbstverständlich dachte ich, dass meines das Beste sein wird und in der Connect-IQ Liste mit den beliebtesten Watch Faces nach kurzer Zeit ganz oben erscheinen wird!

Mit 240×240 Pixeln haben die Garmin Smartwatches nicht ganz so viele Pixel wie die schärfsten Konkurrenten wie zum Beispiel die Samsung Galaxy Watch mit 360×360 Pixeln oder der Apple Watch 4 mit 312 x 390 (40 mm Display) bis zu 384 x 480 (44 mm Display) Pixeln. Aber aus einem normalen Abstand von ca. 30 cm ist das kaum zu erkennen. Und Garmins transreflektives Chroma Display bleibt halt dauerhaft sichtbar.

Trotz der geringeren Auflösung ist es möglich, nahezu jede denkbare Idee als grafische Darstellung auf dem Display zu realisieren. Mein Grundidee war es, die für mich am Tag am häufigsten aufgerufenen Werte jederzeit, und in einer angenehmen Größe sichtbar, anzuzeigen.

Daraus ergab sich eine Viertelung des Anzeigekreises mit einem fetten Streifen in der Mitte, der zur Anzeige der Zeit dient.

Ein guter Startpunkt für Entwickler ist der Programmer’s Guide von Garmins Seiten für Entwickler. Entwickelt wird am besten mit Eclipse. Von Garmin gibt es dazu ein passendes SDK und programmiert wird in Monkey C. 🙂

Tipps

Theoretisch kann man alles in Monkey-C programmieren. Aber für bestimmte Darstellungen ist das ziemlich aufwendig. Wer sich mit einem Vektor Zeichenprogramm wie Corel Draw oder Inkscape auskennt, der kann statische Anteile des Watchfaces damit zeichnen, als PNG exportieren und anschließend einfach auf dem Display anzeigen!

Mit Inkscape habe ich auch die Icons gezeichnet und exportiert.

Mit BMFont kann man aus Truetype-Zeichensätzen passende Bitmap-Zeichensätze für die Watch Face Programmierung erzeugen. Hier ist ein nettes Tutorial dazu.

Bemerkenswertes

Man kann nicht nur Watch Faces programmieren. Sondern richtige kleine Anwendungen. Die nennen sich dann Widgets oder Device Apps. Aber soweit wollte ich nicht einsteigen. Ich habe genug anderes zu tun. Es gibt aber eine Sache, die meiner Meinung nach noch unbedingt erwähnenswert ist. Dies ist die Aktualisierungsrate des Displays, sie wirkt sich nämlich wirklich entscheidend auf den Stromverbrauch aus.

Mehr oder weniger zufällig hatte ich beim Ausprobieren von Watch Faces immer welche gewählt, die aufwendige Funktionen besaßen oder zumindest eine sekündliche Aktualisierung hatten. Das führte dazu, dass ich die Smartwatch spätestens alle 4 bis 5 Tage aufladen musste. Mein eigenes Watch Face (und natürlich viele andere auch) unterstützt keine sekündliche Aktualisierung und läuft darum wesentlich länger. Ich habe es nicht genau gemessen, aber manchmal scheinen über den Tag nur knapp 10 % Energie verbraucht werden!

Meine Watch Faces!

Quadrant

Ein Anwender meines Quadrant-Watch Faces fand es gut, wollte aber eine dunklere Darstellung. Darum entwickelte ich noch eine ähnliche Designvariante mit deutlich dunkleren Farben und nannte sie Quadrant Dark.

Quadrant Dark

Leider haben es meine Watch faces bis jetzt nur ins Mittelfeld der beliebtesten Watch Faces geschafft. Aber sie werden verwendet und das macht mich ein ganz kleines bisschen stolz! 🙂

Noch mehr coole Einsteiger-Motorräder

In meinem Artikel ‘Das beste Motorrad für Anfänger und Reisende‘ habe ich Euch die Honda Transalp vorgestellt. Heute bin ich zufällig an einer anderen Honda vorbei gefahren, die vermutlich ähnlich gut geeignet sein dürfte und mich an noch ein anderes Motorrad erinnert hat. Beide Motorräder haben den Motor von der Honda Transalp und zusätzlich noch eine Kardanwelle als weiteres technisches Schmankerl.

Es sind die Honda NTC 650 Revere und die Honda Deauville.

Beide sind mit brauchbaren Kilometerleistungen für um die 2000 Euro zu bekommen. Allerdings müssen A2-Besitzer sie vermutlich in den meisten Fällen drosseln lassen.

Hier gibts Infos zur Honda NTC 650 Revere und hier zur Honda Deauville.

 

ESP32 als Siebenschläfer

Ein Bericht über meine Versuche mit einem ESP32 und der Arduino IDE einen autarken Email-Versand von Sensordaten aus dem Garten zu realisieren. Das dafür am geeignetsten erscheinende Board ist eines von Banggood, welches zusätzlich zum ESP32 auch noch ein OLED-Display und eine Akkuhalterung für 18650er Akkus integriert hat.

Wenn man sich, ohne wirklich Ahnung zu haben, so wie ich, in die Arduino Welt eingearbeitet hat und erste ‘Real life’-Anwendungen entwickeln möchte, stößt man auf vorher nicht wahrgenommene Probleme. So ging es mir mit der schon tausendfach von anderen realisierten Idee einen Outdoor-Wettersensor zu entwickeln. Eigentlich ist die Idee super simpel. Ein ESP32-Board fragt regelmäßig einen DHT22-Sensor ab und sendet die Werte als Email an meinen Email-Account. Nix Besonderes.

Über Bugs und Troubleshooting

Aber schon mit dem DHT22 fangen die Probleme an. Einmal hatte ich einen, der keine vernünftigen Luftfeuchtigkeitswerte zur Verfügung stellte, ein anderes Mal einen, der nach einigen Tagen gar nicht mehr funktionierte und zur Stimulierung einmal kurz von der Stromversorgung getrennt werden wollte.

Ich habe das jetzt so beiläufig niedergeschrieben, aber in der Praxis bedeuteten diese Dinge jede Menge Aufwand. Anfangs weiß ich ja nicht, warum meine Anwendung nicht richtig funktioniert. Oft denke ich, dass es bestimmt mein Fehler sein muss und ich versuche stundenlang ihn zu finden. Bei dem Problem mit den falschen Werten dachte ich lange an einen Fehler von mir, hatte aber keine Zeit mich darum zu kümmern. Als ich mich dann nach einigen Wochen wieder damit beschäftigte, wusste ich nicht mehr genau, was und wie ich alles installiert hatte. Es handelte sich dabei allerdings um eine Raspberry Pi Anwendung mit Python und C-Bibliotheken und einer HTML/JavaScript-Anzeige. Ich fand den Fehler nicht und lies es erst einmal darauf beruhen. Das System lieferte daraufhin jahrelang falsche Werte für die Luftfeuchtigkeit (Zum Glück war es ja nur ein Experimentier-Projekt) in meine Datenbank!

Im Zusammenhang mit meinem ESP32 Experiment kaufte ich kürzlich einen zweiten Sensor, dachte, den könnte ich ja zum Testen einfach einmal an den Raspberry stecken und sofort wurden richtige Werte geliefert! Das ist wirklich frustrierend.

Doch genau mit diesem Sensor traten nach einigen Tagen wieder Probleme auf, die dazu führten, dass wieder keine Werte in der Datenbank ankamen. Auch diesmal verbrachte ich mehrere Stunden mit der Fehlersuche, nur um irgendwo im Internet zu lesen, dass der DHT22 tatsächlich manchmal einfach ausfällt. Man braucht ihm dann nur kurz den Strom weg zu nehmen und schon läuft er wieder!

Ich habe mich jetzt nicht weiter darum gekümmert, aber für die, die das Problem irgendwie automatisiert in den Griff bekommen wollen, ist eine mögliche Lösung, den positiven Anschluss des Sensors nicht einfach mit Plus zu verbinden, sondern mit einem auf High gesetzten GPIO-Ausgang, der im Fehlerfall kurz auf Low gesetzt wird.

Mobile Stromversorgung

Denkt man an eine mobile Stromversorgung, denkt man heutzutage an eine Powerbank. Und in der Tat funktioniert das mit den meisten ESP32 Boards und der dabei verbauten USB-Buchse scheinbar wunderbar. Diese Ansicht ändert sich aber schnell, wenn man das Board richtig lange betreiben will:

Der größte Nachteil einer Powerbank ist die damit einhergehende Elektronik, die aus dem oder den in der Powerbank eingesetzten Akkus die 5 Volt für die USB-Buchsen erzeugt. Egal wie effizient die Elektronik ihren Job erledigt, es kostet immer etwas Energie. Legt man den ESP32 in den Tiefschlaf, so ist es sogar ein Vielfaches der Energie, die der ESP32 benötigt! Aber es wird noch schlimmer: Der ESP32 verträgt gar keine 5 Volt! Das heißt eine weitere Schaltung – diesmal auf dem Board selbst – muss die 5 Volt von der Powerbank wieder auf 3.3 Volt herunter konvertieren und die benötigt auch wieder Energie. Der Einsatz einer Powerbank ist also doppelt unsinnig und sollte bei mobilen Anwendungen möglichst vermieden werden.

Der zweite Nachteil mancher Powerbanks ist die Eigenschaft sich einfach abzuschalten, wenn der Strom eine bestimmte Menge unterschreitet. Letzteres kann man allerdings softwaregestützt vermeiden, wenn man innerhalb des Zeitraums, indem die Powerbank auf mehr Strom wartet, einfach mal kurz am Strom zieht. 🙂 Dazu kann man an einen GPIO-Eingang einen passenden Widerstand anbringen oder man aktiviert einfach einmal kurz das Wifi!

Beide Nachteile sind denkbar schlechte Voraussetzungen für einen geruhsamen Schlaf des ESP32.

ESP32 mit OLED und 18650 Akku

Vor kurzem entdeckte ich, dass es die ESP32 mit OLED Display auch noch zusätzlich mit einem Fach für einen 18650er Akku gibt. Sogar eine Ladeelektronik ist vorhanden. Und das Board kann gleichzeitig betrieben und geladen werden. Bei der Recherche zu diesem Artikel habe ich gelesen, dass die Spannung eines 18650er Akku, die je nach Ladezustand 3.7 bis 4.2 Volt beträgt, zu hoch für den ESP32 (2.3 bis 3.6 Volt) sein soll und sie darum noch einmal herunter konvertiert werden muss. Bei meinen Versuchen mit dem Board konnte ich aber einen Strom im ‘Deep Sleep’ dieses Boards von unter 1 Milliampere messen und ich kann mir nicht vorstellen, dass ein DC-DC Wandler so wenig Strom verbraucht. Aber wer weiß.

Ich habe nachgemessen und bei einer Akkuspannung von 4 Volt lagen bei VCC nur etwa 3.3 Volt an. Also scheint es einen Gleichspannungswandler zu geben. Das hat mich dazu gebracht noch einmal genauer nachzuforschen. Auf dem Board ist ein ‘Low Dropout’-Regler mit der Bezeichnung AMS1117 verbaut. Vermutlich wird der sowohl für die 5 Volt vom USB-Anschluss als auch für den 18650er verwendet.

Mit meinem Solarpanel wird das Board geladen, jedenfalls leuchtet die entsprechende LED auf dem Board auf, wenn genügend Sonnenlicht auf das Panel fällt. Langzeittests stehen allerdings noch aus. Aber schon jetzt scheint mir das Board zusammen mit einem 18650er eine sehr vielversprechende Lösung für eine mobile Computeranwendung zu sein. Denn bei ersten Versuchen scheint es länger durchzuhalten als meine Soshine E3S-Powerbank, sogar wenn ich zwei 18650er Akkus eingelegt habe!

Zeitprobleme

Wenn wir heutzutage einen Computer einschalten, so ist es ganz selbstverständlich, dass der weiß wie viel Uhr es gerade ist. Er kann dass, weil er irgendwo in seinem Innern einen kleinen Akku besitzt, der dafür sorgt, dass ein kleiner Zähler immer weiter zählen kann, auch wenn wir denken, das er eigentlich stromlos ist. Der ESP32 hat auch so einen Zähler, RTC (Real Time Clock) genannt, allerdings hat er keinen eingebauten Akku. Für die richtige Stromversorgung müssen wir Entwickler sorgen.

Wird unsere mobile Anwendung zum ersten Mal eingeschaltet, so fängt der Zähler bei 0 an zu laufen. Der ESP32 hat in diesem Moment keine Ahnung, ob er in der Vergangenheit, in der Zukunft oder in einem Paralleluniversum aufwacht. Soll er seine Daten mit einem korrekten Datum versenden, müssen wir es ihm mitteilen. Das ginge mit:

  • Mit einem angelötetem Taster und einem mehr oder weniger trickreichen Protokoll, wie ich es zum Beispiel von einer Honda CB1000R her kenne.

  • Per DCF77-Antenne, da holt er sich die unglaublich genaue Zeit einer Atomuhr aus den Funkwellen um uns herum.

  • Aus einem extern angeschlossenen RTC-Modul. Scheint ein bisschen Overkill, da der ESP32 ja schon ein RTC-Modul eingebaut hat.

  • Oder, und so mache ich es, von einem Zeitserver über WiFi aus dem Internet.

Um die Email zu versenden wird ja sowieso gelegentlich eine Internet-Verbindung benötigt. Da kann man auch gleich die Zeit holen. Alle anderen Lösungen benötigen deutlich mehr Aufwand. Leider ist der Zähler nicht sonderlich genau, darum muss er von Zeit zu Zeit synchronisiert werden. Das ist auch der Grund, warum manche Leute eine wesentlich genauere externe RTC anschließen. Es ist aber auch möglich zu ermitteln, um wie viele Sekunden die Uhr pro Tag falsch geht und sie einmal am Tag um diesen Wert zu korrigieren. Damit sollte man einige Monate auskommen.

Deep Sleep

Ein ESP32 benötigt ohne WiFi und ohne Zusatzbeschaltung so ungefähr 20 – 40 mA. Bei direktem Einsatz des ESP32 mit einem 18650er Akku und bei 3.3 Volt sollte der Akku ungefähr 115 Stunden (3500 mAh / 30 mAh) halten, also knapp 5 Tage. Das ist gar nicht schlecht, aber weit von autark entfernt. Nun könnte man ein Solarpanel anschließen und bei etwas Sonne an jedem Tag, sollte die Autarkie gewährleistet sein. Aber schon eine längere Regenzeit zerstört unser Vorstellungen. Darum gilt es das Board so stromsparend wie nur irgend möglich zu machen. Zum Glück bietet der ESP32 dazu eine tolle Möglichkeit an: Er kann in eine Art Tiefschlaf versetzt werden, in denen er nur wenige Mikroampere benötigt! Im Detail kann man darüber hier nachlesen. Denn der ESP32 hat nicht nur einen Dual-Core Prozessor, sondern auch noch einen extrem stromsparenden Co-Prozessor! Das ermöglicht ihm den leistungsfähigen Dual-Core Mikroprozessor komplett abzuschalten und trotzdem weiter zu ‘existieren’. Dabei wird aber auch das RAM abgeschaltet, das heißt keine Variablen und keine Daten mehr. Jedes Mal wenn der ESP32 ‘aufwacht’, ist es für ihn wie beim Booten eines Computers. Seine Speicher waren stromlos und enthalten keinerlei Informationen mehr. Doch die Entwickler des ESP32 haben mit gedacht und dem Co-Prozessor einen kleinen Speicher mit 8 KByte mitgegeben, der auch im Deep Sleep mit minimal Strom versorgt wird. Wenn man ihn nutzen möchte, schreibt man einfach ‘RTC_DATA_ATTR’ vor die Deklaration einer Variablen.

Programmierung

Normalerweise läuft bei einem Arduino Programm die Setup-Funktion genau einmal und anschließend nur noch die Loop-Funktion. Bei einem ‘Deep Sleep’ Einsatz ist das anders. Zwar könnte man auch die Loop-Funktion verwenden, da aber nach einem ‘Deep Sleep’ auf jeden Fall wieder die Setup-Funktion aufgerufen wird, bietet es sich an, den ganzen Code dort unter zu bringen und die Loop-Funktion leer zu lassen.

Man könnte das ganze Programm jetzt in folgende Einzelschritte auflösen:

  • Programm wacht auf.

  • Verbindet sich mit dem Internet.

  • Holt sich die Zeit aus dem Internet.

  • Ermittelt die Sensor-Werte.

  • Sendet eine Email mit den Werten.

  • Beendet die Internetverbindung.

  • Geht in den ‘Deep Sleep’.

Ich möchte aber das Programm auch als Rumpf für andere Aufgaben verwenden und darum soll es deutlich häufiger wach werden, als es Emails versenden muss. Die Zeit soll nur geholt werden, wenn sie auch erforderlich ist. Also nur am Anfang und später dann nur noch, wenn sie für meinen Geschmack zu weit von der tatsächlichen Zeit abgewichen ist. Darum ist es wichtig zu wissen, ob der ESP32 das erste Mal eingeschaltet wurde, oder ob er aus einem ‘Deep Sleep’ zurück kommt. Dafür habe ich mir eine Variable ‘timeIsHere’ deklariert:

RTC_DATA_ATTR boolean timeIsHere = false;

Verschlüsseln

Im Code gibt es zwei Stellen, an denen man den User-Namen und das Passwort als Base64 verschlüsseln muss. Das geht ganz einfach mit dieser Seite. Ich kann Euch aber nicht garantieren, das die eingegebenen Daten nicht noch anderweitig verwendet werden. Falls ihr es lieber selbst kodieren möchtet, verweise ich Euch hiermit an die nötigen Informationen in der Wikipedia.

Solarpanel

Das von mir verwendete Solarpanel lag schon länger bei mir herum und hat mit etwa 12 Volt eine viel zu hohe Spannung für das Board. Darum habe ich mir noch bei Banggood diesen Konverter gekauft. Er stabilisiert die 12 Volt mit angeblich 95%iger Effizienz auf 5 Volt herunter. Wenn zu wenig Licht vorhanden ist, schaltet er ab und ermöglicht so bei wiederkehrender Sonne einen Restart des Ladevorgangs.

Nachgemessen

Während eines Zugriffes auf das Internet über das WiFi verbraucht meine Anwendung für wenige Sekunden 140 mA. Ist dass WiFi aus, sind es nur 40 mA. Und wenn der ESP32 im Tiefschlaf ist, sind es weniger als 1 mA! Mir ist bekannt, dass der reine ESP32 ohne externe Beschaltung mit einigen wenigen µA auskommt. Aber so, mit dem DHT22 und dem Regler für die Spannung finde ich 1 mA schon ziemlich gut.

Code

#include <WiFi.h>
#include <TimeLib.h>
#include <SimpleDHT.h>
#include <SSD1306.h>

#include "soc/rtc_cntl_reg.h"

#define TTY_SPEED 115200        /* Geschwindigkeit der seriellen Schnittstelle */
#define uS_TO_S_FACTOR 1000000  /* Multiplikator für die Umrechnung von Sekunden zu Mikrosekunden */
#define TIME_TO_SLEEP  60       /* Wie viele Sekunden soll der ESP32 schlafen? */

RTC_DATA_ATTR long bootCount = 0;
RTC_DATA_ATTR boolean timeIsHere = false;
RTC_DATA_ATTR boolean timeIsSynchronized = false;

int pinLED = 16;
int pinDHT22 = 17;
const char* SSID = "SSID";
const char* PASS = "PASSPHRASE";
char server[] = "smtp.1und1.de";

esp_sleep_wakeup_cause_t wakeup_reason;

SSD1306 display(0x3c, 5, 4);
SimpleDHT22 dht22(pinDHT22);
WiFiClient client;

String dayTime;
float temperature = 0;
float humidity = 0;

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  Serial.begin(TTY_SPEED);
  Serial.print(bootCount);
  Serial.println(" Mal");

  display.init();
  display.setFont(ArialMT_Plain_10);
  display.flipScreenVertically();
  display.setContrast(255);

  print_wakeup_reason();

  // Ermittlung der aktuellen Zeit in Sekunden.
  struct timeval tv;
  gettimeofday(&tv, NULL);
  long curTime = tv.tv_sec;
  Serial.print(curTime);
  Serial.println(" Sekunden");

  // Ist ein Tag vergangen, muss die Zeit neu vom Zeitserver abgefragt werden.
  if (curTime % 86400 <= TIME_TO_SLEEP) {
    timeIsSynchronized = false;
  }

  // Wenn seit dem letzten Einschalten noch nie die Zeit abgefragt worden ist oder
  // wenn sie neu synchronisiert werden soll, dann versuchen die Zeit neu abzufragen
  // und neu in der ESP32 RTC setzen.
  if (timeIsHere == false || timeIsSynchronized == false) {
    tv = setRealTime();
    tv.tv_sec = tv.tv_sec + 3600;
    tv.tv_usec = 0;
    settimeofday(&tv, NULL);
  }

  // Zeit ausgeben
  char buffer[30];
  strftime(buffer, sizeof(buffer), "%d.%m.%Y  %T", localtime(&tv.tv_sec));
  dayTime = buffer;
  Serial.println(dayTime);
  display.clear();
  display.drawString(0, 0, dayTime);

  // Wenn eine gültige Zeit vorhanden ist...
  if (timeIsHere == true) {
    // ... Sensordaten ermitteln und auf dem Display ausgeben.
    int err = SimpleDHTErrSuccess;
    if ((err = dht22.read2(&temperature, &humidity, NULL)) == SimpleDHTErrSuccess) {
      display.drawString(0, 10, (String) temperature + " C");
      display.drawString(0, 20, (String) humidity + " %");
      display.display();
    } else {
      Serial.print("Read DHT22 failed, err=");
      Serial.println(err);
    }
    // ...nachsehen ob eine Viertelstunde vergangen
    // ist und falls ja, die Daten als Email versenden.
    if (curTime % 900 <= TIME_TO_SLEEP) {
      if (connectWiFi()) {
        byte ret = sendEmail();
      }
      WiFi.disconnect();
    }
  }

  bootCount = bootCount + 1;
  delay(5000);
  
  // Display löschen. Spart bei einem OLED-Display Energie!
  display.clear();
  display.display();

  // Den ESP32 in den 'Deep Sleep' bringen.
  Serial.println("Schlafen gehen...");
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  esp_deep_sleep_start();
  delay (100);
}

void loop() {
}

struct timeval setRealTime () {
  display.clear();
  display.drawString(0, 0, "Try to get act time ...");
  display.display();

  if (connectWiFi()) {
    configTime(0, 0, "ptbtime1.ptb.de", "ptbtime2.ptb.de", "ptbtime3.ptb.de");
    struct tm timeinfo;
    if (getLocalTime(&timeinfo)) {
      timeIsHere = true;
      timeIsSynchronized = true;
      display.drawString(0, 10, "Success!");
      display.display();
    } else {
      display.drawString(0, 10, "I try next boot again...");
      display.display();
    }
    delay (2000);
  }
  WiFi.disconnect();

  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv;
}

bool connectWiFi () {
  bool connectState = false;
  int tryCounter = 10;
  delay(10);
  Serial.println("");
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.println(SSID);
  WiFi.begin(SSID, PASS);
  while ((WiFi.status() != WL_CONNECTED) && (tryCounter > 0)) {
    delay(500);
    Serial.print(".");
    tryCounter = tryCounter - 1;
  }
  Serial.println("");
  if (tryCounter > 0) {
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    connectState = true;
  } else {
    Serial.println("WiFi connect failed");
  }
  return connectState;
}

byte sendEmail() {
  byte thisByte = 0;
  byte respCode;

  if (client.connect(server, 587) == 1) {
    Serial.println(F("connected"));
  } else {
    Serial.println(F("connection failed"));
    return 0;
  }
  if (!eRcv()) return 0;

  Serial.println(F("Sending EHLO"));
  client.println("EHLO smtp.1und1.de");
  if (!eRcv()) return 0;
  Serial.println(F("Sending auth login"));
  client.println("auth login");
  if (!eRcv()) return 0;
  Serial.println(F("Sending User"));
  // Change to your base64, ASCII encoded user
  client.println("XXXXXXXXXX"); //<--------- User
  if (!eRcv()) return 0;
  Serial.println(F("Sending Password"));
  // change to your base64, ASCII encoded password
  client.println("XXXXXXXXXX"); //<--------- Password
  if (!eRcv()) return 0;
  Serial.println(F("Sending From"));
  // change to your email address (sender)
  client.println(F("MAIL From: dummy@compusurf.de"));
  if (!eRcv()) return 0;
  // change to recipient address
  Serial.println(F("Sending To"));
  client.println(F("RCPT To: dummy@compusurf.de"));
  if (!eRcv()) return 0;
  Serial.println(F("Sending DATA"));
  client.println(F("DATA"));
  if (!eRcv()) return 0;
  Serial.println(F("Sending email"));
  // change to recipient address
  client.println(F("To:  dummy@compusurf.de"));
  // change to your address
  client.println(F("From: dummy@compusurf.de"));
  client.println(F("Subject: Dummys Wetter\r\n"));
  client.print(F("Temperatur: "));
  client.print((String) temperature);
  client.println(F(" C"));
  client.println(F("\n"));
  client.print(F("Luftfeuchtigkeit: "));
  client.print((String) humidity);
  client.println(F(" %"));
  client.println(F("\n"));
  client.print(F("Sendezeit: "));
  client.println(dayTime);
  client.println(F("\n"));

  client.println(F("."));
  if (!eRcv()) return 0;
  Serial.println(F("Sending QUIT"));
  client.println(F("QUIT"));
  if (!eRcv()) return 0;
  client.stop();
  Serial.println(F("disconnected"));
  return 1;
}

byte eRcv() {
  byte respCode;
  byte thisByte;
  int loopCount = 0;
  while (!client.available()) {
    delay(1);
    loopCount++;
    // if nothing received for 10 seconds, timeout
    if (loopCount > 10000) {
      client.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }
  respCode = client.peek();
  while (client.available()) {
    thisByte = client.read();
    Serial.write(thisByte);
  }
  if (respCode >= '4') {
    efail();
    return 0;
  }
  return 1;
}

void efail() {
  byte thisByte = 0;
  int loopCount = 0;
  client.println(F("QUIT"));
  while (!client.available()) {
    delay(1);
    loopCount++;
    // if nothing received for 10 seconds, timeout
    if (loopCount > 10000) {
      client.stop();
      Serial.println(F("efail \r\nTimeout"));
      return;
    }
  }
}

void print_wakeup_reason() {
  wakeup_reason = esp_sleep_get_wakeup_cause();
  switch (wakeup_reason) {
    case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case 3  : Serial.println("Wakeup caused by timer"); break;
    case 4  : Serial.println("Wakeup caused by touchpad"); break;
    case 5  : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.println("Wakeup was not caused by deep sleep"); break;
  }
}