Donnerstag, 22 Januar, 2026

Alexloop ferngesteuert abstimmen

In den Ferien habe ich meist zwei Typen von Antennen dabei. Einmal eine FUCHS-Antenne mit 20m Draht sowie die AlexLoop, eine magnetische Loop-Antenne. Beide haben ihre Vor- und Nachteile. Der grösste Nachteil ist die schmale Bandbreite der Loop-Antenne. Bei jedem Frequenzwechsel muss neu eingestellt werden. Meist platziert man darum die Loop in nächster Nähe zum OM der mit QRP sendet. Falls wegen des Wetters man lieber drinnen bleibt braucht man aber etwas um draussen die Antenne abzustimmen.

Die Idee einer Fernsteuerung ging mir schon seit Monaten im Kopf herum.

Was es braucht:

    - Getriebemotor mit sehr langsamer Drehzahl (wirklich langsam)
    - Funkfernbedienung mit zwei oder mehr Kanälen
    - Elektronik zum Steuern des Motors
    - Mechanische Teile um den Einstellknopf der AlexLoop zu drehen

Nach einiger Suche habe ich die passenden Teile gefunden.

Getriebemotor: Conrad Bestell-Nr.: 1289388 Hst.-Teile-Nr.: G1000 | EAN: 4037373693313
Fernbedienung: https://hobby-elektronik.ch/Module-Sensoren/Funk-Netzwerk-RFID/433-Mhz-Fernbedienung-4-Kanal-Lernfaehig-mit-Empfaenger::705.html

Motorsteuerung: https://www.itead.cc/mboard.html / Dieses Teil hatte ich schon Jahre früher mal bestellt
Mechanische Teile: konstruiert auf Alibre 3D CAD und hergestellt mit einem Ultimaker 3D+ Drucker

Wie es funktioniert:

Das Hauptproblem war die Verbindung vom Getriebemotor zum Drehknopf der AlexLoop. Einfach den Knopf zu entfernen und direkt mit dem Motor zu verbinden wäre zwar einfach. Leider hat man keine Möglichkeit die Endpositionen des Drehkondensators der AlexLoop festzustellen. Der Motor hat ein 1000:1 Getriebe. Trotz des kleinen Motors treten auf der Abtriebsachse enorme Drehmomentkräfte auf, die Getriebe und Drehkondensator beschädigen könnten. Am einfachsten wäre eine Rutschkupplung.

Die Lösung:

Früher gab es Mopeds der Marke VéloSolex wo ein Reibrad das Vorderrad antrieb. Hier verwende ich einen Schleifkörper wie sie zum Beispiel von Dremel oder Proxxon erhältlich sind. Geht der Drehkondensator in eine Endstellung, dreht der Schleifkörper einfach durch und kann nichts beschädigen.

al1.jpg

Komplett montierte Teile an der AlexLoop. Der Klemmring zieht über die Gummis das Reibrad zum Knopf
pixel.png

al2.jpg

Bewegliche Teile mit Motor und Schleifkörperhalter
pixel.png

al3.jpg

Alle Teile zusammen
pixel.png

al4.jpg

Ein kleiner USB-Powerbank als Energielieferant
pixel.png

al5.jpg

Arduino kompatibles Board mit H-Brückenschaltung
pixel.png
Video

Steuerung:

Als Steuerung verwende ich ein MBOARD welches eine H-Brückenschaltung für den verwendeten Bürstenmotor enthält. Die Fernsteuerung hat vier Knöpfe welche die digitalen Ausgänge auf der Fernbedienung steuern. Beim Drücken der Knöpfe wird zusätzlich ein ‘received valid data’ Ausgang aktiviert, der von der Software ausgewertet wird. Zwei Knöpfe drehen den Motor mit voller Geschwindigkeit, die beiden anderen senden zuerst einen kleinen Impuls und lassen dann den Motor mit verringerter Geschwindigkeit drehen.

Selbstverständlich kann man jegliche Motorsteuerung verwenden. Das Hauptziel war jedoch, einen Antrieb mit einer sehr kleinen Drehzahl und zwei Geschwindigkeiten zu verwenden.

3D Teile

Downloads

3D Teile STL Dateien
Software

Modifikation: Magnetische Monoband Loop-Antenne für 15m

case_15m.png

Der Deckel schliesst den unteren Bereich der Haube und bildet so ein geschlossenes Segment, dass den Drehkondensator schützt.
Basiert auf 40m - 15m Magnetloop - mit Steuerung übers Koaxialkabel
pixel.png

kondensator.jpg

In dieser für das Monoband 15m ausgelegte Modell wird ein Kondensator mit einer variablen und einer festen Kapazität verwendet.
pixel.png

pcbs.jpg

Die Elektronik wurde ebenfalls angepasst und erhielt zusätzlichen Schutz vor HF-Einstrahlungen.
pixel.png

40m - 15m Magnetloop - mit Steuerung übers Koaxialkabel

mla-40-15m.jpg

Unter der Woche nutze ich ein QTH welches eher ländlich ist und trotzdem einen ungewöhnlich hohen Störpegel im KW-Bereich aufweist. Grund dafür scheint die oberirdische Versorgung umliegender Häuser mit Telefonie und Internet zu sein. Da ich mit magnetischen Loopantennen im Urlaub gute Erfahrungen gemacht habe, entstand der Wunsch eine solche für dieses QTH zu entwerfen und zu bauen.

Auslegung
Die Antenne soll hauptsächlich im 40m und 20m Band (evtl. 17-15m) eingesetzt werden und eine Sendeleistung von ca. 100 W bewältigen. Eine bedingte Wetterfestigkeit ist wünschenswert. Die Einstellung der Frequenz sowie die horizontale Aurichtung soll ohne separates Steuerkabel möglich sein. Die elektrische Versorgung der Steuerung und Antennenelektronik wird durch die bereits für den TRX bereitgestellte Spannung geleistet.
pixel.png

Loop berechnen

Mit den im Internet gefundenen Berechnungsprogrammen ergaben sich folgende Grössen;

    Loop-Durchmesser: ca. 1.3m (4m Umfang)
    Loop-Material: Rigid 12.5mm Koaxialkabel (wegen der mechanischen Stabilität)
    Drehkondensator: ca. 150pf / 4500V Spannungsfestigkeit
    Koppelschlaufe: 1/5 Loopdurchmesser, Draht oder Faraday-Schleife

Links

Magnet-Loop-Antennen-Rechner von DGØKW, Klaus
Small Transmitting Loop Antenna Calculator
Magnetic Loop Calculator

Mechanischer Aufbau

Das Antennengehäuse besteht aus mehreren Segmenten und ist komplett per CAD konstruiert und im 3D-Ducker entstanden. So lassen sich jederzeit einzelne Segmente neu gestalten.

Jetzt der Reihe nach (von oben nach unten, die 3D-Elemente sind nicht aus derselben Sicht dargestellt)

cover.png

Haube

Die Haube schützt den Drehkondensator und führt im Deckel das HF-Signal über eine BNC-Buchse nach aussen. Sie ist zweigeteilt um den 3D-Druck zu vereinfachen. Im Sockel sind 6-kant Distanzhalter eingeklebt in denen die 3mm Gewindestangen befestigt werden. Das Bild zeigt noch die erste Version des Deckels wo die Loopstützstange eingeklebt wird. In der neuen Version wird die Stange eingeschraubt um später andere Loops mit passenden Stangen montieren zu können.
pixel.png

looptop.png

Loopdeckel

Der Deckel schliesst den unteren Bereich der Haube und bildet so ein geschlossenes Segment, dass den Drehkondensator schützt.
pixel.png

loopbody.png

Looprahmen

Im Looprahmen sind die beiden Loopklemmen verschraubt. Der Loop wird hier mit zwei Klemmelementen mit dem Kondensator verbunden.
pixel.png

loopabnehmer.png

Loopabnehmer

Der Loop wird hier mit zwei Klemmelementen mit dem Kondensator verbunden. Das Anlöten der Leitungen an die Loop ist wegen des massiven Kupferschirms sehr schwierig. Klemmen haben ausserdem den immensen Vorteil, dass sie wieder problemlos gelöst werden können.
pixel.png

loopklemme.png
loopanschluss1.jpg
loopanschluss2.jpg

Loopklemme

Damit wird die Loop im Looprahmen festgeklemmt.
pixel.png

geartop.png

Getriebedeckel

Bildet den Abschluss vom Rotorgetriebe.
pixel.png

gearbody.png

Getrieberahmen

Der Rahmen, hier auf den Kopf dargestellt, enthält in der Mitte ein Kugellager das die Gewichtskräfte der Loop auf dem Mast trägt. Durch die Verwendung von Kugellager bleiben die nötigen Kräfte zum Drehen der Antenne gering.
pixel.png

gearassembly.png

Hauptzahnrad

Das Hauptzahnrad des Rotor ist mehrteilig ausgeführt. Es besteht aus dem Zahnrad selbst sowie zwei Adapterteilen. Das eine Adapterteil zentriert und stützt das Zahnrad im Kugellager, während das andere Adapterteil den Innensechskant für den Mastkoppler enthält. Diese drei Teile werden miteinander verklebt.
pixel.png

mastkoppler.png

Mastkoppler

Der Mastkoppler wird in das Mastrohr fest eingeklebt. Der überstehende Sechskant-Kopf greift in das grosse Zahnradadapterteil und dreht die Antenne wenn sich der Rotor-Motor bewegt.
pixel.png

rotorbasetop.png

Rotordeckel

Am Rotordeckel wird der Rotor-Motor befestigt. Die Montagelöcher sind so gestaltet, dass das Getriebespiel durch Drehen des Motors exakt eingestellt werden kann.
pixel.png

rotorbasebody.png

Rotorrahmen

Die Steuerelektronik und der Rotor-Motor finden hier ihren Platz. Im Zentrum die Durchführung für dem Mast.
pixel.png

rotorbase.png

Rotorboden

Er dient dazu den HF belasteten Boden nach oben abzuschirmen und das Mastrohr im Zentrum zu führen.
pixel.png

base.png

Boden

Im Boden ist die BIAS-Tee Elektronik und leitet die HF über SMA/RG-178 Koaxialkabel zum BNC-Stecker in der Haube. Die Gleichspannung wird durch den Rotorboden zur Antennenelektronik geleitet.
pixel.png

Variabler Kondensator (Drehkondensator)

Der variable Kondensator ist als drehbarer Plattenkondensator aufgebaut. Es handelt sich hier um einen sogenannten Split-Stator Kondensator. Variable Kondensatoren, über die viel Energie fliesst, benötigen einen besonderen mechanischen Aufbau. Normalerweise greifen zwei Stapel von Metallplatten berührungsfrei ineinander. Die eine ist mechanisch fest montiert, die andere wird gedreht um die überlappende Fläche zu variieren und damit die Kapazität zu ändern. Die sich drehende Fläche muss dann über einen Schleifer elektrisch angeschlossen werden. Aufgrund von höheren Übergangswiderständen und mechanisch schwierig zu lösenden Problemen bezüglich der Leistungsübertragung werden dafür schleiferlose Varianten verwendet. Dazu gehören der Schmetterlingskondensator und der Split-Stator Kondensator. Das Split-Stator Prinzip gleicht schematisch zwei seriell verbundenen Kondensatoren. Die Drehachse ist zugleich die Verbindung der zwei inneren Kondensatorenplatten. Die aussenliegenden Plattenpakete sind fest montiert und daher elektrisch einfach zu verdrahten.

Die Stator und Rotorplatten sowie Abstandsringe für dieses Projekt habe ich von der Firma Otto Schubert bezogen. Natürlich können diese Teile auch selbst gefertigt werden. Aber der Aufwand die Platten gratfrei und vollkommen eben herzustellen sind ohne entsprechende Geräte enorm. Bereits die vielen Abstandsringe geben viel Arbeit.

Der Kondensator besteht aus zwei Plattenpaaren mit jeweils 12 Stator- und Rotorplatten. Die beiden Rotorplatten sind wie oben beschrieben über die Drehachse elektrisch und mechanisch verbunden. Die kugelgelagerte Drehachse wird von einem Schrittmotor über ein Reduziergetriebe bewegt. Die Kugellager bestehen aus Nylon mit keramischen Kugeln.

Kondensator Details

Kopplerschlaufe

Die Kopplerschlaufe besteht in dieser ersten Version aus einer einfachen Drahtschleife mit ca. 2 mm2 Querschnitt. Dank des modularen Aufbaus sind andere Varianten einfach zu adaptieren. In Frage kommen sogenannte Faraday-Varianten, welche den Einfluss von lokalen e-Feldern minimieren helfen.

Kopplerschlaufe Details

3D-Druck

Was es braucht

Wie beim Schreiben und Produzieren von Software braucht es auch beim 3D-Druck eine sogenannte Toolchain. Bevor ein Teil gedruckt werden kann, muss es zuerst konstruiert werden. Wichtig ist, dass diese Software das 3D-Teil im Format STL abspeichern kann. Das nächste Programm in der Kette ist der Slicer. Er berechnet die mechanischen Bewegungen der verschiedenen Schichten für den Aufbau des Teils im Drucker. Er generiert eine Datei die GCode enthält. Der 3D-Drucker wiederum liest aus dem GCode die Anweisungen zur Steuerung des Druckkopfes.

Meine Toolchain
Sie ist eher kurz und sieht so aus

CAD
Nachdem ich einen Ultimaker Bausatz gekauft und aufgebaut habe brauchte ich eine Software für das Zeichnen der 3D-Teile. Erst habe ich mit SketchUp experimentiert. Für einfache Formen war das O.K. Aber komplexere Teile sind schlecht zu aufwändig zu ändern. Nach einiger Recherge bin ich auf Alibre gestossen. Es ist eine Software die mit parametrischen Elementen arbeitet. Damit können alle Parameter nachträglich in ihren geometrischen Grenzen einfach angepasst werden. Während den letzten sechs Jahren hat sich Programm mehrfach gewandelt {Anektode dazu} und wird jetzt als Atom3D vermarktet. Die Screenshots der einzelnen Segmente stammen aus diesem Programm.

Slicer / Drucker

Zum Ultimaker Original+ ist vor wenigen Monaten ein Prusa Mk3 dazu gekommen. Der Unterschied zwischen den beiden zeigt die enorme Entwicklung des FDM-3D-Drucks der letzten Jahre. Kann der Ultimaker hauptsächlich PLA verarbeiten, sind beim Prusa auch weiche Filamente kein Problem. Ebenfalls unterschiedlich sind die Slicer-Programme, die aus den STL-Dateien druckbaren GCode erzeugen. Die Flexibilität der Slicer-Software PrucaSlicer von Prusa überrascht mich immer wieder. Sie wird zurzeit sehr stark weiterentwickelt. Ultimaker verwendet hier Cura. Diese Software hat bei mir seit vielen Versionen ein Problem. Innere Radien wie Löcher oder Ausschnitte werden zuweilen einige 1/10mm zu klein gedruckt. Meist sind mehrere Korrekturen nötig um ein Teil passend zu erzeugen.

Steuerungstechnik

Geplant ist, dass die Spannungsversorgung der Antennenelektronik sowie die Übermittlung Steuerfunktionen ohne zusätzliches Steuerkabel übertragen werden. Am einfachsten wäre die Verwendung des Antennenkabels selbst.

In der SAT-Empfangstechnik wird die Betriebsspannung des LNB seit langem über das Koaxialkabel zugeführt. Mit unterschiedlich hohen Spannungen (14V/18V) und Frequenzen (0kHz/22kHz) werden dabei die gewünschten Betriebsmodi ausgewählt.

Funktionsweise

Für die Bedienung der Antenne sind sechs Steuerkommandos erforderlich. Es sind dies Änderung der Kapazität des Kondensators der Loop (++/+/-/–), sowie das Drehen der Antenne (L/R). Statt die Versorgungsspannung in der Höhe zu variieren oder aufwändig mit Frequenzen im kHz-Bereich zu belegen, kam mir die Idee PWM zu verwenden. PWM bedeutet Pulsweitenmodulation und wird unter anderem zur Regelung von Beleuchtung oder Antrieben verwendet. Man hat eine festgelegte Periode (zum Beispiel 100ms) und schaltet das Signal prozentual dieser Periode ein und aus. Ein PWM Signal mit 10% ist daher während einer Periode 10 ms aktiv, in den verbleibenden 90 ms nicht. Dabei spielt die Periodendauer nur eine sekundäre Rolle. Im prozentualen Verhältnis zwischen Ein/Aus/Ein ist die Information enthalten. Theoretisch sind bei 10&% Schritten acht Kommandos möglich. Die PWM -Anteile 0% oder 100% sind wegen des fehlenden Pegelwechsels nicht als Signal nutzbar.

Elektronik Steuerung

Sie hat zwei primäre Aufgaben; Erzeugen einer Versorgungsspannung auf dem Koaxialkabel für die Antennenelektronik und übermitteln von Kommandos per PWM.

Die Versorgungsspannung von rund 13.8V wird über einen LM7805 auf 5V reduziert und speist den µController. Ein zusätzlicher LM317 regelt die Versorgungsspannung der Antenne auf 12V, die durch den µController für das PWM-Signal weiter auf 9V abgesenkt wird.

Bias-Tee

Bias-Tee Darüber wird das Koaxialkabel mit 12V Gleichspannung gespiesen und die Elektronik auf Antennenseite versorgt. Vom TRX kommend wird die HF erst über einen Kondensator geleitet. Die Gleichspannung wird danach über eine Induktivität auf das Koaxialkabel aufgebracht. Die HF kann kaum durch die Induktivität, die Gleichspannung kann nicht durch den Kondensator zurück zum TRX. Somit sind beide Quellen (HF, Gleichspannung) voneinander getrennt. Am Ende des Koaxialkabels macht man es umgekehrt um die HF und Gleichspannung wieder voneinander zu trennen. Der Kondensator leitet die HF weiter und sperrt die Gleichspannung, die Induktivität davor leitet die Gleichspannung aus und blockt die HF.

Die Grössen der Induktivitat L und Kapazität C sind von der minimal zu übertragenden Frequenz abhängig. C sollte ca. 10% der Kabelimpedanz betragen, L hingegen das 10-fache dessen betragen. Basierend auf 50 Ohm für moderne Transceiver wären das Impedanzen für C < 5 Ohm und L > 500 Ohm. Für 7.000 MHz (40m) ist eine Kapazität von rund 4.7 nF und eine Induktivität von 22 uH erforderlich.

Links

Bias Tee Calculator

Antennenelektronik

Sie erzeugt wiederum über einen LM7805 die Versorgungsspannung ihres µControllers. Die Detektion des PWM-Signals wird mit dem im Controller vorhandenen Analog-Komparator realisiert. Dazu wird über zwei Spannungsteiler die Versorgungsspannung in den Spannungsbereich des Komparators (0-5V) im Verhältnis ca. 2:1 heruntergeteilt. Spannungsteiler1 ist direkt einem Komparatoreingang verbunden. Spannungsteiler2 wird über eine Diode versorgt und besitzt am Ausgang einen zusätzlichen Kondensator, der die Spannung integriert. Wird kein PWM-Signal gesendet, hat Spannungsteiler1 eine leicht höhere Ausgangsspannung als Nummer 2, weil über dessen Diode rund 0.4V Spannung abfallen. Fällt die Versorgungsspannung auf 9V ab, folgt die Spannung am Spannungsteiler1 sofort der Verorgungsspannung. Durch die Diode und den Kondensator am Spannunsteiler2 bleibt die zuvor integrierte Spannung länger erhalten und die Polarität der beiden Komparatoreingänge wechselt. Der µController löst bei jedem Wechsel einen Interrupt aus, die anschliessend per Software verarbeitet werden kann.

Erste Prototypen

Schemas (finale Version)

- Steuergerät Hauptplatine
- Steuergerät Tastenfeld
- Steuergerät Antennenelektronik
- Steuergerät Antennenelektronik Bias-Tee

Boards (finale Version)

Bild existiert nicht: images/magnetloop-main/pcbfinal/jclpcb.jpg
Die Platinen gefertigt von JLCPCB.com Noch nie war es so einfach selbst entworfene Leiterplatten-Layouts fertigen zu lassen. Für dieses Projekt wurden diese noch in EAGLE erstellt, kommende Designs werden dann in KiCad realisiert.
Bild existiert nicht: images/magnetloop-main/pcbfinal/pcbassembliert.jpg

Erkenntnisse (Okt. 2019)
Der interne Pullup im Controller reicht nicht aus, um die Eingänge ausreichend vor HF zu schützen. So kam es vor, dass bei HF-Aussendungen > 5W die Steuerelektronik gedrückte Tasten erkannte und dann jeweils das erste Kommando interpretierte (Kondensator drehen). Das Buffern der Eingänge mit 100nF Kondensatoren gegen Masse hat das Problem behoben. Unglücklicherweise ist wegen mehrfacher PIN-Nutzung auch die ISP Schnitstelle betroffen. Ein Programmierung war damit nicht mehr möglich. In einer neuer Version werden die ISP-Pins separat geführt und die Tasten auf bisher ungenutzte Pins gelegt.

Software

Im Steuergerät wird für jede der sechs Steuertasten ein entsprechendes PWM-Signal generiert. Dazu steuert der Prozessor einen Mosfet-Transistor, der die Versorgungsspannung der Antenne zwischen 12V und 9V umschaltet. Die Erzeugung des PWM-Signals erfolgt dabei teilweise in Software. Alle 10 ms erzeugt ein Hardwaretimer einen Interrupt. Darin wird jeweils ein Flag gesetzt um der Hauptroutine dieses Event mitzuteilen. Ebenfalls wird geprüft, ob ein Kommando gesendet werden soll. Dann wird die Spannung auf dem Koaxialkabel für das entsprechende Kommando auf 9V reduziert. Weil hier von einer festen PWM-Periode ausgegangen wird, ist nur die nur Startflanke zeitbestimmend.

Die Elektronik in der Antenne misst diese PWM-Pulsdauer und leitet daraus die Steuerkommandos ab. Dabei wird er interne Komparator und ein Timer des Controllers verwendet. Die Interruptroutinen beider Hardwarefunktionen arbeiten daher zusammen. Fällt oder steigt die Spannung am Koaxialkabel erzeugt der Komparator einen Interrupt, da die Spannungspotentiale an dessen Eingängen sich dabei umkehren (A grösser als B oder A kleiner als B). Aus einem Register lässt sich herauslesen ob A oder B jetzt einen höheren Pegel hat. Bei einer fallenden Spannung wird der Zähler für Timer1 auf null gesetzt. Alle 0.2ms wird der Zähler um eins erhöht, jedoch nur bis zu einem maximalen Wert. Wird dieser erreicht geht die Software von einem Fehlimpuls aus und verwirft die Messung, ansonsten wird der Wert des Zählers gespeichert und diese Impulslänge in ein Steuerkommando interpretiert. Die Software wertet jeden unlogischen Zustand als Abbruch der laufenden Messung. Somit wird vermieden, das sehr kurze oder sehr lange Impulse Fehlfunktionen auslösen.

Downloads

- Software Steuergerät
- Software Antenne

Besonderheiten

Theoretisch könnte man die PWM-Impulse sehr klein einteilen und zum Beispiel hundert verschiedene Kommandos übertragen (zBsp. 1% PWM Intervall). Das Problem ist jedoch, dass das Signal über eine Spannungsversorgung übertragen wird. Die Spannung wird zur HF-Unterdrückung mittels Kondensatoren gebuffert und ist daher träge für kurze Spannungsschwankungen.

Senden von APRS Nachrichten mit CircuitPython und VHF-Modul

APRS gibt es im Amateurfunk bereits seit langer Zeit. Auf die Besonderheiten im speziellen gehe ich im weiteren Text ein. Zu jener Zeit gab es extra dafür konzipierte analoge integrierte Schaltungen (IC’s) welche die benötigte Modulation des Senders übernommen haben. Diese sind heute leider nicht mehr verfügbar. Ich möchte jetzt nicht allzu tief in das APRS-Protokoll eingehen, es existieren sehr viele Infoseiten im Web dazu (siehe unter Links).

Seit geraumer Zeit verwende ich ein 2m-Handfunkgerät um gelegentlich einige Fahrten im Auto per APRS zu loggen. Eigentlich ist es dafür viel zu schade. Warum es nicht gegen ein selbst gebautes Gerät ersetzen?

Beim Einlesen in das Thema APRS merkt man aber schnell, dass man die Thematik in verschiedene Bereiche aufteilen muss, um den Überblick zu bewahren.

Funktionsweise von APRS.

Welche Protokolle kommen für die Übertragung zur Anwendung?

APRS verwendet das übergeordnete Kommunikationsprotokoll AX.25. Dieses ist ein sehr mächtiges Protokoll und APRS verwendet nur einen winzig kleinen Teil davon. Was aber nicht bedeutet das es einfach zu verwenden ist. Genau genommen ist AX.25 in der Lage Informationen zielgerichtet weiterzuleiten. Dieses Routing wird im Amateurfunk-APRS aber kaum/nicht verwendet. Die Meldungen, welche versendet werden haben kein bestimmtes Ziel und sollen von verschieden Arten von Repeatern abgewickelt werden.

Wie wird moduliert?

Die Übertragung der Daten erfolgt über zwei Töne von 1200Hz und 2200Hz. Als Modulation kommt ein spezielles Verfahren zum Einsatz, welches mir Anfangs etwas Kopfzerbrechen bereitet hat.

Die Modulation verwendet eine Symbolrate von 1200 Baud. Das bedeutet, 1200 Datenwerte pro Sekunde gesendet werden. Mit den beiden Tonfrequenzen von 1200Hz und 2200Hz ergeben sich folgende Zusammenhänge:

Wird ein 1200Hz Ton gesendet entspricht der Zeitraum eines Symbols einer Wellenlänge von 1200 Hz. Ein 2200Hz Ton wird während dieser 1/1200 Sekunde mit 1,83333 Wellenlängen übertragen. Die Definition verlangt, dass die Phase beim Tonwechsel erhalten bleibt. Dazu muss die Phase natürlich bekannt sein und bei der Erzeugung des nächsten Tones berücksichtigt werden. Auch wichtig! Es wird NICHT für Bit=1 der eine Ton und für Bit=0 der andere verwendet. Das hier verwendete Verfahren heisst NRZI und steht für “Non Zero Return Inverted encoding”. Wird ein Bit=0 gesendet, erfolgt ein Tonwechsel. Für Bit=1 bleibt der Ton bestehen. Es spielt daher keine Rolle mit welchem Ton die Aussendung beginnt. Um die Synchronisation über mehrere 1-Bits zu erhalten, wird vom Sender nach dem fünften Bit=1 ein zusätzlicher Tonwechsel eingefügt. Dieser Wechsel, auch Bit-Stuffing genannt (würde einem Bit=0 entsprechen) wird vom mit zählendem Empfänger aber ignoriert. Er dient einzig dazu das Timing zu synchronisieren. Eine weitere Besonderheit besteht beim Beginn und Beenden einer Übertragung. Hier werden zur Signalisation am Anfang und Ende einer Nachricht mehrere gleiche Bytes (0×7E) übertragen, die nicht vom Bit-Stuffing verändert werden und daher vom Empfänger als Start und Endpunkt einer Nachricht erkannt werden können. Diese Bit-Kombination mit 6 x Bit=1 kommt somit in der eigentlichen Nachricht nicht vor.

Technische Umsetzung

Wie wird das modulierte Signal aufbereitet?

Das Herz der Schaltung ist ein Adafruit Feather-M4 Mikrokontroller mit 2MB Speicher, 192kB RAM und diverser Schnittstellen. Darunter auch ein zweikanaliger DAC mit bis zu 1Mbit Sampling-Rate. Der Feather M4 Mikrocontroller stellt einige interessante Funktionen bereit. So lassen sich zum Beispiel gespeicherte MP3 oder WAV-Dateien über den DAC auszugeben. Ebenso kann man eigene Signale als Array erzeugen und vom DAC mit der gewünschten Samplinmgrate ausgeben lassen. Das geschieht ohne CPU direkt über interne DMA Funktionen.

Wie bereits erwähnt, muss beim Tonwechsel die Phase fortgeführt werden. Ein einfaches Abspielen von Tönen gelingt hier nicht, da der Kontroller jeweils seinen Ton bei Phase = 0 Grad beginnt. Bei diesem Mikrokontroller wird das über die Funktion mit dem Abspielen eines Arrays genutzt. Der DAC hat eine Auflösung von 12bit. Um Speicher zu sparen werden nur 8bit verwendet. Somit passt ein Sample in ein Byte.

Für die weitere Vorgehensweise braucht es zuerst noch etwas Theorie. Um eine Sinuswelle ausgeben zu können muss man sich darauf festlegen, aus wie vielen Samples (Datenpunkten) diese bestehen soll. Bei xx Datenpunkten entsprächen für den 1200Hz Ton ein Sample jeweils eine Phasenverschiebung von 360 / xx. Für den 2200Hz Ton sind es 360 / xx * 2200 / 1200. Mit einem kleinen Tabellenprogramm lässt sich in Kürze eine passende Kombination herausfinden. Bei 30 Samples pro Symbol kommt man auf folgende Werte:

Bitrate 1200
Samples pro Bit 30
Samplingrate = 36000

Phasenwinkel:
Mark 1200Hz => 360 / 30 = 12 Grad
Space 2200Hz => 360 / 30 * (2200/1200) = 22 Grad

Da hier beide Phasenwinkel ganzzahlig sind, lassen sich die Sinuswerte für 0-359 Grad einfach vorberechnen und als statisches Array im Speicher ablegen. Für jedes Sample wird dann dessen Phasenversatz addiert und daraus der passende Sinuswert aus dem Array ausgelesen.

Update (13.03.2021)
Circuitpython hat im Feather-M4-Express ca. 160 kB RAM zur Verfügung. Es hat sich herausgestellt, dass bei 30 Samples pro Bit der Speicher nicht immer ausreicht. Da Circuitpython eine interpretierte Sprache ist, sind keine genauen Voraussagen zum Speichermanagement möglich. Die Reduzierung auf 15 Samples pro Bit haben soweit keine Einbussen bezüglich Detektierbarkeit gezeigt. Es empfiehlt sich auch die Komprimierung der Dateien mit dem MPY-CROSS Tool um unnötigen Balast aus den Dateien zu entfernen. Das Sendemodul DRA818V weist zudem einige Nachteile auf. So benötigt das Modul nach Setzen des PTT-Signals ca. 1 Sekunde bis das Audiosignal stabil ausgesendet wird. Nach dem Lösen der PTT sendet es noch einen niederfrequenten Zweiton aus (Roger-Beep?). Dieser lässt sich unterdrücken, wenn das Module in den Powersafe Modus versetzt wird. Die aktuelle Software berücksichtigt diese Umstände. Leider dauern die Aussendungen dadurch länger als nötig (ca. 1.5 Sekunden für den Vorlauf).

Welche Funktionen des Protokolls werden in der Software implementiert?

Da das Modul nur im Fahrzeug verwendet wird, werden nur Positions- und Umweltdaten versendet.

Wie wird das Signal ausgesendet?

Für die Aussendung wird das 2m HF-Modul DRA818V eingesetzt.

Hardware / Software

Der Prototyp enthält folgende Module

- Spannungswandler von 12V auf 3.3V. Die finale Version wird dann über 5V versorgt, damit der Akkulader benutzt werden kann und eine Bufferung möglich ist (mit Auto-PowerOff).
- Adafruit Feather M4 Express
- GPS Modul (Adafruit Ultimate GPS Breakout) mit Antennenanschluss
- Temperatur, Höhensensor (Adafruit BMP 280)
- Beschleunigungssensor (Adafruit LIS3DH)
- SD-Kartenmodul (Adafruit Micro-SD Breakout Board)
Die Software basiert komplett auf CircuitPython. Die Bibliotheken für die Sensoren stammen von Adafruit.

Update

14.03.2021

Die Software hat seit dem letzten Post zahlreiche Verbesserungen erfahren. Besondere Aufmerksamkeit musste dem RAM Speicherbedarf gewidmet werden. Das Array für das Senden der Daten wird intern berechnet und hat bei einer Samplingrate von 36′000 nicht (immer) genügend Speicher zur Verfügung. Eine Analyse der Kurvenform mit reduzierter Rate auf 18′000 Punkte / Sekunde zeigte keine Schwierigkeiten beim Dekodieren. Für noch mehr freies RAM sorgt die Komprimierung der .py Dateien in .mpy mit dem MPY-CROSS Tool.

Weitere Bytes im RAM lassen sich gewinnen, wenn klasseninterne Variablen nicht über getter/setter Funktionen angesprochen werden. Python kennt keine lokal geschützen klasseninternen Variablen. Wenn man deren Namen kennt, kann man darauf zugreifen. Einzig die Namenskonvention deutet auf die gedachte Verwendung hin. Variablen die als __var1 deklariert sind, werden von Python aber etwas versteckt. Variablennamen wie _var2 sind frei zugänglich, sollen aber dem Programmierer auf die private Eigenschaft derer hinweisen. Daher sind im aktuellen Quellcode alle öffentlichen Variablen einer Klasse direkt ohne getter/setter abrufbar. Das gilt natürlich nur für solche Variablen, die keine Berechnungen oder zusätzliche Bearbeitung benötigen.

Source

siehe Codeberg Repository

Links

APRS Dokumentation
Gute Dokumentation über die Eigenheiten von APRS

Bilder

prototype.jpg

Petromax 150 elektrisch

sam_0617.jpg

Vorgeschichte

Im Outdoorbereich ist Licht ein zentrales Thema. Aus meiner Militärzeit kenne ich Benzinvergaserlampen, die sehr hell und lange Zeit leuchten. Für den Gartensitzplatz wollte ich auch so etwas. Also erwarb ich eine Petromax 500. Betrieben wird diese allerdings mit Petroleum, was mir mehr zusagte da hier kein lästiger Benzingeruch entsteht. Die Lampe wurde anfangs häufig benutzt. Mit der Zeit zeigten sich diverse Probleme mit der Technik. Um zu verstehen wo das Problem liegt, muss man etwas über das Funktionsprinzip wissen. Die Lampe hat einen Glühstrumpf wie man es von den Butangaslampen vom Camping her kennt. Dort verdampft Flüssiggas und gelangt in denGlühstrumpf wo bei der Verbrennung Licht erzeugt wird. Damit das mit Petrolium funktioniert, muss dazu vorgängig der Verdampfer in Form einer Röhrenschlaufe kurz oberhalb des Glühstrumpfes vorgewärmt werden. Dazu füllt man die kleine Wanne unterhalb mit Spiritus und entzündet sie. Ist die Schale leer gebrannt und die Schlaufe heiss genug, öffnet man das Ventil vom Tank und der zuvor mittels Druckpumpe unter Druck gesetzte gefüllte Petroliumbehälter befördert das Petrolium zum Verdampfer und von da gelangt es weiter in den Glühstrumpf. Das erzeugte Gas verbrennt und der Strumpf leuchtet hell auf. Leider machte diese Lampe immer wieder Probleme. Öfters brannte das Gasgemisch ausserhalb des Strumpfes wobei kaum Licht, dafür Russ und unerwünschte Abgase entstanden. Die Luftpumpe war ineffizient. Beim Pumpen wurde der Glühstrumpf bei ruppigen Pumpstössen manchmal beschädigt und musste ersetzt werden. Also wurde die Lampe kurzerhand elektrifiziert. Der Boden des Tanks wurde aufgesägt, die innenliegenden Teile wie Pumpenrohr soweit als möglich gekürzt und ein 12V Blei-Gel Akkus eingebaut. Ein passender Halter wurde mittels eines 3D-Druckers erstellt. Flugs noch einen Schalter und eine Ladebuchse anstelle von Pumpe und Druckanzeige eingebaut und fertig.

Eine Petromax 150 Messing elektrifizieren

Petromax Lampen lassen sich eigentlich nicht dimmen, elektrische jedoch schon. Was lag da näher als eine weitere Petromax auf elektrisch umzurüsten. Ins Auge stach mir die 150er aus Messing mit vergoldetem Schirm (Trompetengold). Der Händler konnte mir einen Rabatt gewähren, da ich die Lampe auf Elektrik umbaute und er darum keine Modifikationen machen musste. Wie das gemacht wurde ist im folgenden auf dieser Seite dokumentiert.

Spezifikationen

Energieversorgung

Jedes batteriebetriebene Projekt braucht den richtigen Akku. Doch welchen? Es kamen drei Akkutypen zur Auswahl;

LiPo

    + sehr hoehe Energiedichte
    + sehr leicht
    + in vielen Grössen verfügbar
    - benötigt spezielle Ladeelektronik
    - ungeeignet für tiefe Temperaturen
    - benötigt humane Überwachung beim Laden
    - bedingt geeignet für den unbeaufsichtigten Verbleib im Gerät

LiFePo

    + hohe Energiedichte
    + leicht
    + einfache Ladeelektronik
    - nur in wenigen Grössen verfügbar
    - Grössen meist unpassend

NiMh

    + robust
    + einfachste Ladetechnik möglich
    + grosser Temperaturbereich
    - weniger Energiegehalt zu anderen Technologien
    * Grössen meist in Standardformen AA / AAA etc.

Funktionen

Akku laden

Die Ladeelektronik soll direkt in der Lampe eingebaut werden. Zum Laden wird lediglich ein ausreichend dimensioniertes Netzteil benötigt. Vorgesehen ist ein 24V Netzteil welches ca. 1A Strom liefern kann.

Akku-Ladestatus

Zur Anzeige von Akkuspannung und Ladestatus erhält die Lampe eine RGB-LED. Gemessen wird die Spannung des Akkus. Bei Anschluss des Ladegeräts zeigt die Farbe Blau ein Laden an, Weiss bedeutet Akku voll. Beim Gebrauch der Lampe wechselt die Anzeige von Grün nach Orange zu Rot. Sinkt die Akkuspannung unter das im Programm festgelegte Limit, schaltet sich die Lampe aus.

EIN/AUS – Helligkeit

Die Lampe sollte mittels eines einzigen Tasters bedient werden können. Man findet diese Funktion auch an Lichtdimmern für den Haushaltoder bei LED Nachtischlampen.

Elektronik

Controller Board

controller_schema.png

Die Schaltung ist auf minimalen Stromverbrauch ausgelegt. 12 Zellen NiMh Eneloop versorgen die gesamte Schaltung. Die Lampe selber benötigt 12V und hat dabei einen Strom von ca. 300mA. Da die Gesamtspannung bei voll geladenem Akku 16.2 (12 x 1.35V) beträgt, regelt die Elektronik die Impulslänge entsprechend herunter. Die dazu nötigen Eckwerte sind in der Software abgebildet.
pixel.png

Ladestrom und Verpolungsschutz

schema_laderegelung.png

Die Ladeelektronik ist ausgelegt für ein 24V Netzteil mit mindestens 12W Leistung. Die Schaltung wird durch D1 gegen Verpolung geschützt. IC2 ist ein klassischer LM317 in Konstantstromschaltung. Der Strom wird durch R5 und R6 definiert. In Serie geschalten ergeben ihre 4Ω einen maximalen Strom von rund 300mA (1.25V / 4Ω = 0.32A) R1 und R10 bilden einen Spannungsteiler dessen Mittelpunkt zu einem ADC-Eingang des Prozessors führt. Damit wird detektiert, ob ein stromführendes Ladegerät angesteckt ist.
pixel.png

Ladeschalter

schema_laderegelung2.png

Der Prozessor schaltet den Ladestrom über T3 und Q1 zum Akku durch. R2 und R3 sorgen dafür, dass beide MOSFETs ohne Signal vom Prozessor gesperrt bleiben. Aufgrund der hohen Ladespannung (>5V) kann Q1 nicht direkt durch den Prozessor gesteuert werden. Diode D3 sorgt dafür,das kein Strom vom Akku über die im MOSFET Q1 vorhandene rückwärts gerichtete Diode zur Stromregelung fliesst. Denn damit würde der Spannungsteiler R1 / R10 aktiv und der Prozessor würde fälschlicherweise ein aktives Ladegerät detektieren.
pixel.png

Lampe schalten

schema_lampe.png

MOSFET Transistor T2 schaltet die Lampe ein und aus.
R4 sorgt für eine Sperrung von T2 wenn vom Prozessor kein aktiver Pegel anliegt.
pixel.png

Stromversorgung Prozessor und Status-LED

schema_5vreg.png

Die Spannung vom Akku wird mittels IC3 auf 5V reguliert. R8 und R9 bilden einen Spannungsteiler, dessen Wert an einen ADC-Eingang des Prozessors geführt wird. Er ermittelt damit die aktuelle Spannung des Akkus.
pixel.png

Digitale Status-LED

gauge_schema.png

Zur Überwachung des Akkuszustandes und dessen Ladung wird eine digitale RGB-LED vom Typ WS2812 verwendet. In der Regel wird diese LED in programierbaren Lichterketten eingesetzt, doch natürlich lassen sich solche Typen auch einzeln einsetzen. Die LED hat je einen Versorgungspin für LED und Logik. Diese wurden der Einfachheit halber zusammengefasst. Das hat sich als nachteilig erwiesen, weil die Logik auch im Standbymodus der Lampe Strom verbraucht. Die Schaltung wurde daher so angepasst, dass die LED direkt aus einem Port des Prozessor versorgt wird. Weil in der Dunkelheit die Leuchtkraft der LED sowieso reduziert werden muss, kann der Strom unterhalb der 40mA Limite für diesen Pin gehalten werden.
pixel.png

Hardware

Erste Versuche auf dem Steckbrett

sam_0561.jpg

Ein Steckbrett (engl. Breadboard) eignet sich ideal um erste Versuche mit einer Schaltung zu machen. Es gibt sie in diversen Grössen. Änderungen sind jederzeit möglich, nichts ist fix. Ein Nachteil heute ist die Verwendung von Bauteilen in SMD Dimensionen. Sie lassen sich wegen ihrer Bauform nicht in das Board einstecken. Abhilfe schaffen hier Adapterplatinen die es für fast alle SMD-Bauformen gibt. Alternativ kann man auch selbst eines fertigen.
pixel.png

Prozessor Interfacing

sam_0562.jpg

Wer ATMEL Prozessoren direkt programmieren möchte, benötigt nebst passenden Programmer natürlich Verbindung zum Prozessor. Bei Verwendungvon DIL-Gehäusen bietet sich ein solcher DIL-Messadapter an. Es können die normalen WireWrap Steckverbinder (M-F) verwendet werden. Um das Programmerkabel zu fixieren, wird es über das Steckbrett mit dem Prozessor verbunden. Die unbenutzten Pins am Adapter eignen sich hervorragend um Messungen mit dem Oszilloskop oder Voltmeter durchzuführen.
pixel.png

Funktionstest

sam_0599.jpg

Das Steckbrett eignet sich bestens zu debuggen von Schaltung und Software. Zusätzliche Messpunkte können einfach eingesteckt werden. Kein Löten ist notwendig. Einziger Nachteil bei etwas grösseren Schaltungen ist die Anzahl an Kabeln welche gerne die Sicht auf das Wesentliche behindern.
pixel.png

Fertige Platine

sam_0560.jpg

Obere Seite: zu sehen sind der Prozessorsockel und die Anschlüsse für Akku, Taster, LED, Akku, Ladekabel.
pixel.png
Bild existiert nicht: images/petromax-main/sam_0558.png
Untere Seite: Dies ist die erste Version. Im Bild die riesigen Dioden, die aus einem ausgeschlachteten DELL-Server stammen. Der MOSFET für die Lampe war noch unterdimensioniert und brannte mehrmals durch. Der MOSFET zum Laden des Akkus wurde ebenfalls durch einen robusteren Typ ersetzt.
pixel.png

LED Halter

Bild existiert nicht: images/petromax-main/sam_0553.jpg
Das ist die RGB-LED auf der Adapterplatine. Sie zeigt Akku und Ladezustand an. Sie sitzt da, wo ursprünglich die Druckanzeige war. Mehr Details im Abschnitt über den Umbau der Lampe.
pixel.png

Controller Halter

sam_0609.jpg

Der Halter für die Elektronik ist im 3D Druck entstanden. Er wird in den Montagering eingeklebt, der auch den ausgefrästen Deckelboden aufnimmt.
pixel.png

Software

Allgemein

Der verwendete Prozessor ist ein Atmel Tiny 861. Die folgenden Funktionen der Hardware werden verwendet:

    - ADC zum Messen der Akkuspannung und Prüfen des Vorhandeseins eines angeschlossenen Ladegeräts
    - PWM zum Regeln der Helligkeit der Lampe
    - WATCHDOG zum Energiemanagement
    - Interne Interrupts (TIMER0)
    - Externe Interrupts (INT0) für den Taster

Dazu kommen Bibliotheken zur Steuerung angeschlossener Peripherie (NEOPIXEL).

Funktionen

Status: Lampe inaktiv.

Der Watchdog weckt den Prozessor alle 8 Sekunden. Dieser prüft ob das Laderät angeschlossen ist. Wenn nicht, wird der Watchdog neugesetzt und der Prozessor in den Schlafmodus versetzt.

Wird ein Ladegerät erkannt bleibt der Prozessor wach und es wird weiter zur Hauptroutine gesprungen => Lampe aktiv

Status: Lampe aktiv

Die Hauptroutine besteht aus zwei Modulen.

Das erste Modul kümmert sich um Ladung des Akkus und den maximalen Strom der Lampe. Es wird alle 100ms durch einen Timerinterruptgetriggert. Weil der Akku voll geladen eine höhere Spannung hat als die Lampe verkraften kann, reduziert die Software das maximale PWM Verhältnis. Die in der Software angegebenen Werte wurden messtechnisch ermittelt. Dieses Modul steuert ebenfalls die Anzeigeder LED und zeigt den aktuellen Ladestatus respektive Akkustatus an.

Das zweite Modul wird alle 10ms durch einen Timerinterrupt getriggert. Hier wird der Taster ausgewertet um die Lampe heller oder dunkler zu machen oder Lampe ganz auszuschalten.

controller.bas

1 $regfile = „attiny861.dat“
  2 $crystal = 16000000
  3 $hwstack = 32
  4 $swstack = 64
  5 $framesize = 64
  6
  7 CONFIG SUBMODE = NEW
  8 CONST USELCD = 0
  9
 10 CONST true = 1
 11 CONST false = 0
 12
 13 ‚Voltage per digit x voltage-divider factor
 14 CONST ChargeDividerFactor = 0.00107 * 23.0
 15 CONST AccuDividerFactor = 0.00107 * 23.0
 16
 17 CONST up = 1
 18 CONST down = 0
 19 CONST ein = 1
 20 CONST aus = 0
 21 CONST pushed = 0
 22
 23 ‚Accu / Charge Levels in Volt
 24 CONST AccuGreen = 13.0
 25 CONST AccuOrange = 12.0
 26 CONST AccuRed = 11.00
 27 CONST AccuChargeLimit = 17.00
 28 CONST MinDCLevel = 14.0
 29 CONST MinLightBrightness = 25
 30 CONST LightChangeDirDelayTime = 100                         ‚1 Sec.
 31
 32 ‚NeoPixel Color Index
 33 CONST NPblack = 0
 34 CONST NPred = 1
 35 CONST NPgreen = 2
 36 CONST NPblue = 3
 37 CONST NPwhite = 4
 38 CONST NPdarkred = 5
 39 CONST NPdarkgreen = 6
 40 CONST NPdarkblue = 7
 41 CONST NPdarkwhite = 8
 42 CONST NPorange = 9
 43 CONST NPdarkorange = 10
 44
 45 NeoPixelPower ALIAS PORTA.6
 46 LightPWM ALIAS OCR1A
 47 Lamp Alias PORTB.1
 48 ChargeEnable ALIAS PORTB.4
 49 StatusLED ALIAS PORTA.7
 50 Switch ALIAS PINB.6
 51 SwitchPullup ALIAS PORTB.6
 52 ‚DebugPin ALIAS PORTA.4
 53 ‚DebugPin2 ALIAS PORTA.5
 54
 55 DIM ResetOrigin AS Byte
 56
 57 DIM AccuVoltage AS Single
 58 DIM ChargeVoltage AS Single
 59 DIM DoCharge as Byte
 60 DIM ChargerDetected as Byte
 61 DIM CheckInterval as Byte
 62 DIM v0 AS Long
 63 DIM v1 AS Long
 64 DIM i AS Byte
 65
 66 DIM Event10ms AS Byte
 67 DIM Event100ms AS Byte
 68 DIM Event100msCntr AS Byte
 69
 70 DIM SwitchCntr AS Byte
 71 DIM LightBrightness AS Byte
 72 DIM LightChangeDir AS Byte
 73 DIM LightOn AS Byte
 74 DIM StoredLightBrightness AS ERAM Byte
 75 DIM MaxLightBrightness AS Byte
 76 DIM LightChangeDirDelay AS Byte
 77
 78 DIM NP_red AS Byte
 79 DIM NP_green AS Byte
 80 DIM NP_blue AS Byte
 81 DIM NPindex AS Byte
 82
 83 ’store sub code in separate files
 84 $INCLUDE sub_adc.inc
 85 $INCLUDE sub_watchdog.inc
 86 $INCLUDE sub_neopixel.inc
 87 $INCLUDE sub_lcd.inc
 88
 89 ’save source of reset
 90 ResetOrigin = Peek(0)
 91 MCUSR = 0
 92
 93 CONFIG NeoPixelPower = OUTPUT : NeoPixelPower = aus
 94 CONFIG Lamp = OUTPUT
 95 CONFIG ChargeEnable = OUTPUT : ChargeEnable = false
 96 CONFIG StatusLED = OUTPUT
 97 CONFIG Switch = INPUT : SwitchPullup = 1
 98 ‚CONFIG DebugPin = OUTPUT : DebugPin = false
 99 ‚CONFIG DebugPin2 = OUTPUT : DebugPin2 = false
100
101 LightChangeDir = up
102
103 ‚Unused Pins / set Pullup
104 ‚SET PORTA.4                                                 ‚DebugPin / comment out when in use
105 ‚SET PORTA.5                                                 ‚DebugPin2 / comment out when in use
106 ‚SET PORTB.0
107 ‚SET PORTB.2
108 ‚SET PORTB.3
109
110 ‚Init INT0 interrupts
111 MCUCR.ISC00 = 0
112 MCUCR.ISC01 = 0
113 GIMSK.INT0 = 1
114 On INT0 isrINT0 NoSave
115
116 ‚Init Timer0 (10ms cycle)
117 CONFIG TIMER0 = TIMER , PRESCALE = 1024
118 START TIMER0
119 ON OVF0 isrTimer0_Overflow NoSave
120 ENABLE OVF0
121
122 ‚Init PWM Timer1
123 Set Pllcsr.plle
124 Waitus 100
125 While Pllcsr.plock = 0
126 Wend
127 Set Pllcsr.pcke
128 TCCR1A = &B10000010
129 TCCR1B = &B00001000
130 LightPWM = 0
131
132 ‚Watchdog
133 InitWatchdog
134
135 ‚Init ADC
136 InitADC
137
138 ENABLE INTERRUPTS
139
140 ‚Do one dummy reading on each channel because this is the first ADC reading at all
141 ReadChargeVoltage
142 ReadAccuVoltage
143 ‚then get actual values
144 CheckVoltages
145
146 ‚Init LCD for debugging
147 #IF USELCD
148   Init_LCD
149   Write_LCD
150 #ENDIF
151
152 ‚Is watchdog source of reset?
153 If ResetOrigin.WDRF = true Then
154   ‚ brief check if charger is plugged in
155   If ChargeVoltage < MinDCLevel Then
156     ‚No, then sleep further
157     GIMSK.INT0 = 1                                          ‚activate wakeup interrupt
158     ’stop all loads
159     STOP ADC
160     NeoPixelPower = aus
161     Config POWERMODE = Powerdown
162     ‚*********************
163     ‚*** SLEEPING ZONE ***
164     ‚*********************
165     ‚Switch pressed? Wake up again
166     ‚do some inits again
167     InitADC
168     RESET Watchdog
169   End If
170 End If
171
172 ‚Restore the last used Brightness
173 LightBrightness = StoredLightBrightness
174 MaxLightBrightness = 255
175
176 ‚Put Power to the NeoPixel
177 NeoPixelPower = ein
178
179 ‚MAIN
180 Do
181   ‚all 100 ms
182   If Event100ms = true Then
183     Event100ms = false
184     ‚count intervals
185     INCR CheckInterval
186     Select Case CheckInterval
187       ‚every 5 seconds, the charging is disabled to have valid voltages
188       Case 50
189         ChargeEnable = false
190       ’now measure exact voltages
191       Case Is > 50
192         CheckVoltages
193         If AccuVoltage > 15.5 Then
194           MaxLightBrightness = 148                          ‚58%
195         ElseIf AccuVoltage > 15.0 Then
196           MaxLightBrightness = 153                          ‚60%
197         ElseIf AccuVoltage > 14.5 Then
198           MaxLightBrightness = 166                          ‚65%
199         ElseIf AccuVoltage > 14.0 Then
200           MaxLightBrightness = 178                          ‚70%
201         ElseIf AccuVoltage > 13.5 Then
202           MaxLightBrightness = 215                          ‚85%
203         Else
204           MaxLightBrightness = 255
205         End If
206         If LightBrightness > MaxLightBrightness Then
207           LightBrightness = MaxLightBrightness
208         End If
209         CheckInterval = 0
210       ‚if no measure is running, do powermanagement and set led color
211       Case Else
212         If ChargerDetected = true Then
213           If DoCharge = true Then
214             SetPixelColor NPdarkblue
215             ChargeEnable = true
216           Else
217             SetPixelColor NPdarkwhite
218             ChargeEnable = false
219           End If
220         Else
221           If LightOn = true Then
222             Select Case AccuVoltage
223               Case Is > AccuGreen
224                 SetPixelColor NPdarkgreen
225               Case Is > AccuOrange
226                 SetPixelColor NPdarkorange
227               Case Is > AccuRed
228                 SetPixelColor NPdarkred
229               Case Else
230                 LightOn = false
231             End Select
232           Else
233             SetPixelColor NPblack
234           End If
235         End If
236     End Select
237
238     ’send color to neopixel
239     WritePixel
240
241     ‚If LCD is attached lets display some data
242     #IF USELCD
243       Write_LCD2
244     #ENDIF
245
246     ‚do not forget to reset watchdog timer
247     If ChargerDetected = true Then
248       Reset Watchdog
249     Else
250       If LightOn = true Then
251         Reset Watchdog
252       End If
253     End If
254   End If
255
256   ‚all 10 ms
257   If Event10ms = true Then
258     Event10ms = false
259     If Switch = pushed Then
260       If SwitchCntr < 25 Then INCR SwitchCntr
261       If SwitchCntr > 20 Then
262         If LightChangeDir = up Then
263           If LightBrightness < MaxLightBrightness Then
264             INCR LightBrightness
265           Else
266             INCR LightChangeDirDelay
267             If LightChangeDirDelay > LightChangeDirDelayTime Then
268               LightChangeDir = down
269               LightChangeDirDelay = 0
270             End If
271           End If
272         Else
273           If LightBrightness > MinLightBrightness Then
274             DECR LightBrightness
275           Else
276             INCR LightChangeDirDelay
277             If LightChangeDirDelay > LightChangeDirDelayTime Then
278               LightChangeDir = up
279               LightChangeDirDelay = 0
280             End If
281           End If
282         End If
283       End If
284     Else
285       If SwitchCntr > 20 Then
286         If LightChangeDir = up Then
287           LightChangeDir = down
288         Else
289           LightChangeDir = up
290         End If
291       End If
292       If SwitchCntr > 3 and SwitchCntr < 20 Then
293         If LightOn = false then
294           LightOn = true
295         Else
296           StoredLightBrightness = LightBrightness
297           LightOn = false
298         End If
299       End If
300       SwitchCntr = 0
301       LightChangeDirDelay = 0
302     End If
303
304     ’set light on/off as needed
305     If LightOn = true Then
306       LightPWM = LightBrightness
307     Else
308       LightPWM = aus
309     End If
310   End If
311 Loop
312
313 ‚ISRs
314 isrTimer0_Overflow:
315   $ASM
316     PUSH R16
317     PUSH R23
318     IN R24,SREG
319     PUSH R24
320   $END ASM
321   ’set 10ms interval
322   TIMER0 = 98
323   Event10ms = true
324   INCR Event100msCntr
325   If Event100msCntr > 10 Then
326     Event100msCntr = 1
327     Event100ms = true
328   End If
329   $ASM
330     POP R24
331     OUT SREG , R24
332     POP R23
333     POP R16
334   $END ASM
335
336 Return
337
338 isrINT0:
339  ‚Clear INT0 Interrupt to detect pushed switch
340   $ASM
341     PUSH R23
342     IN R24,SREG
343     PUSH R24
344     IN R23,GIMSK
345     ANDI R23,$BF
346     OUT GIMSK , R23
347     POP R24
348     OUT SREG , R24
349     POP R23
350   $END ASM
351 Return

Administration

Archiv

Datenschutz

Erklärung