Software-Update für den Gewitter Monitor v2

Gestern ist wieder einmal ein heftiges Gewitter durch unsere Region gezogen und hinterließ seine Spuren auf dem Display des Gewitter-Monitors. Das war eine gute Gelegenheit, die letzten Software-Updates zu testen. Zur Zeit des Fotos lag das Maximum des Gewitters etwa 1 Stunde zurück. Die Trendanalyse über die letzten 45 Minuten (jetzt durch Pfeilsymbole  unterstützt) zeigte, dass die Summe der Blitze pro Minute stark rückläufig war. Der Mittelwert der letzten 15 Minuten lag aber immer noch so hoch, dass alle drei Alarm-LEDs aktiviert waren.

Seitdem ich die Version 2 im Februar in Betrieb genommen hatte, gab es viele Gelegenheiten, die Funktion der Software im Detail zu testen. Allerlei Feinheiten mussten korrigiert werden. Besonders ärgerlich war ein Fehler in der Trendanalyse, der den Prozessor in eine Endlosschleife schickte, wenn die Zahl der Blitze pro Minute sehr hoch wurde. Außerdem gab es Ungereimtheiten mit der Anzeige des Maximums. Jetzt funktioniert aber alles so, wie es soll.

Die neue Software steht wie immer auf der Ressourcen-Seite zum Download bereit. Die neue Software benötigt die Smart I2C GLCD-Software ab Juni 2018. Sonst können die Pfeilsymbole nicht dargestellt werden.

Von Herrn Wolfgang Richter erreichte mich ein Foto. Er hat seinen Gewitter-Monitor in ein Gehäuse aus schwarzem ABS-Kunststoff (200 x 100 x 65 mm) gesetzt. Sehr schön ist die Antenne,  die über dem Gerät schwebt. Vielen Dank für das Foto!

Gewitter-Monitor von Wolfgang Richter

Herr Richter hat mich auch auf die Forschungen von Hans Baumer zu den sogenannten Sferics aufmerksam gemacht. Dabei handelt es sich um elektrische Entladungen in den Wolken, die ohne Lichterscheinungen von Blitzen einhergehen. Tatsächlich ist mir schon seit langem aufgefallen, dass der Gewitter-Monitor bei labilen Wetterlagen (feuchte und warme Luft) deutliche Aktivitäten anzeigt, und zwar schon lange bevor Gewitter zu beobachten sind. Hierbei handelt es sich wahrscheinlich um die genannten Sferics. Übrigens habe ich die Empfindlichkeit des Geräts so eingestellt, dass die Alarmlevel (rote Leuchtdioden) erst dann aktiviert werden, wenn tatsächliche Gewitter im Umkreis von einigen hundert km registriert sind. Zur Kontrolle eignet sich die sehr informative Website Blitzortung.org.

Neue Software für das Smart I2C Graphik-LCD

Es ist an der Zeit für ein paar kleine Updates zum beschriebenen I2C-Interface für Graphik LC Displays.

Erstens … wollte ich für den Gewitter-Monitor Pfeilsymbole haben, die die Trendanalyse unterstützen. Ein oder zwei Pfeil nach oben oder unten – so schwer kann das doch nicht sein. Herausgekommen ist ein weiterer Zeichensatz, Font #7, mit einigen Symbolen. Der neue Zeichensatz mit einer Höhe von 12 Pixeln wird auch im User-Dokument beschrieben.
Bei Gelegenheit werden noch ein paar Symbole dazu kommen.

Außerdem wurde der Startup-Screen, der sich nach dem Anlegen der Betriebsspannung zeigt, erweitert. Neben der Software-Versionsnummer und Datum werden der Display-Typ mit der Anzahl der Pixel in horizontaler Richtung, die I2C-Puffergröße und Adresse und die aktuelle Helligkeitseinstellung (0 …. 10) präsentiert. Übrigens lässt sich der Startup-Screen unterdrücken durch Abschalten des Verbose-Mode.

Smart I2C GLCD Startup Screen im “Verbose”-Mode

Abgesehen von diesen Erweiterungen und zwei kleinen Bugfixes wurde die Software nicht mehr verändert. Das Display hat sich als recht zuverlässig erwiesen.

Zweitens … ist der erste Satz Platinen (für Display Typ 3 mit 4 Zoll Diagonale) bereits verbaut und tut in verschiedenen Anwendungen seinen Dienst. Deshalb musste ich neue Platinen bestellen. Bei der Gelegenheit habe ich das Layout noch einmal überarbeitet. Die Platine ist etwas kleiner geworden. Es gibt ein Befestigungsloch, das mit dem entsprechenden Loch der Display-Platine fluchtet. Bei der Gelegenheit habe ich den PNP-Transistor für die Steuerung der Beleuchtung ausgetauscht. Der eher seltene BC636 wurde durch den Standard-Transistor BC327 ersetzt.

Neues Layout für das Smart I2C GLCD Interface
Neues Layout für das Smart I2C GLCD Interface
Transistor Q2 (ursprünglich BC636) wurde durch den weit verbreiteten BC327 ersetzt.

Und drittens … gibt es eine erweiterte Arduino-Library zur Ansteuerung des Displays. Die Bibliothek glcd_functions_avr ist speziell für die kleinen 8Bit-AVR-Prozessoren (z. B. ATmega168 oder ATmega328) gedacht, wie sie im Arduino Nano oder Uno zum Einsatz kommen. Dort hat man oft das ärgerliche Problem, dass der beschränkte RAM-Speicher (1 oder 2k Byte) nicht ausreicht. Das hat zwar mit dem Display erst einmal nichts zu tun. Aber wenn man viele Texte im Programm verwalten und auf dem Display anzeigen möchte, dann wird RAM-Speicherplatz sehr schnell eng.  Deshalb ist es sinnvoll, konstante Texte im viel größeren ROM-Speicher zu halten. Dazu gibt es die zusätzlichen Funktionen
draw_pgm_str()draw_center_pgm_str() und draw_radj_pgm_str(). Diese Funktionen übernehmen Texte direkt aus dem Programmspeicher, so dass dafür kein RAM “verbraucht” wird.

Diese zusätzlichen Funktionen machen aber nur Sinn für die kleinen AVR-Prozessoren. Deshalb sollten alle anderen Arduinos (z.B. mit STM32, ESP32, etc.), die wesentlich mehr RAM-Speicher zur Verfügung haben, die normale Library glcd_functions verwenden.

Die neuen Gerber-Files, Software und Dokumente sind auf der Ressourcen-Seite verfügbar.

Übrigens: Da ich jetzt einen kleinen Vorrat an Platinen habe, gebe ich gerne Einzelstücke zum Selbstkostenpreis ab. Einfach per E-Mail melden.

Neues vom Gewitter-Monitor: Version 2

Der Gewitter-Monitor mit graphischer Anzeige war ein Projekt, das ich im Jahr 2014 fertig gestellt hatte. Seit dem habe ich das Gerät immer wieder einmal im Einsatz, und es tut gute Dienste. Inzwischen ist es aber an der Zeit für etwas Modell-Pflege. Rechtzeitig vor der nächsten Gewitter-Saison stelle ich hier die neue Version 2 vor.

Version 2 verwendet im Kern einen Arduino, wodurch das Programmieren und Flashen vereinfacht wurde. Das I2C-Smart Graphic LCD ermöglicht ansprechende Graphiken. Dazu gibt es eine vollständig neu entwickelte Software mit vielen neuen Features, z.B. einen mehrstufigen Alarm-Level, eine Trend-Analyse und ein Konfigurations-Menü.

Bewährtes Design mit neuen Funktionen

Das Grundprinzip des Gewitter-Monitors bleibt bestehen und wird hier kurz zusammengefasst.

Wer Radiohören noch aus den Zeiten von Mittelwelle und Langewelle kennt, der weiß, dass Gewitter-Blitze als störendes Krachen im Lautsprecher zu hören waren. Seit dem Umstieg auf Frequenzmodulation oder gar digitale Verfahren ist das aus unserem Radio-Alltag verschwunden. Das Prinzip eignet sich aber nach wie vor, um Gewitter-Blitze zu beobachten und zu registrieren.

Die hier vorgestellte Schaltung arbeitet mit zwei Langewelle-Empfängern, die auf einer freien Frequenz (ungefähr 100kHz) ständig in den Äther hören. Sobald ein Signal erfasst wird, wird es von einem Mikrocontroller untersucht. Typisch für Blitze sind schnell ansteigende Flanken (im Lautsprecher als “Knacken” vernehmbar), die mit Hilfe des Analog-Digital-Converters (ADC) im Mikrocontroller selektiert und vermessen werden. Die Software sammelt die Anzahl der registrierten Blitze und die Summe der Pegel, die für jeden Blitz erreicht werden. Die Daten werden dann auf einem graphischen Display angezeigt. Das Display zeigt nicht nur die aktuell gemessenen Werte, sondern auch den Verlauf über die letzten Stunden. Die Daten erlauben die Analyse des Alarm-Levels, der über Leuchtdioden angezeigt werden. Darüber hinaus gibt es eine Trend-Analyse, um abzuschätzen, wie sich die Gewitteraktivitäten entwickeln werden.

Block-Diagramm
Block-Diagramm

Der analoge Schaltungsteil des vorherigen Gewitter-Monitors mit AM-Empfängern und der Peak-Detection-Schaltung hat sich bewährt und wurde übernommen. Die einzige Veränderung bezieht sich auf die Zeitkonstante der Peak-Detection, was weiter unten beschrieben wird.

Es gibt aber drei wesentliche Neuerungen:

(1) Die erste Veränderung trägt dem Feedback von einigen Nachbauten Rechnung. Basierend auf der zunehmenden Popularität des Arduino-Frameworks habe ich mich entschlossen, den ATmega-Prozessor im DIL-Gehäuse durch einen Arduino Nano zu ersetzen. Ich muss zugeben, dass ich für meine Entwicklungen lieber direkt mit den AVR-Prozessoren arbeite. Die  Arduino-Boards waren bisher immer gross, teuer und unhandlich für die Entwicklung von eigenständigen Geräten. Mit der Verfügbarkeit des kleinen und preisgünstigen Arduino Nano-Boards hat sich das aber verändert. Die kleine Platine hat ein komplettes Kernsystem für den ATmega-Prozessor an Board, was den Aufbau vereinfacht. Es bleibt der Nachteil, dass der Arduino im Vergleich zu einem “nackten” ATmega-Prozessor relativ strom-hungrig ist, da die Peripherie, z.B. das USB-Interface und die eingebaute Leuchtdiode, immer unter Spannung stehen. Da der Gewitter-Monitor aber wahrscheinlich nicht mit Batterie-Strom betrieben wird, ist dieser Nachteil verschmerzbar.

Arduino Nano
Der Arduino Nano hat ein komplettes System auf einem kleinen Board: ATmega328 Prozessor, 16 MHz Quarz, USB-Interface, LEDs und Spannungsregler. Sogar ein Reset-Taster ist dabei.

(2) Die zweite Veränderung bezieht sich auf das Graphik-Display. Bei dem vorher verwendeten ST7920 gab es Beschaffungsprobleme für die SPI-Variante. Außerdem fand ich die u8glib-Bibliothek unhandlich. Was lag also näher als eines der gut verfügbaren KS0108-Displays einzusetzen und mit dem Smart-I2C-Interface zu kombinieren, das an anderer Stelle beschrieben ist (siehe Universelles I2C-Interface für Graphik-LCD). Konkret habe ich mich für das 4-Zoll Display (Typ 3) entschieden, dass mit einer Auflösung von 192 x 64 Pixeln bei ansprechender Größe neue Möglichkeiten eröffnet. Das Graphik LCD-Display ist z.B. bei eBay unter dem Stichwort 4″ 192×64 Graphic LCD Modul Display in verschiedenen Farben erhältlich.

(3) Und schließlich war es an der Zeit, die Software komplett zu überarbeiten. Der neue Gewitter-Monitor hat einige neue Funktionen bekommen, speziell zur Analyse des Alarm-Status und der Trend-Entwicklung. Außerdem lässt sich das neue System flexible konfigurieren über ein Menü zur Einstellung der wichtigsten Parameter. Die Software wurde komplett in der Arduino-Entwicklungsumgebung geschrieben und kann mit dem vorhandenen USB-Interface des Arduinos in den Programmspeicher übertragen werden. Ein separater AVR-Programmer ist dafür nicht notwendig.

Die Schaltung

Der neue Gewitter-Monitor besteht aus dem Antennen-Modul, das wie oben beschrieben ohne Veränderung von der vorherigen Version übernommen wurde, und dem Hauptteil, das für die Auswertung und Anzeige zuständig ist. Das Antennen-Modul wird über ein 6-poliges Flachband-Kabel mit dem Hauptteil verbunden.

Gewitter-Monitor Antennen Modul
Schaltung des Antennen Modul mit dem AM-Empfänger IC TA7642 und einer Ferritstab-Antenne. Dieses Modul ist zweimal vorhanden.

Hier arbeitet ein AM-Empfänger mit dem TA7642 und einem Ferritstab als magnetische Antenne. Der Ferritstab hat eine Richtwirkung mit engen aber stark ausgeprägten Minima in Richtung der Ferritstab-Achse. Deshalb werden zwei Empfänger eingesetzt, die senkrecht zueinander stehen. So wird eine lückenlose Abdeckung von 360 Grad erreicht.

Gewitter Monitor Antenne-Modul
Antenne-Modul mit zwei senkrecht zueinander angeordneten Ferritstäben

Der Hauptteil des Gerätes verwendet, wie oben beschrieben, einen Arduino Nano und das Smart-I2C-Graphic-Display.

Schaltung des neuen Gewitter Monitors
Schaltung des neuen Gewitter Monitors

Das Signal vom Antennen-Modul wird mit einem Transistor (BC549C) verstärkt und dann an die Peak-Detection-Schaltung mit dem Operationsverstärker MCP602 geführt. Diese Schaltung folgt ansteigen Flanken sehr schnell und lässt das Signal dann langsam abfallen. So wird es möglich, mit dem naturgemäß relativ langsamen ADC die kurzen Blitz-Impulse sicher zu erfassen. Die Funktionsweise der Peak-Detection lässt sich mit dem Oszilloskop beobachten.

Eingang und Ausgang der Peak-Detection.
Eingang (untere Kurve) und Ausgang (obere Kurve) der Peak-Detection-Schaltung. Die Anregung erfolgt mit einem kurzen Impuls von wenigen µsec und erzeugt eine abfallende Flanke über mehrere msec. Der ADC tastet den Eingang mit einer Periode von 500µsec ab (4 mal pro Raster-Einheit).

Im Gegensatz zum vorherigen Gewitter-Monitor wurde die ADC-Abtast-Frequenz erhöht auf 2000 Hz pro Kanal. Entsprechend konnte die Zeitkonstante der Peak-Detection-Schaltung reduziert werden (10nF statt vorher 100nF). Dadurch erreicht das neue System eine etwa 10-fach höhere zeitliche Auflösung. Ereignisse, die vorher als ein einziger Blitz registriert wurden, können jetzt in mehrere diskrete Blitze aufgelöst werden.

Rechts oben im Schaltplan befindet sich die Spannungsversorgung für das Antennen-Modul. Die Empfangs-Empfindlichkeit der TA7642-ICs lässt sich über die Versorgungsspannung einstellen. Die Schaltung verwendet eine Band Gap-Referenz (TL431), die exakte 2.5V produziert, und einen Emitterfolger mit einem weiteren BC549C. Mit einem Trimmer kann der gewünschte Spannungswert gewählt werden. Ich habe die besten Erfahrungen mit 1.6V gemacht, gemessen am Eingang des Antennenmoduls (vor der Diode).

Für die Bedienung des Geräts sind drei Tasten verfügbar, die mit Select, Down und Up bezeichnet sind. Die Tasten befinden sich zusammen mit den Leuchtdioden für die Anzeige des Alarm-Levels und der Blitz-Erkennung auf einer kleinen Platine, die hier als Front-Panel bezeichnet wird.

Die Spannungsversorgung der Schaltung geschieht über ein externes Stecker-Netzteil, das mindestens 7V liefern sollte. Der Strombedarf ist abhängig von der eingestellten Beleuchtungsstärke des Displays und liegt maximal bei 150mA. Intern arbeitet ein Festspannungsregler. Zwar hat der Arduino einen eigenen 5V-Regler an Board, den man auch zur Versorgung der anderen Schaltungsteile heranziehen könnte. Ich habe mich aber für eine separate Versorgung entschlossen, weil der Regler auf dem Arduino bei größeren Eingangsspannungen vom Stecker-Netzteil (in meinem Fall 12V) und Strömen oberhalb von 100mA durchaus recht warm werden.

Damit ist die Schaltung beschrieben. Durch den Einsatz des integrierten Arduino Nano-Boards ist der Aufbau überschaubar. Dazu trägt auch die Tatsache bei, dass der Audio-Verstärker, der in der vorherige Version vorhanden war, hier weggelassen wurde.  Es hat sich gezeigt, dass beim laufenden System keine Notwendigkeit besteht, das Signal akustisch auszugeben.

Rückseite des Gewitter Monitor v2
Ein Blick hinter die Kulissen: Im Inneren geht es recht aufgeräumt zu. Das Arduino-Board sitzt auf zwei 15-poligen Pfostenleisten, so dass man es im Falle eines Falles leicht austauschen kann. Die USB-Micro Buchse ist gut zugänglich.

Vollständig neue Software

Der Umstieg auf Arduino und das Smart-I2C-GLCD erforderte eine vollständige Überarbeitung der Software. Das Grundprinzip ist aber weitgehend gleich geblieben.

Die Software besteht aus 4 Modulen:

  • GewitterMonitor_v2.ino ist das Hauptprogramm mit den setup() und loop()-Funktion und der Timer-getriebene Interrupt-Routine
  • GewitterMonitor_graphs.ino beinhaltet die Funktionen zur Anzeige auf dem Display
  • GewitterMonitor_stats.ino beherbergt die Statistik-Funktionen
  • GewitterMonitor_config.ino ist für die Verwaltung der Konfiguration zuständig.

Zusätzlich benötigt das Programm die Arduino-Bibliothek für das Graphik-Display glcd_functions. Um erfolgreich zu kompilieren, muss sich der glcd_functions-Folder im librariers-Ordner der Arduino-Sketche befinden – – wie bei Arduino üblich.

File-Struktur im Arduino-Verzeichnis
File-Struktur im Arduino-Verzeichnis

Alle Dateien sind auf der Ressourcen-Seite zum Download verfügbar. Für die glcd_functions-Bibliothek muss darauf geachtet werden, dass die Version vom 21-Feb-2018 (oder neuer) benötigt wird.

Kernstück der Software ist die Interrupt-Routine im Hauptprogramm. Diese Routine wird durch einen Timer-Interrupt 4000 mal pro Sekunde aufgerufen und liest wechselweise die ADC-Kanäle 0 und 1 ein. Das bedeutet, dass die Ausgänge vom Antennen-Modul wie oben beschrieben 2000 mal pro Sekunde abgefragt werden. Wenn sich zwei aufeinanderfolgende Werte um einen bestimmten Wert unterscheiden, wird dieses als Erkennung einer ansteigenden Flanke gewertet und entsprechend ein Blitz registriert. Der Schwellwert zur Blitzerkennung ist ein wichtiger Parameter des Systems, der sich konfigurieren lässt. Kleinere Werte bedeuten höhere Empfindlichkeit aber auch höhere Anfälligkeit gegen Störsignale. Größere Werte bedeuten geringere Empfindlichkeit. Als Default-Wert wird 150 eingesetzt, was bei dem Wertebereich des ADC von 1024 also etwa 15% Ausschlag entspricht. Damit habe ich die besten Erfahrungen gemacht.

Wenn der Trigger für die Blitzerkennung ausgelöst wurde, ermittelt das Programm den Maximalwert des Blitzes. Für jede Minute speichert das Programm die Anzahl der Blitze (flash_cnt) und die Summe der gemessenen Blitz-Maxima (flash_sum) in einem Array ab. Die Werte der letzten 150 Minuten stehen zur Anzeige zur Verfügung.

4 verschiedene Alarm-Level

Der Alarm-Level soll Auskunft geben, wie stark oder möglicherweise gefährlich die derzeitige Gewitter-Aktivität ist. Diese Information mag den interessierten Wetterbeobachter erfreuen oder hilfreich sein, um z.B. ein geplantes Picknick im Freien zu verschieben oder eine windanfällige Markise einzufahren.

Das System kennt 4 verschiedene Alarm-Level. Der Alarm-Level 1 schaltet die Display-Beleuchtung ein. Die Idee ist, dass das Gerät bei geringer Gewitteraktivität selbstständig um Aufmerksamkeit bittet. Die folgenden Alarm-Level 2 bis 4 werden über die drei roten Leuchtdioden als aufsteigende Reihe angezeigt.

Für die Berechnung des Alarm-Levels werden die Daten der letzten 15 Minuten herangezogen, sofern nichts anderes eingestellt wurde. Das Zeitfenster für die Auswertung des Alarm-Levels (alarm window) ist wiederum ein Parameter, den der Anwender konfigurieren kann. Der Default-Wert von 15 Minuten kann zwischen 5 und 60 Minuten gewählt werden.

Die Datenbasis für den Alarm-Level ist das Array mit den Summenwerten der Blitze pro Minute (flash_sum). Das Programm erlaubt zwischen zwei verschiedenen Algorithmen zu wählen. Entweder wird der Durchschnittswert (average) der Summenwerte berechnet, oder es wird der Maximalwert (max) gesucht. Durchschnittswerte sind robuster gegen einzelne Ausreißer, aber sie reagieren auch träger auf Veränderungen. Hier muss man Erfahrung sammeln, um zu schauen, was sich am Besten eignet. Für meinen Einsatz bevorzuge ich die Durchschnittsberechnung. In jedem Fall liefert das Programm einen Wert, entweder Durchschnitt oder Maximum, der dann mit einem Alarm-Schwellwert verglichen wird. Wird der Schwellwert übertroffen, dann wird der Alarm-Level 1 ausgelöst. Die anderen Alarm-Level verhalten sich entsprechend einer geometrischen Reihe:

  • Durchschnitt oder Maximum > Schwellwert: Alarm-Level 1
  • Durchschnitt oder Maximum > 2 * Schwellwert: Alarm-Level 2
  • Durchschnitt oder Maximum > 4 * Schwellwert: Alarm-Level 3
  • Durchschnitt oder Maximum > 8 * Schwellwert: Alarm-Level 4

Man kann leicht erkennen, dass es bei einem Alarm-Level 4 wirklich gewaltig kracht und das Gewitter in direkter Nähe ist.

Der Schwellwert des Alarm-Levels (alarm threshold) lässt sich ebenfalls konfigurieren. Man kann sowohl den gewünschten Algorithmus (Durchschnitt oder Maximum) als auch den Wert selber wählen. Als Default-Wert verwendet das System die Durchschnitts-Methode bei einem Schwellwert von 50.

Ich muss an dieser Stelle erwähnen, dass ich aufgrund der winterlichen Wetterlage bisher noch keine praktische Erfahrung mit den Alarm-Leveln sammeln konnte. Sicherlich wird es im Laufe des Sommers den einen oder anderen Software-Update geben.

Anzeige und Bedienung

Nach diesen Erklärungen sind das Display und die Bedienelemente hoffentlich einleuchtend.

Display und Bedienungselemente
Display und Bedienungselemente

Das 4-Zoll Display macht den Hauptteil der Frontseite aus. Es gibt dort zwei Bereiche: Auf der rechten Seite werden die aktuellen Messdaten für die laufende Minute gezeigt. Count steht für die Anzahl der registrierten Blitze in dieser Minute, und Sum für den Summenwerte über die gemessenen Maxima. Der Sekundenzähler unten in Bild läuft immer von 0 bis 60. Sobald die Minute voll ist, werden die aktuellen Daten übernommen und in den Verlauf eingefügt, der dabei um eine Reihe (= eine Minute) nach links verschoben wird.

Im rückblickenden Verlauf steht jede vertikale Linie für die Summe der Blitze während einer Minute. Am oberen Rand ist die Zeit-Skala angedeutet. Die kleinen Striche stehen für jeweils 15 Minuten, und der etwas größere Strich für eine Stunde. Man muss beachten, dass die vertikale Achse automatisch skaliert wird, um auch den größten gemessenen Wert sinnvoll abbilden zu können. Wenn z.B. der größte gemessene Wert 350 ist, dann wird die Skala bis 500 skaliert, usw.

Die gepunktete vertikale Linie zeigt das Zeitfenster für die Berechnung des Alarm-Levels. Alle Werte zwischen der gepunkteten Linie und dem rechten Rand (der aktuellen Zeit) werden für die Berechnung der Alarm-Level herangezogen. Wenn man im Konfigurations-Menü das Zeitfenster anders einstellet, wandert die gepunktete Linien an ihren neuen Platz.

Oben links im Display wird das Maximum (max) und der Durchschnittswert (avg) für das aktuelle gewählte Zeitfenster angezeigt.

Die restlichen Bedienelemente sind schnell erklärt. Die beiden gelben Leuchtdioden oben leuchten kurz auf (200 msec), sobald ein Blitz registriert wurde. Mit den beiden gelben Tasten lassen sich die Graphik-Bildschirme durchschalten. Man kann entweder die Anzeige der Summen oder die Anzeige der Anzahl der Blitze wählen. Schließlich ist die rote Taste ist für das Konfigurations-Menü vorgesehen.

Die Beleuchtung der Anzeige schaltet sich nach einiger Zeit ab, sofern kein Alarm-Level gesetzt ist. Wenn der neugierige Zeitgenosse trotzdem die aktuellen Daten sehen möchte, genügt ein Druck auf eine der Tasten, womit die Beleuchtung für 2 Minuten aktiviert wird.

Trend-Analyse

Interessanter als der Verlauf der letzten Minuten oder Stunden ist eigentlich das, was kommt. Wird das Gewitter noch stärker werden oder zieht es ab? In die Zukunft schauen kann der Gewitter Monitor natürlich nicht. Aber die Daten der Vergangenheit geben Anhaltspunkte. Zu dem Zweck habe ich eine Trend-Analyse in das Programm aufgenommen. Genaugenommen wird eine lineare Regression nach der Methode der kleinsten Quadrate über die Werte der letzten 45 Minuten (Regressions-Zeitfenster) berechnet und angezeigt. Die resultierende Gerade kann ansteigen oder abfallen, was sich in einem positiven oder negativen Steigungs-Koeffizienten erkennen lässt. Dieser Wert wird angezeigt – allerdings nur, wenn der Korrelations-Koeffizient grösser als 0.5 ist und somit einen sinnvollen Zusammenhang zeigt. Positive Werte bedeuten also, dass die Gewitter-Aktivität in den letzten 45 Minuten zugenommen hat, während negative Werte die Abnahme anzeigen. Wenn die Messwerte durchgängig bei 0 liegen oder wild streuen, so dass die Statistik keinen Trend erkennen lässt, dann wird im Display nur “–.-” angezeigt.

Trend-Analyse mit linearer Regression.
Das Schlimmste ist vorbei! Trend-Analyse mit linearer Regression.

Die Trend-Analyse kann jederzeit mit den Up– oder Down-Tasten dazu geschaltet werden. Die beiden gelben Tasten laufen hintereinander 4 verschiedene Darstellungen durch:

  • Zeitverlauf der Summenwerte (Flash Sum)
  • Zeitverlauf der Summenwerte zusätzlich mit Trend-Analyse (Flash Sum + Trend)
  • Zeitverlauf der Anzahl der Blitze pro Minute (Flash Count)
  • Zeitverlauf der Anzahl der Blitze pro Minute mit Trend-Analyse (Flash Count + Trend)

Auch hier gilt die oben gemachte Bemerkung, dass ich bisher noch keine Erfahrung mit dieser Funktion sammeln konnte. Der Sommer wird möglicherweise Software-Updates bringen.

Konfiguration

Wie oben beschrieben gibt es die Möglichkeit, die wichtigsten System-Parameter zu konfigurieren und an den Aufstellungsort und die Anwender-Vorlieben anzupassen. Ein langer Druck (> 3 sec) auf die rote Select-Taste führt in das Konfigurations-Menü.

Konfigurations-Menü
Konfigurations-Menü

Die Auswahl des gewünschten Parameters erfolgt über die Up– and Down-Tasten. Dann führt ein Druck auf die rote Select-Taste in die Einstellung für den gewählten Wert.

Editieren eines Konfigurations-Wertes
Editieren eines Konfigurations-Wertes

Mit den Up– und Down-Tasten kann der gewählte Werte verändert werden. Ein weiterer Druck auf Select übernimmt den neuen Wert und führt zurück zum Menü. Mit der Anwahl des letzten Eintrags, Exit, verlässt man das Konfigurations-Menü.

Alle Parameter haben Default-Werte, die bei dem ersten Programmstart eingestellt werden. Diese Werte haben sich bisher als eine gute Wahl während des Testbetriebs herausgestellt.

Hier eine kurze Zusammenfassung der Konfigurations-Parameter mit ihren Default-Werten

  • Trigger threshold ist die minimale Schrittgröße zwischen zwei aufeinander folgenden Messwerten, um eine ansteigende Flanke als Blitz zu interpretieren. Kleine Werte erhöhen die Empfindlichkeit aber auch die Anfälligkeit gegenüber Störsignalen.
    Default-Wert: 150
  • Alarm window ist die Anzahl der letzten, verstrichenen Minuten, die zur Berechnung des Alarm-Levels herangezogen werden.
    Default-Wert: 15
  • Alarm threshold selektiert den Algorithmus (Durchschnitt oder Maximum) und den Schwellwert für das Setzen der Alarm-Levels. Alarm-Level 1 wird beim Überschreiten des einfachen Schwellwertes aktiviert, Alam-Level 2 beim doppelten Wert, usw.
    Default-Wert: Avg 50
  • Display light setzt die Helligkeit des Displays. Die Werte reichen von 0 (= 0%, aus) bis 10 (= 100%, maximale Helligkeit).
    Default-Wert: 8
  • Startup screen selektiert die Graphik, die nach dem Einschalten des Geräts gezeigt wird. Mögliche Werte sind:
    Flash Sum
    Flash Sum + Trend
    Flash Count
    Flash Count + Trend
    Default-Wert: Flash Sum

Es bleibt noch zu erwähnen, dass alle Konfigurations-Parameter im EEPROM des Prozessors abgelegt werden. Damit bleiben die eingestellten Parameter auch nach dem Abschalten (oder beim Überwintern im Bastelkeller) erhalten – wie es sich für eine Anwendung dieser Art gehört.

Aufstellung und Einstellung

Zum Schluss ein paar Tips für die Inbetriebnahme. Das Gerät empfängt die magnetische Komponenten der elektromagnetische Schwingungen von Blitzen. Zum Glück sind die magnetischen Störfelder im Haus meist weniger stark ausgeprägt als die elektrischen Felder. Trotzdem reagiert das Gerät empfindlich auf Störsignale von manchen Schaltnetzteilen. Das ist natürlich insbesondere relevant für das Stecker-Netzteil, mit dem das Gerät betrieben wird. Hier gibt es deutliche Unterschiede. Im Zweifelsfall ist es keine schlechte Idee, etwas mehr Geld zu investieren. In meinem Fall steht das Gerät in einer Fensterecke, die sich ein bisschen abseits von den anderen Geräten befindet.

Es kann sinnvoll sein, das Gerät an eine Erdung (z.B. Wasserleitung, Heizung, etc.) anzuschliessen. In meinem Fall konnte ich dadurch den Störpegel deutlich reduzieren und die Empfindlichkeit weiter erhöhen. Das sollte aber nicht unbedingt notwendig sein.

Für die erste Inbetriebnahme sollte die Versorgungsspannung des Antennen-Moduls am Trimpoti auf 1.6V eingestellt werden. Für die Software empfehlen sich die Default-Parameter wie oben beschrieben.  Nach dem Einschalten – und in Abwesenheit von Gewittern – sollten die Blitz-Indikatoren nicht aufleuchten. Wenn es gelegentlich ein Signal gibt, dann ist das normal und kommt wahrscheinlich von technischen Geräten. In jedem Fall sollten die Werte aber deutlich unter der Schwelle für den ersten Alarm-Level liegen.

Zum Testen der Funktion nehme ich eine alte 9V-Batterie, die ich mit einem etwa 30 cm langen Drahtstück ein paar Mal kurz schließe. Wenn ich das in etwa 20 bis 30 cm Entfernung von der Antenne mache, sollte das Gerät dies als Blitze registrieren. Wenn das geklappt hat, ist alles in Ordnung und man kann entspannt auf die nächste gewittrige Wetterlage warten.

Es gibt zwei Optionen, die Empfindlichkeit zu verändern. Zuerst kann man mit dem Trimmpoti die Antennen-Spannungsversorgung vergrößern (höhere Empfindlichkeit) oder verkleinern (geringere Empfindlichkeit). Als zweite Option, und besonders um unerwünschte Störsignale heraus zu filtern, kann der Konfigurations-Parameter Trigger Threshold verkleinert (höhere Empfindlichkeit) oder vergrößert (geringere Empfindlichkeit) werden.  Tatsächlich ist eine sehr große Empfindlichkeit gar nicht wünschenswert. In Sommernächten kann das Gerät Reichweiten von vielen 100 km erreichen. Dann ist es fraglich, ob man sich ein Gewitter in den fernen Alpen anzeigen lassen möchte.

Zum Schluss

Ich hoffe, dass der neuen Gewitter Monitor v2 das Interesse des einen oder anderen Bastlers weckt. Wie immer freue ich mich über Rückmeldungen, Kommentare, Vorschläge oder Ideen. Natürlich bin ich auch gerne bereit, bei der Beschaffung von Komponenten zu unterstützen oder Prozessoren zu programmieren.

Die Software hat ein gewisses Mass an Komplexität erreicht – und wird sicherlich allerlei Fehler enthalten. Auch hierzu sind Rückmeldungen willkommen. Ich gehe davon aus, dass es bei Gelegenheit Updates geben wird, die – Arduino sei Dank – über die USB-Schnittstelle sehr einfach eingespielt werden können.

Die Software für dieses Projekt kann von der Ressourcen-Seite herunter geladen werden.

 

 

 

 

 

 

Nano-Scope: Oszilloskop mit Arduino und Graphic LC-Display

Kürzlich wurden in der Zeitschrift Elektor Mini-Oszilloskope besprochen. Es sind einfache Geräte, die im Kern einen Mikrocontroller mit schnellem Analog-Digital-Converter (ADC) aufweisen und mit einem einfach Display versehen sind. Die Ergebnisse sind durchaus beachtlich. Durch diesen Bericht animiert stellte ich mir die Frage: Kann man so etwas mit ganz einfachen Mitteln machen? Wie weit kommt man mit dem Arduino Nano, basierend auf einem ATmega32 mit 16MHz Taktfrequenz und einem I2C Graphic-LCD?

Die Frage lässt sich nur durch einen Test-Aufbau beantworten. Von Anfang an war klar, dass es kein “konkurrenzfähiges” Produkt werden soll. Die getesteten Mini-Oszilloskope sind so günstig zu kaufen, zum Teil als Bausatz, dass es keinen Sinn macht, ein vergleichbares Gerät selbst zu entwickeln. Hier geht es also um das Prinzip. Und wie immer gibt es dabei viel zu lernen.

Vorüberlegungen

Der ATmega32 hat einen ADC auf dem Chip, der bereits mit einer sample-and-hold Schaltung ausgerüstet und somit für die Erfassung dynamischer Spannungsverläufe gut geeignet ist. Die Grundidee ist ganz einfach: Ein regelmäßiger Timer-Interrupt liest mit Hilfe des ADC den aktuellen Spannungswert am Eingang ein. Mit einer Trigger-Logik wird festgestellt, ob ein (einstellbarer) Schwellwert (trigger threshold) überschritten wurde. Wenn das der Fall ist, erfolgt die Datensammlung in ein Array. Sobald das Array gefüllt ist, wird es als Kurve auf dem Display ausgegeben.

Die Auflösung des ADC beträgt 10 Bit, also Werte von 0 bis 1023, was mehr als genug ist für diese Anwendung. Tatsächlich ist das Display mit seinen vertikalen 64 Pixeln, also 6 Bit, der beschränkende Faktor. Im Programm wird die Auflösung in zwei Stufen reduziert. Zuerst einmal wird nur das höherwertige Byte des ADC ausgelesen. Das lässt sich einfach machen, indem das Flag for left adjusted result (ADLAR) gesetzt wird. Es bleiben also 8 Bit. Diese Auflösung wird für die Trigger-Logik verwendet. Für die Anzeige der Kurve auf dem Display wird der Wert dann noch einmal um 2 Bit nach rechts verschoben, wodurch der verbleibende Wertebereich 0 bis 63 beträgt und somit gut auf das Display passt.

Der ADC arbeitet hier mit der internen Spannungsreferenz des ATmega von knapp 1.1V, wodurch der Messbereich festgelegt ist. Für diese einfache Anwendung habe ich auf eine analoge Verstärkung oder Aufbereitung des Signals, wie es für ein praktisch einsetzbares Oszilloskop unabdingbar wäre,  verzichtet.

Eine kritische Frage ist die errechbare Geschwindigkeit des Daten-Samplings, ein wichtiges Qualitätsmerkmal jedes digitalen Oszilloskops. Der ADC des ATmega ist von einfacher Bauweise. Deshalb sollte man keine zu großen Ansprüche stellen. Der ADC wird mit einem internen Takt versorgt, der mit einem Vorteiler aus dem Systemtakt generiert wird. Das ATMEL Datenblatt empfiehlt Taktraten zwischen 50 und 200 kHz. Außerdem kann man dort erfahren, dass eine Umwandlung 13 Taktzyklen benötigt. Bei 200 kHz würde eine Umwandlung also 65µsec benötigen, was einer Sampling-Frequenz von 15 kHz entspricht. Geht es schneller? Das Datenblatt erwähnt, dass höhere Taktraten möglich sind, wenn man nicht die volle Auflösung von 10 Bit benötigt. Da in dieser Anwendung nur die höheren 8 Bit verwendet werden, habe ich mich für eine Taktrate von 500 kHz entschieden. Dadurch sinkt die Umwandlungszeit auf  26µsec, entsprechend 38kHz. Tatsächlich läuft die Abfrage des ADC mit einem Interrupt von 20kHz, was sich in den Experimenten als eine stabile Frequenz erwiesen hat. Man sollte aber nicht unterschätzen, dass der Prozessor damit unter signifikanter Systemlast steht.

Hardware

Der Aufbau ist minimalistisch und lässt sich schnell auf eine Steckbrett zusammen setzen. Im Zentrum stehen der Arduino Nano und das Graphik-Display, die über den I2C-Bus miteinander verbunden werden. Alle Details zum Graphik-Display sind an anderer Stelle beschrieben (Universelles I2C Interface für Graphik LC-Displays)  Die Stromversorgung kommt über den USB-Port des Arduino. Das zu messende Eingangssignal gelangt über einen Kondensator an den Analog-Port A0 des Arduino. Ein lineares 100kOhm-Poti fügt eine feste Gleichspannung hinzu, womit die vertikale Position eingestellt werden kann. Für die interne ADC Spannungsreferenz wird noch ein 100nF-Kondensator gegen Masse am Referenz-Pin benötigt.

Eine LED am digitalen Port D6 dient als Anzeige des Trigger-Modus. Schließlich gibt es noch vier Tasten an den digitalen Ports D2 bis D5, über die die horizontale Zeitachse und der Trigger-Level eingestellt werden können. Damit ist der Aufbau auch schon beschrieben.

Schaltplan des Arduino Nano-Oszilloskops
Schaltplan des Arduino Nano-Oszilloskops

Software

Der Arduino-Sketch sieht komplizierter aus als er ist. Allerdings habe ich für die Steuerung von Interrupt und ADC nicht die Arduino-Funktionen gewählt, sonder die ATmega-Register direkt angesprochen. So war es möglich, das enge Timing besser unter Kontrolle zu halten. Zum Glück ist all das innerhalb der Arduino-IDE ohne Probleme möglich.

Eine zentrale Funktion ist die Interrupt-Service-Routine (ISR), die mit 20kHz aufgerufen wird. In dieser Routine wir der ADC ausgelesen und gleich wieder gestartet für den nächsten Durchlauf. Darauf folgt die Trigger-Logik und bei gesetztem Trigger das Abspeichern der Daten im Array für die Anzeige. Im zweiten Teil der ISR werden die vier Tasten (im Programm-Code etwas hochtrabend als keyboard bezeichnet) abgefragt und entprellt. Es gibt sogar eine einfache Tasten-Repeat-Funktion.

Die Sampling-Frequenz lässt sich über die Tastatur herunter regeln, was einer langsameren Zeitachse entspricht. Die Tabelle sar_table enthält die möglichen Einstellungen. Die derzeitige Software erlaubt 7 verschiedene Werte. Die ISR läuft in jedem Fall mit 20kHz. Für langsamere Einstellungen werden mehrere ADC-Werte gemittelt wie in der Tabelle angegeben (interrupts per sample).

Einstellbereich der Zeitachse.
Einstellbereich der Zeitachse. Die Werte werden über die Taster angewählt. Der aktuelle Wert für die Dauer eines Rasterfeldes (time per grid) wird in der unteren, rechten Ecke des Displays angezeigt.

Die setup()-Funktion erledigt alle Systemeinstellung und zeichnet die statischen Elemente auf den Bildschirm. Die loop()-Funktion schließlich wartet auf das Signal von der Interrupt-Routine, dass Daten zur Anzeige bereitstehen, und erledigt dieses mit der glcd-Funktion draw_function(). Die Software ergänzt den Kurven-Verlauf mit einem Raster aus gepunkteten Linien. Außerdem werden im Hauptprogramm mögliche Aktivitäten des Keyboards ausgewertet.

Für die Datenanzeige gibt es noch eine erwähnenswerte Besonderheit. Bevor ein neuer Kurvenzug gezeichnet werden kann, muss vorher der bestehende, “alte” Kurvenzug gelöscht werden. In einer ersten Version des Programmes hatte ich dazu den Bildschirm vollständig gelöscht, was allerdings ein deutlich sichtbares Flackern zur Folge hatte. Eleganter geht das mit zwei Datenarrays. Eines enthält die vorherigen, “alten” Daten und wird zum Löschen benutzt, während das zweite die aktuellen, “neuen” Daten hat. Mit jedem Durchlauf wird zwischen den beiden Datenarrays hin- und hergeschaltet. Mit dieser Logik ist die Anzeige weitgehend frei von Flackern.

Anwendung

Die Anzeige ist einfach zu lesen. Die vertikalen, gepunkteten Linien sind das Raster für die Zeitachse. Die horizontale, gepunktete Linie zeigt den aktuelle Trigger-Wert. Am rechten Rand des Bildschirms befinden sich die eingestellten Parameter: der Trigger-Wert und die Zeitachse. Der Wert für die Zeitachse ist die Dauer eines Raster-Feldes in msec.

Zu beachten ist, dass das Gerät nur dann aktiv wird, wenn der Trigger eine ansteigende Flanke erkannt hat. Es gibt also keinen Auto-Modus wie bei anderen Geräten, in dem auch ohne Trigger der Signalverlauf angezeigt wird. Die LED, die bei jedem Trigger kurz aufleuchtet, erweist sich als ein gutes Hilfsmittel.

Anzeige des Nano-Scopes
Anzeige des Arduino Nano Oszilloskops. Der Messbereich liegt zwischen 0 und 1.1V. Die horizontale gestichelte Linie zeigt den aktuellen Trigger-Level, hier 0.1V, und die ms-Angabe am unteren rechten Rand die Zeitdauer eines Rasterfeldes, hier 10 msec.

Fazit

Das kleine Oszilloskop macht sich in der Praxis erstaunlich gut, sofern die vergleichsweise niedrige Abtastrate kein Problem ist. Frequenzen von einigen 100Hz lassen sich sehr gut darstellen. Auch bei 2000Hz (entspricht 10 Datenpunkte pro Schwingung) bekommt man noch einen brauchbaren Eindruck der Signalform. Darüber ist aber kein sinnvolles Arbeiten mehr möglich. Ein schnellerer ADC wäre wünschenswert. Auch die vertikale Auflösung des Displays setzt klare Grenzen. Trotzdem ist es beeindruckend, was mit diesem geringen Materialaufwand und der einfachen Software machbar ist.

Download

Sketch des Arduino Nano Scope: Arduino_Nano_Scope (03-Jan-2018)

 

 

Smart I2C GLCD am Arduino: Ein einfaches Beispiel

Das Smart I2C Graphic LCD kommt inzwischen öfter am Arduino zum Einsatz, wodurch Arduino-Projekte leicht mit graphischen Ausgaben bereichert werden können.

Hier ein einfaches Beispiel: Ein Analogwert – in diesem Fall ein Potentiometer zwischen Masse und Betriebsspannung – wird mit dem ADC ausgelesen und als horizontaler Balken angezeigt.

Horizontale Balken-Anzeige mit dem GLCD
Ein analoger Wert wird als horizontaler Balken angezeigt

Hardware

Für diese Demo verwende ich einen Arduino Nano. Der Aufbau lässt sich schnell auf einer kleinen Lochraster-Platine realisieren. Die Stromversorgung kommt vom USB-Anschluss des Arduinos und versorgt auch gleich das Display mit 5V. Wir brauchen vier Anschlüsse zum Display: +5V, Masse und die beiden I2C-Anschlüsse SCL und SDA. Das Potentiometer wird mit dem analogen Port A0 des Arduino verdrahtet. Damit ist der Aufbau fertig.

Aufbau für das GLCD-Beispiel
Aufbau für das GLCD-Beispiel

Software

Um das GLCD über den Arduino anzusprechen, wird eine Bibliothek gebraucht, die die Graphik-Funktionen bereitstellt. Die glcd-Bibliothek besteht aus 3 Dateien im Ordner glcd_functions:

  • glcd_functions.cpp beinhaltet den Programm-Code für die Graphik-Funktionen. Die Logik ist sehr einfach. Im Prinzip werden die Parameter, z.B. Koordinaten der Linien und Rechtecke, übernommen und mit den entsprechenden Instruktions-Token an die I2C-Schnittstelle gesendet.
  • glcd_functions.h ist die zugehörige Header-Datei und beinhaltet die Definitionen der Graphik-Funktionen
  • keywords.txt listet die Schlüsselwörter der Bibliothek, so dass sie im Arduino-Editor farblich markiert werden

Der Folder glcd_functions mit diesen drei Dateien wird in den Folder libraries der Arduino-Umgebung kopiert. Damit ist alles vorbereitet.

glcd-Bibliothek im Libraries-Folder der Arduino-Umgebung
glcd-Bibliothek im Libraries-Folder der Arduino-Umgebung

Im eigentlichen Programm für diese Beispiel, es ist der Sketch glcd_demo.ino, wird ganz am Anfang die glcd-Bibliothek mit dem entsprechenden #include-Statement eingebunden. Außerdem wird eine Instanz des Graphik-Displays als globale Variable initiiert. Dabei wird die I2C-Adresse, in diesem Fall hexadezimal 20, übergeben. Damit sind alle Graphik-Funktionen verfügbar.

#include <glcd_functions.h>

glcd my_gd(0x20);   //instance of the graphic display

Für den Bar-Graphen gibt es eine Datenstruktur bar_graph, die alle wichtige Daten zusammenfasst, z.B. Koordinaten der linken, oberen Ecke, Länge und Breite, und der aktuell angezeigte Wert. Dazu sind zwei Funktionen vorhanden: draw_bar_graph_frame() zeichnet einen Ramen mit einer Skala von 0 bis 100. Diese Funktion wird ganz am Anfang im setup()-Block aufgerufen. Die zweite Funktion refresh_bar_graph() erzeugt dann den Balken mit dem aktuellen Wert, der vom ADC kommt. Diese Funktion wird im loop()-Block aufgerufen. Schließlich sorgt der Aufruf von delay(100) dafür, dass die Loop etwa 10 mal pro Sekunde durchlaufen wird.

Neben den verschiedenen Zeichenfunktionen zeigt dieses Beispiel auch die Möglichkeiten, die Hintergrund-Beleuchtung zu steuern, wie es z.B. zum Stromsparen bei Batterie-Betrieb notwendig sein kann. Solange der ADC-Wert unverändert bleibt, wird nach Ablauf einer voreingestellten Zeit (verwaltet mi dem Zähler delay_cnt) das Display mit der Funktion dim_on()  dunkel geschaltet. Sobald sich der ADC-Wert verändert, wird die Display-Beleuchtung mit dim_off() wieder auf ihren ursprünglichen Wert zurück gesetzt.

Fazit

Dieses Beispiel soll zeigen, dass das Display sehr einfach in eine Arduino-Anwendung einzubinden ist. Der Aufwand für Hardware und Software ist gering und eröffnet viele Möglichkeiten für ansprechende Darstellungen.

Downloads

  • Arduino-Sketch: adc_bar_graph (28-Dec-2017)
  • Arduino glcd-Bibliothek: siehe Ressourcen, Smart I2C Display, Arduino

 

Pointer auf Funktionen: Neue Software für das Graphik-Display

Das Graphik-Display “Smart I2C-GLCD” hat inzwischen eine ganze Reihe Anwendungsgebiete gefunden. Dabei sind einige neue Funktionen hinzugekommen, z.B. das Zeichnen von gepunkteten Linien oder die Ausgabe von negativen Zahlen. Durch den größeren Funktionsumfang war der Instruktions-Interpreter aber nicht mehr effizient und musste verbessert werden.

Zur Erinnerung: Das Graphik-Display empfängt Instruktionen über das I2C-Interface. Das erste Byte jeder Datensendung ist das Command-Token und bestimmt, welche Funktion ausgeführt werden soll. Z.B steht 17 für das Zeichnen einer Linie oder 32 für die Ausgabe eines Zeichens. Im bisherigen Programm gab es eine Switch/Case-Konstruktion, die sich durch die Liste der möglichen Instruktion-Tokens hindurch hangelte, bis der passende Token gefunden wurde. Dort wurde dann in die entsprechende Graphik-Funktion verzweigt. Das funktionierte gut mit 5 oder 10 möglichen Tokens, macht aber keinen Sinn mehr für die derzeitige Liste von über 30.

Wie geht es besser? Die Idee ist ganz einfach: Eine Tabelle, die für jeden Token einen Zeiger auf die zugehörige Graphik-Funktion. Mit Hilfe dieser Tabelle kann der Instruktions-Token als Index genutzt werden, um ohne Schleifen direkt den jeweiligen Tabellen-Eintrag zu finden.

Allerdings benötigt der Instruktionsinterpreter nicht nur den Zeiger auf die zugehörige Funktion, sondern auch die Anzahl der Parameter, die zum Ausführen der Funktion benötigt werden. Die Graphik-Funktion draw_char() braucht nur einen Parameter, eben das zu zeichnende Zeichen, während die Funktion draw_line() 5 Parameter benötigt, die Koordinaten des Start- und Endpunktes und der Modus. So ergibt sich eine Tabelle mit zwei Spalten: dem Zeiger auf die zugehörige Graphik-Funktion und der Anzahl der Parameter.

Tabelle mit Zeigern auf Funktionen
Tabelle mit Zeigern auf Funktionen

Die Sprache C macht den Umgang mit Zeigern nicht gerade einfach. Auch nach vielen Jahren Programmierpraxis ist die zugehörige Syntax immer wieder verwirrend. Zum Glück konnte ich noch meinen alten “Kernighan & Ritchie” im Regal finden (meine Ausgabe ist von 1986). Dieses immer wieder erstaunliche Buch zeigt die zugehörige Syntax.

Kernighan & Ritchie, Ausgabe 1986
Kernighan & Ritchie, Ausgabe 1986

Und so ist der neue Instruktions-Interpreter entstanden. Das Kernstück, die zweidimensionale Tabelle, wird mit Hilfe einer Struktur definiert.

typedef struct {
   void (*cmd_func)(void);
   int8_t parm_count;
} cmd_entry_t;

Die Formulierung void (*cmd_func)(void) ist ein Platzhalter für die Zeiger auf die jeweiligen Graphik-Funktion. Die Instruktions-Tabelle ist ein Array von der oben definierten Struktur. Sie wird gleich mit den entsprechenden Einträgen initialisiert:

 cmd_entry_t cmd_table[] = {
   {cmd_ignore, 0, },              // 0 
   {cmd_glcd_on, 0, },             // 1
   {cmd_glcd_off, 0, },            // 2
   {cmd_set_display_light, 1, },   // 3
   {cmd_set_dim_on, 0, },          // 4
   {cmd_set_dim_off, 0, },         // 5
   {cmd_set_i2c, 1, },             // 6
   ...
};

Natürlich müssen die Funktionen, die in der Tabelle auftauchen, entsprechend definiert sein. Hier sind die Funktions-Prototypen gezeigt, die üblicherweise in einer #include-Datei stehen:

// command function prototypes
void cmd_ignore(void);
void cmd_glcd_on(void);
void cmd_glcd_off(void);
void cmd_set_display_light(void);
void cmd_set_dim_off(void);
void cmd_set_dim_on(void);
void cmd_set_i2c(void); 
...

Im Instruktions-Interpreter wird das Command-Token über das I2C-Interface eingelesen, der Wertebereich überprüft, und wenn der passt die entsprechende Funktion aufgerufen.

cmd_token = I2C_fetch_byte();        // get instruction token 
if (cmd_token < sizeof(cmd_table)/sizeof(cmd_entry_t)) { // range check
   parm_buffer[0] = cmd_token;
   for (i = 1; i <= cmd_table[cmd_token].parm_count; ++i) 
      parm_buffer[i] = I2C_fetch_byte(); // if yes, get parameters 
   (*cmd_table[cmd_token].cmd_func)(); // and call graphic function
} else {
   cmd_show_error();                  // if not, show error
};

parm_buffer[] ist ein globales Array, in dem der aktuelle Command-Token und die zugehörigen Parameter abgelegt werden. Dieses Array wird von den Graphik-Funktionen genutzt, um die jeweilige Aktion zu steuern. Als Beispiel wird hier die Funktion cmd_draw_line() gezeigt, die die zugehörige Graphik-Funktion zum Zeichnen einer Linie aufruft:

/* cmd_draw_line - plots a straight line -----------------------*/
void cmd_draw_line(void) {
   draw_line(parm_buffer[1], parm_buffer[2], parm_buffer[3], parm_buffer[4], parm_buffer[5]);
};

Nach einigen Versuchen funktioniert der neue Instruktions-Interpreter ganz hervorragend. Das Programm ist damit deutlich kürzer und effizienter geworden.

Die neue Software ist bei den Ressourcen zu finden unter Smart I2C Display, Firmware

Solar LED-Strahler für den Garten

Solarenergie eignet sich ganz hervorragend zur Beleuchtung im Garten. Aber leider waren meine bisherigen Versuche, eine ansprechende Lampe zu finden, erfolglos. Deshalb habe ich mich auf den Weg gemacht, einen preisgünstigen Solar-Strahler so umzubauen, dass er meinen Ansprüchen gerecht wird. Hier folgt eine Beschreibung dieses Selbstbau-Projekts.

Dieser Bericht ist auch bei http://www.elektronik-labor.de/ erschienen.

Schnäppchen-Angebot aus dem Baumarkt

Der lokale Baumarkt hat immer wieder sehr preisgünstige Solarlampen für den Garten im Angebot, die dann verkaufsoptimiert in Regalen direkt an der Kasse liegen. So eine Lampe landete neulich auch in meinem Einkaufswagen. Zu Hause zeigte sich aber, dass die Lichtausbeute gering ist. Auch die kalt-weiße Lichtfarbe gefiel mir nicht. Nach dem Aufschrauben fand ich drei parallel geschaltete 5 mm-LEDs, die über ein vierbeiniges IC mit dem kleinen Solarpanel und einer NiMH-Zelle verbunden waren. Eine Festinduktivität deutete auf eine „joule-thief“-Schaltung hin.

Sicherlich kann man für den kleinen Preis nicht mehr Technik erwarten. Die Frage ist: Wenn ich bereit bin, etwas mehr zu investieren, wie kann man es besser machen? Auf der Wunschliste stehen: Helleres und warm-weißes Licht mit gleichbleibender Leuchtstärke, begrenzte Brenndauer am Abend zum schonenden Umgang mit der beschränkten Solarenergie und ein pfleglicher Umgang mit dem Akku für eine lange Lebensdauer.

Hier ein Vorschlag, der diese Kriterien erfüllt – und inzwischen unseren heimischen Garten an verschiedenen Punkten erleuchtet.

SMD-LED

Mehr Licht braucht in erster Linie eine stärkere LED. Die ursprünglichen 5mm-LEDs wurden durch eine SMD-LED, hier die STW8Q14C von Seoul Semiconductor ersetzt. Diese LED ist für 100mA Dauerleistung bei etwa 3V ausgelegt und in meiner bevorzugten warm-weißen Licht-Farbe zu bekommen. Diese LED ist trotz SMD-Bauform ausreichend groß, so dass man sie ohne Probleme auf einem Stück Lochrasterplatine auflöten kann. Zusammen mit einem Vorwiderstand von 10 Ohm auf der Rückseite der Platine kommt die neue LED auf den Reflektor und wird dort mit eine Tropfen Sekundenkleber befestigt. Das Strahlergehäuse vom Baumarkt erfüllt gute Dienste. Diese Anordnung produziert ein sehr schönes und kräftiges Licht.

Die SMD-LED wird mit einem Stück Lochrasterplatine auf dem Reflektor befestigt.
SMD-LED an ihrem Arbeitsplatz

Energieversorgung

Die stärkere LED braucht mehr Strom, was unweigerlich zu einem größeren Solarpanel und Energiespeicher führt. Von früheren Projekten hatte ich noch ein Panel von 11 x 6 cm Größe in der Bastelkiste. Das Panel liefert eine Leerlaufspannung von maximal 5.5V und einen Kurzschlussstrom von 150mA. Als Energiespeicher kommen drei NiMH-Zellen, Größe AA, aus dem besagten Baumarkt zum Einsatz. Die Akkus werden in Reihe zu einem „Battery-Pack“ zusammengeschaltet und liefern so eine Ausgangsspannung zwischen 3.0 und etwa 3.8V. Das Solarpanel versorgt den Akku über eine Schottky-Diode, die die Batterie vor Entladung schützt. Meine Messungen zeigten einen Ladestrom zwischen 130mA am leeren und 80mA am vollen Akku. An sehr sonnigen Tagen muss der Akku gegebenenfalls 80mA Dauerladung aushalten, was mir akzeptabel erscheint. Eine Abschaltung bei Vollladung ist also nicht vorgesehen.

Schaltzentrale

Für die Steuerung kommt ein bewährter ATtiny45 zur Anwendung. Der Mikrocontroller hat 3 Aufgaben:

    1. Erstens schaltet er die LED am Abend abhängig von der Spannung des Solarpanels ein und nach einigen Stunden wieder aus. Schließlich besteht kein Bedarf, die Gartenbeleuchtung die ganze Nacht zu betreiben. Stattdessen soll eine Akkufüllung auch bei schlechtem Wetter für mehrere Abende reichen.
    2. Zweitens sorgt der ATtiny als Step-Up Wandler mit Hilfe einer Speicherdrossel für eine konstante Spannung an der LED, so dass die Helligkeit immer gleichbleibend und unabhängig vom Ladezustand des Akkus ist.
    3. Und drittens beobachtet der Prozessor die Akkuspannung und schaltet den LED-Verbraucher aus, wenn die Akkuspannung unter den kritischen Wert von 3.0V fällt. So wird eine schädigende Tiefentladung des Akkus vermieden.
Schaltplan des Solar LED-Strahlers
Schaltplan des Solar LED-Strahlers

Der Mikrocontroller bekommt Input von 2 Quellen, die mit Hilfe des ADC ausgelesen werden: ADC-Kanal 2 misst die Spannung am Solarpanel vor der Schottky-Diode, und ADC-Kanal 3 die Akkuspannung. Als Referenz für den ADC wird die die interne Referenz-Spannung von 1.1V verwendet. Deshalb werden die externen Spannungen mit Spannungsteilern (100 versus 33 kOhm) auf das passende Niveau reduziert.

Der Ausgang PB1 schaltet die LED über einen P-Kanal FET (IRLML2244) ein oder aus. Seit einiger Zeit gibt es MOSFETs, die auch mit 3V Steuerspannung durchschalten. MOSFETs haben gegenüber bipolaren Transistoren den Vorteil eines sehr kleinen Durchlasswiderstandes. Dadurch verbessert sich der Wirkungsgrad der Schaltung. Außerdem kann das Gate direkt ohne Vorwiderstand an den Ausgang des Prozessors angeschlossen werden. Nebenbei bemerkt sind die hier verwendeten Power MOSFETs ausgesprochen preisgünstig und in der Tat die billigsten Transistoren, die ich bisher je erworben habe.

Eine Besonderheit dieser Schaltung ist die Spannungserhöhung mit Hilfe eines Step-Up Wandlers. Der Ausgang PB0 produziert ein PWM-Signal von etwa 32kHz, das mit Hilfe eines N-Kanal FETs (IRLML6244) die Speicherdrossel periodisch auf Masse legt. Die Schottky-Diode koppelt die erhöhte Spannung aus, die dann mit dem Elko geglättet wird. Das Ausmaß der Spannungserhöhung kann per Software über das Duty-Verhältnis des PWM-Signals eingestellt werden. Zur Regelung wird der aktuelle Spannungswert am Ausgang über einen weiteren Spannungsteiler auf den ADC-Kanal 1 gegeben. Je nachdem, ob der Wert unter oder über der Zielgröße liegt, wird das Duty-Verhältnis des PWM-Signals angepasst. Diese Regelung klappt sehr gut und funktioniert mit minimaler Hardware. Allerdings geht sie recht langsam von statten, was für diese Anwendung kein Problem ist. Es geht schließlich nur darum, die Ausgangsspannung (und damit den LED-Strom) bei abfallender Akkuleistung nachzuregeln. Und das sind Veränderungen im Minuten- oder Stunden-Bereich.

Software

Die Software ist recht überschaubar und passt in eine kurze Datei: solar_led.c Das Programm ist um 3 verschiedene Systemzustände herum organisiert:

  • STATE_DAY ist der Betrieb am Tag. Der Akku wird geladen und die LED ist ausgeschaltet.
  • STATE_NIGHT ist der Status nach Einbruch der Dämmerung. Wenn die Spannung an der Solarzelle unter einen Grenzwert absinkt, wird die LED eingeschaltet.
  • STATE_BAT_LOW nach Absinken der Akku-Spannung unter 3.0V, und STATE_TIME_OUT nach Ablauf der geplanten Leuchtdauer sind eigentlich zwei verschiedene Zustände, die aber identische Eigenschaften haben. In beiden Fällen ist die LED ausgeschaltet. Das System wartet auf den nächsten Morgen.
System-Zustände und ihre Übergänge
System-Zustände und ihre Übergänge

Zur Verwaltung der Zustände wird ein regelmäßiger Timer-Interrupt verwendet, der die CPU einmal pro Sekunde aus dem Sleep-Modus weckt. Hier verwende ich den Watchdog-Timer, der im Gegensatz zu den anderen Timern den Vorteil eines sehr geringen Strombedarfs hat. Außerdem erlaubt er die Verwendung des „PWR_DOWN“ Sleep-Mode, was den Chip auf minimalen Stromverbrauch trimmt. Die Schaltung verbraucht bei abgeschalteter LED weniger als 30 µA, was hauptsächlich dem Spannungsteiler geschuldete ist. Der Watchdog-Timer hat den Nachteil geringerer Frequenzstabilität. Bei dieser Anwendung kommt es aber nicht auf exaktes Timing an.

Für den Step-Up Wandler produziert der ATtiny ein PWM-Signal, dessen Duty-Verhältnis über OCR0A eingestellt wird. Der Wert 255 entspricht dem kleinsten Duty-Cycle. Kleinere OCR0A-Werte erhöhen den Duty-Cycle und damit die Ausgangsspannung. Die Routine zur Regelung wird einmal pro Sekunde aufgerufen und ist sehr minimalistisch. Mit jedem Durchlauf wird OCR0A um den Wert 1 erhöht oder vermindert. Wie schon erwähnt ergibt das eine sehr langsame Regelung. Natürlich könnte man einen effizienteren Regelalgorithmus implementieren, aber für diese Anwendung ist die Langsamkeit eine sehr sympathische Eigenschaft. Aus einer nostalgischen Perspektive ist es schön zu sehen, dass die Lampe nach dem Einschalten 30 oder 40 Sekunden benötigt, um volle Helligkeit zu erreichen, ganz wie die alten Natriumdampflampen in früheren Straßenlaternen …

Die Konstante TIME_OUT definiert die Brenndauer der LED in Sekunden. Im Programm-Listing ist der Wert von 14400 vorgegeben, was 4 Stunden entspricht. Hier sind natürlich beliebige andere Werte möglich.

Das Programm verwendet eine Umschaltverzögerung von 1 Minute. Ohne diese Verzögerung besteht die Gefahr, dass in der Nacht eine kurzzeitige Beleuchtung der Solarzelle (z.B. ein vorbeifahrendes Auto) den Prozess neu startet. Die Dauer der Verzögerung kann über die Konstante SWITCH_DELAY eingestellt werden.

Der ATtiny arbeitet in dieser Anwendung mit dem internen 8MHz Taktgenerator. Dazu muss die CKDIV8-Fuse gelöscht werden. Alle anderen Fuse-Einstellungen bleiben unverändert.

Praktisches

Mit etwas Geduld und einer ruhigen Hand kann man die Schaltung auf einem recht kleinen Stück doppelseitiger Lochraster-Platine aufbauen. Das folgende Bild zeigt ein mögliches Layout.

Layout auf einer doppelseitigen Lochrasterplatine.
Layout auf einer doppelseitigen Lochrasterplatine. Schwarze Linien zeigen Verbindungen auf der Unterseite, und roten Linien Drahtbrücken auf der Oberseite. Die Speicherdrossel L wird senkrecht gestellt. Die Anschlüsse für Akku, Solar-Panel und LED werden mit flexiblen Kabeln herausgeführt.

Die FETs sind kleine SMD-Bauteile, die aber mit dem Lötkolben noch einigermaßen handhabbar sind. Es hat sich bewährt, sie ziemlich am Anfang der Lötarbeiten einzubauen. Dafür lasse ich kurze versilberte Kupferdrähte auf der Oberseite der Platine passend herausstehen, auf die die FETs dann aufgelötet werden. Dasselbe gilt für die SMD-Speicherdrossel, die aber erfreulicherweise wesentlich grösser ist.

Montage der SMD FETs. Oben: Zuerst schauen kurze versilberte Kupferdrähte aus der Oberseite der Platine (oben links), auf denen die Transistoren dann Platz finden (oben Mitte). Entsprechend wird auch die SMD-Speicherdrossel eingebaut (oben rechts). Unten: Fertig bestückte Platine mit Anschlussdrähten

Vor dem Einbau in das Gehäuse muss der gewünschte LED-Strom über den Trimmer eingestellt werden. Den LED-Strom kann man sehr einfach als Spannung am 10 Ohm-Vorwiderstand der LED messen. Nach dem Anschluss eines nicht ganz voll geladenen Akkus, jetzt noch ohne Solarzelle, sollte die LED kurz aufleuchten als Funktionskontrolle und dann erst einmal dunkel bleiben. Jetzt heißt es Warten auf den verzögerten Zustandswechsel. Nach 1 Minute schaltet sich die LED ein. Damit beginnt die Regelung der Ausgangsspannung. Im Sekunden-Rhythmus steigt der LED-Strom an, um dann bei einem Maximalwert zu verharren. Am Trimmer lässt sich dieser Wert einstellen. Sinnvolle Werte liegen zwischen 0.7 und 1.0 V (entspricht 70 bis 100 mA). Allerdings braucht der Einstellvorgang etwas Geduld, da die Software auf jede Änderung in kleinen Schritten reagiert.

Das Gehäuse besteht aus der um etwa 45 Grad schräg gestellten Solarzelle und Plastikteilen für Boden, Seiten und Rückwand, die aus einer Kunststoffplatte aus dem Bastelbedarf zugeschnitten werden. Kleine Holzleisten dienen zur Stabilisierung. Die Teile werden mit 5-Minuten Epoxy verklebt, was auch zur Dichtung gegen Spritzwasser dient. Die Solar-LED ist für den längerfristigen Einsatz im Garten gedacht. Zum weiteren Schutz vor Regen werden Elektronik und Akku in Schrumpfschlauch untergebracht. Der Einbau sollte aber nicht komplett luftdicht sein, um Kondenswasser zu vermeiden. Zum Schluss wird die Rückwand aufgeschraubt.

Links: Gehäuse-Teil für die Elektronik
Rechts: Blick in das Gehäuse mit geöffneter Solarzelle

Dem Einsatz im Garten steht jetzt nichts mehr im Wege. Es ist erstaunlich, wieviel Licht diese kleine LED produziert. Das Schöne an solar-getriebenen Leuchten ist, dass sie (hoffentlich) täglich und klaglos ohne weitere Zutun ihren Dienst leisten.

Solar LED im Garten
Solar LED im Garten

Ressource: Der Schaltplan, das Lochraster-Layout und die aktuelle Firmware (Atmel Studio 7) sind auf der Ressourcen-Seite verfügbar zum Download

Universelles I2C-Interface für Graphik-LC Displays

Viele Mikrocontroller-Systeme verwenden kleine LC-Displays für die Anzeige von Systemzuständen, Daten, Ereignissen, und vieles anderes. Monochrome Text-Displays basierend auf dem HD44780-Controller haben sich als weit verbreiteter Standard etabliert. Sie sind preisgünstig, in verschiedenen Größen und Farben zu bekommen, sind zurückhaltend im Stromhunger und lassen sich einfach an die meisten Mikrocontroller-Systeme anschließen. Oft kommt aber der Wunsch nach mehr Funktionalität. Für viele Anwendungen sind Graphiken wie z.B. Balkendiagramme, Pegelanzeigen, Kurvenverläufe usw. viel besser geeignet als Text. Solche Diagramme helfen dem Auge, die Daten intuitive zu erfassen.

Der Einsatz von graphischen Displays stellt aber insbesondere kleine Systeme mit beschränkten Ressourcen vor erhebliche Probleme. Hier beschreibe ich ein universelles Interface, das die Anwendung der weit verbreiteten KS0108-Displays sehr einfach macht und das Host-System soweit wie möglich entlastet. Das Interface bietet eine Reihe von Graphik-Funktionen an, die über das universelle I2C-Interface aufgerufen werden. So lassen sich KS0108-Displays durch beliebige Systeme vom 8-Bit Mikrocontroller bis zum Raspberry Pi ohne zusätzliche Treiber ansteuern.

Vielseitige Anwendungen des I2C-Interfaces für graphische Displays
Das Smart I2C Graphik-LCD im Einsatz:
Anzeige eines Mikrocontroller-gesteuerten SDRs (links)
Log-Daten eines Gewitter-Monitors (rechts)

Ausgangspunkt

Auf der Suche nach einem Display, das im einfachen Handling den HD44780-Typen entspricht, jedoch auch graphische Qualitäten hat, bin ich auf die (schon etwas ältere) Familie der KS0108-Controller gestoßen. Schon seit geraumer Zeit gibt es eine Vielzahl von solchen graphischen LCDs in verschiedenen Größen und Farben, meistens mit Auflösungen von 64 * 128 oder 64 * 192 Pixeln. Auch wenn diese eher geringe Auflösung nicht unbedingt auf der Höhe der Zeit ist, so erlauben diese Displays doch genau die Art der Diagramme, die ich bei verschiedenen Projekten einsetzen wollte. Außerdem sind diese Displays sind sehr preisgünstig zu bekommen und sparsam im Stromverbrauch.

Die nähere Beschäftigung mit den Graphik-LCDs zeigte jedoch, dass die Ansteuerung deutlich anspruchsvoller ist als für die bewährten Text LCDs. Der Datentransfer zwischen Host-System und Display ist naturgemäß intensiver und benötigt einen 8-Bit parallelen Port zuzüglich einer Reihe von Steuerleitungen. Damit sind die verfügbaren Ports am Mikrocontroller schnell vergeben. Die mitgebrachte Funktionalität der KS0108-Systeme ist sehr beschränkt und erlaubt nur das byte-weise Setzen oder Löschen von Pixeln. Das Zeichnen von Linien, Kreisen oder Texten benötigt allerlei logische Operationen mit dem Display-Memory, wobei das notwendige Timing exakt eingehalten werden muss. Es gibt zwar gute Bibliotheken für die meisten Zielsysteme (z.B. Referenz 1, 2). Trotzdem ist der Aufwand für das Host-System beträchtlich, da ein großer Teil der Ports, Timer, des Programmspeichers und der Rechenpower durch die Ansteuerung des Graphik-LCD ausgelastet sind. Die verbleibenden Ressourcen für die eigentliche Aufgabe des Host-Systems sind beschränkt.

So entwickelte sich die Idee, einen dedizierten Treiber mit Hard- und Software zu konstruieren, der auf der einen Seite die Komplexität der Graphik-Ansteuerung vollständig übernimmt und auf der anderen Seite dem Host-System ein serielles Interface anbietet, das Graphik-Anweisungen entgegennimmt. Das Smart I2C Graphic LCD Interface war entstanden.

Interfaces

Im Zentrum des Graphik-LCD-Interfaces befindet sich ein ATmega328, der dediziert für die Arbeit mit dem Display abgestellt ist. Der ATmega versorgt die Daten- und Steuerleitungen des Displays. Auf der Eingabe-Seite kommuniziert er mit dem Host System als I2C-Slave. Die Wahl fiel auf die I2C-Schnittstelle, weil die meisten Mikrocontroller-Systeme dieses Protokoll bereits verwenden, um mit Sensoren, Speicherbausteinen oder anderen Komponenten in Verbindung zu treten. Es sollte also relativ einfach sein, das I2C GLCD in ein bestehendes System einzufügen. Hilfreich ist auch die Tatsache, dass die I2C-Adresse über ein entsprechendes Kommando im verfügbaren Adressraum frei gewählt werden kann. Es ist sogar möglich, mehrere Displays an einem Host-System zu betreiben.

Da das I2C-Protokoll ist Plattform-unabhängig ist, arbeitet das Graphik-Display gleichermaßen gut mit AVR, Arduino, STM32 oder dem Raspberry PI zusammen. Der ATmega wird mit 3.3V versorgt, ist aber 5V-tolerant, so dass keine Pegelwandler benötigt werden. Die hier gezeigte Implementierung funktioniert sehr gut mit I2C-Taktgeschwindigkeiten zwischen 100 und 400kHz (Standard-mode und Fast-mode).

Das I2C-Interface nimmt Instruktionen byte-weise entgegen. Das Format ist für alle Instruktionen gleich: Zuerst wird ein Instruktions-Code gesendet, z.B. für das Zeichnen einer Linie oder der Ausgabe eines Textes, gefolgt von verschiedenen Paramater, z.B. Start- und End-Koordinaten der Linie oder die Zeichen des Text-Strings. Im Laufe der Entwicklung des Interfaces hat sich die Liste der verfügbaren Instruktionen stetig entwickelt und ist recht umfangreich geworden. Sie beinhaltet das Zeichnen von durchgezogenen oder gepunkteten Linien, gefüllten oder offenen Kreisen oder Rechtecken, die Ausgabe von Texten in verschiedenen Schrifttypen, und mehr.

Instruktions-Beispiel für das Zeichnen einer Linie
Beispiel für die Anweisung zum Zeichnen einer Linie: 6 Bytes werden gebraucht, um die Linie zu definieren.

Das Dokument Smart I2C GLCD Instruction Set zeigt eine tabellarische Aufstellung aller verfügbaren Instruktionen. Neben Funktionen zum Zeichnen und Löschen von graphischen Elementen gibt es auch Funktionen zur Ausgabe von Zeichen und Texten.

Verfügbare Zeichensätze
Verfügbare Zeichensätze: 7 Fonts sind bereits enthalten

“Rundum sorglos Paket”

Eine Besonderheit ist der interne Datenpuffer, der das Host-System von jeder Sorge bezüglich Timing befreit. Der ATmega ist so programmiert, dass die Anforderungen vom Host über das I2C-Interface einen Interrupt triggern. In der Interrupt-Routine werden die Daten entgegengenommen und in einem Ringpuffer abgelegt. Das Hauptprogramm arbeitet den Puffer sukzessive ab. Die Tatsache, dass manche Anweisung (z.B. die Ausgabe eines längeren Strings) mehr Zeit benötigen als andere (z.B. das Setzen eines Pixels) ist aus Sicht des Host vollständig uninteressant. Solange der Puffer nicht voll ist – was in der Praxis praktisch nicht vorkommt – kann das Host-System die Graphik-Instruktionen zu jeder Zeit absetzten und braucht sich nicht darum zu kümmern, ob das Display bereit ist zur Eingabe oder nicht. Dieses „rundum sorglos Paket“ vereinfacht die Arbeit mit dem Display enorm.

Ringpuffer mit Schreib- und Lesepointer.
Ringpuffer mit Schreib- und Lesepointer. Die I2C-Interrupt-Funktion fügt ankommende Bytes bei TWI_add_pointer hinzu. Die Funktion TWI_fetch_byte(), aufgerufen vom Instruktions-Interpreter, liest die Daten am TWI_fetch_pointer aus dem Puffer. Wenn Schreib- und Lesepointer auf dieselbe Position zeigen, dann ist der Puffer aktuelle leer.

Für Daten-intensive Anwendungen, bei denen ein Puffer-Overflow denkbar wäre, ist ein „Buffer Empty (B/E)“ Signal herausgeführt. Das Host-System kann den Status testen und gegebenenfalls warten, bis der Puffer leer ist. Bislang hat sich bei meinen Anwendungen dafür nur selten Bedarf ergeben.

Instruktions-Umfang

Das Display stellt eine lange Liste von Graphik-Funktionen bereit, z.B. das Setzen und Löschen von einzelnen Pixel, das Zeichnen von Linien, Rechtecken, gefüllten Flächen, Kreisen oder Segmente von Kreisen. Darüber hinaus gibt es die Möglichkeit der Textausgabe als einzelne Zeichen oder längere Strings. Die Textausgabe wird über einen Cursor gesteuert, der beliebig gesetzt werden kann. Es gibt die Möglichkeit automatischen Zeilenumbruch und Textscrollen zu setzen, sodass das Display auch für eine fließende Terminal-Ausgabe verwendet werden kann. Standardmäßig stehen 6 verschiedene Schriftsätze zur Verfügung.

Weiter gibt es Funktionen für die Ausgabe von Daten als Linien- oder Punkte-Diagramme. Diese Funktionen sind z.B. nützlich für die Visualisierung von zeitlichen Abläufen (z.B. Temperatur-Log) oder wissenschaftliche Daten.

Das I2C-Interface wird bi-direktional verwendet und bietet die Möglichkeit, Display-Parameter auszulesen. Zum Beispiel können die aktuelle Cursor-Position, die Länge von Strings in Pixeln oder die Höhe des angewählten Fonts abgefragt werden. Diese Funktionen sind nützlich, um die Grösse von weiteren graphische Elemente anzupassen. Das folgende Beispiel für den Arduino zeigt die Ausgabe eines Textes links oben im Display, gefolgt von der Abfrage der aktuelle Cursor-Position (der steht jetzt am Ende des Textes) und der aktuellen Höhe des Zeichensatzes. Mit diesen Daten wird dann eine Linie direkt unter den Text gezogen.

my_gd.set_font(4); 
my_gd.set_cursor(0, 0);
my_gd.draw_str("Smart I2C GLCD Demo with Arduino"); 
delay(40); // ensure display ist ready prior to read request
my_gd.get_cursor(&x_cur, &y_cur);
font_height = my_gd.get_font_height();
my_gd.draw_line(0, font_height + 1, x_cur - 1, font_height + 1, 1);

Allerdings gibt es beim Auslesen von Display-Parametern die Einschränkung, dass der Lese-Zugriff vom Host in Echtzeit stattfindet, also nicht gepuffert ist. Das Display muss die Daten aufbereiten, bevor der I2C-Read-Zugriff ausgeführt wird. Ansonsten kommen vorherige Werte aus dem Lese-Puffer über die Leitung. Deshalb empfiehlt es sich, entweder vor dem Ausführen der Abfrage einen Moment zu warten (40 msec wie im obigen Beispiel sind meist ausreichend) oder das Buffer/Empty-Signal abzufragen, bis der Puffer leer ist. Dann klappt es aber reibungslos.

Die vollständige  Liste der Instruktionen ist als PDF verfügbar. Smart I2C GLCD Instruction Set_v1-1 Weitere Funktionen werden nach Bedarf hinzu kommen. Input ist auf jeden Fall willkommen.

Weitere nützliche Funktionen

Wenn schon ein I2C-kommunizierender ATmega am Display vorhanden ist, kann er auch noch andere nützliche Aufgaben übernehmen, z.B. die Versorgung der Hintergrund-Beleuchtung des Displays. Dazu erzeugt der ATmega ein PWM-Signal, das über zwei Transistoren die Beleuchtung regelt. Die Helligkeit wird ebenfalls über eine I2C-Instruktion gesteuert. Werte zwischen 0 (aus) und 10 (maximale Leuchtstärke) sind einstellbar. Die Helligkeits-Werte werden mit Hilfe einer logarithmischen Tabelle in die entsprechenden PWM-Wert umgesetzt, so dass eine gleichmäßige Abstufung entsteht.

Schließlich ist das System so ausgelegt, das Schlüssel-Parameter wie die aktuelle I2C-Adresse und Beleuchtungseinstellung im eePROM abgelegt werden, so dass sie beim Power-On wieder hergestellt werden.

Die Hardware

Die Schaltung ist sehr einfach. Ein low-drop Spannungsregler mit zugehörigen Kondensatoren erzeugt 3.3V für den Controller. Das Display benötigt in jedem Fall 5V. Abgesehen vom ATmega gibt es noch zwei Transistoren, die das PWM-Signal für die Beleuchtung verstärken. Je nach Display-Typ können hier bis zu 150 mA fließen. Der maximale Strom wird durch den 22 Ohm Widerstand am BC636 begrenzt. Einige Displays haben bereits eingebaute Vorwiderstände für die LED-Beleuchtung. Gegebenenfalls muss der Widerstand angepasst werden oder kann komplett entfallen. Weiterhin gibt es auf der Platine die Möglichkeit, die I2C-Leitungen mit Pull-Up-Widerständen zu versorgen, hier 4.7 k Ohm, falls das noch nicht an anderer Stelle im System geschehen ist. In der Regel werden diese Widerstände nicht gebraucht.

Schaltplan des I2C GLCD Interfaces
Der Schaltplan des I2C GLCD Interface kommt mit wenigen Komponenten aus.

Der ATmega arbeitet mit seinem internen 8MHz R/C-Oszillator, so dass für die Takterzeugung keine weiteren Maßnahmen notwendig sind, abgesehen von dem Löschen des CLKDIV8-Flag in den Fuses.

Das Interface-Modul ist relativ sparsam. Der ATmega ist schon von sich aus moderat in Bezug auf den Strombedarf. Wenn es nichts zu tun gibt, wird er in den Sleep-Modus versetzt. Bei abgeschalteter Beleuchtung liegt der Eigenstrom-Bedarf unter 1mA.

Kleiner Form-Faktor

Der ATmega mit etwas Peripherie passt gut auf eine kleine Platine, die von hinten auf das Display aufgesteckt werden kann. Die ersten Prototypen wurden auf Lochraster-Platinen aufgebaut. Die Verbindung zum Display geschieht über einreihige 20-polige Stift- und Sockelleisten. Diese Leiste gibt dem Modul einen ausreichenden mechanischen Halt.

Prototyp auf einer Lochraster-Platine
Prototyp-Aufbau auf einer Lochraster-Platine. Die Sockelleiste zur Verbindung mit dem Display befindet sich auf der Rückseite.

Nachdem der Prototyp erfolgreich im Einsatz war, wuchs der Bedarf an Display-Interfaces, so dass sich die Entwicklung und Herstellung einer kleinen Platine lohnte. Die Sockelleiste kommt diese Mal auf die Bestückungsseite. Wenn man niedrige Bauteile für die Bestückung verwendet, verschwindet das komplette Interface-Modul unauffällig hinter dem Display.

GLCD I2C Interface Modul
GLCD I2C Interface Modul mit Anschlussleiste für das Display

Die Verbindung zum Host-System ist an der Seite als gewinkelte Pfoste-Leiste herausgeführt. Normalerweise werden nur 4 Leitungen benötigt: Masse und +5V zur Stromversorgung und SCL und SDA für den I2C-Bus. Außerdem, falls Bedarf besteht, steht dort das oben angesprochene B/E-Signal an einem Pin zur Verfügung.

Aufgestecktes Interface-Modul.
Das aufgesteckte Interface-Modul verschwindet unauffällig auf der Rückseite des Displays.

Das Board wurde für Display-Typ 3 entwickelt (siehe nächsten Absatz). Einen ZIP-Ordner mit den Gerber-Files zum Download gibt es auf der Ressourcen-Seite.

Layout und Bestückungsplan für das Interface-Board
Layout und Bestückungsplan für das Interface-Board

GLCD Typen

Im Laufe meiner Arbeiten sind mir (mindestens) drei verschiedene Typen von KS0108-Displays begegnet. Im Prinzip funktionieren sie alle ähnlich, unterscheiden sich aber in der Anzahl der KS0108 Chips, der daraus resultierenden Auflösung, der Anschluss-Belegung und der Logik für die Auswahl des jeweiligen KS0108-Chips. Die Tabelle zeigt die drei Display-Typen, wobei die Tabelle natürlich keinen Anspruch auf Vollständigkeit erhebt. Diese drei Typen sind in der Software vorgesehen. Der gewünschte Display-Typ muss vor der Compilierung in der Datei ks0108.h ausgewählt werden.

Eigenschaften und Pin-Belegung von 3 verschiedenen GLCD-Display-Typen. Tabelle der ATmega-Port-Belegung.
Links: Eigenschaften und Pin-Belegung von 3 verschiedenen GLCD-Display-Typen. Rechts: Tabelle der ATmega-Port-Belegung.

Die Displays haben mehrer KS0108-Panels an Board, wobei ein Panel für jeweils 64 * 64 Pixel zuständig ist. Entsprechend werden also 2 oder 3 Panels eingesetzt. Die Auswahl der Panels geschieht über die Display-Anschlüsse CS1 bis CS3. Display Typ 1 hat nur zwei Chips die mit CS1 und CS2 selektiert werden. Dabei ist “low” der aktive Zustand. Display Typ 3 funktioniert analog mit 3 Chips, also ein linkes, ein mittleres und ein rechtes Panel, und verwendet die Anschlüsse CS1 bis CS3. Display Typ 2 hat ebenfalls 3 Chips, selektiert diese aber mit nur zwei Leitungen CS1 und CS2. Wenn beide Leitungen “low” sind, dann ist das linke Panel angewählt. CS1 auf “low” wählt das mittlere, und CS2 auf “low” das rechte Panel.

In jedem Fall wird die Panel-Selektion von der Software des Interface-Moduls verwaltet – sofern der richtige Display-Typ gewählt wurde – und ist für den Anwender vollständig transparent.

GLCD Display-Typologie
GLCD Display-Typologie
Links Typ 1, 128×64 Pixel, 72 x 39 mm, Anschlussleiste unten
Mitte Typ 2, 192×64 Pixel, 84 x 31 mm, Anschlussleiste oben
Rechts Typ 3, 192×64 Pixel, 97 x 33 mm, Anschlussleiste unten

Software

Auch wenn die Hardware überschaubar ist, so ist die Software für dieses Projekt deutlich komplexer. Die Software wurde in C mit dem AtmelStudio(Version 7) entwickelt. Sie besteht aus den folgenden Modulen:

  • main.c enthält den System-Initialisierung und Instruktions-Interpreter.
  • GLCD_routines.c beinhaltet die höheren Graphik-Funktionen einschließlich Fehler- und Bereich-Checks. Diese Funktionen werden vom Instruktions-Interpreter aufgerufen.
  • ks0108.c beinhaltet die Hardware-nahen Graphik-Funktionen, die direkt mit dem KS0108-Chip zusammenarbeiten
  • twi_slave.c sorgt sich um das I2C-Interface und verwaltet den Ringpuffer mit den Funktionen zum Auslesen der Daten aus dem Ringpuffer.
  • smart_I2C_display.h enthält eine Liste der Instruktion-Codes.

Das Software-Paket hat (zur Zeit) insgesamt 7 Zeichensätze für die Ausgabe von Text, die in eigenen #include-Dateien abgelegt sind. Erweiterungen sind jederzeit möglich.

  • Font #0: system.h, 5×8 fixed space
  • Font #1: Font_3x5.h
  • Font #2: Font_4x8.h
  • Font #3: Arial_8.h
  • Font #4: Calibri_10.h
  • Font #5: Arial_12.h
  • Font #6: Arial_bold_14.h

Zum Teil wurden die Fonts mit einem Public Domain GLCDFontCreator erzeugt (Referenz).  Die Datenstruktur der Font-Files folgt einem üblichen Standard ist relativ einfach durchschaubar. Es ist durchaus möglich, einen weiteren Zeichensatz zu kreieren, z.B. für Anwendungs-spezifische Symbole, Pfeil, Sterne, usw. Der Programm-Speicher des ATmega biete noch eine Menge Platz für viel Kreativität.

Anwendungsbeispiel:
Smart I2C GLCD-Interface am Raspberry Pi

Das Smart I2C GLCD Interface macht die Anwendung der KS1018-Displays sehr einfach. Sofern das Host-System über ein I2C-Master-Interface verfügt, können die Instruktionen direkt zum Display gesendet werden. Und da der Raspberry Pi diese Schnittstelle aufweist, ist der Anschluss an das GPIO sehr einfach.

Anschluss des GLCD-Interfaces an den Raspberry Pi.
Das GLCD Interface-Modul wird über 4 Leitungen an das GPIO des Raspberry Pi angeschlossen.

Sobald die vier Leitungen angeschlossen sind, sollte sich das GLCD bei der Abfrage mit sudo i2cdetect -y 1 unter der gewählten I2C-Adresse melden.

Auf dem Raspberry Pi Command Prompt sollte sich das GLCD unter der aktuellen Adresse melden. Der i2cdetect-Befehl zeigt die Adressen im Hexadezimal-Format. 0x20 entspricht dezimal 32.

Der Python-Interpreter erlaubt das interaktive Ausprobieren der einzelnen Instruktionen und macht viel Spaß mit dem Display. Zuerst muss noch der SMBus gestartet werden, und dann kann es losgehen. Die Python-Funktionen write_byte(), write_word_data() und write_i2c_block_data() eignen sich, um das GLCD anzusprechen:

import smbus
s = smbus.SMBus(1)

# clear screen, instruction code 15
s.write_word_data(32, 15, 0)

# dim backlight to 70%, instruction code 3
s.write_word_data(32, 3, 7)

# draw line from 1/1 to 190/60, instruction code 17
s.write_i2c_block_data(32, 17, [1, 1, 190, 60, 1])

# draw circle, instruction code 25
s.write_i2c_block_data(32, 25, [100, 30, 20, 0xff, 1])

Da das Eintippen der Instruktionen auf die Dauer ermüdend ist, habe ich eine Python-Klasse angelegt, die die Anwendung vereinfacht (siehe glcd_module). Sobald die Datei mit der glcd-Klassendefinition im Suchpfad von Python verfügbar ist, genügen die beiden Anweisungen …

>>> import glcd_module
>>> gl = glcd_module.glcd(32)

… um eine Instanz des GLCD Modules zu eröffnen. Jetzt stehen alle Instruktionen zur Verfügung, z.B.:

>>> gl.clear_screen()
>>> gl.set_font(5)
>>> gl.set_cursor(96, 25)
>>> gl.draw_center_string("Hello World")

Das kleine Beispielprogramm glcd_demo zeigt einen wandernden Strich auf dem Bildschirm in der Art, wie man es vielleicht von früheren Bildschirmschonern kennt.

GLCD-Interface Modul am Raspberry Pi
GLCD-Interface Modul am Raspberry Pi

Weitere Anwendungen für das GLCD-Interface Modul an ATmega- und Arduino-Host-Systemen folgen in eigenen Beiträgen.

Downloads

Die Seite Ressourcen stellt umfangreiches Material bereit, einschließlich Source-Code im Atmel Studio, Beschreibung der verfügbaren Graphik-Funktionen, Board-Layout für den Display Typ3 3, Bibliotheken und Beispiele für Arduino und Python

Referenzen

  1. U8glib library:
    github.com/olikraus/u8glib/wiki/userreference
  2. ScienceProg: Controlling graphical 128×64 LCD based on KS0108:
    scienceprog.com/controlling-graphical-128×64-lcd-based-on-ks0108
  3. M. Thiele: KS0108 Library and Font Creator
    https://www.mikrocontroller.net/articles/KS0108_Library

Gewitter-Monitor mit graphischer Anzeige

Nach Auskunft der Meteorologen lässt der Klimawandel es häufiger blitzen. Mit jedem Grad globaler Erwärmung steigt die Zahl der Blitze. Dabei haben die gewaltigen elektrostatischen Entladungen mit den entfesselten Naturkräften nichts von ihrer Faszination verloren. Um so mehr ein Grund, sich als Hobby-Elektroniker mit diesem Thema zu beschäftigen.

So habe ich mit viel Interesse die Diskussionen und Entwicklungen im Internet verfolgt. Z.B. ist der Franzis-Bausatz „Gewitterwarner“ ist ein schönes Gerät mit allerlei genialen Ideen, zum Beispiel, den AM-Empfänger TA7642 zum Empfang zu verwenden, die Empfindlichkeit durch die Betriebsspannung einzustellen, und die Blitze durch einen Flankendetektor im Mikrocontroller zu erfassen. Super!
Für meine eigenen Versuche wollte ich einen Schritt weiter gehen und den Analog-Digital-Konverter (ADC) des Mikrocontrollers dazu verwenden, Blitze mit hoher Empfindlichkeit über weite Entfernungen zu erfassen und quantitativ auszuwerten. Außerdem wollte ich den Verlauf der Intensität und Häufigkeit der Blitze über die Zeit aufzuzeichnen. Herausgekommen ist mein „Gewitter-Monitor“, den ich hier beschreibe.

Vorüberlegungen

Die Idee war, ein Gerät zu entwickeln, das elektrostatische Aktivitäten in der Atmosphäre beobachtet und Auskunft über die Häufigkeit und Stärke von Blitzen gibt. Mir ging es dabei um große Reichweite, so dass Gewitter lange vor dem Erscheinen von Blitz und Donner am Ort erkannt werden. Außerdem wollte ich den Verlauf aufzeichnen, zum Beispiel um zu sehen, ob die Blitz-Aktivitäten zu- oder abnehmen.

Das Design ist einfach: Die elektromagnetischen Impulse von Blitzen werden mit dem AM-Radio-Chip TA7642 empfangen, verstärkt und mit dem ADC eines ATmega ausgewertet. Der ADC erfasst für jeden registrierten Blitz den maximalen Pegel. Der Mikrocontroller summiert die Maxima und berechnet die Summe pro Minute. Ein graphisches LC-Display (GLCD) zeigt den Verlauf, und mit einer Leuchtdiode wird ein Warnlevel angezeigt.

Die Schaltung

Das Gerät besteht aus zwei Komponenten, dem Analogteil um den AM-Empfänger 7642, und dem Digitalteil basierend auf einem ATmega16.

Analogteil: Das Signal der Blitze erreicht die Schaltung über die Antennen. Ich habe die Eingangsschaltung vom Franzis-Gewitterwarner mit dem AM-Empfänger TA7642 und nachgeschaltetem Transistor weitgehend übernommen. Allerdings wollte ich die Empfangsfrequenz so tief wie möglich legen, um näher an das Frequenzmaximum von Gewitterblitzen zu kommen. Der Antennenschwingkreis besteht aus einer Spule von 10 cm Länge auf einem Ferritstab, 0.3 mm Kupferdraht, und zwei parallel-geschalteten 470 pF Kondensatoren. Die Resonanzfrequenz liegt ungefähr bei 100 kHz. Das ist so ziemlich am unteren Rand des Frequenzbereiches, den der TA7642 noch sinnvoll verstärkt (siehe „Frequenzgang des TA7642“, Elektronik-Labor). Aber es reicht noch aus für gute Empfindlichkeit.

Ferritantennen haben eine Richtwirkung. Deshalb kommen zwei Analog-Teile mit jeweils einer eigenen Antenne zum Einsatz. Die Antennen sind rechtwinklig zu einander und horizontal montiert sind. Die horizontale Anordnung bewirkt, dass die häufigeren Wolke-zu-Wolke Blitze erfasst werden. Die bereits zitierten Meteorologen sagen, dass im Durchschnitt 60% der Blitze zwischen den Wolken stattfinden, also horizontal orientiert sind, während die verbleibenden 40% zwischen Wolke und Erde verlaufen. Der eine Ferritstab hat seine höchste Empfindlichkeit in Nord-Süd-Richtung, der andere in Ost-West-Richtung. Die Richtungsinformation, die sich daraus ergibt, lässt sich allerdings kaum verwerten, da die Maxima der Ferritantennen sehr breit sind. Das Digital-Teil berechnet die Summe über beide Kanäle.

Antennen des Gewitter-Monitors
Antennen über Kreuz: Hier werden alle Himmelsrichtungen erfasst. Die Ferritstäbe sind zusammen mit den TA7642 auf eigenen Platinen montiert. Betriebsspannung und Ausgangssignale werden über ein kurzes Flachbandkabel an das Gerät angekoppelt.

Die Spannungsversorgung der beiden TA7642 stellt gleichzeitig die Empfangsempfindlichkeit ein. Ich verwende eine Konstantspannungsquelle mit einer Bandgap-Referenz TL431, die als einstellbare Zenerdiode fungiert. Mit einem Trimmer lässt sich die Spannung und damit die grundsätzliche Empfindlichkeit der Antennen einstellen. Ich habe mit Spannungswerten zwischen 1.5 und 1.6 Volt am 1 kOhm-Widerstand vor dem Empfänger-IC (siehe Schaltung) die besten Erfahrungen gesammelt.

Blitze sind seltene und sehr kurze Ereignisse. Um sie zuverlässig mit dem ADC zu erfassen, müsste man den ADC mit einer hohen Abtastfrequenz betreiben. Ich habe mich für einen anderen Weg entschieden und mit Hilfe des Operationsverstärkers MCP601 einen Maximalwerte-Speicher dazwischen geschaltet. Solche Peak-Detection-Schaltungen waren früher bei Audio-Aussteuerungsanzeigen, z.B. LED-Balken-Anzeigen, verbreitet. Der Ausgang des OpAmp lädt über eine Diode eine RC-Kombination (22 nF und 1 MOhm), die sich dann entsprechend ihrer Zeitkonstante wieder entlädt. Der Spannungswert steht damit ausreichend lange am ADC-Eingang zur Verfügung, so dass eine gemächliche ADC-Abtastrate von 250 Hz pro Kanal gut funktioniert. Da beide Antennen im Wechsel abgefragt werden, läuft der ADC mit 500 Hz, wobei er ständig zwischen den beiden Eingängen hin und her schaltet. Dieses Tempo ist gut verträgliches für einen ATmega ist. Bild 3 zeigt ein Oszilloskop-Bild am Eingang und Ausgang der Peak-Detection Schaltung.

Messung am Peak-Detektor
Messung am Peak-Detektor: Kanal 1 (blau) zeigt das Eingangssignal am OpAmp mit zwei kurzen Blitz-Impulsen. Kanal 2 (gelb) zeigt das langsam abfallende Ausgangssignal. In jedes 10 mS Intervall fallen im Schnitt 2.5 ADC-Wandlungen pro Kanal.

Schließlich enthält der Analogteil noch einen kleinen Audioverstärker, den man als akustischen Monitor zuschalten kann. Das ist zum Beispiel sehr nützlich, um einen geeigneten Aufstellungsort mit geringen Störsignalen zu finden.

Schaltung des Analogteils
Schaltung des Analogteils

Digitalteil: Der Digitalteil ist um den bewährten Atmega168 herum aufgebaut. Der Mikrocontroller wird mit einem 8 MHz-Quarz getaktet. Für den Betrieb der graphischen Anzeige ist eine ganze Menge Festkomma-Arithmetik notwendig, die zum Teil zeitkritisch ist. Deshalb ist die Taktrate von 8 MHz durchaus angemessen.

Die Ausgangsspannungen vom Analogteil erreichen den Mikrocontroller an den Eingängen ADC0 und ADC1. Der ADC wird so konfiguriert, dass er die interne Spannungsreferenz von 1.1V verwendet. Dieser Spannungslevel passt sehr gut zu den Ausgängen der OpAmps und kann ohne weitere Anpassung direkt verwendet werden.

Zwei weiße Leuchtdioden an Port C4 und C5 blinken kurz auf, wenn ein Blitz registriert wird. Die Software verwendet zwei Warnstufen, die durch die Blitzaktivitäten pro Minute ausgelöst werden. In der ersten Warnstufe schaltet Port C2 über einen PNP-Transistor die Hintergrund-Beleuchtung ein. Die Idee ist, dass das Gerät im Alltag ständig läuft und beim Aufziehen von Gewittern selbstständig das Display hell schaltet. Dann weiß man, dass etwas im Busche ist. Wenn die zweite Warnstufe erreicht ist, wird zusätzlich die rote Leuchtdiode an Port C3 aktiviert. Jetzt ist ein Gewitter sehr nah oder vielleicht auch schon direkt am Ort. Für neugierige Zeitgenossen – wie ich einer bin – gibt es eine Taste an Port B0, der die Hintergrund­beleuchtung manuell für 30 Sekunden aktiviert. Dann kann man registrierten Blitzaktivitäten sehen, auch wenn noch keine Warnstufe erreicht wurde.

Schaltung des Digitalteils
Schaltung des Digitalteils

Graphik-Display: Das graphische LC-Display von Sitronix war ein günstiger Kauf im Internet und lag schon eine ganze Weile auf meinem Arbeitstisch in Erwartung von interessanten Aufgaben. Seit einiger Zeit werden diese Displays mit einer Auflösung von 128 x 64 Pixeln für wenig Geld angeboten. Für mich war es das erste Projekt mit diesem Displaytyp, und es geht erstaunlich einfach. Der Display-Controller ST7920 hat die angenehme Eigenschaft, ein paralleles und ein serielles Interface mitzubringen (siehe GLCD Datenblatt). Wenn der Anschluss PSB auf Masse liegt, wird das Interface auf serielles SPI geschaltet. Dann sind nur 3 Leitungen zur Signalübertragung erforderlich. Zusammen mit den Stromversorgungen für Display und Hintergrundbeleuchtung kann man das Display mit nur 6 Leitungen am Mikrocontroller betreiben. Einfacher geht es nicht!

Die andere nützliche Eigenschaft des Displays ist, dass es dazu eine fix- und fertige Software-Bibliothek in C gibt, u8glib, die eine umfangreiche Sammlung von Treibern und Graphik-Primitiven anbietet (siehe U8glib). In meinem Programm kommen die Funktionen DrawPixel, DrawLine, und DrawString zum Einsatz. Tatsächlich funktionierte alles auf Anhieb. Ein Dank an die Macher dieser vielseitigen Bibliothek!

Graphik-Display mit SPI-Interface
Das Graphik-Display mit SPI-Interface benötigt nur 6 Leitungen zum Controller.

Die Software wurde in C entwickelt und wird direkt mit einem AVR-Programmer in den Flash-Speicher des Mikrocontroller geschrieben. Kernstück des Programms ist der regelmäßige Timer-Interrupt, der die Interrupt-Routine mit einer Frequenz von 500 Hz abarbeitet. Dort werden abwechselnd die beiden Antennensignale über die ADC-Kanäle eingelesen. Ein einfacher Software-Flankendetektor sucht nach Sprüngen zwischen zwei Werten, die einen Grenzwert (hier 150) übersteigen. Wenn ein solcher Sprung gefunden ist, sucht die Routine das Maximum des Blitzes und meldet an das Hauptprogramm, dass es etwas zu tun gibt. Das Hauptprogramm zeigt den gefundenen Maximalwert im Display auf der rechten Seite an. Außerdem berechnet es die Summe der Maxima pro Minute und produziert die Balkengraphik mit einer senkrechten Pixelreihe pro Minute. Das Display bietet Platz für die Aufzeichnung von 100 Minuten, wobei die alten Werte im Minutenrhythmus nach links geschoben werden. Schließlich wir einmal pro Minute eine lineare Regression der letzten 30 Minuten berechnet. Die resultierende Steigung wird unten rechts im Display angezeigt und ist eine Trendanalyse, ein Maß, ob der Pegel der Blitze in den letzten 30 Minuten angestiegen (= positive Werte) oder abgefallen (= negative Werte) ist. Allerdings ist der praktische Nutzen dieser Trendanalyse noch nicht recht überzeugend. Da gibt es noch Raum für Experimente.

Die Skalierung muss noch erklärt werden: Der ADC liefert Blitz-Maxima mit Werten zwischen 150 und 1024. Diese Werte werden auf 15 bis 100 skaliert. Der Wert 100 heißt also, dass ein Blitz den ADC maximal ausgesteuert hat. Die Werte werden pro Minute summiert. Eine Minuten-Summe von 500 zum Beispiel bedeutet, dass 5 maximal-starke Blitze registriert wurden, oder entsprechend eine größere Zahl schwächerer Blitze . Die Skala der Y-Achse reicht im Normalfall 0 bis 600 mit Markierungen in 100er-Schritten.

Wie beschrieben gibt es zwei Warnstufen: Wenn eine Minutensumme von 250 oder mehr erreicht wird, schaltet sich das Display automatisch ein. In der Regel ist dann von einem Gewitter noch lange nichts zu sehen oder zu hören. Die Signale kommen (noch) aus großer Entfernung. Wenn die Minutensumme 500 übersteigt, dann wird zusätzlich die rote Leuchtdiode aktiviert. Außerdem wird die Skala der Graphik auf einen Bereich von 0 bis 1200 umgeschaltet. Bei diesen Pegelwerten ist das Gewitter schon näher, zum Beispiel mit Wetterleuchten in der Ferne. Die Warnstufen werden nach 5 Minuten wieder zurückgesetzt.

Zum Testen von Hard- und Software braucht man nicht auf das nächste Gewitter zu warten. Ich habe mir mit einer weitgehend verbrauchten 9-Volt Block-Batterie einen „Blitz-Generator“ gebaut. Zwei etwa 10 cm lange Drahtstücke an die Batterieklemmen gelötet verwandeln die Batterie. Wenn man die blanken Drahtenden kurz miteinander in Kontakt bringt und das in 10 oder 20 cm Entfernung von den Antennen macht, dann sollte dieses Minigewitter Signale auf der Anzeige produzieren.

Praktische Erfahrungen

Ich habe das Gerät jetzt seit zwei Monaten in Betrieb und beobachte natürlich gespannt die Wetteraktivitäten. Der erste Eindruck: Die Empfindlichkeit ist enorm, besonders bei Nacht, wenn langwellige Radiosignale eine weite Ausbreitung haben. Wir hatten einige Nächte mit heftigen Gewittern in Südfrankreich oder Italien, immerhin 600 km oder mehr von meinem Wohnort entfernt. Ich konnte die Gewitter­aktivitäten mit Signalpegeln von 200 oder 300 pro Minute gut beobachten. Im August und September gab es kaum eine Nacht ohne empfangene Gewittersignale. Erst im Oktober wurde es ruhiger und brachte dann auch Tage und Nächte ganz ohne Aktivitäten auf der Anzeige.

Der Durchzug eines Wetterwechsels kündigt sich fast immer mit Gewitteraktivitäten an, die schon von weiter Entfernung als Signale auf der Anzeige erscheinen. Wenn ein Gewitter näher kommt und wir zum Beispiel am Abend auf der Terrasse Wetterleuchten beobachten können, dann zeigt das Gerät Pegel von 500 und mehr pro Minute. Wenn Gewittergrollen zu hören und ein Gewitter in direkter Nähe ist, dann ist das Gerät vollständig aus- und zum Teil auch übersteuert. Es werden durchgängig Maximalwerte angezeigt. Die folgenden Bilder zeigen, wie die Anzeige funktioniert und einige Beispiele.

Display-Anzeige
Viel Information auf kleinem Raum: So sieht die Anzeige an einem gewittrigen Abend aus. Die Gewitterfront ist mehrere hundert km weit weg, kommt aber stetig näher.
Mehr Beispiele von gemessenen Gewitter-Aktivitäten
Im linken Bild ist eine Gewitterzelle in der Ferne vorbeigezogen, ohne wirklich näher zu kommen. Im rechten Bild hat sich innerhalb von 40 Minuten ein heftiges lokales Gewitter entwickelt. Die rote Leuchtdiode wurde gesetzt, und die Skala auf den größeren Bereich umgeschaltet.

Im Laufe der Zeit hat sich das Gerät als eine schöne Erweiterung zu den verbreiteten Wetterstationen etabliert und gibt bereitwillig Auskunft über die atmosphärischen Aktivitäten und die Wetterlage.

Referenzen

Downloads

Firmware des GewitterMonitors, programmiert im AtmelStudio:  GewitterMonitor-Firmware

 

 

 

 

FM Stereo Radio mit TDA7021

Von Zeit zu Zeit beschäftige ich mich mit nostalgischem Radiobasteln – zur Entspannung und einfach, weil es Freude macht. Oft ist der Weg von der ursprünglichen Idee bis zum fertigen Gerät länger als gedacht. Aber wenn ich mir die Zeit lasse, dann ist es immer ein vergnüglicher Weg, der viele neue Erkenntnisse bringt.

Nach verschiedenen Experimenten mit MW- und KW-Radios war es an der Zeit, mich an einem FM-Radio zu probieren, das den UKW-Bereich abdeckt. Von Philips gibt es eine Familie von Radio-Chips basierend auf dem TDA7000, die den Hochfrequenz-Aufbau sehr vereinfachen. Auch wenn dieses Chips inzwischen sehr in die Jahre gekommen sind, so bieten sie guten UKW-Empfang bei einfachem Aufbau. Und wenn ich schon dabei war, sollte es doch auch möglich sein, mit dem entsprechenden Stereo-Dekoder ein “richtig brauchbares” Stereo-Radio zu bauen.

Dieses Projekt wurde angeregt durch Diskussionen und Ideen vom Elektronik-Labor von B. Kainka. Die Beschreibung des FM Stereo Radios wurde dort auch veröffentlicht.

Zielsetzung

Es sollte also ein praxistauglicher FM-Stereo-Empfänger werden. Und er sollte offen sein für neugierige Einblicke: Wie schon bei anderen Projekten wollte ich die Elektronik in einem Plexiglas-Gehäuse als freie Verdrahtung unterbringen. Bei dieser Bauweise kommt keine Platine zum Einsatz. Statt dessen wird die Schaltung so aufgebaut, dass die Bauteile über ihre Anschlussdrähte und Lötösen auf der durchsichtigen Grundplatte Halt finden. Das ist nun eigentlich gar nicht für Hochfrequenz geeignet. Aber zum Glück machen die Philips-Bausteine die Sache einfach, da die ICs die hohen Frequenzen weitgehend intern verarbeiten. Das sollte auch mit einem Drahtverhau funktionieren.

Die Bedienung für Senderwahl und Lautstärke sollte über Drehknöpfe erfolgen, so wie früher, als Elektronik noch nicht über Tipptasten oder Touchscreens kontrolliert wurde. Auch eine Frequenzskala mit beweglicher Markierung via Skalenseil wurde in das Pflichtenheft mit aufgenommen. Und schließlich sollte noch eine Leuchtbandanzeige (in Anlehnung an ein „magisches Auge“) die Empfangsstärke anzeigen und bei der Abstimmung Unterstützung leisten.

Schaltplan

Für die Schaltung kam der Empfänger TDA7021 zum Einsatz. Dieser Chip hat keine automatische Senderabstimmung, ist deshalb besser geeignet für eine manuelle Abstimmung mit Drehknopf. Außerdem stellt er an Pin 9 die Empfangs-Feldstärke als Spannungswert bereit. Als Stereo-Dekoder kam ein TDA7040 dazu, der sehr gut mit dem 7021 harmoniert.

Die Chips waren gar nicht so einfach zu bekommen. Aber es gibt nichts, das es im Internet nicht gibt. Ich wurde bei einem Internet-Auktionshaus fündig, so dass schließlich für wenige Euro ein kleiner Umschlag aus Hongkong mit den Philips-Bausteinen in meinem Briefkasten landete. Das ging ja einfacher, als ich gedacht hatte.

Schaltplan des FM Stereo Radios
Schaltplan des FM Stereo Radios

Aber der Reihe nach. Die Schaltung wird über eine 9-Volt-Batterie versorgt, was gut für den NF-Verstärker aber deutlich zu viel für die TDA-Chips ist. Deshalb sorgt ein 78L03 für stabile 3 Volt auf der HF-Seite. Die Schaltung folgt fast vollständig der Anwendung, die im Philips-Datenblatt gezeigt ist. Der frequenzbestimmende Oszillatorkreis besteht aus einer Spule (Luftspule aus 4 Windungen, 5 mm Durchmesser, etwa 10 mm Länge) und einer Kapazitätsdiode 1SV101. Die Abstimmung erfolgt über ein lineares 47 k-Potentiometer. Mit dem Spannungsbereich von 0 bis 3 Volt lässt sich das UKW-Band sehr gut überstreichen. Die Widerstände links und rechts vom Abstimm-Poti begrenzen den Empfangsbereich auf das nutzbare Radioband. Als Antenne wird ein Drahtstück von 1 m Länge am Eingangskreise angeschlossen. Die Induktivität L3 in der Stromversorgung des TDA7021 ist übrigens in der Philips-Applikation nicht zu finden. Bei meinem Aufbau eliminierte sie Zwitschergeräusche, die andernfalls ab und zu zu hören waren.

Der Stereo-Dekoder übernimmt das MPX-Signal und liefert die Niederfrequenz an das Stereo-Poti zu Lautstärke-Einstellung.

Für die NF-Verstärkung konnte ich zwei LM386 zur Mitarbeit überreden, die sich in der Bastelkiste langweilten. Sie arbeiten hier mit niedriger Verstärkung und treiben zwei kleine Lautsprecher. Die Schaltung hat noch einige Elkos und 100 nF Blockkondensatoren zur Stabilisierung und Vermeidung von ungewollten Schwingungen.

Für die Feldstärke-Anzeige musste auch wieder die Bastelkiste herhalten. Die Messungen an Pin 9 des TDA7021 zeigten, dass ohne Sender etwa 2.7 Volt anlagen. Je stärker der Sender, desto geringer war die Spannung bis herunter auf minimal etwa 0.3 Volt. Das Signal hätte man mit Komparator, Inverter und LED-Treiber aufbereiten können. Ein Blick in meine Vorräte brachte mich aber auf eine andere Idee. Schon vor ein paar Wochen hatte ich einen Satz ATtiny44 bekommen, die auf eine Aufgabe warteten. Dieser AVR-Controller ist dem ATtiny13 sehr ähnlich, verfügt aber über wesentlich mehr Ausgänge. Das war ideal für meinen Zweck. Der ADC des Mikrocontrollers übernimmt den Spannungswert an PA7 und steuert die Leuchtdioden an PA0 bis PA6. Die Pegelanpassung wurde komplett per Software gemacht, was den Aufbau natürlich sehr vereinfachte. Die Anzahl von 7 LEDs erschien mir als guter Kompromiss zwischen Auflösung und Stromverbrauch. Tatsächlich arbeitetet die Anzeige mit einer Auflösung von 14 statt 7 Stufen. Bei allen ungeraden Werten wird die jeweils nächst höhere LED im Pulsweiten-Modus mit 25 % betrieben, was etwa die halbe Helligkeit ergibt. Dadurch erscheinen die Übergänge „weicher“, schon beinahe wie mit analoger Elektronik. Der Controller läuft mit dem internen 1 Mhz-Oszillator und hat nicht wirklich viel zu tun. Er darf deshalb den größten Teil der Zeit im Sleep-Modus entspannen.

Das Programm ist in C geschrieben und recht einfach. Die Details sind den Kommentaren im C-Programm zu entnehmen. Die Fuses am fabrikneuen Chip brauchen nicht verändert zu werden.

Experimente

Bevor ich mich an den Aufbau des Radios im Plexiglas-Gehäuse machen konnte, musste etwas Forschungsarbeit betrieben werden. Die erste Frage war: Wie bekomme ich SMD-Bausteine in eine frei-fliegende Verdrahtung? Ich habe einige Varianten probiert und bin dann mit der Montage auf einer IC-Fassung am Besten zurecht gekommen. Die SMD-Chips wurden mit einem kleine Stück Holz etwas erhöht auf die IC-Fassung geklebt und dann Pin für Pin verdrahtet. Ein spitzer Lötkolben, eine ruhige Hand (!) und eine kräftige Lesebrille machten es möglich. Die SMD-Chips mit 1,27 mm Pin-Abstand sind eigentlich recht gutmütig, und nach ein bisschen Übung geht das Löten zügig von der Hand. Die montierten ICs sind mechanisch sehr robust.

Montage des SMD-Chips auf einer IC-Fassung
Montage des SMD-Chips auf einer IC-Fassung

Der nächste Schritt war ein Probe-Aufbau auf einem Holzbrett. Ich hatte verschiedene Varianten der Anordnung ausprobiert, um Leitungslängen klein zu halten. Als Draht kam versilberter Kupferdraht mit 1 mm Durchmesser zum Einsatz, der einerseits gute, mechanische Stabilität bietet und andererseits hübsch anzuschauen ist. Die Schaltung war erstaunlich unproblematisch und robust.

Probe-Aufbau auf einem Holzbrett
Probe-Aufbau auf einem Holzbrett

Das dritte Experiment beschäftigte sich mit dem Skalentrieb. Das Seilrad am Abstimmpoti sollte einen Durchmesser von 5 cm Durchmesser bekommen. Das ergab bei einem nutzbaren Drehwinkel von 270 Grad eine Skalenlänge von etwa 11 cm. Dadurch waren dann auch die Gehäusemasse definierte. Aus Platzgründen wurde das Abstimmpoti um 90 Grad verdreht angeordnet. Das Seil ließ sich gut über Umlenkrollen führen. Als Gegenstück arbeitete ein kleines Seilrad mit 2 cm Durchmesser, das auf einer freien Achse (eine M6-Schraube) mit Drehknopf montiert war. Die Abstimmung hat also eine Untersetzung von 2 auf 5, ein guter Wert für feinfühligen Abstimmen. Das Seil kam übrigens von einer Nylon-Drachenschnur. Es wurde mit einer kleiner Feder gespannt.

Testaufbau des Skalen-Antriebs
Testaufbau des Skalen-Antriebs

Finaler Aufbau

Nachdem die Forschung erfolgreich abgeschlossen war, konnte es an den Zusammenbau gehen. Für das Gehäuse kamen Plexiglas und Aluminium zum Einsatz. Die Plexiglasplatten sind leider sehr empfindlich, wenn die Schutzfolie erst einmal entfernt ist. Deshalb hatte ich die Schaltung komplett auf einem Holzbrett aufgebaut und erst dann auf die fertig bearbeitete und gebohrte Plexiglasplatte transferiert. Die aufgebaute Schaltung war auch ohne Grundplatte einigermaßen stabil, so dass sie sich gut an ihren Arbeitsplatz transferieren ließ.

Die fertige Schaltung an ihrem Arbeitsplatz
Die fertige Schaltung an ihrem Arbeitsplatz

Der Abgleich war sehr einfach. Erster Punkt war das Auseinanderziehen oder Zusammendrücken der Oszillatorspule, bis der Frequenzbereich mit dem UKW-Band übereinstimmte. Das brauchte ein bisschen Geduld und Fingerspitzengefühl.

Zum Abgleich von P2 und P3 schweigt sich das Philips-Datenblatt leider aus. In der Praxis sind die Einstellungen aber unproblematisch. Das Radio läuft prima mit P2 und P3 ungefähr in Mittelstellung. Kollege Google hat ausführlichere Tipps, wenn ein Oszilloskop oder Frequenzzähler zur Verfügung stehen:

P3 ist für den PLL-Oszillator des Stereo-Dekoders zuständig. Zum Abgleich wird die Abstimmung in einen Bereich ohne Sender gedreht, so dass der Oszillator frei läuft. Jetzt den 100 nF-Kondensator an Pin 7 des TDA7040 lösen und Pin7 über einen 10 kOhm-Widerstand an die Spannungsversorgung (3 V) legen. Mit einem Oszilloskop oder Frequenzzähler die Frequenz des Oszillators abnehmen und möglichst exakt auf 19 kHz eingestellt. Damit hat der Oszillator die optimalen Voraussetzungen, auf das Pilot-Signal eines Senders einzurasten. Zum Schluss den Umbau rückgängig machen.

P2 an Pin 15 des TDA7021 wird so eingestellt, dass auch ein schwacher Sender mit deutlich erkennbarem Stereo-Sound übertragen wurde.

Zum Schluss kam noch, sozusagen als i-Tüpfelchen, die Frequenzskala. Um die Positionen der Frequenzen zu finden, habe ich mit Hilfe meines Reiseempfänger die Frequenzen des Oszillators am TDA7021 ermittelt. Das klappt prima, weil die Zwischenfrequenz mit 70 kHz quasi vernachlässigbar ist. Den Empfänger stellte ich mit eingeschobener Antenne direkt neben mein Radio. Die gesuchte Frequenz wurde am Reiseempfänger eingestellt, z.B. 90 MHz. Jetzt war der Oszillator beim Durchdrehen der Abstimmung einwandfrei im Reiseempfänger zu finden, so dass ich die 90 MHz-Position auf der Skala übernehmen konnte. Das wurde schrittweise für mehrere Frequenzen wiederholt, bis die Skala komplett war. Die Skala habe ich dann auf transparente Folie gedruckt und mit Tesafilm auf den durchsichtigen Skalenträger montiert. So, fertig.

Skala mit Zeiger
Skala mit Zeiger

Empfangspraxis

Und dann war es soweit: Das Radio konnte vorgeführt und ausprobiert werden. Die Empfindlichkeit hat mich von Anfang an überrascht. Der TDA7021 kommt auch mit schwachen Sender gut zurecht und ist sicherlich mit dem UKW-Band meines Reiseempfängers auf Augenhöhe. Beim Durchdrehen des Abstimmknopfes erscheinen die Sender dicht gepackt auf der Skala. Die LED-Anzeige ist flink und beim Abstimmen hilfreich. Es kommen schnell Assoziationen an Omas Röhrenradio mit Skala und magischem Auge. Auch die Klangqualität ist gut; und der Stereo-Effekt ist durch den relativ großen Abstand der beiden Lautsprecher im breiten Gehäuse schön zu hören. Der Empfang ist absolut klar, zumindest solange die Sender mit ausreichender Feldstärke hereinkommen. Wenn der Empfang schwächer ist (3 oder 4 LEDs), dann sind die Sender von ausgeprägtem Stereo-Rauschen begleitet. Aber das kann man der kleinen Schaltung nicht übel nehmen.

Detailansicht der frei-schwebenden Verdrahtung
Detailansicht der frei-schwebenden Verdrahtung

Das Radio steht nun schon seit ein paar Wochen in der Küche. Wir benutzen es oft und gerne und möchten es nicht mehr missen. Und das gut einsehbare Innenleben beschert interessante Einblicke, die auch oft Besucher in ihren Bann ziehen.

Eine Demonstration ist auf YouTube zu sehen.

C-Quellcode der Feldstärken-Anzeige: MagischesAuge

Schaltplan und Source-Code für das Magische Auge sind auch auf der Ressourcen-Seite abrufbar.