micropython/esp8266/scripts/onewire.py

128 lines
3.3 KiB
Python

# 1-Wire driver for MicroPython on ESP8266
# MIT license; Copyright (c) 2016 Damien P. George
import _onewire as _ow
class OneWireError(Exception):
pass
class OneWire:
SEARCH_ROM = const(0xf0)
MATCH_ROM = const(0x55)
SKIP_ROM = const(0xcc)
def __init__(self, pin):
self.pin = pin
self.pin.init(pin.OPEN_DRAIN)
def reset(self):
return _ow.reset(self.pin)
def readbit(self):
return _ow.readbit(self.pin)
def readbyte(self):
return _ow.readbyte(self.pin)
def read(self, count):
buf = bytearray(count)
for i in range(count):
buf[i] = _ow.readbyte(self.pin)
return buf
def writebit(self, value):
return _ow.writebit(self.pin, value)
def writebyte(self, value):
return _ow.writebyte(self.pin, value)
def write(self, buf):
for b in buf:
_ow.writebyte(self.pin, b)
def select_rom(self, rom):
self.reset()
self.writebyte(MATCH_ROM)
self.write(rom)
def scan(self):
devices = []
diff = 65
rom = False
for i in range(0xff):
rom, diff = self._search_rom(rom, diff)
if rom:
devices += [rom]
if diff == 0:
break
return devices
def _search_rom(self, l_rom, diff):
if not self.reset():
return None, 0
self.writebyte(SEARCH_ROM)
if not l_rom:
l_rom = bytearray(8)
rom = bytearray(8)
next_diff = 0
i = 64
for byte in range(8):
r_b = 0
for bit in range(8):
b = self.readbit()
if self.readbit():
if b: # there are no devices or there is an error on the bus
return None, 0
else:
if not b: # collision, two devices with different bit meaning
if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i):
b = 1
next_diff = i
self.writebit(b)
if b:
r_b |= 1 << bit
i -= 1
rom[byte] = r_b
return rom, next_diff
def crc8(self, data):
return _ow.crc8(data)
class DS18B20:
CONVERT = const(0x44)
RD_SCRATCH = const(0xbe)
WR_SCRATCH = const(0x4e)
def __init__(self, onewire):
self.ow = onewire
def scan(self):
return [rom for rom in self.ow.scan() if rom[0] == 0x28]
def convert_temp(self):
if not self.ow.reset():
raise OneWireError
self.ow.writebyte(SKIP_ROM)
self.ow.writebyte(CONVERT)
def read_scratch(self, rom):
if not self.ow.reset():
raise OneWireError
self.ow.select_rom(rom)
self.ow.writebyte(RD_SCRATCH)
buf = self.ow.read(9)
if self.ow.crc8(buf):
raise OneWireError
return buf
def write_scratch(self, rom, buf):
if not self.ow.reset():
raise OneWireError
self.ow.select_rom(rom)
self.ow.writebyte(WR_SCRATCH)
self.ow.write(buf)
def read_temp(self, rom):
buf = self.read_scratch(rom)
return (buf[1] << 8 | buf[0]) / 16