On Tue, 18 Aug 2020 14:29:43 -0700 (PDT), in
gmane.comp.hardware.beagleboard.user Ren W
<rwaldura-re5jqeeqqe8avxtiumw...@public.gmane.org> wrote:

>
>AdaFruit sells such a thing (AM2302 <https://www.adafruit.com/product/393>), 
>but the protocol looks iffy (I'm using Bonescript, not Python). SparkFun 
>has a bunch of options also, but they all look like "internal" sensors, 
>i.e. not meant for exposure. 
>I've seen other projects go with an all-in-one weather sensor kit sold by 
>Davis; it looks like a bit much. And rather pricey. 
>
>I'm curious to hear what other enthusiasts use... Thanks! 

        Pretty much ANY sensors will need you to provide a suitable housing
(even that AM2302 is not warded against splashes. You want a white housing
(white to reflect sunlight) with downward slanting louvers on all sides for
air-flow, but which will block rain splatters from the stuff on the inside
(obviously a rain gauge will be outside -- most of them work on a trip
system that counts each time a bucket exceeds some mass and empties).

        You likely won't want to run all that many wires either -- especially
if each sensor is using a different protocol*.

        I really think what I'd do is obtain an Arduino (or Adafruit Circuit
Python Metro card), as both are microcontrollers capable of strict timing
tasks. Wire all sensors to this card, and use a simple program that just
loops reading each sensor, and then formatting the data into a simple
string that could be sent over a serial port. The Arduino/Metro would be
mounted in the top of the sensor housing, and would require a source of
power, and a (long run) serial line (due to length, one might want to run a
slow baud rate to reduce line noise effects). Four wires: 5V, GND, Tx, Rx.
(Actually, if you have the unit continuously sending data, and have not
command mode, you could drop one of the serial lines).


*       The protocol used by DHT-type sensors is rather timing critical. I'm
pretty sure Python will not keep up on its own, and suspect Bonescript will
have the same problem. I vaguely recall once trying to code a bit-banged
version in C, and I'm not certain I was able to get reliable readings on a
BBB -- the OS overhead and process swapping got in the way. You could write
something that runs on a PRU to get reliable timing.

        The basic/simplest reading process consists of sending the START
signal, then timing (simple loop counting loop cycles) the first signal
transition from the DHT. This gives you the timing baseline, late 1s and 0s
tend to be longer or shorter than the baseline (check spec sheet). Each bit
transition needs to be counted/timed. After you've obtained the timing for
all bits you can make the determination of 1 or 0, package them into bytes,
and return them as a value.

        If one has access to a system clock, it does remove the need to count
loop cycles. I can't locate my C attempt; my Python attempt -- which as I
recall wasn't fast enough -- years ago, was:

-=-=-=-
"""
    DHT11.py        Simple Humidity and Temperature Sensor
    April 2, 2016   Dennis L Bieber

    This file defines a class to read DHT11 sensors using the
    Adafruit_BBIO library.

    Minimal error checking is performed, timeout testing is
    performed as CPU-hog polling loops are being used to
    detect transitions (the Adafruit_BBIO wait_for_edge()
    block indefinitely and seemed to be hanging on some calls)

    NOTE: time.clock() appears to have a very coarse resolution,
    so timeouts need be significant
"""

import Adafruit_BBIO.GPIO as IO
import time

class DHTError(Exception):
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return "DHT Sensor Error: %s" % value

class DHT11(object):
    def __init__(self, pinStr, timeout=1.0):
        self._pinStr = pinStr
        self._timeout = timeout

    def readC(self):
        #   return humidity and degC
        #   spec sheet recommends reading twice as the first
        #   might return stale data
        (h, t) = self._read()
        return self._read()

    def readF(self):
        #   return humidity and degF
        (h, t) = self.readC()
        return (h, (t * 9.0) / 5.0 + 32.0)

    def _read(self):
        time.sleep(2.0) #to ensure device cycles
        
        #   prepare receive buffer
        data = [0, 0, 0, 0, 0]

        #   wait, if needed, for bus to go high
        #   (if it is low, some device has it)
        #   this is the only timeout check implemented
        ts = time.clock()
        IO.setup(self._pinStr, IO.IN)
        while not IO.input(self._pinStr):
            if (time.clock() - ts) > self._timeout:
                raise DHTError("Timeout waiting for bus available")

        #   send wake-up signal; spec is minimum 18msec
        IO.setup(self._pinStr, IO.OUT)
        IO.output(self._pinStr, IO.LOW)

        time.sleep(0.020)

        IO.output(self._pinStr, IO.HIGH)
        IO.setup(self._pinStr, IO.IN)

        #   wait for start of response
        ts = time.clock()
        while IO.input(self._pinStr):
            if (time.clock() - ts) > self._timeout:
                raise DHTError("Timeout waiting for start of response")

        #   wait for return to high
        ts = time.clock()
        while not IO.input(self._pinStr):
            if (time.clock() - ts) > self._timeout:
                raise DHTError("Timeout waiting for end of response")


        #   wait for start of bit indicator
        ts = time.clock()
        while IO.input(self._pinStr):
            if (time.clock() - ts) > self._timeout:
                raise DHTError("Timeout waiting for start of bit
indicator")

        #   loop over the data bytes
        for (i, d) in enumerate(data):
            #   get 8 bits per byte
            for b in range(8):
                #   wait for bit itself
                ts = time.clock()
                while not IO.input(self._pinStr):
                    if (time.clock() - ts) > self._timeout:
                        raise DHTError("Timeout waiting for start of bit")

                #   capture time time
                tbit = time.clock()

                #   wait for end of bit (start of next)
                ts = time.clock()
                while IO.input(self._pinStr):
                    if (time.clock() - ts) > self._timeout:
                        raise DHTError("Timeout waiting for end of bit")

                #   determine duration
                dur = time.clock() - tbit

                if dur > 0.000045:
                    d = (d << 1) + 1
                else:
                    d = (d << 1)  #+ 0
                    
            data[i] = d

        #   checksum validation, and conversion to floating point
        if sum(data[:3]) % 256 != data[4]:
            raise DHTError("Checksum Mismatch")

        #   good checksum, convert values
        humidity = data[0] + (data[1] / 10.0)
        temperature = data[2] + (data[3] / 10.0)
        return (humidity, temperature)

def closeIO():
    IO.cleanup()

if __name__ == "__main__":
    mySensor = DHT11("P8_15")   #   GPIO 48

    try:
        while True:
            (h, t) = mySensor.readF()
            print("Humidity: %s \%\tTemperature: %s degF\n" % (h, t))
            time.sleep(5.0)
    except KeyboardInterrupt:
        closeIO()
    except:     #   nasty naked except
        closeIO()
        raise   #   but we reraise the exception
-=-=-=-

        I don't know if using Adafruit_blinka and a CircuitPython library to
read a DHT sensor might be feasible. I should maybe see what's now
available and try.


-- 
Dennis L Bieber

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to beagleboard+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/beagleboard/dvgqjfl3mkj8g0hmi2m6c3ac2dogeo5036%404ax.com.

Reply via email to