注釈
こんにちは、SunFounder Raspberry Pi & Arduino & ESP32 Enthusiast Community on Facebookへようこそ!他の愛好家と一緒に、Raspberry Pi、Arduino、ESP32の世界により深く入り込みましょう。
参加する理由
専門家サポート: 購入後の問題や技術的な課題を、コミュニティと私たちのチームの助けを借りて解決します。
学習と共有: ヒントやチュートリアルを交換して、スキルを向上させましょう。
限定プレビュー: 新製品の発表や先行プレビューに早期アクセスできます。
特別割引: 最新製品を特別割引でお楽しみいただけます。
季節限定キャンペーンとプレゼント: プレゼント企画やホリデーキャンペーンに参加しましょう。
👉 一緒に発見し、創造する準備はできましたか? [こちら] をクリックして、今すぐ参加しましょう!
(Example) AI 搭載モールス信号デコーダー
はじめに
このプロジェクトでは、ボタンの押下タイミングのパターンを AI で解釈するインテリジェントな モールス信号デコーダー を作成します。 システムは正確なタイミングデータを取得し、OpenAI の GPT を活用して、モールス信号のメッセージをリアルタイムでデコードします。主な機能は以下の通りです:
押下・解放の正確な時刻を記録する タイミングベース入力
GPT を用いた AI デコード による点・線パターンの解釈
デコード中であることを示す LED の 視覚インジケーター
入力用ボタンと制御用ボタンを分けた 2 ボタンインターフェース
入力中のタイミングデータをその場で表示する リアルタイムフィードバック
このシステムはボタンの押下時間を記録し、そのタイミングデータを AI に送って解釈させることで、世界共通の救難信号である「SOS」のようなモールス信号列を正確にデコードできます。
タイミングに敏感な入力と AI による解釈を組み合わせることで、さまざまな符号化システムに応用できます。以下も参照してください:
必要なもの
このプロジェクトに必要な部品は以下の通りです:
COMPONENT |
PURCHASE LINK |
|---|---|
購入 (x2) |
|
- |
|
Raspberry Pi |
- |
配線図
以下のように部品を Raspberry Pi に接続します:
APIキーの取得と保存
OpenAI Platform にアクセスしてログインします。 API keys ページで Create new secret key をクリックします。
必要事項(Owner、Name、Project、必要に応じて権限)を入力し、 Create secret key をクリックします。
キーが作成されたら、すぐにコピーしてください。後から再表示できません。紛失した場合は新しく作成し直す必要があります。
プロジェクトフォルダ(例:
/)内にsecret.pyというファイルを作成します:cd ~/ai-lab-kit/llm sudo nano secret.py
ファイルにキーを次のように貼り付けます:
# secret.py # Store secrets here. Never commit this file to Git. OPENAI_API_KEY = "sk-xxx"
請求設定の有効化と利用可能モデルの確認
キーを使用する前に、OpenAI アカウントの Billing ページで支払い情報を追加し、少額のクレジットをチャージしてください。
続いて Limits ページで、アカウントで利用可能なモデルを確認し、コードで使用する正確なモデルIDをコピーします。
サンプルの実行
コードを実行する
cd ~/ai-lab-kit/llm sudo python3 llm_openai_morse_decoder.py
簡単なモールス信号メッセージを試す(例:"SOS")
プログラム開始後、start/stop ボタンを押して記録を開始します。 その後、モールス用ボタンを使って、点(短押し)と線(長押し)を入力します。
入力が終わったら、もう一度 start/stop ボタンを押して記録を終了し、メッセージをデコードします。
コンソール出力を確認する
コンソールには押下/解放のタイムスタンプが表示され、AI がそのタイミングデータを解析して、 デコード結果を出力します。
"SOS" を入力したときの典型的なコンソール出力:
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".
ワークフローを理解する
記録開始:start/stop ボタン(GPIO 17)を押すと LED が ON になります
モールス信号を入力:モールス用ボタン(GPIO 22)で点と線を入力します
リアルタイム表示:コンソールに押下/解放のタイムスタンプが表示されます
停止してデコード:もう一度 start/stop ボタンを押すと LED が OFF になります
AI 解析:タイミングデータが OpenAI GPT に送られて解釈されます
デコード結果:AI が解読したメッセージを表示します
コード
以下は AI 搭載モールス信号デコーダーの 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
コードの理解
GPIO ピンの設定
3 本の GPIO ピンをそれぞれ異なる用途で設定しています:
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)
バウンスタイム(0.05 秒):メカニカルスイッチのチャタリングによる多重検出を防ぎます
プルダウン:ボタン未押下時に安定した LOW 信号を保ちます
役割分離:入力ボタンと制御ボタンを分けることで誤入力を防ぎます
タイミングデータの保存
押下/解放イベントは正確なタイムスタンプとともに保存されます:
morse_events = [] # Empty list to store events # Each event stored as tuple: ('pressed'/'released', timestamp) morse_events.append(('pressed', 1767773542.1257536)) morse_events.append(('released', 1767773542.285196))
デバウンス機構
スイッチのチャタリングによる誤検出を防ぎます:
def morse_input_released(): if release_time - start_time < 0.1: # 100ms debounce return # Ignore very short releases morse_events.append(('released', release_time))
状態管理
システムはフラグを使って記録状態を管理します:
input_active = False # Initially not recording def handle_start_stop(): if input_active: # Stop recording and decode input_active = False else: # Start recording input_active = True morse_events.clear() # Clear previous data
視覚インジケーター
LED によって記録状態を視覚的に確認できます:
def handle_start_stop(): if input_active: led.off() # LED OFF when not recording else: led.on() # LED ON when recording
AI へのプロンプト構築
タイミングデータは AI が処理しやすいよう文字列化して送信します:
input_text = str(morse_events) # Example format sent to AI: # "[('pressed', 1767773542.1257536), ('released', 1767773542.285196), ...]"
ストリーミング応答
AI の応答はリアルタイムで処理・表示されます:
response = llm.prompt(input_text, stream=True) for next_word in response: if next_word: print(next_word, end="", flush=True)
イベント駆動アーキテクチャ
ボタンイベントに対して即時にコールバックが実行されます:
# Assign callback functions to button events start_stop_button.when_activated = handle_start_stop morse_input.when_activated = morse_input_pressed morse_input.when_deactivated = morse_input_released
タイミング精度
time.time()を使って高精度のタイミングを取得します:start_time = time.time() # Current time in seconds since epoch # Calculate press duration: duration = release_time - start_time
データのクリア
デコード後は、次のメッセージ入力に備えてイベントリストをクリアします:
def decode_and_print(): # ... process events ... morse_events = [] # Clear for next message
モールス信号のタイミング基準
標準タイミング(単語 PARIS 基準):
点:1 単位
線:3 単位
文字内間隔(点・線の間):1 単位
文字間隔(文字と文字の間):3 単位
単語間隔(単語と単語の間):7 単位
実用上の目安:
点:0.3 秒未満(短押し)
線:0.5 秒超(長押し)
要素間:0.5 秒未満の間隔
文字間:0.5〜1.5 秒の間隔
単語間:1.5 秒超の間隔
よく使うモールス信号の文字:
A: • —(点・線)
B: — • • •(線・点・点・点)
C: — • — •(線・点・線・点)
S: • • •(点・点・点)
O: — — —(線・線・線)
トラブルシューティング
ボタン入力が認識されない
配線を確認してください:GPIO 22 / 17 からボタンへ、反対側は Ground へ接続
プルダウン設定を確認してください
簡単なスクリプトでテスト:
print(Pin(22, mode=Pin.IN, pull=Pin.PULL_DOWN).read())バウンスタイム設定を確認してください(0.05 秒が長すぎる場合があります)
LED が点灯しない
LED の極性を確認してください:アノード(長い脚)は抵抗を介して GPIO 27 へ
抵抗値を確認してください(220Ω 推奨)
直接テスト:
Pin(27, Pin.OUT).on()で LED が点灯するはずですGND 接続が正しく完了しているか確認してください
タイミングデータがおかしい
システムクロックを確認:
dateコマンド反応が敏感すぎる場合はデバウンス時間を下げてください
print を追加してコールバックが正しく実行されているか確認してください
一定の長さで押すテストを行ってください
AI が正しくデコードできない
API キーとインターネット接続を確認してください
AI に送っているタイミングデータを確認してください(
morse_eventsを print)押下時間を安定させてください(点は短く、線は長く)
文字の間により明確な間隔を入れてください
1 回押しただけで複数回トリガーされる
bounce_timeパラメータを増やしてください(0.1 秒など)メカニカルスイッチのチャタリングを確認してください
コンデンサによるハードウェアデバウンスを追加してください
ボタン配線が正しいか確認してください
start/stop に反応しない
他のコールバックが干渉していないか確認してください
input_activeフラグのロジックを確認してくださいhandle_start_stop()にデバッグ用 print を追加してください他のプロセスが GPIO を使用していないことを確認してください
AI の応答が遅い
インターネット接続速度を確認してください
イベント数を減らしてください(短いメッセージで試す)
代替としてローカルデコードの導入も検討してください
AI 応答にタイムアウト処理を追加してください
点と線を区別しにくい
タイミングを一定にする練習をしてください
AI への instructions 内の閾値を調整してください
AI に送る前にローカル前処理を追加してください
入力中に視覚フィードバックを追加すると分かりやすくなります
この AI 搭載モールス信号デコーダーは、正確なタイミングデータと高度なパターン認識を組み合わせることで、歴史ある通信手段を現代的に再解釈し、新しい世代にとって学びやすく親しみやすい形で活用できることを示しています。