chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

組み込みRust再々入門(I2C on ESP32C3)

Rust ESP Development boardにはI2Cで接続できる温湿度センサ(SHTC3)が搭載されているのでこれにアクセスしてみる
I2Cサンプルは以下
esp-idf-hal/i2c_ssd1306.rs at master · esp-rs/esp-idf-hal · GitHub
作ったソースは以下

use log::*;

use esp_idf_hal::delay::{FreeRtos, BLOCK};
use esp_idf_hal::i2c::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;

fn main() -> anyhow::Result<()> {
    esp_idf_sys::link_patches();
    esp_idf_svc::log::EspLogger::initialize_default();

    info!("Hello, world!");

    let peripherals = Peripherals::take().unwrap();
    let i2c = peripherals.i2c0;
    let sda = peripherals.pins.gpio10;
    let scl = peripherals.pins.gpio8;

    let config = I2cConfig::new().baudrate(5.kHz().into());
    let mut i2c = I2cDriver::new(i2c, sda, scl, &config)?;

    // wake up
    i2c.write(0x70, &[0x35, 0x17], BLOCK)?;
    // read temp
    i2c.write(0x70, &[0x78, 0x66], BLOCK)?;

    let buf = &mut[0u8; 6];
    loop{
        _ = i2c.read(0x70, buf, 10);
        for n in 0..6 {
            print!("[{:x}]",buf[n]);
        }
        println!("\n");
        let temp =  -45.0 + 175.0 * (((buf[0] as i32) << 8 | (buf[1] as i32)) as f32)  / (0x10000 as f32);
        println!("temp:{}", temp);
        FreeRtos::delay_ms(1000);
    }
}

出力結果は以下

[0][0][0][0][0][0]
temp:-45
[6a][a4][2][62][85][82]
temp:27.898865
[6a][a4][2][62][85][82]
temp:27.898865
[6a][a4][2][62][85][82]
temp:27.898865

試作していて分かり切らない点

  • i2c0の0って何か? I2CのHWチャンネルか?
  • 関数最後の?とは何か? error handlingだったような
  • [xx]は配列だとして、&[xx]はアドレスか??
  • anyhowはエラーと値を渡すマクロ?だったように覚えているが詳細忘れた

今後の取り組み:
SPIバスは試していないが、I2Cと同様の方法で制御できると期待して、次はWi-Fi接続、MQTT通信に移りたい。

■雑感
Python/MicroPythonは言語仕様がシンプルでREPLも使えて気楽に試せるけど、Rustはコンパイル言語なので試行錯誤はあまりできない。勉強途中なので細かい仕様は分かり切らない。だけど、Rustでコードを書いていると、なんかシビレル。なぜシビレルのか分からないが。

■参考URL
GitHub - esp-rs/esp-rust-board: Open Hardware with ESP32-C3 compatible with Feather specification designed in KiCad
ESP Rust Board上の温湿度センサの値を読む - chakokuのブログ(rev4)