From f5c3f84d80ebb00e233407e0daf07dc748c3190f Mon Sep 17 00:00:00 2001 From: Louis Bertrand Date: Wed, 31 Jul 2019 14:21:03 -0400 Subject: [PATCH 1/3] Add asynchhronous functions Add two new functions: start a conversion and return immediately, and read temperature. --- adafruit_ds18x20.py | 15 +++++++++++++++ docs/examples.rst | 6 +++++- examples/ds18x20_asynctest.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 examples/ds18x20_asynctest.py diff --git a/adafruit_ds18x20.py b/adafruit_ds18x20.py index f1494b2..d716547 100644 --- a/adafruit_ds18x20.py +++ b/adafruit_ds18x20.py @@ -40,6 +40,8 @@ _WR_SCRATCH = b'\x4E' _CONVERSION_TIMEOUT = const(1) RESOLUTION = (9, 10, 11, 12) +# Maximum conversion delay in seconds, from DS18B20 datasheet. +_CONVERSION_DELAY = {9:0.09375, 10:0.1875, 11:0.375, 12:0.750} class DS18X20(object): """Class which provides interface to DS18X20 temperature sensor.""" @@ -49,6 +51,7 @@ def __init__(self, bus, address): self._address = address self._device = OneWireDevice(bus, address) self._buf = bytearray(9) + self._conv_delay = _CONVERSION_DELAY[12] # pessimistic default else: raise ValueError('Incorrect family code in device address.') @@ -111,3 +114,15 @@ def _write_scratch(self, buf): with self._device as dev: dev.write(_WR_SCRATCH) dev.write(buf, end=3) + + def start_temperature_read(self): + """Start asynchronous conversion, returns immediately. + Returns maximum conversion delay [seconds] based on resolution.""" + with self._device as dev: + dev.write(_CONVERT) + return _CONVERSION_DELAY[self.resolution] + + def read_temperature(self): + """Read the temperature. No polling of the conversion busy bit + (assumes that the conversion has completed).""" + return self._read_temp() diff --git a/docs/examples.rst b/docs/examples.rst index ca75b12..f7315c1 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -1,8 +1,12 @@ Simple test ------------ -Ensure your device works with this simple test. +Ensure your device works with these simple tests. .. literalinclude:: ../examples/ds18x20_simpletest.py :caption: examples/ds18x20_simpletest.py :linenos: + +.. literalinclude:: ../examples/ds18x20_asynctest.py + :caption: examples/ds18x20_asynctest.py + :linenos: diff --git a/examples/ds18x20_asynctest.py b/examples/ds18x20_asynctest.py new file mode 100644 index 0000000..492b0be --- /dev/null +++ b/examples/ds18x20_asynctest.py @@ -0,0 +1,28 @@ +# Simple demo of printing the temperature from the first found DS18x20 sensor every second. +# Using the asynchronous functions start_temperature_read() and +# read_temperature() to allow the main loop to keep processing while +# the conversion is in progress. +# Author: Louis Bertrand, based on original by Tony DiCola + +import time + +import board + +from adafruit_onewire.bus import OneWireBus +from adafruit_ds18x20 import DS18X20 + + +# Initialize one-wire bus on board pin D1. +ow_bus = OneWireBus(board.D1) + +# Scan for sensors and grab the first one found. +ds18 = DS18X20(ow_bus, ow_bus.scan()[0]) + +# Main loop to print the temperature every second. +while True: + conversion_delay = ds18.start_temperature_read() + conversion_ready_at = time.monotonic() + conversion_delay + if time.monotonic() < conversion_ready_at: + print("waiting...") + print('Temperature: {0:0.3f}C'.format(ds18.read_temperature())) + time.sleep(1.0) From 5b4058ae140ce95dfd2f0d434ffe604281d11f75 Mon Sep 17 00:00:00 2001 From: Louis Bertrand Date: Wed, 31 Jul 2019 15:05:44 -0400 Subject: [PATCH 2/3] Update ds18x20_asynctest.py Fix newbie mistake s/if/while/ and neater output; also force 12 bit resolution to better demonstrate the operation. --- examples/ds18x20_asynctest.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/ds18x20_asynctest.py b/examples/ds18x20_asynctest.py index 492b0be..c066fe9 100644 --- a/examples/ds18x20_asynctest.py +++ b/examples/ds18x20_asynctest.py @@ -17,12 +17,15 @@ # Scan for sensors and grab the first one found. ds18 = DS18X20(ow_bus, ow_bus.scan()[0]) +ds18.resolution = 12 # Main loop to print the temperature every second. while True: conversion_delay = ds18.start_temperature_read() conversion_ready_at = time.monotonic() + conversion_delay - if time.monotonic() < conversion_ready_at: - print("waiting...") - print('Temperature: {0:0.3f}C'.format(ds18.read_temperature())) + print("waiting", end="") + while time.monotonic() < conversion_ready_at: + print(".", end="") + time.sleep(0.1) + print('\nTemperature: {0:0.3f}C\n'.format(ds18.read_temperature())) time.sleep(1.0) From 972f828cfadd71b1b9fe5657c72927d044025f0b Mon Sep 17 00:00:00 2001 From: Louis Bertrand Date: Wed, 7 Aug 2019 16:09:42 -0400 Subject: [PATCH 3/3] Fix pylint warning Removed trailing spaces to resolve PyLint warning. --- adafruit_ds18x20.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_ds18x20.py b/adafruit_ds18x20.py index d716547..6dd0111 100644 --- a/adafruit_ds18x20.py +++ b/adafruit_ds18x20.py @@ -121,7 +121,7 @@ def start_temperature_read(self): with self._device as dev: dev.write(_CONVERT) return _CONVERSION_DELAY[self.resolution] - + def read_temperature(self): """Read the temperature. No polling of the conversion busy bit (assumes that the conversion has completed)."""