.. include:: /index.rst
:start-after: start_hello_message
:end-before: end_hello_message
.. _py_fun_morse_code_generator:
4.4 モールス信号ジェネレーター
===========================================
**はじめに**
このプロジェクトでは、Raspberry Pi を使ってモールス信号ジェネレーターを作成します。ターミナルから文字列を入力すると、システムが対応するモールス信号をブザーと LED を使って出力します。このプロジェクトでは、基本的な GPIO 制御を学べるだけでなく、電信で歴史的に使われてきた興味深い通信手段であるモールス信号についても知ることができます。
----------------------------------------------
**必要なもの**
このプロジェクトで必要なコンポーネントは以下のとおりです。
.. list-table::
:widths: 30 20
:header-rows: 1
* - COMPONENT INTRODUCTION
- PURCHASE LINK
* - :ref:`cpn_breadboard`
- |link_breadboard_buy|
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_resistor`
- |link_resistor_buy|
* - :ref:`cpn_led`
- |link_led_buy|
* - :ref:`cpn_buzzer`
- \-
* - :ref:`cpn_transistor`
- |link_transistor_buy|
* - :ref:`cpn_fusion_hat`
- \-
* - Raspberry Pi
- \-
----------------------------------------------
**回路図**
回路図は以下のとおりです。
.. image:: img/fzz/4.1.13_sch.png
:width: 100%
:align: center
----------------------------------------------
**配線図**
以下の図に従って回路を組み立ててください。ブザーの極性に注意してください( ``+`` の付いた端子がプラス極です)。
.. image:: img/fzz/4.1.13_bb.png
:width: 80%
:align: center
----------------------------------------------
**サンプルの実行**
このチュートリアルで使用するすべてのサンプルコードは ``ai-lab-kit`` ディレクトリに含まれています。
以下の手順に従ってサンプルを実行してください。
.. raw:: html
.. code-block:: shell
cd ~/ai-lab-kit/python/
sudo python3 4.4_MorseCodeGenerator.py
* スクリプトを実行すると、ターミナルにメッセージを入力できるようになり、その内容がブザーと LED を使ってモールス信号として出力されます。
* 点(dot)は短いビープ音/短い点灯で表され、線(dash)は長いビープ音/長い点灯で表されます。
* 文字の間には短い間隔が入り、メッセージ中のスペースは単語間のより長い間隔として扱われます。
* プログラムは新しい入力を待ち続け、 ``Ctrl + C`` を押すとブザーと LED の両方をオフにして安全に終了します。
----------------------------------------------
**コード**
以下は、このプロジェクトで使用する Python コードです。
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
from fusion_hat.pin import Pin, Mode
import time
# Initialize Buzzer and LED to GPIO pins
BeepPin = Pin(22, mode=Mode.OUT)
ALedPin = Pin(17, mode=Mode.OUT)
# Morse code representation for characters
MORSECODE = {
'A': '01', 'B': '1000', 'C': '1010', 'D': '100', 'E': '0', 'F': '0010', 'G': '110',
'H': '0000', 'I': '00', 'J': '0111', 'K': '101', 'L': '0100', 'M': '11', 'N': '10',
'O': '111', 'P': '0110', 'Q': '1101', 'R': '010', 'S': '000', 'T': '1',
'U': '001', 'V': '0001', 'W': '011', 'X': '1001', 'Y': '1011', 'Z': '1100',
'1': '01111', '2': '00111', '3': '00011', '4': '00001', '5': '00000',
'6': '10000', '7': '11000', '8': '11100', '9': '11110', '0': '11111',
'?': '001100', '/': '10010', ',': '110011', '.': '010101', ';': '101010',
'!': '101011', '@': '011010', ':': '111000',
}
# Timing (seconds)
UNIT = 0.25 # base unit
DOT = UNIT / 2 # dot length
DASH = UNIT # dash length
INTRA_SYMBOL_GAP = UNIT / 2 # gap between dot/dash in one letter
LETTER_GAP = UNIT # gap between letters
WORD_GAP = UNIT * 2 # gap between words (space)
def on():
"""Turn on the buzzer and LED."""
BeepPin.on()
ALedPin.on()
def off():
"""Turn off the buzzer and LED."""
BeepPin.off()
ALedPin.off()
def beep(duration):
"""Beep (and flash LED) for 'duration' seconds."""
on()
time.sleep(duration)
off()
def play_symbol(symbol):
"""Play one morse symbol: '0' (dot) or '1' (dash)."""
if symbol == '0':
beep(DOT)
elif symbol == '1':
beep(DASH)
time.sleep(INTRA_SYMBOL_GAP)
def morsecode(text):
"""
Convert text to Morse code and output via buzzer+LED.
Supports spaces between words and ignores unsupported characters.
"""
for ch in text:
if ch == ' ':
# Space means word gap
time.sleep(WORD_GAP)
continue
# Skip unsupported characters instead of crashing
if ch not in MORSECODE:
continue
pattern = MORSECODE[ch]
for sym in pattern:
play_symbol(sym)
# Pause between letters
time.sleep(LETTER_GAP)
def destroy():
"""Ensure buzzer and LED are turned off."""
BeepPin.off()
ALedPin.off()
print("")
try:
while True:
code = input("Please input the messenger:").upper()
print(code)
morsecode(code)
except KeyboardInterrupt:
destroy()
この Python スクリプトは、ユーザーが入力したメッセージをモールス信号に変換し、ブザーと LED で出力します。動作の流れは次のとおりです。
1. **モールス信号への変換**: スクリプトは、あらかじめ定義された辞書 ``MORSECODE`` を使って、入力された文字列(英字、数字、一部の特殊文字)をモールス信号へ変換します。
2. **音と光によるモールス信号の出力**:
- 点( ``0`` )の場合、ブザーと LED は短時間だけ動作します。
- 線( ``1`` )の場合、ブザーと LED はより長い時間動作します。
3. **ユーザー入力**:
- ユーザーがメッセージを入力すると、システムはそれを対応するモールス信号に変換して出力します。
- プログラムは中断されるまで、新しいメッセージの入力を待ち続けます。
4. **安全な終了**: ``Ctrl+C`` が押されると、スクリプトは停止し、ブザーと LED をオフにして安全に終了します。
----------------------------------------------
**コードの解説**
1. **コンポーネントの設定**
ブザーと LED は、それぞれ GPIO22 と GPIO17 に初期化されています。
2. **モールス信号辞書**
モールス信号は、点を ``0``、線を ``1`` として表現しています。たとえば、 ``A`` は ``"01"`` と表されます。
3. **信号出力関数**
* ``on()`` および ``off()`` 関数は、ブザーと LED をオン/オフします。
* ``beep()`` 関数は、指定した長さの信号を出力します。
4. **モールス信号変換**
``morsecode()`` 関数は、入力メッセージの各文字を順番に処理し、モールス信号辞書に基づいて信号を出力します。
5. **メインループ**
プログラムは継続的にユーザー入力を受け取り、その内容をモールス信号に変換して出力します。 ``Ctrl+C`` を押すことで安全に終了できます。
----------------------------------------------
**トラブルシューティング**
1. **ブザーまたは LED が動作しない**
- **原因** : 配線ミス、または GPIO 設定が正しくない可能性があります。
- **対処方法** :
- ブザーが GPIO22、LED が GPIO17 に接続されていることを確認してください。
- 簡単な GPIO 制御スクリプトで、ブザーと LED を個別にテストしてください。
2. **モールス信号の出力が正しくない**
- **原因** : 入力文字が ``MORSECODE`` 辞書に含まれていません。
- **対処方法** :
- 入力には、対応している文字(A-Z、0-9、および一部の記号)のみを使用してください。
- 必要に応じて ``MORSECODE`` 辞書に文字を追加してください。
3. **信号が速すぎる、または重なって聞こえる**
- **原因** : 信号長や間隔が短すぎます。
- **対処方法** : ``morsecode()`` 関数内で使用する待機時間を調整して、より分かりやすい出力にしてください。
.. code-block:: python
pause = 0.5 # Increase pause duration for slower output
4. **入力が受け付けられない**
- **原因** : 実行環境が ``input()`` に対応していない可能性があります(例:コンソールがない環境)。
- **対処方法** : ``input()`` を利用できるターミナル環境でスクリプトを実行してください。
----------------------------------------------
**拡張アイデア**
1. **速度調整機能**: ユーザーが待機時間を入力して、モールス信号の出力速度を調整できるようにします。
.. code-block:: python
pause = float(input("Enter pause duration (seconds): "))
2. **複数デバイスでの出力**: 追加の LED やブザーを接続して、複数のデバイスで同時にモールス信号を表示します。
3. **モールス信号ログ保存**: 各メッセージのモールス信号列をファイルに保存します。
.. code-block:: python
with open("morse_log.txt", "a") as log_file:
log_file.write(f"{message} -> {morse_sequence}\n")
----------------------------------------------
**まとめ**
このプロジェクトは、Raspberry Pi を使ってモールス信号とその応用を学ぶための楽しい方法です。ブザーや LED のようなシンプルな部品を使うことで、歴史的な通信手段と現代の電子工作を結びつけるシステムを作ることができます。ぜひコードを調整しながら理解を深め、自分なりに発展させてみてください。