//! RMT Onewire Example //! //! Example demonstrating the use of the onewire component to measure temperature from the ds18b20 temperature probe. //! //! In order to use this example, an overidden `Cargo.toml` must be defined with the following definitions: //! ``` //! [[package.metadata.esp-idf-sys.extra_components]] //! remote_component = { name = "onewire_bus", version = "^1.0.2" } //! //! //! [patch.crates-io] //! esp-idf-sys = { git = "https://github.com/esp-rs/esp-idf-sys", rev = "2728b85" } //! //! ``` //! //! The example can then be run with //! `MCU= cargo run --example rmt_onewire --manifest-path /path/to/other/Cargo.toml` //! //! Below is a connection sketch, the signal pin must be externally pulled-up //! with a 4.7kOhm resistor. //! This example uses gpio 16, but any pin capable of //! input AND output is suitable. //! //! If the example is successful, it should print the address of each //! onewire device attached to the bus. //! //! ┌──────────────────────────┐ //! │ 3.3V├───────┬─────────────┬──────────────────────┐ //! │ │ ┌┴┐ │VDD │VDD //! │ ESP Board │ 4.7k│ │ ┌──────┴──────┐ ┌──────┴──────┐ //! │ │ └┬┘ DQ│ │ DQ│ │ //! │ ONEWIRE_GPIO_PIN├───────┴──┬───┤ DS18B20 │ ┌───┤ DS18B20 │ ...... //! │ │ └───│-------------│────┴───│-------------│── //! │ │ └──────┬──────┘ └──────┬──────┘ //! │ │ │GND │GND //! │ GND├─────────────────────┴──────────────────────┘ //! └──────────────────────────┘ //! //! //! This example demonstrates: //! * A RMT device in both TX and RX mode. //! * Usage of the onewire bus driver interface. //! * How to iterate through a device search to discover devices on the bus. #![allow(unknown_lints)] #![allow(unexpected_cfgs)] #[cfg(all( esp_idf_soc_rmt_supported, not(feature = "rmt-legacy"), esp_idf_comp_espressif__onewire_bus_enabled, ))] use esp_idf_hal::onewire::{OWAddress, OWCommand, OWDriver}; #[cfg(all( esp_idf_soc_rmt_supported, not(esp_idf_version_major = "4"), esp_idf_comp_espressif__onewire_bus_enabled, ))] fn main() -> anyhow::Result<()> { use esp_idf_hal::delay::FreeRtos; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::sys::EspError; use std::time::Duration; println!("Starting APP!"); let peripherals = Peripherals::take()?; let channel = peripherals.rmt.channel0; let onewire_gpio_pin = peripherals.pins.gpio16; let mut onewire_bus: OWDriver = OWDriver::new(onewire_gpio_pin, channel)?; let device = { let mut search = onewire_bus.search()?; search.next() }; if device.is_none() { println!("No device found"); return Ok(()); } let device = device.unwrap(); if let Err(err) = device { println!("An error occured searching for the device, err = {}", err); return Err(err.into()); } let device = device.unwrap(); println!( "Found Device: {:?}, family code = {}", device, device.family_code() ); loop { ds18b20_trigger_temp_conversion(&device, &onewire_bus)?; let temp = ds18b20_get_temperature(&device, &onewire_bus)?; println!("Temperature: {}", temp); FreeRtos::delay_ms(3000); } } #[cfg(any( feature = "rmt-legacy", esp_idf_version_major = "4", not(esp_idf_comp_espressif__onewire_bus_enabled), not(esp_idf_soc_rmt_supported), ))] fn main() -> anyhow::Result<()> { println!("This example requires feature `rmt-legacy` disabled, using ESP-IDF > v4.4.X, the component included in `Cargo.toml`, or is not supported on this MCU"); loop { std::thread::sleep(std::time::Duration::from_millis(1000)); } } #[cfg(all( esp_idf_soc_rmt_supported, not(esp_idf_version_major = "4"), esp_idf_comp_espressif__onewire_bus_enabled, ))] fn ds18b20_send_command<'a>(addr: &OWAddress, bus: &OWDriver, cmd: u8) -> Result<(), EspError> { let mut buf = [0; 10]; buf[0] = OWCommand::MatchRom as _; let addr = addr.address().to_le_bytes(); buf[1..9].copy_from_slice(&addr); buf[9] = cmd; bus.write(&buf) } #[allow(dead_code)] #[repr(u8)] enum Ds18b20Command { ConvertTemp = 0x44, WriteScratch = 0x4E, ReadScratch = 0xBE, } #[cfg(all( esp_idf_soc_rmt_supported, not(esp_idf_version_major = "4"), esp_idf_comp_espressif__onewire_bus_enabled, ))] fn ds18b20_trigger_temp_conversion<'a>(addr: &OWAddress, bus: &OWDriver) -> Result<(), EspError> { // reset bus and check if the ds18b20 is present bus.reset()?; ds18b20_send_command(addr, bus, Ds18b20Command::ConvertTemp as u8)?; // delay proper time for temp conversion, // assume max resolution (12-bits) std::thread::sleep(Duration::from_millis(800)); Ok(()) } #[cfg(all( esp_idf_soc_rmt_supported, not(esp_idf_version_major = "4"), esp_idf_comp_espressif__onewire_bus_enabled, ))] fn ds18b20_get_temperature<'a>(addr: &OWAddress, bus: &OWDriver) -> Result { bus.reset()?; ds18b20_send_command(addr, bus, Ds18b20Command::ReadScratch as u8)?; let mut buf = [0u8; 9]; bus.read(&mut buf)?; let lsb = buf[0]; let msb = buf[1]; let temp_raw: u16 = (u16::from(msb) << 8) | u16::from(lsb); Ok(f32::from(temp_raw) / 16.0) }