Great advice! Thank you, Dennis.
On Wednesday, August 19, 2020 at 9:11:16 AM UTC-7 Dennis Bieber wrote: > On Tue, 18 Aug 2020 14:29:43 -0700 (PDT), in > gmane.comp.hardware.beagleboard.user Ren W > <[email protected]> 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/199175ee-2942-41eb-84b7-b785000f9db4n%40googlegroups.com.
