メインコンテンツへスキップ

LLMが行う。スマホのボタン画面からマイコン(ESP32等?)を制御する設計からソースまでの実験

    全4部くらい   ソース等未確認

    大丈夫かな?Claude 。でも旧バージョンの仕様書があってそこからの焼き直しぐらいなら十分にできる(と思う)そういうものがないと、今回程度の完全新規は無理。

    Powered by Claude 
    ================================================================================
    スマホ上のボタン画面からマイコン(ESP32)を制御する実験 #1
    打ち合わせまとめ&ソースコード
    作成日:2026年4月25日
    ================================================================================

    ■ 大枠

    マイコン(ESP8266,32)をWiFi経由でスマートフォンから制御するシステムの実験。
    スマホ側はRustで実装する方針だが、まずはPCで動作確認できるアプリを先に作成する。
    マイコン側はMicroPythonで実装予定(次フェーズ)。

    ■ 今回のスコープ(#1)

    - PC上でRust+SlintによるGUIアプリを作成
    - ボタンを2つ表示し、押すとブザー音(サイン波)が鳴る
    - 外部WAVファイル不要。rodioクレートでプログラム的に音を生成
    - ESP32との通信は今回スコープ外

    ■ 使用技術

    項目 内容
    -------- --------------------------------
    実装言語 Rust
    GUIフレームワーク Slint(ビジュアルデザイナー対応)
    音声生成 rodio クレート(サイン波生成)
    対象OS Windows / Linux / macOS
    マイコン側 MicroPython(次フェーズ)

    ■ 画面仕様

    - ウィンドウサイズ:480 x 320 px
    - ボタンA:880 Hz(高音)
    - ボタンB:440 Hz(低音)
    - 音声遅延:200ms以内
    - 外部ファイル不要(アプリ内サイン波生成)

    ■ 今後の予定

    #2 ESP32側をMicroPythonで実装(WebサーバorWebSocket)
    #3 PCアプリからESP32へ制御コマンド送信
    #4 Android版へ移植(Rust+Slint Android対応)

    ================================================================================
    ソースコード
    ================================================================================

    --------------------------------------------------------------------------------
    【1】 Cargo.toml
    --------------------------------------------------------------------------------
    [package]
    name = "soundboard"
    version = "0.1.0"
    edition = "2021"

    [dependencies]
    slint = "1.5"
    rodio = "0.19"

    [build-dependencies]
    slint-build = "1.5"


    --------------------------------------------------------------------------------
    【2】 build.rs
    --------------------------------------------------------------------------------
    fn main() {
    slint_build::compile("ui/main.slint").unwrap();
    }


    --------------------------------------------------------------------------------
    【3】 ui/main.slint
    --------------------------------------------------------------------------------
    import { Button, VerticalBox, HorizontalBox } from "std-widgets.slint";

    export component MainWindow inherits Window {
    title: "SoundBoard — Rust / Slint";
    width: 480px;
    height: 320px;
    background: #f5f5f5 ;

    callback button_a_pressed();
    callback button_b_pressed();

    VerticalBox {
    alignment: center;
    spacing: 32px;

    Text {
    text: "ボタンを押して音を鳴らす";
    font-size: 16px;
    horizontal-alignment: center;
    color: #555555 ;
    }

    HorizontalBox {
    alignment: center;
    spacing: 32px;

    Rectangle {
    width: 160px;
    height: 80px;
    background: white;
    border-radius: 8px;
    border-width: 1px;
    border-color: #cccccc ;

    ta_a := TouchArea {
    clicked => { root.button_a_pressed(); }
    }

    VerticalBox {
    alignment: center;
    Text {
    text: "BUTTON A";
    font-size: 16px;
    font-weight: 600;
    horizontal-alignment: center;
    color: ta_a.pressed ? #333333 : #000000 ;
    }
    Text {
    text: "880 Hz";
    font-size: 12px;
    horizontal-alignment: center;
    color: #888888 ;
    }
    }
    }

    Rectangle {
    width: 160px;
    height: 80px;
    background: white;
    border-radius: 8px;
    border-width: 1px;
    border-color: #cccccc ;

    ta_b := TouchArea {
    clicked => { root.button_b_pressed(); }
    }

    VerticalBox {
    alignment: center;
    Text {
    text: "BUTTON B";
    font-size: 16px;
    font-weight: 600;
    horizontal-alignment: center;
    color: ta_b.pressed ? #333333 : #000000 ;
    }
    Text {
    text: "440 Hz";
    font-size: 12px;
    horizontal-alignment: center;
    color: #888888 ;
    }
    }
    }
    }

    Text {
    text: "待機中";
    font-size: 13px;
    horizontal-alignment: center;
    color: #aaaaaa ;
    }
    }
    }


    --------------------------------------------------------------------------------
    【4】 src/main.rs
    --------------------------------------------------------------------------------
    use rodio::{OutputStream, Sink, source::SineWave, Source};
    use std::time::Duration;

    slint::include_modules!();

    fn play_tone(freq: f32) {
    // OutputStream はスレッドをまたげないので都度生成
    let Ok((_stream, stream_handle)) = OutputStream::try_default() else {
    eprintln!("音声デバイスが見つかりません");
    return;
    };
    let Ok(sink) = Sink::try_new(&stream_handle) else {
    return;
    };

    // サイン波を生成して 0.4 秒だけ再生
    let source = SineWave::new(freq)
    .take_duration(Duration::from_millis(400))
    .amplify(0.5);

    sink.append(source);
    sink.sleep_until_end(); // 再生完了まで待機
    }

    fn main() -> Result<(), slint::PlatformError> {
    let ui = MainWindow::new()?;

    // BUTTON A(880 Hz・高音)
    let ui_handle = ui.as_weak();
    ui.on_button_a_pressed(move || {
    let _ = ui_handle.upgrade();
    std::thread::spawn(|| play_tone(880.0));
    });

    // BUTTON B(440 Hz・低音)
    let ui_handle2 = ui.as_weak();
    ui.on_button_b_pressed(move || {
    let _ = ui_handle2.upgrade();
    std::thread::spawn(|| play_tone(440.0));
    });

    ui.run()
    }


    --------------------------------------------------------------------------------
    【ビルド・実行方法】
    --------------------------------------------------------------------------------
    # Rustが未インストールの場合
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

    # ビルド&実行
    cd soundboard
    cargo run

    # リリースビルド(配布用)
    cargo build --release
    # 実行ファイル:target/release/soundboard(Windows: .exe)

    ================================================================================
    以上
    ========================================================

     
     
    備忘録です。ほとんど、全部LLMがWriterです。内容等は 無保証、あるがままです。 書いた人がLLMですので嘘が多いです、マジ。備忘録のため内容確認せずあげてる場合もあります。 書きかけ、途中等もあります。 古い記事は陳腐化している場合がある!!

    あなたへのおすすめ