🧠

組込 Rust on ESP32 をやっていたと思ったらターミナルが汚染されてすごいことに……

2025/02/23に公開

Result

ターミナルに延々と HelloButton! と表示される

問題のコード

main.rs
use esp_idf_hal::prelude::*;
use esp_idf_hal::gpio::PinDriver;
use esp_idf_sys::EspError;

fn main() -> Result<(), EspError> {
    esp_idf_svc::log::EspLogger::initialize_default();

    let peripherals = Peripherals::take().unwrap();
    let pin = PinDriver::input(peripherals.pins.gpio35)?;

    loop {
        if pin.is_low() {
            println!("HelloButton!")
        }
    }
}

解決したい

  • else で待機してほしいので「組み込み 待機」などで調べる
  • 「組み込み」部分がややこしい記事を出してくる(自分は Arduino くらいのことからスタートしたいのに……)
  • なので「Arduino 待機」で調べる

参考文献を見つけて,else に空を置く

main.rs
// 省略
    loop {
        if pin.is_high() {
            println!("HelloButton!")
        } else {
            
        }
    }
  • 自分のレベルでは全くわからないエラーを吐く

pin.is_high にしたのがおかしいことを誘発したのか?と思い pin.is_low() に戻す

main.rs
// 省略
    loop {
        if pin.is_low() {
            println!("HelloButton!")
        } else {
            
        }
    }
  • またもや無限に HelloButton! する

pin.is_set_high を試す

main.rs
// 省略
    loop {
        if pin.is_set_high() {
            println!("HelloButton!")
        } else {
            
        }
    }
error[E0277]: the trait bound `esp_idf_hal::gpio::Input: OutputMode` is not satisfied
   --> src/main.rs:12:16
    |
12  |         if pin.is_set_high() {
    |                ^^^^^^^^^^^ the trait `OutputMode` is not implemented for `esp_idf_hal::gpio::Input`
    |
    = help: the following other types implement trait `OutputMode`:
              InputOutput
              RtcInputOutput
              RtcOutput
              esp_idf_hal::gpio::Output
note: required by a bound in `PinDriver::<'d, T, MODE>::is_set_high`
   --> /home/placeless/.cargo/registry/src/index.crates.io-6f17d22bba15001f/esp-idf-hal-0.45.2/src/gpio.rs:881:15
    |
879 |     pub fn is_set_high(&self) -> bool
    |            ----------- required by a bound in this associated function
880 |     where
881 |         MODE: OutputMode,
    |               ^^^^^^^^^^ required by this bound in `PinDriver::<'d, T, MODE>::is_set_high`

For more information about this error, try `rustc --explain E0277`.
  • 多分 pin.is_set_low が正解なのかな?

ということで試す

main.rs
// 省略
    loop {
        if pin.is_set_low() {
            println!("HelloButton!")
        } else {
            
        }
    }
error[E0277]: the trait bound `esp_idf_hal::gpio::Input: OutputMode` is not satisfied
   --> src/main.rs:12:16
    |
12  |         if pin.is_set_low() {
    |                ^^^^^^^^^^ the trait `OutputMode` is not implemented for `esp_idf_hal::gpio::Input`
    |
    = help: the following other types implement trait `OutputMode`:
              InputOutput
              RtcInputOutput
              RtcOutput
              esp_idf_hal::gpio::Output
note: required by a bound in `PinDriver::<'d, T, MODE>::is_set_low`
   --> /home/placeless/.cargo/registry/src/index.crates.io-6f17d22bba15001f/esp-idf-hal-0.45.2/src/gpio.rs:890:15
    |
888 |     pub fn is_set_low(&self) -> bool
    |            ---------- required by a bound in this associated function
889 |     where
890 |         MODE: OutputMode,
    |               ^^^^^^^^^^ required by this bound in `PinDriver::<'d, T, MODE>::is_set_low`

For more information about this error, try `rustc --explain E0277`.
  • トレイト境界で怒られまくるってことは set_~~ 系は全部だめっぽい
  • ということはだ……最初の HelloButton! を出力しまくるやつの if と else を逆にしたら良いのでは?

試してみる

main.rs
// 省略
    loop {
        if pin.is_low() {
            
        } else {
            println!("HelloButton!")
        }
    }
  • 自分のレベルでは全くわからないエラーループ2

もう loop ごと消すか \(^o^)/オワタ

main.rs
// 省略
    if pin.is_low() {
                    
        } else {
            println!("HelloButton!")
        }
        Ok(())
  • 何もしないやつができた(大きな進捗)
  • Ok(()) は入れとかないとエラーを吐きます
  • ???「全部同じじゃないですか!?」

割り込みピンにしているのを少し変えてみようかな……

main.rs
use esp_idf_hal::prelude::*;
use esp_idf_hal::gpio::PinDriver;
use esp_idf_sys::EspError;

fn main() -> Result<(), EspError> {
    esp_idf_svc::log::EspLogger::initialize_default();

    let peripherals = Peripherals::take().unwrap();
    let pin = PinDriver::input(peripherals.pins.gpio21)?;

        if pin.is_high() {
                    
        } else {
            println!("HelloButton!")
        }
        Ok(())
}
  • またもや何もしないやつができた(こうなってはもう進捗ではない.悲しいことに……)

22も試してみよう(コード省略) -> またもや何もしないやつが……

今回はここまで

虚無ってきた……これが embedded の「よくわからないマイコンのよくわからないコードのよくわからないバグを直した」ってやつなのか……?(直ってない)

私はただ,ボタンを押したときにターミナルにメッセージを出したいだけなんです……

Discussion