// Package ds18b20 provides a driver for the DS18B20 digital thermometer // // Datasheet: // https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf package ds18b20 // import "tinygo.org/x/drivers/ds18b20" import ( "errors" ) // Device ROM commands const ( CONVERT_TEMPERATURE uint8 = 0x44 READ_SCRATCHPAD uint8 = 0xBE WRITE_SCRATCHPAD uint8 = 0x4E ) type OneWireDevice interface { Write(uint8) Read() uint8 Select([]uint8) error Сrc8([]uint8) uint8 } // Device wraps a connection to an 1-Wire devices. type Device struct { owd OneWireDevice } // Errors list var ( errReadTemperature = errors.New("Error: DS18B20. Read temperature error: CRC mismatch.") ) func New(owd OneWireDevice) Device { return Device{ owd: owd, } } // Configure. Initializes the device, left for compatibility reasons. func (d Device) Configure() {} // ThermometerResolution sets thermometer resolution from 9 to 12 bits func (d Device) ThermometerResolution(romid []uint8, resolution uint8) { if 9 <= resolution && resolution <= 12 { d.owd.Select(romid) d.owd.Write(WRITE_SCRATCHPAD) // send three data bytes to scratchpad (TH, TL, and config) d.owd.Write(0xFF) // to TH d.owd.Write(0x00) // to TL d.owd.Write(((resolution - 9) << 5) | 0x1F) // to resolution config } } // RequestTemperature sends request to device func (d Device) RequestTemperature(romid []uint8) { d.owd.Select(romid) d.owd.Write(CONVERT_TEMPERATURE) } // ReadTemperatureRaw returns the raw temperature. // ScratchPad memory map: // byte 0: Temperature LSB // byte 1: Temperature MSB func (d Device) ReadTemperatureRaw(romid []uint8) ([]uint8, error) { spb := make([]uint8, 9) // ScratchPad buffer d.owd.Select(romid) d.owd.Write(READ_SCRATCHPAD) for i := 0; i < 9; i++ { spb[i] = d.owd.Read() } if d.owd.Сrc8(spb) != 0 { return nil, errReadTemperature } return spb[:2:2], nil } // ReadTemperature returns the temperature in celsius milli degrees (°C/1000) func (d Device) ReadTemperature(romid []uint8) (int32, error) { raw, err := d.ReadTemperatureRaw(romid) if err != nil { return 0, err } t := int32(uint16(raw[0]) | uint16(raw[1])<<8) if t&0x8000 == 0x8000 { t -= 0x10000 } return (t * 625 / 10), nil }