AtTiny13-Morse-Baken        

von Ralf Beesner, DK5BU                
Elektronik-Labor   Projekte   AVR 




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


Elektronik-Labor   Projekte   AVR