1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use byteorder::ByteOrder; use byteorder::LittleEndian; use hal::blocking::delay::DelayUs; use Error; use Device; use Sensor; use OneWire; pub const FAMILY_CODE : u8 = 0x28; #[repr(u8)] pub enum Command { Convert = 0x44, WriteScratchpad = 0x4e, ReadScratchpad = 0xBE, CopyScratchpad = 0x48, RecallE2 = 0xB8, ReadPowerSupply = 0xB4, } #[repr(u8)] #[derive(Debug, Copy, Clone)] pub enum MeasureResolution { TC8 = 0b0001_1111, TC4 = 0b0011_1111, TC2 = 0b0101_1111, TC = 0b0111_1111, } impl MeasureResolution { pub fn time_ms(&self) -> u16 { match self { &MeasureResolution::TC8 => 94, &MeasureResolution::TC4 => 188, &MeasureResolution::TC2 => 375, &MeasureResolution::TC => 750, } } } pub struct DS18B20 { device: Device, resolution: MeasureResolution, } impl DS18B20 { pub fn new(device: Device) -> Result<DS18B20, Error> { if device.address[0] != FAMILY_CODE { Err(Error::FamilyCodeMismatch(FAMILY_CODE, device.address[0])) } else { Ok(DS18B20 { device, resolution: MeasureResolution::TC, }) } } pub unsafe fn new_forced(device: Device) -> DS18B20 { DS18B20 { device, resolution: MeasureResolution::TC } } pub fn measure_temperature(&self, wire: &mut OneWire, delay: &mut DelayUs<u16>) -> Result<MeasureResolution, Error> { wire.reset_select_write_only(delay, &self.device, &[Command::Convert as u8])?; Ok(self.resolution) } pub fn read_temperature(&self, wire: &mut OneWire, delay: &mut DelayUs<u16>) -> Result<f32, Error> { let mut scratchpad = [0u8; 9]; wire.reset_select_write_read(delay, &self.device, &[Command::ReadScratchpad as u8], &mut scratchpad[..])?; super::ensure_correct_rcr8(&self.device,&scratchpad[..8], scratchpad[8])?; Ok(DS18B20::read_temperature_from_scratchpad(&scratchpad)) } fn read_temperature_from_scratchpad(scratchpad: &[u8]) -> f32 { let temp_u16 = LittleEndian::read_u16(&scratchpad[0..2]); let temp_f32 = temp_u16 as i16 as f32 / 16_f32; temp_f32 } } impl Sensor for DS18B20 { fn family_code() -> u8 { FAMILY_CODE } fn start_measurement(&self, wire: &mut OneWire, delay: &mut DelayUs<u16>) -> Result<u16, Error> { Ok(self.measure_temperature(wire, delay)?.time_ms()) } fn read_measurement(&self, wire: &mut OneWire, delay: &mut DelayUs<u16>) -> Result<f32, Error> { self.read_temperature(wire, delay) } }