I²C Sensor Reading Exercise

In this exercise you will learn how to read out sensors on the I²C bus.

The board has two sensors that can be read via the I²C bus: `

PeripheralPart numberReferenceCrateAddress
IMUICM-42670-PDatasheetLink0x68
Temperature and HumiditySHTC3DatasheetLink0x70

The task is to use an existing driver from crates.io to read out the temperature and humidity sensor over I²C. After that, a second sensor will be read out over the same I²C bus using shared-bus. The driver for the second sensor is available locally in common/.

Part 1: Reading Temperature & Humidity

Create an instance of the of the Humidity sensor SHTC3 and read and print the values for humidity and temperature every 600 ms.

i2c-sensor-reading/examples/part_1.rs contains a working solution of Part 1. To run the solution add --example part_1 to your run command:

$ cargo espflash --release --example part_1 --monitor /dev/SERIAL_DEVICE

i2c-sensor-reading/src/main.rs contains skeleton code, that already contains necessary imports for this part.

Steps:

✅ Go to the i2c-sensor-reading/ folder and open the relevant documentation with the following command:

$ cargo doc --open

✅ Define two pins, one as SDA and one as SCL.

SignalGPIO
SDAGPIO10
SCLGPIO8

✅ Create an Instance of the I²C peripheral with the help of the documentation you generated. This requires a baud rate: You can use 400kHz, a default value.

✅ Use the shtcx driver crate, make an instance of the SHTC3 sensor passing the I²C instance into them. Check the documentation for guidance.

✅ To check if the sensor is addressed correctly, read it's device ID and print the value.

Expected Output:

Device ID: 71

✅ Make a measurement, and read the sensor values and print them. Check the documentation for guidance on sensor methods.

Expected Output:

TEMP: [local temperature] °C
HUM: [local humidity] %

❗ Some sensors need some time to pass between measurement and reading value. ❗ Watch out for the expected units!

Hints

  • There are methods that turn the sensor values into the desired unit.

Part 2: Reading Accelerometer data.

Using a bus manager, implement the second sensor. Read out its values and print the values from both sensors.

Continue with your own solution from part one. Alternatively you can start with the provided partial solution of Part 1: i2c-sensor-reading/examples/part_1.rs.

i2c-sensor-reading/examples/part_2.rs contains a working solution of Part 2. You can consult it if you need help.

Steps

✅ Import the driver crate for the ICM42670p.


#![allow(unused)]
fn main() {
use imc42670p;
}

✅ Create an instance of the sensor.

✅ Why does passing the same I²C instance to two sensors not work, despite both being on the same I²C bus?

Answer

This is an ownership issue. Every place in memory needs to be owned by something. If we pass the I²C bus to the SHTC3, the sensor owns the I²C bus. It can't be owned by another sensor. Borrowing is also not possible, because the I²C bus needs to be mutable. Both sensors need to be able to change it. We solve this problem by introducing a bus manager, that creates a number of proxies of the I²C bus. These proxies can than be owned by the respective sensors.

✅ Import the bus manager crate.


#![allow(unused)]
fn main() {
use shared_bus;
}

✅ Create an instance of a simple bus manager. Make two proxies and use them instead of the original I²C instance to pass to the sensors.

✅ Read & print the device ID from both sensors.

Expected Output:

Device ID SHTC3: 71
Device ID ICM42670p: 96

✅ Start the ICM42670p in low noise mode.

✅ Read the gyroscope sensor values and print them with 2 decimal places alongside the temperature and humidity values.

Expected Output:

GYRO: X: 0.00 Y: 0.00 Z: 0:00
TEMP: [local temperature] °C
HUM: [local humidity] %