Skip to content

Commit 9be0d59

Browse files
committed
drivers: Add onewire driver and ds18x20 temperature sensor driver.
1 parent f2a8895 commit 9be0d59

File tree

2 files changed

+440
-0
lines changed

2 files changed

+440
-0
lines changed

drivers/onewire/ds18x20.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""
2+
DS18x20 temperature sensor driver for MicroPython.
3+
4+
This driver uses the OneWire driver to control DS18S20 and DS18B20
5+
temperature sensors. It supports multiple devices on the same 1-wire bus.
6+
7+
The following example assumes the ground of your DS18x20 is connected to
8+
Y11, vcc is connected to Y9 and the data pin is connected to Y10.
9+
10+
>>> gnd = Pin('Y11')
11+
>>> gnd.init(Pin.OUT_PP)
12+
>>> gnd.low()
13+
14+
>>> vcc = Pin('Y9')
15+
>>> vcc.init(Pin.OUT_PP)
16+
>>> vcc.high()
17+
18+
>>> d = DS18X20(Pin('Y10'))
19+
20+
Call read_temps to read all sensors:
21+
22+
>>> result = d.read_temps()
23+
>>> print(result)
24+
[20.875, 20.8125]
25+
26+
Call read_temp to read the temperature of a specific sensor:
27+
28+
>>> result = d.read_temp(d.roms[0])
29+
>>> print(result)
30+
20.25
31+
32+
If only one DS18x20 is attached to the bus, then you don't need to
33+
pass a ROM to read_temp:
34+
35+
>>> result = d.read_temp()
36+
>>> print(result)
37+
20.25
38+
39+
"""
40+
41+
from onewire import OneWire
42+
43+
class DS18X20(object):
44+
def __init__(self, pin):
45+
self.ow = OneWire(pin)
46+
# Scan the 1-wire devices, but only keep those which have the
47+
# correct # first byte in their rom for a DS18x20 device.
48+
self.roms = [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28]
49+
50+
def _select_rom(self, rom):
51+
if rom:
52+
self.ow.select_rom(rom)
53+
else:
54+
self.ow.skip_rom()
55+
56+
def read_temp(self, rom=None):
57+
"""
58+
Read and return the temperature of one DS18x20 device.
59+
Pass the 8-byte bytes object with the ROM of the specific device you want to read.
60+
If only one DS18x20 device is attached to the bus you may omit the rom parameter.
61+
"""
62+
ow = self.ow
63+
ow.reset()
64+
self._select_rom(rom)
65+
ow.write_byte(0x44) # Convert Temp
66+
while True:
67+
if ow.read_bit():
68+
break
69+
ow.reset()
70+
self._select_rom(rom)
71+
ow.write_byte(0xbe) # Read scratch
72+
data = ow.read_bytes(9)
73+
return self.convert_temp(rom[0], data)
74+
75+
def read_temps(self):
76+
"""
77+
Read and return the temperatures of all attached DS18x20 devices.
78+
"""
79+
temps = []
80+
for rom in self.roms:
81+
temps.append(self.read_temp(rom))
82+
return temps
83+
84+
def convert_temp(self, rom0, data):
85+
"""
86+
Convert the raw temperature data into degrees celsius and return as a float.
87+
"""
88+
temp_lsb = data[0]
89+
temp_msb = data[1]
90+
if rom0 == 0x10:
91+
if temp_msb != 0:
92+
# convert negative number
93+
temp_read = temp_lsb >> 1 | 0x80 # truncate bit 0 by shifting, fill high bit with 1.
94+
temp_read = -((~temp_read + 1) & 0xff) # now convert from two's complement
95+
else:
96+
temp_read = temp_lsb >> 1 # truncate bit 0 by shifting
97+
count_remain = data[6]
98+
count_per_c = data[7]
99+
temp = temp_read - 0.25 + (count_per_c - count_remain) / count_per_c
100+
return temp
101+
elif rom0 == 0x28:
102+
return (temp_msb << 8 | temp_lsb) / 16
103+
else:
104+
assert False

0 commit comments

Comments
 (0)