├── LICENSE.txt ├── README.md ├── at24c32n.py ├── docs ├── AT24C32N-AT24C64N.pdf ├── DS1307-RTC.pdf └── demo.jpg ├── ds1307.py └── ds18x20.py /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Mike Causer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MicroPython TinyRTC I2C module 2 | 3 | MicroPython driver for the TinyRTC I2C module, featuring a DS1307 RTC and AT24C32N EEPROM. 4 | 5 | ![demo](docs/demo.jpg) 6 | 7 | ## Pins 8 | 9 | Pins are available on both sides. You can use either. One side exposes more pins. 10 | 11 | Pin | Name | Description 12 | --- | --------------- | ---------------------------------------------------- 13 | BAT | Battery Voltage | For monitoring battery voltage 14 | GND | Ground | Ground 15 | VCC | Input Supply | +5V power for module and to charge coin cell battery 16 | SDA | I2C Data | I2C data for DS1307 and EEPROM 17 | SCL | I2C Clock | I2C clock for DS1307 and EEPROM 18 | DS | DS18B20 | Optional temperature sensor 1-wire data 19 | SQ | Square Wave | Optional square wave or logic level output 20 | 21 | # DS1307 RTC Examples 22 | 23 | ```python 24 | # VCC-GND STM32F407VET6 on SPI3 25 | >>> from machine import I2C, Pin 26 | >>> i2c = I2C(3) # SCL=A8, SDA=C9 27 | >>> i2c.scan() 28 | [80, 104] 29 | 30 | # 80 == 0x50 == AT24C32N EEPROM 31 | # 104 == 0x68 == DS1307 32 | 33 | >>> import ds1307 34 | >>> ds = ds1307.DS1307(i2c) 35 | ds.datetime() 36 | ds.datetime(now) 37 | 38 | # initial datetime value, oscillator disabled 39 | >>> ds.datetime() 40 | (2000, 1, 1, 0, 0, 0, 0, 0) 41 | 42 | # read datetime after 1 second (no change) 43 | >>> ds.datetime() 44 | (2000, 1, 1, 0, 0, 0, 0, 0) 45 | 46 | # enable oscillator 47 | >>> ds.halt(False) 48 | 49 | # read datetime after 1 second 50 | >>> ds.datetime() 51 | (2000, 1, 1, 0, 0, 0, 1, 0) 52 | 53 | # read datetime after 1 more second 54 | >>> ds.datetime() 55 | (2000, 1, 1, 0, 0, 0, 2, 0) 56 | 57 | # read datetime after 1 more second 58 | >>> ds.datetime() 59 | (2000, 1, 1, 0, 0, 0, 3, 0) 60 | 61 | # set the datetime 24th March 2018 at 1:45:21 PM 62 | >>> now = (2018, 3, 24, 6, 13, 45, 21, 0) 63 | >>> ds.datetime(now) 64 | 65 | # read datetime after 1 second 66 | >>> ds.datetime() 67 | (2018, 3, 24, 6, 13, 45, 22, 0) 68 | 69 | # read datetime after 1 second 70 | >>> ds.datetime() 71 | (2018, 3, 24, 6, 13, 45, 23, 0) 72 | 73 | # disable oscillator 74 | >>> ds.halt(True) 75 | 76 | # read datetime after 1 second 77 | >>> ds.datetime() 78 | (2018, 3, 24, 6, 13, 45, 24, 0) 79 | 80 | # read datetime after 1 second (no change) 81 | >>> ds.datetime() 82 | (2018, 3, 24, 6, 13, 45, 24, 0) 83 | 84 | # minute increment (00:00:59 -> 00:01:00) 85 | >>> ds.datetime((2018, 3, 24, 6, 0, 0, 58, 0)) 86 | >>> ds.datetime() 87 | (2018, 3, 24, 6, 0, 0, 59, 0) 88 | >>> ds.datetime() 89 | (2018, 3, 24, 6, 0, 1, 0, 0) 90 | 91 | # hour increment (00:59:59 -> 01:00:00) 92 | >>> ds.datetime((2018, 3, 24, 6, 0, 59, 58, 0)) 93 | >>> ds.datetime() 94 | (2018, 3, 24, 6, 0, 59, 59, 0) 95 | >>> ds.datetime() 96 | (2018, 3, 24, 6, 1, 0, 0, 0) 97 | 98 | # day + weekday increment (23:59:59 Sat -> 00:00:00 Sun) 99 | >>> ds.datetime((2018, 3, 24, 6, 23, 59, 58, 0)) 100 | >>> ds.datetime() 101 | (2018, 3, 24, 6, 23, 59, 59, 0) 102 | >>> ds.datetime() 103 | (2018, 3, 25, 0, 0, 0, 0, 0) 104 | 105 | # month increment (Wed 28th Feb 2018 -> Thu 1st Mar 2018) 106 | >>> ds.datetime((2018, 2, 28, 3, 23, 59, 58, 0)) 107 | >>> ds.datetime() 108 | (2018, 2, 28, 3, 23, 59, 59, 0) 109 | >>> ds.datetime() 110 | (2018, 3, 1, 4, 0, 0, 0, 0) 111 | 112 | # month increment on leap year Feb has 29 days (Sun 28th Feb 2016 -> Mon 29th Feb 2016) 113 | >>> ds.datetime((2016, 2, 28, 0, 23, 59, 58, 0)) 114 | >>> ds.datetime() 115 | (2016, 2, 28, 0, 23, 59, 59, 0) 116 | >>> ds.datetime() 117 | (2016, 2, 29, 1, 0, 0, 0, 0) 118 | 119 | # month increment on leap year (Mon 29th Feb 2016 -> Tue 1st Mar 2016) 120 | >>> ds.datetime((2016, 2, 29, 1, 23, 59, 58, 0)) 121 | >>> ds.datetime() 122 | (2016, 2, 29, 1, 23, 59, 59, 0) 123 | >>> ds.datetime() 124 | (2016, 3, 1, 2, 0, 0, 0, 0) 125 | 126 | # year increment (31st Dec 2018 -> 1st Jan 2019) 127 | >>> ds.datetime((2018, 12, 31, 1, 23, 59, 58, 0)) 128 | >>> ds.datetime() 129 | (2018, 12, 31, 1, 23, 59, 59, 0) 130 | >>> ds.datetime() 131 | (2019, 1, 1, 2, 0, 0, 0, 0) 132 | 133 | # square wave output on pin SQ - 1Hz 134 | >>> ds.square_wave(1, 0) 135 | 136 | # square wave output on pin SQ - 4.096kHz 137 | >>> ds.square_wave(4, 0) 138 | 139 | # square wave output on pin SQ - 8.192kHz 140 | >>> ds.square_wave(8, 0) 141 | 142 | # square wave output on pin SQ - 32.768kHz 143 | >>> ds.square_wave(32, 0) 144 | 145 | # logic level output on pin SQ - high 146 | >>> ds.square_wave(0, 1) 147 | 148 | # logic level output on pin SQ - low 149 | >>> ds.square_wave(0, 0) 150 | ``` 151 | 152 | # DS18B20 1-Wire Temperature Sensor Examples 153 | 154 | ```python 155 | >>> from machine import Pin 156 | >>> import onewire 157 | >>> ow = onewire.OneWire(Pin('A9')) 158 | >>> ow.scan() 159 | [bytearray(b'(\xc9E\x01\x00\x00\x80/')] 160 | 161 | >>> import time, ds18x20 162 | >>> ds = ds18x20.DS18X20(ow) 163 | >>> roms = ds.scan() 164 | >>> ds.convert_temp() 165 | >>> time.sleep_ms(750) 166 | >>> for rom in roms: 167 | ... print(ds.read_temp(rom)) 168 | 23.8125 169 | ``` 170 | 171 | # AT24C32N EEPROM Examples 172 | 173 | ```python 174 | >>> from machine import I2C, Pin 175 | >>> i2c = I2C(3) # SCL=A8, SDA=C9 176 | >>> i2c.scan() 177 | [80, 104] 178 | 179 | >>> import at24c32n 180 | >>> eeprom = at24c32n.AT24C32N(i2c) 181 | 182 | # read 32 bytes starting from memory address 0 183 | >>> eeprom.read(0, 32) 184 | b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' 185 | 186 | # write hello world to memory address 0 187 | >>> eeprom.write(0, 'hello world') 188 | 189 | # read back the hello world 190 | >>> eeprom.read(0, 32) 191 | b'hello world\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' 192 | >>> eeprom.read(0, 11) 193 | b'hello world' 194 | 195 | # write multiple pages (32 bytes per page) 196 | >>> eeprom.write(0, b'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ') 197 | 198 | # read multiple pages (32 bytes per page) 199 | >>> eeprom.read(0,64) 200 | b'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\xff\xff' 201 | 202 | # mutliple page writes (fill pages 0 and 1 with test data) 203 | # write is performed in two steps, "0" x 32 in the first page, then "1" x 32 in the next page 204 | # memory address was at the start of a page boundary so each write is a full 32 byte page write 205 | >>> eeprom.write(0, b'0000000000000000000000000000000011111111111111111111111111111111') 206 | >>> eeprom.read(0,64) 207 | b'0000000000000000000000000000000011111111111111111111111111111111' 208 | 209 | # partial page writes 210 | # write some bytes spanning two pages, not starting at a page boundary 211 | # write is performed in two steps, "abc" in the first page then "def" in the next page 212 | >>> eeprom.write(29, b'abcdef') 213 | >>> eeprom.read(0,64) 214 | b'00000000000000000000000000000abcdef11111111111111111111111111111' 215 | 216 | # fill entire eeprom with 0xFF 217 | >>> buf = b'\xff' * 32 218 | >>> for i in range(128): 219 | ... eeprom.write(i*32, buf) 220 | 221 | # show page boundaries 222 | >>> for i in range(128): 223 | ... eeprom.write(i*32, '|-Page-{:-<24}|'.format(i)) 224 | >>> eeprom.read(0,128) 225 | b'|-Page-0-----------------------||-Page-1-----------------------||-Page-2-----------------------||-Page-3-----------------------|' 226 | 227 | # read entire eeprom 228 | >>> eeprom.read(0,4096) 229 | ``` 230 | 231 | ## PyBoard / STM32F4 built-in RTC 232 | 233 | You do not need this module if you are using a PyBoard or STM32 microcontroller with [built in RTC hardware](http://www.st.com/content/ccc/resource/technical/document/application_note/7a/9c/de/da/84/e7/47/8a/DM00025071.pdf/files/DM00025071.pdf/jcr:content/translations/en.DM00025071.pdf). 234 | 235 | Simply add a coin cell battery between GND + VBAT and use [pyb.RTC](http://docs.micropython.org/en/latest/pyboard/library/pyb.RTC.html#pyb-rtc). 236 | 237 | On the early pyboards, VBAT is the backup battery for the RTC. On the newer boards, VBAT is for powering the pyboard using a battery and the RTC battery is called Vbackup. 238 | - Dave Hylands on the [micropython forum](https://forum.micropython.org/viewtopic.php?f=6&t=229&p=15352&hilit=vbat#p15352) 239 | 240 | ```python 241 | # on the PyBoard or a STM32F407 242 | rtc = pyb.RTC() 243 | # set time 244 | rtc.datetime((2018, 3, 24, 6, 13, 45, 21, 0)) 245 | # attach battery between GND + VBAT 246 | # disconnect, reconnect 247 | # get time 248 | print(rtc.datetime()) 249 | ``` 250 | 251 | ## Troubleshooting 252 | 253 | If you are using the ESP32 [loboris port](https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo), swap the `addrsize=16` for a `adrlen=2`. 254 | 255 | ## Parts 256 | 257 | * [TinyRTC I2C module](https://www.aliexpress.com/item/Tiny-RTC-I2C-modules-24C32-memory-DS1307-clock-RTC-module-without-battery-good-quality-low-price/2020927349.html) $0.53 AUD 258 | * [LIR2032 rechargeable coin cell](https://www.aliexpress.com/item/2x-LIR2032-Rechargeable-Lithium-Li-ion-Batteries-3-6V-40mAh-Button-Coin-Cells-Battery-For-Watch/32842926682.html) $1.19 AUD 259 | 260 | ## Connections 261 | 262 | STM32F407VET6 | TinyRTC I2C module 263 | ------------- | ---------------------- 264 | A9 (any pin) | DS 265 | A8 (I2C3 SCL) | SCL 266 | C9 (I2C3 SDA) | SDA 267 | 3V3 | VCC 268 | GND | GND 269 | 270 | ## Links 271 | 272 | * [micropython.org](http://micropython.org) 273 | * [Binary-coded decimal](https://en.wikipedia.org/wiki/Binary-coded_decimal) 274 | * [DS1307 datasheet](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) 275 | * [AT24C32 datasheet](http://ww1.microchip.com/downloads/en/devicedoc/doc0336.pdf) 276 | 277 | ## License 278 | 279 | Licensed under the [MIT License](http://opensource.org/licenses/MIT). 280 | -------------------------------------------------------------------------------- /at24c32n.py: -------------------------------------------------------------------------------- 1 | """ 2 | MicroPython TinyRTC I2C Module, DS1307 RTC + AT24C32N EEPROM 3 | https://github.com/mcauser/micropython-tinyrtc-i2c 4 | 5 | MIT License 6 | Copyright (c) 2018 Mike Causer 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | """ 26 | 27 | # AT24C32A, 32K (32768 kbit / 4 KB), 128 pages, 32 bytes per page, i2c addr 0x50 28 | 29 | import time 30 | 31 | class AT24C32N(object): 32 | """Driver for the AT24C32N 32K EEPROM.""" 33 | 34 | def __init__(self, i2c, i2c_addr=0x50, pages=128, bpp=32): 35 | self.i2c = i2c 36 | self.i2c_addr = i2c_addr 37 | self.pages = pages 38 | self.bpp = bpp # bytes per page 39 | 40 | def capacity(self): 41 | """Storage capacity in bytes""" 42 | return self.pages * self.bpp 43 | 44 | def read(self, addr, nbytes): 45 | """Read one or more bytes from the EEPROM starting from a specific address""" 46 | return self.i2c.readfrom_mem(self.i2c_addr, addr, nbytes, addrsize=16) 47 | 48 | def write(self, addr, buf): 49 | """Write one or more bytes to the EEPROM starting from a specific address""" 50 | offset = addr % self.bpp 51 | partial = 0 52 | # partial page write 53 | if offset > 0: 54 | partial = self.bpp - offset 55 | self.i2c.writeto_mem(self.i2c_addr, addr, buf[0:partial], addrsize=16) 56 | time.sleep_ms(5) 57 | addr += partial 58 | # full page write 59 | for i in range(partial, len(buf), self.bpp): 60 | self.i2c.writeto_mem(self.i2c_addr, addr+i-partial, buf[i:i+self.bpp], addrsize=16) 61 | time.sleep_ms(5) 62 | -------------------------------------------------------------------------------- /docs/AT24C32N-AT24C64N.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-tinyrtc-i2c/8c9904a7d36e87467637f641e5f6438464076462/docs/AT24C32N-AT24C64N.pdf -------------------------------------------------------------------------------- /docs/DS1307-RTC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-tinyrtc-i2c/8c9904a7d36e87467637f641e5f6438464076462/docs/DS1307-RTC.pdf -------------------------------------------------------------------------------- /docs/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcauser/micropython-tinyrtc-i2c/8c9904a7d36e87467637f641e5f6438464076462/docs/demo.jpg -------------------------------------------------------------------------------- /ds1307.py: -------------------------------------------------------------------------------- 1 | """ 2 | MicroPython TinyRTC I2C Module, DS1307 RTC + AT24C32N EEPROM 3 | https://github.com/mcauser/micropython-tinyrtc-i2c 4 | 5 | MIT License 6 | Copyright (c) 2018 Mike Causer 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | 26 | BCD Format: 27 | https://en.wikipedia.org/wiki/Binary-coded_decimal 28 | """ 29 | 30 | from micropython import const 31 | 32 | DATETIME_REG = const(0) # 0x00-0x06 33 | CHIP_HALT = const(128) 34 | CONTROL_REG = const(7) # 0x07 35 | RAM_REG = const(8) # 0x08-0x3F 36 | 37 | class DS1307(object): 38 | """Driver for the DS1307 RTC.""" 39 | def __init__(self, i2c, addr=0x68): 40 | self.i2c = i2c 41 | self.addr = addr 42 | self.weekday_start = 1 43 | self._halt = False 44 | 45 | def _dec2bcd(self, value): 46 | """Convert decimal to binary coded decimal (BCD) format""" 47 | return (value // 10) << 4 | (value % 10) 48 | 49 | def _bcd2dec(self, value): 50 | """Convert binary coded decimal (BCD) format to decimal""" 51 | return ((value >> 4) * 10) + (value & 0x0F) 52 | 53 | def datetime(self, datetime=None): 54 | """Get or set datetime""" 55 | if datetime is None: 56 | buf = self.i2c.readfrom_mem(self.addr, DATETIME_REG, 7) 57 | return ( 58 | self._bcd2dec(buf[6]) + 2000, # year 59 | self._bcd2dec(buf[5]), # month 60 | self._bcd2dec(buf[4]), # day 61 | self._bcd2dec(buf[3] - self.weekday_start), # weekday 62 | self._bcd2dec(buf[2]), # hour 63 | self._bcd2dec(buf[1]), # minute 64 | self._bcd2dec(buf[0] & 0x7F), # second 65 | 0 # subseconds 66 | ) 67 | buf = bytearray(7) 68 | buf[0] = self._dec2bcd(datetime[6]) & 0x7F # second, msb = CH, 1=halt, 0=go 69 | buf[1] = self._dec2bcd(datetime[5]) # minute 70 | buf[2] = self._dec2bcd(datetime[4]) # hour 71 | buf[3] = self._dec2bcd(datetime[3] + self.weekday_start) # weekday 72 | buf[4] = self._dec2bcd(datetime[2]) # day 73 | buf[5] = self._dec2bcd(datetime[1]) # month 74 | buf[6] = self._dec2bcd(datetime[0] - 2000) # year 75 | if (self._halt): 76 | buf[0] |= (1 << 7) 77 | self.i2c.writeto_mem(self.addr, DATETIME_REG, buf) 78 | 79 | def halt(self, val=None): 80 | """Power up, power down or check status""" 81 | if val is None: 82 | return self._halt 83 | reg = self.i2c.readfrom_mem(self.addr, DATETIME_REG, 1)[0] 84 | if val: 85 | reg |= CHIP_HALT 86 | else: 87 | reg &= ~CHIP_HALT 88 | self._halt = bool(val) 89 | self.i2c.writeto_mem(self.addr, DATETIME_REG, bytearray([reg])) 90 | 91 | def square_wave(self, sqw=0, out=0): 92 | """Output square wave on pin SQ at 1Hz, 4.096kHz, 8.192kHz or 32.768kHz, 93 | or disable the oscillator and output logic level high/low.""" 94 | rs0 = 1 if sqw == 4 or sqw == 32 else 0 95 | rs1 = 1 if sqw == 8 or sqw == 32 else 0 96 | out = 1 if out > 0 else 0 97 | sqw = 1 if sqw > 0 else 0 98 | reg = rs0 | rs1 << 1 | sqw << 4 | out << 7 99 | self.i2c.writeto_mem(self.addr, CONTROL_REG, bytearray([reg])) 100 | -------------------------------------------------------------------------------- /ds18x20.py: -------------------------------------------------------------------------------- 1 | # https://github.com/micropython/micropython/blob/master/drivers/onewire/ds18x20.py 2 | # DS18x20 temperature sensor driver for MicroPython. 3 | # MIT license; Copyright (c) 2016 Damien P. George 4 | 5 | from micropython import const 6 | 7 | _CONVERT = const(0x44) 8 | _RD_SCRATCH = const(0xbe) 9 | _WR_SCRATCH = const(0x4e) 10 | 11 | class DS18X20: 12 | def __init__(self, onewire): 13 | self.ow = onewire 14 | self.buf = bytearray(9) 15 | 16 | def scan(self): 17 | return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28] 18 | 19 | def convert_temp(self): 20 | self.ow.reset(True) 21 | self.ow.writebyte(self.ow.SKIP_ROM) 22 | self.ow.writebyte(_CONVERT) 23 | 24 | def read_scratch(self, rom): 25 | self.ow.reset(True) 26 | self.ow.select_rom(rom) 27 | self.ow.writebyte(_RD_SCRATCH) 28 | self.ow.readinto(self.buf) 29 | if self.ow.crc8(self.buf): 30 | raise Exception('CRC error') 31 | return self.buf 32 | 33 | def write_scratch(self, rom, buf): 34 | self.ow.reset(True) 35 | self.ow.select_rom(rom) 36 | self.ow.writebyte(_WR_SCRATCH) 37 | self.ow.write(buf) 38 | 39 | def read_temp(self, rom): 40 | buf = self.read_scratch(rom) 41 | if rom[0] == 0x10: 42 | if buf[1]: 43 | t = buf[0] >> 1 | 0x80 44 | t = -((~t + 1) & 0xff) 45 | else: 46 | t = buf[0] >> 1 47 | return t - 0.25 + (buf[7] - buf[6]) / buf[7] 48 | else: 49 | t = buf[1] << 8 | buf[0] 50 | if t & 0x8000: # sign bit set 51 | t = -((t ^ 0xffff) + 1) 52 | return t / 16 53 | --------------------------------------------------------------------------------