Programme Leitung Oszilloskop seriell0 NetzHW_seriell Morsen Senden/Empfangen RS232 Terminal3 Terminal4 Fehlerkorrektur Threads CTS-Interrupt Routing Socket-Programmierung Timer Java Spiel
Pfad: Startseite / Fächer / Informatik / Netze / Programme / Morsen
Autor: mk
20.01.2011 18:07
2809
Morsen

Achtung

Die folgenden Delphi-Programme enthalten den Protokollfehler, dass die Pause zwischen gesendeten Buchstaben fälschlich nur 2 Dit statt 3 Dit lang ist.

Akustischer Sender

Der Sender hält sich an die bei wikipedia veröffentlichten Details des Morse-Codes und verwendet auch die gleiche Syntax für den Sendestring.

GUI zu Morse-Sender 0 MorseSender0.zip Klassendiagramm zu Sender 0

Es folgen Auszüge aus dem Quellcode:

//-------- create (public) ---------------------------------------------
constructor TMorseSender.create;
begin
  inherited create;
  dit := 100;
  frequenz := 2000;
end;

//-------- sende (public) ----------------------------------------------
procedure TMorseSender.sende (mstr: string);
var
  i,n : integer;
begin
  n := Length(mstr);
  for i := 1 to n do
  begin
    case mstr[i] of
      '.' : begin
              windows.Beep(frequenz,dit);
              sleep(dit);
            end;
      '-' : begin
              windows.Beep(frequenz,3*dit);
              sleep(dit);
            end;
      ' ' : begin
              sleep(dit);   // 1 dit Pause bereits hinter Symbol . oder -
            end;
      '/' : begin
              sleep(6*dit); // 1 dit Pause bereits hinter Symbol . oder -
            end;
    end; // of case
  end;
end;

Morse-Sender über serielle Schnittstelle

GUI zu Morse-Sender 1 Klassendiagramm zu Sender 1 MorseSender1.zip

Empfänger für serielle Schnittstelle mit grafischer Protokollierung

GUI zum Morse-Empfänger 1 MorseEmpfaenger1.zip

Morse-Empfänger

Grundprinzip

Prinzip des Empfängers Das eingehende Signal wird mit Hilfe eine Timers permanent "abgetastet". Es werden immer zwei aufeinander folgende Zustände in alterzustand und zustand gespeichert.

ansteigende Flanke

Pause Eine "ansteigende Flanke" ansteigende Flanke kann dann durch (alterzustand = false) and (zustand = true) detektiert werden. Über den QueryPerformanceCounter wird die momentane Systemzeit tauf bestimmt. Geht man zunächst davon aus, dass analog bei der fallenden Flanke tab bestimmt wurde, so kann die Pausenlänge mit pLaenge := tauf - tab; bestimmt werden.

fallende Flanke

Impuls Eine "fallende Flanke" ansteigende Flanke kann dann durch (alterzustand = true) and (zustand = false) detektiert werden. Über den QueryPerformanceCounter wird die momentane Systemzeit tab bestimmt. Geht man zunächst davon aus, dass analog bei der steigenden Flanke tauf bestimmt wurde, so kann die Impulslänge mit iLaenge := tab - tauf; bestimmt werden.

Quelltext-Auszug
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  zustand := HW.GetEin;
  if (alterzustand = false) and (zustand = true) // auf
  then
  begin
    QueryPerformanceCounter(n); tauf := n/c;
    pLaenge := tauf-tab;
    if (1.5*dit < pLaenge) and (pLaenge < 2.5*dit)
    then puffer := puffer+' ';
    if (6*dit < pLaenge) and (pLaenge < 8*dit)
    then puffer := puffer+'/';
  end;
  if (alterzustand = true) and (zustand = false) // ab
  then
  begin
    QueryPerformanceCounter(n); tab := n/c;
    iLaenge := tab-tauf;
    if (0.5*dit < iLaenge) and (iLaenge < 1.5*dit)
    then puffer := puffer+'.';
    if (2.5*dit < iLaenge) and (iLaenge < 3.5*dit)
    then puffer := puffer+'-';
  end;
  alterzustand := zustand;
end;

MorseEmpfaenger2.zip

Klassendiagramm Empfänger

Morse-Codierer/-Decodierer

Klassendiagramm Codierer mTMorseKodierer.zip

Morse-Sender mit Codierung

GUI zu Morse-Sender 2 MorseSender2.zip, exe-Dateien: MorseSender2_1.zip, MorseSender2_2.zip

Morse-Empfänger mit Decodierung

GUI zu Morse-Empfänger mit Decodierung MorseEmpfaenger3.zip, exe-Dateien: MorseEmpfaenger3_1.zip, MorseEmpfaenger3_2.zip

Elemente einer Python-Realisierung

import threading
import time

class Timer(threading.Thread):
    def __init__(self,interval,routine):
        threading.Thread.__init__(self)
        self.interval = interval
        self.routine = routine

    def run(self):
        time.sleep(self.interval)
        self.routine()

import serial

import sys

def zeit():
    if sys.platform == 'linux2':
        return time.time()                 # fuer Linux
    else:
        return time.clock()

class Empf(object):
    def __init__(self,ser,dit=0.1):
        self.puffer = ''
        self.s = ser                       # serielle Schnittstelle
        self.akt = None                    # aktueller Zustand
        self.alt = self.s.getCTS()         # alter Zustand
        self.auf = 0                       # Zeit bei ansteigender Flanke
        self.ab = 0                        # Zeit bei abfallender Flanke
        self.dit = dit                     # dit-Zeit 
        self.interval = 0.01               # Polling-Intervall
        self.enabled = True
        self.timer = Timer(self.interval,self.poll)
        self.timer.start()

    def __del__(self):
        self.s.close()

    def poll(self):
        # Pollingroutine
        self.akt = self.s.getCTS()
        if not self.alt and self.akt:      # ansteigende Flanke
            self.auf = zeit()
            pausenlaenge = self.auf - self.ab 
            if 2.5*self.dit < pausenlaenge < 3.5*self.dit:
                self.puffer = self.puffer + ' '
                print(self.puffer)             # DEBUG
            elif 6*self.dit < pausenlaenge < 8*self.dit:
                self.puffer = self.puffer + '/'
                print(self.puffer)             # DEBUG
        elif self.alt and not self.akt:    # fallende Flanke
            self.ab = zeit()
            impulslaenge = self.ab - self.auf
            if 0.5*self.dit < impulslaenge < 1.5*self.dit:
                self.puffer = self.puffer + '.'
                print(self.puffer)             # DEBUG
            elif 2.5*self.dit < impulslaenge < 3.5*self.dit:
                self.puffer = self.puffer + '-'
                print(self.puffer)             # DEBUG
        self.alt = self.akt
        # Polling fortsetzen              
        if self.enabled:
            self.timer = Timer(self.interval,self.poll)
            self.timer.start()

s = serial.Serial('/dev/ttyS0')

e = Empf(s)

Test

Es wurde 'ABC' mit dit = 0,1s gesendet. Bitte beachten, wie der Empfänger ausgeschaltet wird.

>>> .
.-
.- 
.- -
.- -.
.- -..
.- -...
.- -... 
.- -... -
.- -... -.
.- -... -.-
.- -... -.-.
e.enabled = False
>>> 

Links