やりたいこと: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
