GithubHelp home page GithubHelp logo

onewire's Introduction

OneWire

This crate is an OneWire-Bus implementation ontop of generic Input- and OutputPins from the embedded-hal.

Build Status License Crates.io Documentation PRs Welcome

How to use

Below is an example how to create a new OneWire instance, search for devices and read the temperature from a DS18B20. The example currently requires the stm32f103xx-hal to be patched with this PR.

fn main() -> ! {
    let mut cp: cortex_m::Peripherals = cortex_m::Peripherals::take().unwrap();
    let mut peripherals = stm32f103xx::Peripherals::take().unwrap();
    let mut flash = peripherals.FLASH.constrain();
    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    let mut rcc = peripherals.RCC.constrain();
    let mut gpioc = peripherals.GPIOC.split(&mut rcc.apb2);
    
    let mut delay = stm32f103xx_hal::delay::Delay::new(cp.SYST, clocks);
    
    let mut one = gpioc
        .pc15
        .into_open_drain_output(&mut gpioc.crh)
        .downgrade();
        
    let mut wire = OneWire::new(&mut one, false);
    
    if wire.reset(&mut delay).is_err() {
        // missing pullup or error on line
        loop {}
    }
    
    // search for devices
    let mut search = DeviceSearch::new();
    while let Some(device) = wire.search_next(&mut search, &mut delay).unwrap() {
        match device.address[0] {
            ds18b20::FAMILY_CODE => {
                let mut ds18b20 = DS18b20::new(device).unwrap();
                
                // request sensor to measure temperature
                let resolution = ds18b20.measure_temperature(&mut wire, &mut delay).unwrap();
                
                // wait for compeltion, depends on resolution 
                delay.delay_ms(resolution.time_ms());
                
                // read temperature
                let temperature = ds18b20.read_temperature(&mut wire, &mut delay).unwrap();
            },
            _ => {
                // unknown device type            
            }
        }
    }
    
    loop {}
}

The code from the example is copy&pasted from a working project, but not tested in this specific combination.

onewire's People

Contributors

chernomor avatar kellerkindt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

onewire's Issues

Porting to avr-hal

I just want to read temperature from a DS18B20. If possible, I would prefer using avr-hal to interface with the board with this crate to interpret the readouts. Intuitively, I would start with this example: https://github.com/Rahix/avr-hal/blob/main/examples/arduino-uno/src/bin/uno-hc-sr04.rs and somehow port this section of your example:

let mut ds18b20 = DS18b20::new(device).unwrap();
                
// request sensor to measure temperature
let resolution = ds18b20.measure_temperature(&mut wire, &mut delay).unwrap();
                
// wait for compeltion, depends on resolution 
delay.delay_ms(resolution.time_ms());
                
// read temperature
let temperature = ds18b20.read_temperature(&mut wire, &mut delay).unwrap();

I assume the avr_hal and stm32f103xx_hal handle delay and reading from the pin similarly. If you think this isn't too complicated, I'd appreciate some pointers.

Get rid of DleayUs

DelayUs - especially in loops - does not provide a consistent timing behavior (because of multiple calls with unknown timings in-between). The better solution would be to have something similar to Instant::now() and duration_since().

Example in README outdated

The example in the README is outdated. The stm32f103xx-hal is deprecated in favor of stm32f1xx-hal. It would also be nice to see the use statements used to get someone successfully compiling an example with this library (what I'm trying to do at the moment ๐Ÿ˜…).

Focus library on generic one wire support

Hello, I'm looking to start my own crate specifically for a different one wire temperature sensor and stumbled upon this crate. It looks like there is good, generic one wire support in this crate, but support for the ds18b20 is mixed in here too. I think it makes sense to clean up this crate to focus on generic one wire support and perhaps spin ds18b20 out into its own crate that uses this crate. Let me know what you think.

If you want, I can open a PR that removes the ds18b20 stuff, but I'm assuming you would want to make a new repo yourself to have a ds18b20 specific crate.

LSB of scratchpad[0] is always high, causing CRC checks to occasionally fail

I am getting a significant number of CRC mismatches while testing a ds18b20 with an stm32f103.
I've tested with 4+ different ds18b20's, and also confirmed they work with an Arduino nano (not using this library).

I disabled the CRC checking, and dumped the scratchpad memory, and it appears that the data coming from the ds18b20 is correct, but the CRC check is failing. Reading the scratchpad multiple times always returns the exact same data.

Here is some sample data I captured of temp data read from the sensor.
Changes in scratchpad index 6 seems to cause a CRC mismatch. I'm still reading through the datasheets to understand how the CRC function works, it might be an easy fix.

Raw Temp Value CRC match? Scratchpad Data (Decimal)
355 true [99, 1, 75, 70, 127, 255, 13, 16, 21]
355 false [99, 1, 75, 70, 127, 255, 14, 16, 3]
353 true [97, 1, 75, 70, 127, 255, 15, 16, 2]
353 false [97, 1, 75, 70, 127, 255, 16, 16, 181]
351 true [95, 1, 75, 70, 127, 255, 1, 16, 155]
351 false [95, 1, 75, 70, 127, 255, 2, 16, 141]

The device id for these samples is [40, 255, 21, 32, 11, 0, 0, 87] (decimal)

Can't find devices

I'm trying to run a ds18b20 on my stm32f103. The code is as follows ( pretty much copied from README).
the program gives me

search for devices
search finished

which means no device is found. But if I remove the 4.7k resistor from the circuit, it will actually complain missing pullups, so I assume my circuit connection is correct.

#![no_std]
#![no_main]

extern crate panic_halt;

use onewire::{
    OneWire,
    DeviceSearch,
    ds18b20,
};

use stm32f1xx_hal::{
    prelude::*,
    pac,
    delay,
};
use cortex_m_rt::entry;

use cortex_m_semihosting::{hprintln};

#[entry]
fn main() -> ! {
   let mut cp: cortex_m::Peripherals = cortex_m::Peripherals::take().unwrap();
    let mut dp = pac::Peripherals::take().unwrap();
    let mut flash = dp.FLASH.constrain();

    let mut rcc = dp.RCC.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);

    let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
    
    let mut delay = delay::Delay::new(cp.SYST, clocks);
    
    let mut one = gpiob
        .pb11
        .into_open_drain_output(&mut gpiob.crh)
        .downgrade();
        
    let mut wire = OneWire::new(&mut one, false);
    
    if wire.reset(&mut delay).is_err() {
        hprintln!("missing pullup, or error on-line");
        loop {}
    }

    hprintln!("search for devices");
    
    // search for devices
    let mut search = DeviceSearch::new();
    while let Some(device) = wire.search_next(&mut search, &mut delay).unwrap() {
        match device.address[0] {
            ds18b20::FAMILY_CODE => {
                let mut ds18b20 = ds18b20::DS18B20::new(device).unwrap();
                
                // request sensor to measure temperature
                let resolution = ds18b20.measure_temperature(&mut wire, &mut delay).unwrap();
                
                // wait for compeltion, depends on resolution 
                delay.delay_ms(resolution.time_ms());
                
                // read temperature
                let temperature = ds18b20.read_temperature(&mut wire, &mut delay).unwrap();
                hprintln!("{0}", temperature);
            },
            _ => {
                hprintln!("unknown device type");
            }
        }
    }
    hprintln!("search finished");
    loop {}
}

Can't get this crate to work with embassy

This is the code: (pretty much the readme example, modified slightly for embassy)

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use embassy_executor::Spawner;
use embassy_rp::gpio::{Input, Level, OutputOpenDrain, Pull, Flex};
use {defmt_rtt as _, panic_probe as _};
use defmt::*;
use onewire::ds18b20::DS18B20;
use embedded_hal::blocking::delay::DelayMs;

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
    let p = embassy_rp::init(Default::default());
    let mut temp_pin = OutputOpenDrain::new(p.PIN_0, Level::High);

    let mut delay = embassy_time::Delay;
    
    let mut wire = onewire::OneWire::new(temp_pin, false);

    if wire.reset(&mut delay).is_err() {
        //missing pullup or error on line
        info!("nope");
        loop {}

    }

    let mut search = onewire::DeviceSearch::new();

    let a = wire.search_next(&mut search, &mut delay).unwrap();
    dbg!("{:?}", a.unwrap().address);

    while let Some(device) = wire.search_next(&mut search, &mut delay).unwrap() {
        info!("got here!");
        match device.address[0] {
            onewire::ds18b20::FAMILY_CODE => {
                let mut ds18b20 = DS18B20::new(device).unwrap();

                //request sensor to measure temperature
                let resolution = ds18b20.measure_temperature(&mut wire, &mut delay).unwrap();

                delay.delay_ms(resolution.time_ms());

                let temperature = ds18b20.read_temperature(&mut wire, &mut delay).unwrap();
                println!("{}", temperature);
            },
            _ => {

            }
        }
    }



}

It compiles fine with cargo version 1.67.0 nightly, but when it is ran on a raspberry pi pico W it panics at line 30, because the wire.search_next is None. I think my wiring is correct, as if I remove the pullup resistor (10k ohm) it complains about a missing pullup.

Cannot get this crate to work with atsamd-hal

Hey, I've been trying for the last few days to get this crate to work with my setup on an atsamd chip (specifically, the feather_m0 board), but have been unable to get it to work. It seems I can't get a pin that clearly implements both the input and output trait as required by the OpenDrainOutput trait.

Here's a slimmed down version of my code:

#![no_std]
#![no_main]

extern crate panic_halt;  // panic handler

use onewire;

use feather_m0 as hal;
use hal::prelude::*;
use hal::{entry, Peripherals, CorePeripherals};

#[entry]
fn main() -> ! {
    // cortex_m::Peripherals::take().unwrap()
    let mut peripherals = Peripherals::take().unwrap();

    let mut pins = hal::Pins::new(peripherals.PORT);
    let mut ow_pin = pins.d11.into_open_drain_output(&mut pins.port);
    let mut one_wire = onewire::OneWire::new(&mut ow_pin, false);
    loop {}
}

I get the following error:

error[E0277]: the trait bound `atsamd_hal::gpio::Pa16<atsamd_hal::gpio::Output<atsamd_hal::gpio::OpenDrain>>: embedded_hal::digital::v1::InputPin` is not satisfied
  --> src/main.rs:71:46
   |
71 |     let mut one_wire = onewire::OneWire::new(&mut ow_pin, false);
   |                                              ^^^^^^^^^^^ the trait `embedded_hal::digital::v1::InputPin` is not implemented for `atsamd_hal::gpio::Pa16<atsamd_hal::gpio::Output<atsamd_hal::gpio::OpenDrain>>`
   |
   = note: required because of the requirements on the impl of `embedded_hal::digital::v2::InputPin` for `atsamd_hal::gpio::Pa16<atsamd_hal::gpio::Output<atsamd_hal::gpio::OpenDrain>>`
   = note: required for the cast to the object type `dyn onewire::OpenDrainOutput<Error = (), Error = ()>`

In your example, you call downgrade() after converting to an open drain output, but it seems the atsamd-hal does not have this method on their GPIO HAL. Any ideas?

Request example of use in a function (ie type sig)

Eg:

 fn read(
        temp_sensor: &mut DS18B20,
        one_w: &mut OneWire<PC13<Output<OpenDrain>>>,
        delay: &mut Delay,
    ) -> Self {
      let resolution = temp_sensor.measure_temperature(one_w, delay).unwrap();
      delay.delay_ms(resolution.time_ms());
      temp_sensor.read_temperature(one_w, delay).unwrap();
}

This doesn't work due to needing the Debug trait on OneWire:

= help: the trait `core::fmt::Debug` is not implemented for `stm32f3xx_hal::gpio::gpioc::PC13<stm32f3xx_hal::gpio::Output<stm32f3xx_hal::gpio::Ope
nDrain>>`

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.