diff --git a/esp8266/modules/ds18x20.py b/esp8266/modules/ds18x20.py
new file mode 100644
index 0000000000000000000000000000000000000000..66983f5bcc0e1732e60e7787c4c717c903e30823
--- /dev/null
+++ b/esp8266/modules/ds18x20.py
@@ -0,0 +1,37 @@
+# DS18x20 temperature sensor driver for MicroPython.
+# MIT license; Copyright (c) 2016 Damien P. George
+
+_CONVERT = const(0x44)
+_RD_SCRATCH = const(0xbe)
+_WR_SCRATCH = const(0x4e)
+
+class DS18X20:
+    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):
+        self.ow.reset(True)
+        self.ow.writebyte(self.ow.SKIP_ROM)
+        self.ow.writebyte(_CONVERT)
+
+    def read_scratch(self, rom):
+        self.ow.reset(True)
+        self.ow.select_rom(rom)
+        self.ow.writebyte(_RD_SCRATCH)
+        buf = self.ow.read(9)
+        if self.ow.crc8(buf):
+            raise Exception('CRC error')
+        return buf
+
+    def write_scratch(self, rom, buf):
+        self.ow.reset(True)
+        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
diff --git a/esp8266/scripts/onewire.py b/esp8266/modules/onewire.py
similarity index 69%
rename from esp8266/scripts/onewire.py
rename to esp8266/modules/onewire.py
index 686616950af51b6286e372e5c968fddd9ed40dfe..af5675649bdc4e8cd01adcd15455f354f9891859 100644
--- a/esp8266/scripts/onewire.py
+++ b/esp8266/modules/onewire.py
@@ -15,8 +15,11 @@ class OneWire:
         self.pin = pin
         self.pin.init(pin.OPEN_DRAIN)
 
-    def reset(self):
-        return _ow.reset(self.pin)
+    def reset(self, required=False):
+        reset = _ow.reset(self.pin)
+        if required and not reset:
+            raise OneWireError
+        return reset
 
     def readbit(self):
         return _ow.readbit(self.pin)
@@ -87,41 +90,3 @@ class OneWire:
 
     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