Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Morse-Transceiver mit Arduino UNO bauen – Optische Kommunikation per Laser & LDR

Komponenten und Materialien

Komponente Anzahl
Arduino UNO 2
Laserdiode (z. B. Keyes KY-008) 1
LED (beliebig) 2
Fotowiderstand (LDR) 1
Piezo-Summer (aktiv) 1

Projektidee

Im Rahmen eines Kommunikationssysteme-Kurses sollte Morse-Code nicht nur theoretisch, sondern erlebbar vermittelt werden. Statt den Code manuell zu lernen, bauten wir ein Gerät, das Text in Morse umwandelt, per Laser überträgt und auf der Empfängerseite wieder in Text decodiert.

Funktionsprinzip

Codierung: Lookup-Tabelle

Jedes ASCII-Zeichen wird über ein Array (MorseTable) auf seine Morse-Darstellung (Punkte und Striche) abgebildet. Die Tabelle deckt Ziffern, Buchstaben (Groß-/Kleinschreibung identisch) und gängige Satzzeichen ab.

Decodierung: Binärer Baum

Morse-Code lässt sich als binärer Baum darstellen: Punkt = links, Strich = rechts. Der Baum wird als Array MorseTree abgelegt (Index 0 ungenutzt, Kind-Indizes: 2n+1 / 2n+2). Beim Empfang wird der Baum durchlaufen, bis eine Pause das Zeichen beendet.

Timing (Sender)

Empfang & Erkennung

Der LDR wird in einer abgedunkelten Röhre vor Fremdlicht geschützt. Die Analogwert-Schwelle (≥ 10) trennt „Licht“ von „Dunkel“. Die Dauer des Hochpegels wird in Zyklen gezählt (ca. 400 Zyklen ≈ 50 ms bei 16 MHz).

Sender-Schaltung

Empfänger-Schaltung

Sender-Code (Transmitter)

const char* MorseTable[] = {
  // Indizes 0-31: Steuerzeichen, Leerzeichen, ! " # $ % & '
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  NULL, "-.-.--", ".-..-.", NULL, NULL, NULL, NULL, ".----.", // ( ) * + , - . /
  "-.--.", "-.--.-", NULL, ".-.-.", "--..--", "-....-", ".-.-.-", "-..-.",
  // 0-9
  "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...",
  "---..", "----.", "---...", "-.-.-.", NULL, "-...-", NULL, "..--..",
  // @ A-Z
  ".--.-.", ".-", "-...", "-.-.", "-..", ".", "..-.", "--.",
  "....", "..", ".---", "-.-", ".-..", "--", "-.", "---",
  ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--",
  "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, "..--.-",
  // ` a-z (identisch mit A-Z)
  NULL, ".-", "-...", "-.-.", "-..", ".", "..-.", "--.",
  "....", "..", ".---", "-.-", ".-..", "--", "-.", "---",
  ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--",
  "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, NULL
};

int dotLength = 50;
int dashLength = dotLength * 3;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    char ch = Serial.read();
    flashDashDot(MorseTable[(int)ch]);
    delay(dotLength * 2); // Zeichenpause
  }
}

void flashDashDot(const char* morseCode) {
  if (!morseCode) return;
  for (int i = 0; morseCode[i]; i++) {
    if (morseCode[i] == '.') dot();
    else if (morseCode[i] == '-') dash();
  }
}

void dot() {
  digitalWrite(13, HIGH);
  delay(dotLength);
  digitalWrite(13, LOW);
  delay(dotLength);
}

void dash() {
  digitalWrite(13, HIGH);
  delay(dashLength);
  digitalWrite(13, LOW);
  delay(dotLength);
}

Empfänger-Code (Receiver)

// Morse Binärbaum: Index 0 = Root, Links=2n+1, Rechts=2n+2
const char MorseTree[] = {
  '\0','E','T','I','A','N','M','S','U','R','W','D','K','G','O',
  'H','V','F','U','L','A','P','J','B','X','C','Y','Z','Q',
  '\0','\0','5','4','\0','3','\0','\0','\0','2',
  '\0','\0','+','\0','\0','\0','\0','1','6','=','/','\0','\0','\0','(',
  '\0','7','\0','\0','\0','8','\0','9','0',
  // ... weitere Zeichen (?, _, ", ., @, -, ;, !, ), ,, :) ...
  // Vollständiges Array siehe Originalcode
};

int val = 0;
int ctrHigh = 0;
int ctrLow = 0;
int codePtr = 0;
int dotLen = 400; // Zyklen für einen Punkt

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  pinMode(9, OUTPUT); // Summer
}

void loop() {
  val = analogRead(A4); // LDR an A4

  if (val >= 10) { // Licht erkannt
    ctrHigh++;
    ctrLow = 0;
    digitalWrite(13, HIGH);
    tone(9, 1000);
  } else { // Dunkel
    ctrLow++;
    if (ctrHigh >= dotLen && ctrHigh < dotLen * 2) {
      Serial.print(".");
      codePtr = (2 * codePtr) + 1; // Links
    } else if (ctrHigh >= dotLen * 2) {
      Serial.print("-");
      codePtr = (2 * codePtr) + 2; // Rechts
    } else {
      if (ctrLow == dotLen * 2) { // Zeichenpause
        Serial.print(MorseTree[codePtr]);
        codePtr = 0;
      }
    }
    ctrHigh = 0;
    digitalWrite(13, LOW);
    noTone(9);
  }
}

Beispielausgabe

Sender-Eingabe: Hello World
Sender-Serial: .... . .-.. .-.. --- .-- --- .-. .-.. -..
Empfänger-Serial: ....H.E.-..L.-..L---O.--W---O.-.R.-..L-..D-.-.--!

Tipps & Erweiterungen

Schaltpläne

Fritzing-Dateien für Sender- und Empfänger-Schaltung liegen bei (morsetransmitter.fzz, morsereceiver.fzz).

Herstellungsprozess

  1. Strichcodescanner: Technologie, Design und Zukunftstrends
  2. C++-Kommentare: Best Practices für lesbaren, wartbaren Code
  3. ADC Code Error Rates meistern: Was Sie wissen müssen
  4. Morse-Code und Double Extortion: Aktuelle Landschaft fortgeschrittener Malware-Bedrohungen
  5. DTMF-Decoder mit Arduino bauen – ganz ohne zusätzlichen IC
  6. SERENA: Eigenes Arduino Mega 2560 Alarmsystem mit TFT-LCD-Touchscreen
  7. Data Matrix vs. QR Codes: Welcher ist am besten für Ihr Business?
  8. CNC G-Codes erklärt: Essentieller Leitfaden für CNC-Programmierer
  9. Komplette Fanuc G-Code Referenz – Alle Befehle erklärt
  10. Umfassender Leitfaden zu CNC G-Codes für Fanuc Steuerungen