AtTiny13-Morse-Baken
Aufgrund einer Nachfrage zu einem alten ELO-Artikel aus 2009 fiel mir
auf, dass er damals nicht bei www.elektronik-labor.de erschienen war.
Da er bei www.elo-web.de hinter einer Login-Schranke liegt, habe ich
ihn für's Elektronik-Labor überarbeitet und "befreit":
Einleitung
Heute bildet die eigene Homepage in Internet so eine Art
"virtuelle Duftmarke".
Bei Funkamateuren gab es in der guten alten Zeit einen ähnlichen Drang,
mit automatisch betriebenen Stationen (Repeater oder Funkbaken) eine
vergleichbare "Duftmarke" zu setzen. Er wurde allerdings reglementiert
(man benötigte für unbemannten Betrieb eine Sondergenehmigung) und war
technisch recht aufwendig, da die erforderliche Ablaufsteuerung und der
Morse-Rufzeichengeber ein wahres "TTL- Grab" bildeten. Inzwischen ist
das sehr einfach geworden; selbst mit einem ATtiny13 lässt sich
erstaunlich viel "anstellen".
Codierung von Morsezeichen
Ein effizientes Verfahren, Morsezeichen zu codieren, fand sich
im WWW, es ist schon mehr als 10 Jahre alt und wurde von mehreren
Autoren aufgegriffen; die Umsetzung erfolgte damals in Assembler auf
PIC-Microcontrollern. Eine kompakte Realisierung ist aber auch in
Bascom auf einem AVR möglich.
Prinzip der Codierung:
- 1 Byte pro Zeichen, niederwertiges Bit zuerst
- hat das Bit den Wert 0: Morsepunkt (dit)
- hat das Bit den Wert 1: Morsestrich (dah)
- da Morsezeichen unterschiedlich lang sind, ist ein Ende- Zeichen erforderlich; es ist ebenfalls ein 1-Bit
- Beispiel Morsezeichen "a" (dit dah): &B00000110
- Beispiel Morsezeichen "9" (dah dah dah dah dit): &B00101111
-
Auslesen der codierten Zeichen: niederwertigstes Bit auslesen, Byte um
1 Stelle nach rechts schieben, niederwertigstes Bit auslesen. Ist der
Wert des gesamten Bytes nur noch 1, ist das Zeichen komplett.
realisierte Varianten
- eine Bake, die 5 sec. Dauerton, anschließend max. 540
Zeichen Text aussendet und 8 sec pausiert. Sie erzeugt Morseton,
PTT-Signal und Schaltsignal für die Stromversorgung des Senders
- eine Bake, die max. 255 Zeichen Text, anschließend zwei analoge
Spannungswerte und den Status eines Alarmkontakts aussendet und für
konfigurierbare Zeit pausiert
Hardware
Abbildung 1: Morse-Bake mit zwei Schaltausgängen
Abbildung 2: Morsebake mit zwei Schaltausgängen; Streifenleitungs-Platine
Abbildung 1 ist die Hardware für die Variante 1 und dient nur
als Anregung; nicht benötigte Schaltungsteile können weggelassen
werden. An den NF- Ausgang muss noch ein Vorwiderstand oder Poti bzw.
fester Spannungsteiler angeschlossen werden, dessen Dimensionierung vom
eingesetzten Sender bzw. Funkgerät abhängt.
Der ATtiny13 liefert folgende Signale:
Ein NF-
Morsesignal an Pin5 (PB0/OC0A); es wird über Trennkondensator und
Schutzwiderstand zur Weiterleitung an den NF- Eingang eines Senders
bereitgestellt; ein Piezo- Buzzer dient als Mithörkontrolle. Ein
parallel zur NF getaktetes Schaltsignal an Pin2 (PB3), es wird durch Q1
invertiert und passt so zum Telegrafieanschluss üblicher
Amateurfunkgeräte.
Soll das Sendegerät nach jedem Zyklus abgeschaltet und vor
Beginn wieder eingeschaltet werden, ist das mit der Schaltstufe für
+12V und ca. 1 A an Pin3 (PB4) möglich. Weist der Sender einen
PTT-Eingang auf, können Q3, R3 und R4 weggelassen werden und die
PTT-Leitung über Q2 auf Masse gezogen werden, um den Sender
einzuschalten.
Das Layout-Programm EAGLE ist zwar nicht für das Design von
Streifenleitungs-Platinen gedacht; lässt sich aber so weit
"hinfummeln", dass eine Vorlage für eine Streifenleitungsplatine
angedeutet wird (siehe Abbildung 2).
Abbildung 3: Morse-Bake mit 3 Eingängen und PTT-Ausgang
Abbildung 4: Morse-Bake mit 3 Eingängen und PTT-Ausgang; Platine
Abbildung 3 stellt die zweite Variante dar. Zwei
Spannungsteiler aus 82 kOhm und 10 kOhm an PB2/ADC1 und PB4/ADC2 teilen
0...10 V auf 0...1,1 V herunter (1,1 V ist die interne
Spannungsreferenz des ATtiny). An PB1 liegt ein Anschluss für einen
Schalter, der an Masse geht. Wird er geschlossen und so der Pin auf
Masse gezogen, wird dieser Status als Alarm gemeldet. Die Eingänge sind
als Schutz gegen HF- Einstrahlung jeweils mit Kondensatoren abgeblockt.
Auch hier wieder ein Vorschlag für die Anordnung auf Streifenleitungs-Platine (Abbildung 4).
Software
Die Bascom- Listings sind ausführlich kommentiert; daher nur ein paar Anmerkungen:
Die Bake nach Variante 1 sendet zunächst 5 Sekunden Dauerton,
dann den Morsetext. Danach wird 10 Sekunden gewartet, anschließend
beginnt der Zyklus von neuem.
Variante 2 gibt Dauerton und Morsetext aus und misst
anschließend jeweils die Spannung an PB2/ADC1 und PB4/ADC2. Der Wert
wird auf zwei Stellen umgerechnet und gesendet. Dann wird der Eingang
PB1 abgefragt. Er liegt durch den internen Pullup auf High. Wird er
durch den externen Schaltkontakt auf Masse gezogen, wird eine
Alarmmeldung angehängt.
Bei Variante 2 wird die Pause nach der Aussendung über den
Watchdog realisiert, um Energie zu sparen. Der AtTiny geht in Powerdown
und wird nach 8 Sekunden über den Watchdog geweckt. Die Pause zwischen
den Aussendungen ist über die Konstante Wdzaehler als Vielfaches von 8
Sekunden konfigurierbar. Der Watchdog ist so konfiguriert, dass er alle
8 sec. statt eines Resets lediglich einen Interrupt auslöst (die
Variable E würde einen Reset nicht überleben). E wird in einer
Zählschleife inkrementiert und bei Überschreiten des Grenzwerts
Wdzaehler wird in die Baken-Routine verzweigt.
Download: T13-morsebake-soft.zip
Quellcode (der ersten Variante):
' Programm: Gibt Morse-Bakentext als NF-Ton und parallel als Keyer-Schaltsignal aus
' Zwischen den Aussendungen 10 sec Pause.
'
' Sprache: Bascom-AVR-Basic Version 2.0.7.5 Demo
' Erläuterungen:
'
' Codierung der Morsezeichen: 1 Byte pro Zeichen, niederwertiges Bit zuerst.
' Hat das Bit den Wert 0: Morsepunkt (dit)
' Hat das Bit den Wert 1: Morsestrich (dah)
' Da Morsezeichen unterschiedlich lang sind, ist das Ende- Zeichen ebenfalls ein 1-Bit.
'
' Beispiel Morsezeichen "a" (dit dah): &B00000110
' Beispiel Morsezeichen "9" (dah dah dah dah dit): &B00101111
' Auslesen der codierten Zeichen:
' Niederwertigstes Bit auslesen, Byte um 1 Stelle nach rechts schieben, niederwertigstes Bit
' auslesen. Ist der Wert des gesamten Bytes nur noch 1 (Ende-Marke), ist das Zeichen komplett.
'
'
' Timer0 erzeugt den Mithörton. Pin PB0 wird als Timer0-Ausgang OC0A verwendet.
' Pin PB3 ist Keyer-Ausgang. Pin PB4 schaltet die Stromversorgung (bzw. PTT) für den Sender.
'
'-------------------------------------------------------------------------------
$regfile = "ATtiny13.dat"
$crystal = 1200000 ' Taktfrequenz: 1,2 Mhz
$hwstack = 8 ' reicht für 4 Unterprogramme, spart SRAM
$swstack = 0 ' wird nicht gebraucht, spart SRAM
$framesize = 0 ' dito
Const Dit = 60 ' Länge eines Punkts, daraus ergibt sich die Morsegeschwindigkeit
Const Dah = Dit * 3 ' Länge eines Strichs
Const Wort = Dit * 8 ' Länge der Pause zwischen Wörtern
Const Tonhoehe = 14 ' Tonhöhe
Dim I As Byte ' wird in Zählschleife verwendet
Dim N As Word ' Aktueller Morsebuchstabe
Dim M As Byte ' wird fürs Auslesen der Morsebits verwendet
Dim L As Byte ' niederwertigstes Bit von M verwendet
Acsr.acd = 1 ' Analog-Komparator ausschalten, spart etwas Strom
Ddrb = &B00011001 ' Pins PB0+PB3+PB4 als Ausgänge konfigurieren (1), Rest ist Eingang (0)
Didr0 = &B0000111 ' Digitaleingaenge PinB.0 - PinB.2 deaktivieren
' Morseton mit Timer0 erzeugen:
'
' Timer0 zählt das Register TCNT0 hoch. Es wird mit Register OCR0A verglichen.
' Wenn TCNT0 = OCR0A, wird Output OC0A/PB0 umgeschaltet (getoggled)
' Timer0 erzeugt so Dauerton; er wird jedoch nur an den Ausgangsport durchgeschaltet,
' wenn das Datenrichtungs- Register DDRB.0 = 1 ist. Bei 0 wird der Ton unterdrückt.
'
Config Timer0 = Counter , Prescale = 64 , Compare A = Toggle , Clear Timer = 1
Ocr0a = Tonhoehe
'-------------------------------------------------------------------------------
' Hauptprogramm:
Ddrb.0 = 0 ' Ton und PTT aus
Portb.3 = 0
Wait 1
Do
Portb.4 = 1 ' Stromversorgung Sender an
Ddrb.0 = 1 ' Ton an
Portb.3 = 1 ' Keyer an
Wait 5 ' 5sec Dauerton
Ddrb.0 = 0 ' Ton aus
Portb.3 = 0 ' Keyer aus
Wait 1
Restore Message
For N = 1 To 560 ' max. Msg_laenge 560
Read M
If M = 255 Then
Goto Pause
End If
Gosub Morse
Next N
Pause:
Portb.4 = 0 ' Stromversorgung Sender aus
Wait 10
Loop
' Morsezeichenerzeugung:
Morse:
If M = 0 Then ' Sonderfall: Leerzeichen;
Waitms Wort
Goto Sign_end
End If
For I = 1 To 8
If M = 1 Then ' Das Byte hat nur noch den Wert 1; Zeichenende!
Goto Sign_end
End If
L = M And &B0000001 ' niederwertigstes Bit lesen
Ddrb.0 = 1 ' Ausgänge einschalten
Portb.3 = 1
If L = 1 Then
Waitms Dah ' ist das Bit 1 -> dah
Else
Waitms Dit ' ist das Bit 0 -> dit
End If
Ddrb.0 = 0 ' Ausgänge abschalten
Portb.3 = 0
Waitms Dit ' Pause innerhalb des Morsezeichens
Shift M , Right , 1 ' Bits um eine Stelle nach rechts shiften
Next I
Sign_end:
Waitms Dah ' Pause zwischen Morsezeichen
Return
End
'- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
' Codierung der Morsezeichen. Bei einem Prozessor mit viel SRAM würde man alle Zeichen
' in ein Array einlesen (Übersetzungstabelle), den eigentlichen Bakentext in einen String packen
' und diesen String zeichenenweise abarbeiten.
'
' Da der Attiny13 nur ca. 64 Byte SRAM hat, wäre nur Platz für etwa 50 Bytes. Daher ist der Weg hier
' anders: Der Bakentext ist (in Morsecodierung) in Datazeilen (also im Programmspeicher) abgelegt,
' allerdings durch Verwendung von Konstanten in einer leicht lesbaren Schreibweise.
' Die Data-Zeilen werden sequenziell ausgelesen.
' Nur die wirklich benötigten Zeichen werden (beim Kompilieren des Programmes) umgewandelt.
Const #a = &B00000110
Const #b = &B00010001
Const #c = &B00010101
Const #d = &B00001001
Const #e = &B00000010
Const #f = &B00010100
Const #g = &B00001011
Const #h = &B00010000
Const #i = &B00000100
Const #j = &B00011110
Const #k = &B00001101
Const #l = &B00010010
Const #m = &B00000111
Const #n = &B00000101
Const #o = &B00001111
Const #p = &B00010110
Const #q = &B00011011
Const #r = &B00001010
Const #s = &B00001000
Const #t = &B00000011
Const #u = &B00001100
Const #v = &B00011000
Const #w = &B00001110
Const #x = &B00011001
Const #y = &B00011101
Const #z = &B00010011
Const #ae = &B00011010
Const #oe = &B00010111
Const #ue = &B00011100
Const #0 = &B00111111
Const #1 = &B00111110
Const #2 = &B00111100
Const #3 = &B00111000
Const #4 = &B00110000
Const #5 = &B00100000
Const #6 = &B00100001
Const #7 = &B00100011
Const #8 = &B00100111
Const #9 = &B00101111
Const Leerz = 0
Const Anfuehrz = &B01010010
Const Kl_auf = &B00101101
Const Kl_zu = &B01101101
Const Plus = &B00101010
Const Komma = &B01110011
Const Minus = &B01100001
Const Punkt = &B01101010
Const Slash = &B00101001
Const Dopp_pkt = &B01000111
Const Gleich = &B00110001
Const Fragez = &B01001100
Const Ende = 255
Message:
' Mustertext (65 byte; Platz wäre für etwa 560 Zeichen):
Data #d , #k , #5 , #b , #u , Leerz , #b , #e , #a , #c , #o , #n , Leerz , Leerz
Data #n , #a , #m , #e , Leerz , #r , #a , #l , #f , Leerz ,
Data #q , #t , #h , Leerz , #b , #r , #e , #m , #e , #n , Leerz , Leerz
Data #p , #w , #r , Leerz , #1 , #0 , #0 , #m , #w , Leerz
Data #a , #n , #t , Leerz , #d , #i , #p , #o , #l , #e , Leerz , #u , #p , Leerz , #7 , #m ,
Data Leerz , Leerz, Plus
Data Ende