Rust challenge 60/100 - reading the generic node's humidity and temperature sensor
Table of content
What is this
The rules of the game are explained in my original.
59th Challenge
Challenge
Build on yesterday’s example and actually read the temperature and the humidity from the sensor
Solution
Lets start from a template again, same folder as yesterday.
cargo generate \
--git https://github.com/stm32-rs/stm32wlxx-hal\
--name stm32
The template, looks like this, when running tree -L 3
.
├── CHANGELOG.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── examples
│ ├── Cargo.toml
│ ├── examples
│ └── src
├── hal
│ ├── Cargo.toml
│ └── src
├── lora-e5-bsp
│ ├── Cargo.toml
│ ├── README.md
│ └── src
├── memory.x
├── nucleo-wl55jc-bsp
│ ├── Cargo.toml
│ ├── README.md
│ └── src
├── rustfmt.toml
└── testsuite
├── Cargo.toml
├── README.md
├── runall.py
└── src
Lets revisit the commands. Yesterday we sucesfully read out the id of the sensor. Today we want to get some tempeperature readings.
| Command | Value |
| -------- | ------- |
| Sleep | 0xB098 |
| Wakeup | 0x3517 |
| measurement cmd | 0x7866 |
| readout id | 0xEFC8 |
I actually used the measurement command with clock stretching that reads the rh value first. The formula for calculating the temp and humidity was taken from the datasheet.
#![no_std]
#![no_main]
use defmt::unwrap;
use defmt_rtt as _; // global logger
use nucleo_wl55jc_bsp::hal::{
cortex_m::{self, delay::Delay},
embedded_hal::blocking::i2c::{WriteRead,Write,Read},
gpio::{pins, Output, PinState,PortB,PortA},
i2c::{I2c1},
pac::{self},
rcc,
util::new_delay,
};
use panic_probe as _;
const I2C_FREQUENCY: u32 = 100_000;
#[defmt_test::tests]
mod tests {
use super::*;
struct TestArgs {
i2c: I2c1<(pins::A9, pins::A10)>,
delay: Delay,
}
#[init]
fn init() -> TestArgs {
cortex_m::interrupt::free(|cs| {
let mut dp: pac::Peripherals = unwrap!(pac::Peripherals::take());
let cp: pac::CorePeripherals = defmt::unwrap!(pac::CorePeripherals::take());
unsafe { rcc::set_sysclk_msi_max(&mut dp.FLASH, &mut dp.PWR, &mut dp.RCC, cs) };
let gpioa: PortA = PortA::split(dp.GPIOA, &mut dp.RCC);
let gpiob: PortB = PortB::split(dp.GPIOB, &mut dp.RCC);
let mut sensor_power_enable: Output<pins::B12> =
cortex_m::interrupt::free(|cs| Output::default(gpiob.b12, cs));
// Power the sensor
sensor_power_enable.set_level(PinState::High);
// wait for the sensor to be powered up
let mut delay: Delay = new_delay(cp.SYST, &dp.RCC);
delay.delay_us(240);
let i2c = I2c1::new(
dp.I2C1,
(gpioa.a9, gpioa.a10),
I2C_FREQUENCY,
&mut dp.RCC,
false,
cs,
);
TestArgs{
i2c,
delay
}
})
}
#[test]
fn shtc3_measurement(ta: &mut TestArgs) {
defmt::warn!("A SHTC3 sensor must be connected to the board on pins A9 (SCL) & A10 (SDA) for this test to work");
let mut response: [u8; 6] = [0; 6];
// send wake up command
let result = ta.i2c.write(0x70, &[0x35, 0x17]);
match result {
Ok(()) => defmt::info!("SHTC3 was woken up"),
Err(e) => defmt::error!("I2C error: {}", e),
}
// get sensor ID
let result = ta.i2c.write_read(0x70, &[0xEF, 0xC8], &mut response);
match result {
Ok(()) => defmt::info!("SHTC3 ID = {:x} ",response),
Err(e) => defmt::error!("I2C error: {}", e),
}
for _ in 1..10 {
// get measurement read relative humditiy first and enable clock stretching
let result = ta.i2c.write_read(0x70, &[0x5C, 0x24],&mut response);
match result {
Ok(()) => {
defmt::info!("response:{:x}",response);
let relative_humidity = 100.0*((response[1] as u16 + ((response[0] as u16) << 8)) as f32)/65535.0;
let temperature = ((response[4] as u16 + ((response[3] as u16) << 8)) as f32)*175.0/65535.0 - 45.0;
defmt::info!("rh {}%", relative_humidity);
defmt::info!("temp {}°C", temperature);
},
Err(e) => defmt::error!("I2C error: {}", e),
}
ta.delay.delay_ms(100);
}
}
}
When compiling and running DEFMT_LOG=info cargo test -p testsuite --target thumbv7em-none-eabi --bin gn_i2c
we get the temperature and the humidity! yay, the crc I left untouched for now.
───────────────────────────────────────────────────────────────────────────────
(1/1) running `shtc3_measurement`...
└─ gn_i2c::tests::__defmt_test_entry @ src/gn_i2c.rs:68
WARN A SHTC3 sensor must be connected to the board on pins A9 (SCL) & A10 (SDA) for this test to work
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:69
INFO SHTC3 was woken up
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:77
INFO SHTC3 ID = [8, 87, 5b, ff, ff, ff]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:85
INFO response:[7d, 36, 99, 67, 9c, 3e]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.91127%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.827805°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 41, f6, 67, a7, 11]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.928055%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.857178°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 3b, d5, 67, 94, 87]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.9189%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.806442°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 36, 99, 67, a1, b7]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.91127%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.841156°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 37, a8, 67, a2, e4]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.912796%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.843826°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 44, 3, 67, 99, cb]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.932632%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.819794°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 31, e, 67, 9f, 6d]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.90364%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.835815°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 42, a5, 67, af, a8]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.92958%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.87854°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
INFO response:[7d, 2e, 63, 67, a2, e4]
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:95
INFO rh 48.899063%
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:98
INFO temp 25.843826°C
└─ gn_i2c::tests::shtc3_measurement @ src/gn_i2c.rs:99
all tests passed!
└─ gn_i2c::tests::__defmt_test_entry @ src/gn_i2c.rs:19