How to save and pass 'PinDriver' objects
xiaguangbo opened this issue · comments
My basic idea is to encapsulate a onewire struct
and pass a decimal pin number to drive the corresponding pin. But how do you preserve the objects returned by PinDriver: : input_output_od
? I'm not gonna write this:
struch Onewire {
pin : ???
};
...
let mut pin = PinDriver::input_output_od(0) // Use numbers instead, and if no, use `match` a separate line for each peripheral.pins.gpiox.
now:
use esp_idf_hal::delay::FreeRtos;
use esp_idf_svc::hal::{
delay::Delay,
gpio::{PinDriver, Pull},
peripherals::Peripherals,
};
fn main() {
// 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_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
log::info!("Hello, world!");
let peripherals = Peripherals::take().unwrap();
let mut onewire = PinDriver::input_output_od(peripherals.pins.gpio0).unwrap();
onewire.set_pull(Pull::Floating).unwrap(); // Use external pull-up
let delay = Delay::new_default();
loop {
FreeRtos::delay_ms(1000);
// reset
onewire.set_low().unwrap();
delay.delay_us(600);
onewire.set_high().unwrap();
delay.delay_us(80);
if onewire.is_low() {
log::info!("onewire: is exist");
delay.delay_us(900);
if onewire.is_high() {
log::info!("onewire: reset ok");
} else {
log::warn!("onewire: reset err");
continue;
}
} else {
log::warn!("onewire: reset err");
continue;
}
}
}
Hi! I would suggest using the matrix channel (https://matrix.to/#/#esp-rs:matrix.org) for this kind of questions as they are not issues per se and not strictly related with the training. Also, more people could jump in to help you.
Hi! I would suggest using the matrix channel (https://matrix.to/#/#esp-rs:matrix.org) for this kind of questions as they are not issues per se and not strictly related with the training. Also, more people could jump in to help you.
ok
is ok
use embedded_hal::digital;
use esp_idf_svc::hal::delay;
use esp_idf_svc::hal::gpio;
use esp_idf_svc::hal::peripherals;
use esp_idf_svc::hal::uart;
use esp_idf_svc::hal::units;
use std::fmt::Write;
const CMD_SKIP: u8 = 0xcc;
const CMD_WRITE_REG: u8 = 0x4e;
const CMD_TEMP_START: u8 = 0x44;
const CMD_READ_REG: u8 = 0xbe;
fn main() {
// 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_svc::sys::link_patches();
// Bind the log crate to the ESP Logging facilities
esp_idf_svc::log::EspLogger::initialize_default();
log::info!("Hello, world!");
let peripherals = peripherals::Peripherals::take().unwrap();
// onewire
let mut onewire = gpio::PinDriver::input_output_od(peripherals.pins.gpio0).unwrap();
onewire.set_pull(gpio::Pull::Floating).unwrap(); // use external pull-up
// uart
let config = uart::config::Config::default().baudrate(units::Hertz(115_200));
let mut uart = uart::UartDriver::new(
peripherals.uart1,
peripherals.pins.gpio1,
peripherals.pins.gpio2,
Option::<gpio::AnyIOPin>::None,
Option::<gpio::AnyIOPin>::None,
&config,
)
.unwrap();
// delay
let delay = delay::Delay::new_default();
// ds18b20
// wait reset
while !onewire_reset(&mut onewire, &delay) {
delay::FreeRtos::delay_ms(1000);
}
// set accuracy
onewire_write_byte(&mut onewire, &delay, CMD_SKIP);
onewire_write_byte(&mut onewire, &delay, CMD_WRITE_REG);
onewire_write_byte(&mut onewire, &delay, 0xff);
onewire_write_byte(&mut onewire, &delay, 0x00);
onewire_write_byte(&mut onewire, &delay, 0x7f);
loop {
delay::FreeRtos::delay_ms(1000);
// ds18b20
// measurement temp
if !onewire_reset(&mut onewire, &delay) {
continue;
}
onewire_write_byte(&mut onewire, &delay, CMD_SKIP);
onewire_write_byte(&mut onewire, &delay, CMD_TEMP_START);
// read temp
if !onewire_reset(&mut onewire, &delay) {
continue;
}
onewire_write_byte(&mut onewire, &delay, CMD_SKIP);
onewire_write_byte(&mut onewire, &delay, CMD_READ_REG);
let temp_l = onewire_read_byte(&mut onewire, &delay);
let temp_h = onewire_read_byte(&mut onewire, &delay);
let temp = (((temp_h as i16) << 8 | (temp_l as i16)) as f64) * 0.0625;
log::info!("temp: {:.1}", temp);
// uart
writeln!(uart, "temp: {:.1}", temp).unwrap();
}
}
fn onewire_reset<T>(pin: &mut T, delay: &delay::Delay) -> bool
where
T: digital::InputPin + digital::OutputPin,
{
pin.set_low().unwrap();
delay.delay_us(600);
pin.set_high().unwrap();
delay.delay_us(80);
if pin.is_low().unwrap() {
log::info!("onewire: is exist");
delay.delay_us(900);
if pin.is_high().unwrap() {
log::info!("onewire: reset ok");
true
} else {
log::warn!("onewire: reset err");
false
}
} else {
log::warn!("onewire: reset err");
false
}
}
fn onewire_write_byte<T>(pin: &mut T, delay: &delay::Delay, mut byte: u8)
where
T: digital::InputPin + digital::OutputPin,
{
for _ in 0..8 {
let bit = byte & 0x01 != 0;
byte >>= 1;
if bit {
pin.set_low().unwrap();
delay.delay_us(5);
pin.set_high().unwrap();
delay.delay_us(90);
} else {
pin.set_low().unwrap();
delay.delay_us(90);
pin.set_high().unwrap();
delay.delay_us(5);
}
}
}
fn onewire_read_byte<T>(pin: &mut T, delay: &delay::Delay) -> u8
where
T: digital::InputPin + digital::OutputPin,
{
let mut byte: u8 = 0;
for _ in 0..8 {
byte >>= 1;
pin.set_low().unwrap();
delay.delay_us(5);
pin.set_high().unwrap();
delay.delay_us(5);
if pin.is_high().unwrap() {
byte |= 0x80;
}
delay.delay_us(60);
}
byte
}