やりたいこと:ESP Rust Board上に温湿度センサ(SHTC3)が搭載されておりこの値を読みたい
取り組み:I2Cでレジスタアクセスする。サンプルコードを参照して試作
結論:温度だけだが読めた
詳細:
I2Cのサンプルコードを参照して試作したのが以下のソース
センサの準備ができていない時はI2Cのアクセス時、NACKが返ると思われる。値が取れたかどうか0で比較しているが、正しく実装するには、、i2c.readでNACかACKかをチェックすべきだと思う。
use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use esp_idf_hal::delay::{FreeRtos, BLOCK}; use esp_idf_hal::i2c::*; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::prelude::*; const SHTC3_ADDRESS: u8 = 0x70; fn main() -> anyhow::Result<()> { // It is necessary to call this function once. Otherwise some patches to the runtime // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 esp_idf_sys::link_patches(); println!("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(10.kHz().into()); let mut i2c = I2cDriver::new(i2c, sda, scl, &config)?; // wake up i2c.write(SHTC3_ADDRESS, &[0x35, 0x17], BLOCK)?; // read T first i2c.write(SHTC3_ADDRESS, &[0x78, 0x66], BLOCK)?; let buf = &mut[0u8; 6]; for _ in 0..10 { // read FreeRtos::delay_ms(1000); let _ = i2c.read(SHTC3_ADDRESS, buf, 10); if buf[0] != 0 { break; } } println!("values.."); for n in 0..6 { print!("[{:x}]",buf[n]); } println!(""); let temp = -45.0 + 175.0 * (((buf[0] as i32) << 8 | (buf[1] as i32)) as f32) / (0x10000 as f32); println!("temp:{}", temp); loop { FreeRtos::delay_ms(1000); } }
以下が表示例、 室温が22.9℃と計測されている。
Hello, world! values.. [63][63][11][60][4b][3] temp:22.94014
先に作ったMQTT Clientとこのセンサプログラムを結合すると、MQTTでIoT PFにPublishするセンサデバイスができることになるが、、計測したいのはCO2なので、センサはSensirionを使って、I2C版のSensirion用ドライバが必要だ。
■参考URL
SHTC3の仕様書
https://www.mouser.com/datasheet/2/682/Sensirion_04202018_HT_DS_SHTC3_Preliminiary_D2-1323493.pdf
先人の試作も参考にしました
I2Cで使える温度湿度センサーSHT31をESP32-C3+Rustで使ってみる - @74thの制作ログ
i2cのソース
esp-idf-hal/i2c.rs at master · esp-rs/esp-idf-hal · GitHub