.. include:: /index.rst
:start-after: start_hello_message
:end-before: end_hello_message
.. _py_morse_code_decoder:
(Beispiel) AI-gestützter Morsecode-Decoder
=========================================================
**Einführung**
Dieses Projekt erstellt einen intelligenten **Morsecode-Decoder**, der AI verwendet, um Zeitmuster von Tastendrücken zu interpretieren. Das System erfasst präzise Zeitdaten und nutzt OpenAIs GPT, um Morsecode-Nachrichten in Echtzeit zu dekodieren. Der Decoder bietet:
1. **Zeitbasierte Eingabe**, die genaue Druck- und Loslasszeiten erfasst
2. **AI-gestützte Dekodierung** mit GPT zur Interpretation von Punkt-/Strichmustern
3. **Visuellen Indikator** mit einer LED, die den aktiven Dekodierzustand anzeigt
4. **Dual-Button-Oberfläche** mit getrennten Tasten für Eingabe und Steuerung
5. **Echtzeit-Feedback**, das die Zeitdaten während der Eingabe anzeigt
.. raw:: html
Das System zeichnet die Dauer der Tastendrücke auf, sendet die Zeitdaten zur Interpretation an die AI und dekodiert Morsecode-Sequenzen wie das universelle Notsignal „SOS“ zuverlässig.
Sie können zeitkritische Eingaben mit AI-Interpretation für verschiedene Codierungssysteme kombinieren. Siehe:
* :ref:`py_online_llm`
----------------------------------------------
**Was Sie benötigen**
Für dieses Projekt werden die folgenden Komponenten benötigt:
.. list-table::
:widths: 30 20
:header-rows: 1
* - COMPONENT
- PURCHASE LINK
* - :ref:`cpn_button`
- |link_button_buy| (x2)
* - :ref:`cpn_led`
- |link_led_buy|
* - :ref:`cpn_resistor`
- |link_resistor_buy|
* - :ref:`cpn_fusion_hat`
- \-
* - :ref:`cpn_wires`
- |link_wires_buy|
* - Raspberry Pi
- \-
----------------------------------------------
**Schaltplan**
Verbinden Sie die Komponenten wie folgt mit dem Raspberry Pi:
.. image:: img/fzz/morse_decoder_bb.png
:width: 80%
:align: center
----------------------------------------------
.. include:: python_online_llms.rst
:start-after: start_setup_openai
:end-before: end_setup_openai
----------------------------------------------
**Beispiel ausführen**
#. Code ausführen
.. raw:: html
.. code-block:: shell
cd ~/ai-lab-kit/llm
sudo python3 llm_openai_morse_decoder.py
#. Eine einfache Morsecode-Nachricht ausprobieren (Beispiel: "SOS")
Nachdem das Programm gestartet wurde, drücken Sie die Start-/Stopp-Taste, um die Aufzeichnung zu beginnen.
Drücken Sie dann die Morse-Taste, um Punkte (kurze Tastendrücke) und Striche (lange Tastendrücke) einzugeben.
Wenn Sie fertig sind, drücken Sie die Start-/Stopp-Taste erneut, um die Aufzeichnung zu beenden und die Nachricht zu dekodieren.
#. Konsolenausgabe prüfen
Die Konsole zeigt die Zeitstempel für Tastendruck und Loslassen an, und die AI analysiert die Zeitdaten
und gibt die dekodierte Nachricht aus.
**Typische Konsolenausgabe bei der Eingabe von "SOS":**
.. code-block:: text
To decode the Morse code message based on the button press times provided, we need to interpret the duration of each press. Typically, a short press (dot) is around 0.2 to 0.3 seconds, while a long press (dash) is about 0.5 seconds or longer. Let's analyze the press durations:
1. `1767773542.1257536` to `1767773542.285196` - Duration: ~0.16 seconds - Dot (.)
2. `1767773542.4936137` to `1767773542.6315389` - Duration: ~0.14 seconds - Dot (.)
3. `1767773542.9092748` to `1767773543.0543947` - Duration: ~0.15 seconds - Dot (.)
4. `1767773544.2299025` to `1767773544.5774245` - Duration: ~0.35 seconds - Dash (-)
5. `1767773545.1017563` to `1767773545.4954002` - Duration: ~0.39 seconds - Dash (-)
6. `1767773546.11932` to `1767773546.5881057` - Duration: ~0.47 seconds - Dash (-)
7. `1767773547.824543` to `1767773547.9534554` - Duration: ~0.13 seconds - Dot (.)
8. `1767773548.1879761` to `1767773548.2895174` - Duration: ~0.10 seconds - Dot (.)
9. `1767773548.5281847` to `1767773548.6453152` - Duration: ~0.12 seconds - Dot (.)
Now let's decode the sequence into letters using Morse code:
- `...` (Dot Dot Dot) = S
- `---` (Dash Dash Dash) = O
- `...` (Dot Dot Dot) = S
Putting it all together, the decoded message is "SOS".
#. Den Ablauf verstehen
1. Aufzeichnung starten: Drücken Sie die Start-/Stopp-Taste (GPIO 17), und die LED leuchtet auf
2. Morsecode eingeben: Verwenden Sie die Morse-Taste (GPIO 22) für Punkte und Striche
3. Echtzeitanzeige: Die Konsole zeigt Zeitstempel für Tastendruck und Loslassen
4. Stoppen und dekodieren: Drücken Sie die Start-/Stopp-Taste erneut, und die LED erlischt
5. AI-Analyse: Die Zeitdaten werden zur Interpretation an OpenAI GPT gesendet
6. Dekodierte Ausgabe: Die AI gibt die dekodierte Nachricht aus
**Code**
Hier ist das vollständige Python-Skript für den AI-gestützten Morsecode-Decoder:
.. raw:: html
.. code-block:: python
from fusion_hat.llm import OpenAI
from secret import OPENAI_API_KEY
from fusion_hat.pin import Pin
import random, time
# Register OpenAI API
# openai.com
# Export your openai api key with :LLM_API_KEY
# export LLM_API_KEY=sk-xxxxxxxxxxxxxxxxx
# Setup GPIO pins
morse_input = Pin(22, mode=Pin.IN, pull=Pin.PULL_DOWN, bounce_time=0.05)
start_stop_button = Pin(17, mode=Pin.IN, pull=Pin.PULL_DOWN, bounce_time=0.05)
led = Pin(27, Pin.OUT) # Indicator LED on GPIO 27
# Store the morse code events with timing data
morse_events = []
input_active = False # Flag to indicate if input is active
# Setup LLM with Morse code decoding instructions
INSTRUCTIONS = "You are a Morse code decoder. Decode based on the button press time, interpreting short presses as dots and long presses as dashes. The message you receive may be a word or a sentence, please decode it and output it."
WELCOME = "Hello, I am a Morse code decoder. Please press the button to start decoding. When you are done, press the button again to stop."
llm = OpenAI(
api_key=OPENAI_API_KEY,
model="gpt-4o",
)
# Set how many messages to keep
llm.set_max_messages(20)
# Set instructions
llm.set_instructions(INSTRUCTIONS)
# Set welcome message
llm.set_welcome(WELCOME)
print(WELCOME)
# Send the morse code timing data to the AI for decoding
def decode_and_print():
global morse_events
# Convert timing events to string for AI processing
input_text = str(morse_events)
# Get response from AI with streaming
response = llm.prompt(input_text, stream=True)
# Print streaming response
for next_word in response:
if next_word:
print(next_word, end="", flush=True)
print("") # New line after complete response
morse_events = [] # Clear the morse code events for next message
# Morse code input handling variables
start_time = 0
# Function called when morse input button is pressed
def morse_input_pressed():
global start_time
start_time = time.time()
morse_events.append(('pressed', start_time))
print(f" Pressed at {start_time} -", end="")
# Function called when morse input button is released
def morse_input_released():
global morse_events, start_time
release_time = time.time()
# Debounce: ignore releases within 0.1 seconds
if release_time - start_time < 0.1:
return
morse_events.append(('released', release_time))
print(f" {release_time}")
# Start/stop button handler
def handle_start_stop():
global input_active, morse_events
if input_active:
# Stop recording and decode
led.off()
print("Input stopped and decoded.")
decode_and_print()
input_active = False
else:
# Start recording new message
input_active = True
morse_events.clear() # Clear previous events
led.on()
print("Input started.")
# Add event listeners to buttons
start_stop_button.when_activated = handle_start_stop
morse_input.when_activated = morse_input_pressed
morse_input.when_deactivated = morse_input_released
# Main program loop
try:
while True:
time.sleep(0.1)
except KeyboardInterrupt:
pass
----------------------------------------------
**Code verstehen**
1. GPIO-Pin-Konfiguration
Drei GPIO-Pins werden für unterschiedliche Zwecke konfiguriert:
.. code-block:: python
morse_input = Pin(22, mode=Pin.IN, pull=Pin.PULL_DOWN, bounce_time=0.05)
start_stop_button = Pin(17, mode=Pin.IN, pull=Pin.PULL_DOWN, bounce_time=0.05)
led = Pin(27, Pin.OUT)
- Entprellzeit (0.05 s): Verhindert Mehrfachauslösungen durch mechanisches Prellen des Schalters
- Pull-down: Sorgt für ein stabiles LOW-Signal, wenn die Taste nicht gedrückt ist
- Getrennte Funktionen: Eingabe- und Steuertasten verhindern versehentliche Eingaben
2. Speicherung der Zeitdaten
Druck- und Loslassereignisse werden mit präzisen Zeitstempeln gespeichert:
.. code-block:: python
morse_events = [] # Leere Liste zur Speicherung der Ereignisse
# Jedes Ereignis wird als Tupel gespeichert: ('pressed'/'released', Zeitstempel)
morse_events.append(('pressed', 1767773542.1257536))
morse_events.append(('released', 1767773542.285196))
3. Entprellmechanismus
Verhindert Fehlauslösungen durch Prellen des Schalters:
.. code-block:: python
def morse_input_released():
if release_time - start_time < 0.1: # 100 ms Entprellung
return # Sehr kurze Signale ignorieren
morse_events.append(('released', release_time))
4. Zustandsverwaltung
Das System verwendet ein Flag, um den Aufzeichnungszustand zu verfolgen:
.. code-block:: python
input_active = False # Anfangszustand: keine Aufzeichnung
def handle_start_stop():
if input_active:
# Aufzeichnung stoppen und dekodieren
input_active = False
else:
# Aufzeichnung starten
input_active = True
morse_events.clear() # Vorherige Daten löschen
5. Visueller Indikator
Die LED zeigt den Aufzeichnungsstatus visuell an:
.. code-block:: python
def handle_start_stop():
if input_active:
led.off() # LED AUS, wenn nicht aufgezeichnet wird
else:
led.on() # LED EIN während der Aufzeichnung
6. Erstellung des AI-Prompts
Die Zeitdaten werden für die AI-Verarbeitung in einen String umgewandelt:
.. code-block:: python
input_text = str(morse_events)
# Beispiel für das an die AI gesendete Format:
# "[('pressed', 1767773542.1257536), ('released', 1767773542.285196), ...]"
7. Streaming-Antwort
Die AI-Antwort wird in Echtzeit verarbeitet und angezeigt:
.. code-block:: python
response = llm.prompt(input_text, stream=True)
for next_word in response:
if next_word:
print(next_word, end="", flush=True)
8. Ereignisgesteuerte Architektur
Tastenevents lösen sofort Callback-Funktionen aus:
.. code-block:: python
# Callback-Funktionen den Tastenereignissen zuweisen
start_stop_button.when_activated = handle_start_stop
morse_input.when_activated = morse_input_pressed
morse_input.when_deactivated = morse_input_released
9. Zeitmessungsgenauigkeit
Verwendet ``time.time()`` für Zeitmessungen mit hoher Genauigkeit:
.. code-block:: python
start_time = time.time() # Aktuelle Zeit in Sekunden seit der Unix-Epoche
# Dauer des Tastendrucks berechnen:
duration = release_time - start_time
10. Daten zurücksetzen
Nach der Dekodierung wird die Ereignisliste für die nächste Nachricht geleert:
.. code-block:: python
def decode_and_print():
# ... Ereignisse verarbeiten ...
morse_events = [] # Für nächste Nachricht zurücksetzen
----------------------------------------------
**Morsecode-Zeitstandards**
* Standardzeit (basierend auf dem Wort PARIS):
- Punkt: 1 Einheit
- Strich: 3 Einheiten
- Abstand innerhalb eines Zeichens (zwischen Punkten/Strichen): 1 Einheit
- Abstand zwischen Buchstaben: 3 Einheiten
- Abstand zwischen Wörtern: 7 Einheiten
* Praktische Umsetzung:
- Punkt: < 0.3 Sekunden (kurzer Tastendruck)
- Strich: > 0.5 Sekunden (langer Tastendruck)
- Abstand zwischen Elementen: < 0.5 Sekunden Pause
- Abstand zwischen Buchstaben: 0.5–1.5 Sekunden Pause
- Abstand zwischen Wörtern: > 1.5 Sekunden Pause
* Häufige Morsezeichen:
- A: • — (Punkt-Strich)
- B: — • • • (Strich-Punkt-Punkt-Punkt)
- C: — • — • (Strich-Punkt-Strich-Punkt)
- S: • • • (Punkt-Punkt-Punkt)
- O: — — — (Strich-Strich-Strich)
----------------------------------------------
**Fehlerbehebung**
- Tastendrücke werden nicht erkannt
- Verkabelung prüfen: GPIO 22/17 zur Taste, andere Seite an Masse
- Pull-down-Konfiguration überprüfen
- Mit einfachem Skript testen: ``print(Pin(22, mode=Pin.IN, pull=Pin.PULL_DOWN).read())``
- Entprellzeit prüfen (0.05 s könnte zu hoch sein)
- LED leuchtet nicht
- Polarität der LED prüfen: Anode (langes Bein) über Widerstand an GPIO 27
- Widerstandswert prüfen (220 Ω empfohlen)
- LED direkt testen: ``Pin(27, Pin.OUT).on()`` sollte LED einschalten
- Masseverbindung überprüfen
- Zeitdaten wirken falsch
- Systemuhr prüfen: ``date``
- Entprellzeit reduzieren, wenn zu empfindlich
- Debug-Ausgaben hinzufügen, um Callback-Ausführung zu prüfen
- Gleichmäßige Tastendrücke testen
- AI dekodiert falsch
- API-Schlüssel und Internetverbindung prüfen
- Gesendete Zeitdaten überprüfen (``print(morse_events)``)
- Konsistente Tastendrücke verwenden (Punkte kurz, Striche lang)
- Klarere Pausen zwischen Buchstaben machen
- Mehrfachauslösung bei einem Tastendruck
- ``bounce_time`` erhöhen (z. B. 0.1 s)
- Mechanisches Prellen des Schalters prüfen
- Hardware-Entprellung mit Kondensator hinzufügen
- Verkabelung der Taste prüfen
- System reagiert nicht auf Start/Stopp
- Prüfen, ob andere Callback-Funktionen stören
- Logik der Variable ``input_active`` überprüfen
- Debug-Ausgaben in ``handle_start_stop()`` hinzufügen
- Sicherstellen, dass kein anderer Prozess GPIO verwendet
- AI-Antwort zu langsam
- Internetgeschwindigkeit prüfen
- Anzahl der Ereignisse reduzieren (kürzere Nachrichten)
- Lokale Dekodierung als Fallback verwenden
- Timeout für AI-Antwort implementieren
- Punkte und Striche schwer unterscheidbar
- Gleichmäßiges Timing üben
- Schwellenwerte in den AI-Anweisungen anpassen
- Lokale Vorverarbeitung vor dem Senden an die AI hinzufügen
- Visuelles Feedback während der Eingabe verwenden
----------------------------------------------
Dieser AI-gestützte Morsecode-Decoder zeigt, wie präzise Zeitmessungen mit intelligenter Mustererkennung kombiniert werden können, um historische Kommunikationsmethoden neu zu beleben und sie für neue Generationen zugänglich und lehrreich zu machen.