Read a DHT sensor on Raspberry Pi and mqtt the results

In an earlier post I showed how one could address the raspberry GPIO pins, in fact that is quite straightforward given the fact they are digital I/O pins that either are HIGH or LOW.
But what if one wants to read a sensor like a DHT11 attached to one of the GPIO pins? That is also not so difficult, but to make it more all round and easy to use in OpenHAB, I wanted to read a sensor and then MQTT the result to my MQTT broker.
In my case, my MQTT broker is on the same raspberry that I also aimed to attach the DHT11 to, so if I wanted I could read it directly, but just in case I wanted to read it from another raspberry, MQTT is a better solution (for me).

As it is no use to re-invent the wheel, I fortunately found someone already had done most of the work, albeit for a DHT22, but that was easy to alter.

For the next steps I presume you already have python installed. Jessie already should have python 2.7 installed, and should you want to upgrade that, check here.
The Python program calls a few libraries that you most likely already have, maybe with exception of the paho.mqtt.client and the adafruit DHT library.
the mqtt client can be installed as follows:*)
pip install paho-mqtt
if for whatever reason this does not work for you, try:
git clone https://github.com/eclipse/paho.mqtt.python.git => download the client
cd paho.mqtt.python => go to proper directory
python setup.py install => install the client
depending on how you are logged in you may need to add ‘sudo’ before the install commands

The mqtt client is now installed.

For the DHT library do the following:
git clone https://github.com/adafruit/Adafruit_Python_DHT.git => download the library
cd Adafruit_Python_DHT => go to proper directory

Before you install the library, you need some dependencies that may or may not be on your system:
sudo apt-get update
sudo apt-get install build-essential python-dev python-openssl
If you already had modules installed those will be skipped.
Then install the library:
sudo python setup.py install => install the library

At this moment it is a good idea to restart your raspberry.
If you want -when your raspberry is back up and running- you could now try one of the example programs in the Adafruit DHT library, just to make sure everything is working.
Connect your DHT11 to e.g. GPIO4 of your raspberry.
Make sure you are still in  directory: Adafruit_Python_DHT

do:
cd examples
sudo ./AdafruitDHT.py 11 4

You will get the temperature and Humidity reported in your terminal

Now download the DHT_sensor program.
If like me you want to use a DHT11 instead of a DHT22, change line 45:
DHT_TYPE = Adafruit_DHT.DHT22
into
DHT_TYPE = Adafruit_DHT.DHT11

and save the program on your raspberry

I saved it directly in my home/openhabian directory, i.e. the directory that is availble directly after logon

Now have a look at the usage instructions in the program (lines 36-42), but beware:
Presuming you saved the program as “mqtt.dht.sensor.py”, that is the name you need to use instead of “mqtt.channel.py” (the name mentioned in the “Usage”).
also.
I started my program as follows:

./mqtt.dhtsensor.py 'cupboard/temperature1' 'cupboard/humidity1' 4

This says that as my mqtt topics I have cupboard/temperature1 and cupboard/humidity1 and my DHT11 sensor is attached to GPIO pin 4 while the refresh rate is 300 seconds (the default).

To make it a bit easier I created a file called “dht.sh” that contained the single line:
./mqtt.dhtsensor.py 'cupboard/temperature1' 'cupboard/humidity1' 4 50
That does the same as the earlier line, but now I set the refresh rate to 50 seconds. I put it in one file because that is easier to type.
If you want you can make the dht.sh file to automatically start at boot as I describe below.

The MQTT messages are subsequently sent out over the network

And one could use definitions like below in your OpenHAB Items file to use them in OpenHAB

Number Cupboard_temp "Riser temperatuur [%.1f °C]" <temperature> (GF_Corridor) {mqtt="<[mosquitto:cupboard/temperature1:state:default]"}
Number Cupboard_humidity "Riser humidity [%.0f %%]" <line> (GF_Corridor) {mqtt="<[mosquitto:cupboard/humidity1:state:default]"}
Starting the script at boot

The script will run perfectly when started manually, but it will run in an instance of the SSH window and the moment you close that window, the script will stop. It is therefore better to have the script starting at boot. This is simple to do, but you have to be aware of the full PATH you are using.
Change the content of the dht.s file as follows:
Then in your preferred editor open the etc/rc.local file and add a line (the line at the red arrow):
Save the file and reboot. You will now no longer see the temperature and humidity in an ssh window, but the MQTT commands are being sent

A word of warning:
If you are eager to test the program, before you  connected a sensor, it will just skip the sensor and you will get no useful feedback.
Furthermore, Python is quite sensitive to using the proper indentation in its programs as these have a meaning  in how the program is being interpreted, so if you go edit the program, be sure to keep the proper indentation

 

_________________________________

*) I could have used the mosquitto client that was on my raspberry that was already functioning as a broker, but as I also wanted to use it on other raspberries, it was better to use the lightweight paho.mqtt.client

Advertisements

A battery fed MQTT weatherstation

(Note: if you consider building this… I am working on a similar station with a bare ESP12 and a BME280 for even better energy efficiency)

Weatherstations are a popular build for DIY-ers and with the ESP8266 WiFi capabilities that has become very easy.
Here I will present a simple weatherstation (DHT sensor BMP sensor for temperature, humidity and atmospheric pressure) that can be battery fed or mains fed.
It will send the info by MQTT and in order to save batteries, go to sleep most of the time.
Components needed are:

  • A wemos mini D1
  • A DHT11 or DHT22
  • A BMP280
  • A 100k resistor for the battery
  • A small switch or jumper
  • A LithiumIon charger module

Just a word for the wise… the Wemos D1 is not the best option to battery feed, as it has some peripheral components (such as the CH340 chip) that draw current. A better choice would be the bare ESP8266, but it is not for everybody to solder that.

The application has OTA. Using OTA together with deep sleep is always a bit of a tricky situation as you cannot do OTA when the ESP8266 is in deep sleep.
basically there are 3 solutions for that:

  1. Include a pause in which you can do OTA. Problem with that is that you would need some indication of when that pause starts (e.g. once the MQTT messages have come in). Another problem is that that pause in which the processor is not in deep sleep, it wil consume more energy.
  2. Make the deepsleep dependent on the state of a pin. With a jumper or Switch you could make one pin high or low and thus allow deepsleep or not.
  3. By having the software check on a seperate website whether or not there is an update for the software and then download that software. Obviously that requires some more organization and if the Wemos will do that check whenever it awakes, it will do that say every 15 minutes for something that may never happen.

Considering the above, Option 2 seemed the best, so I added a small switch to tell the software whether or not to go into deepsleep.

Software

The program once loaded (get it here) has several tabs in the IDE.
The main program “esp8266_weatherstation” is quite straightforward, it sets up all the usual parameters, variables and the sensors.
It reads the sensors and sends these via MQTT to a broker.
Once that is done, it goes into deepsleep, depending on two parameters:

  • the “FORCE_DEEPSLEEP” variable: if present there will be a 15 min deepsleep. If not set, the deepsleep will be determined by the battery voltage.
  • the state of the ‘SLEEPPIN (D6):  if LOW there will be deepsleep, if HIGH, there will be no deepsleep

If there is no deepsleep, a pause of 30 secs is added to avoid the MQTT messages being send in a frenzy.

You may be puzzled by the following code section:

float h = dht.readHumidity();
float t = dht.readTemperature();
delay(2000);
float h = dht.readHumidity();
float t = dht.readTemperature();

The reason for this is the response time of the DHT22. If you  start a reading, the results you get are from a reading that was started 2 secs before. Usually that is not an issue, but if you put the processor to sleep for 15 minutes, that first reading will give you 15 min old values. If that is not a problem, by all means remove the delay and second reading. It will not make a difference on your battery life as your  DHT22 is not put to sleep.
technically ofcourse it is possible to feed the DHT22 from one of the I/O pins and switch it off when not needed, but the DHT22 also needs a warm-up time of about 2 secs, so you would need to take that into account. No doubt that warm up time could be catered for with the delay(2000) command mentioned above.

The “OTA” section sets up the OTA function. As explained before, OTA and DEEPSLEEP is a bit of an uneasy combination. In order to use OTA, tou would need to put the switch on D6 in the right position (HIGH) and either reset  the WEMOS or wait till the next wake up. Mind you that when DEEPSLEEPing the OTA port  can disappear, but it should come back once the processor is out of DEEPSLEEP.

the “config.h” file defines some variables

the “webconnect” file connects to WiFi. If for some reason that connection cannot be made after 10 times trying, the processor is going back to sleep for 30 more seconds and then tries again.

Libraries

The libaries used are quite standard, with the exception of the PubSubClient library. This is not the well known PubSubclient library from Nick O’Leary, but a fork made by Ian Tester. The reason for using that one is that it is easier to send variables in the MQTT payload.
The DHT library is the DHT sensor Library from Adafruit. If you prefer another DHT library (there are many) you will probably only need to make minor changes.
The BMP280 library is also from Adafruit.

The sensors

DHT22

The DHT22 is the more accurate sibling of the DHT11, but both have a tendency of failure. generally the DHT22 needs a pull up resistor, but one can also use the internal pullup of the I/O pin for that.

There are two specification where the DHT11 is better than the DHT22. That’s the sampling rate which for the DHT11 is 1Hz or one reading every second, while the DHT22 sampling rate is 0,5Hz or one reading every two seconds and also the DHT11 has smaller body size.

If you are using this sensor outside, you can protect it against dirt and  creepy crawlies by covering it with a single layer of teflon tape. Supposedly this is fully permeable for humidity.

The DHT sensors do not have eternal life. they give up working alltogether (and usually permanently) when the humidity is 100%

Properties DHT11 DHT22
Voltage 3-5 Volt 3-5 Volt
Operating current 2.5mA 2.5mA
Temperature range 0 t/m 50 ºC -40 t/m 80 ºC
Temperature accuracy ±2 ºC ±0,5 ºC
Humidity range 20-80% RH 20-95% RH
Humidity accuracy ±5% RH ±2-5% RH
Sampling rate 1Hz 0.5Hz
BMP280

The BMP280 is the successor of the BMP085, BMP 180 and BMP183

Ofcourse it is possible to use one of the above predecessors, but these older sensors are generally more expensive than the BMP280.
The BMP280 can measure barometric pressure with ±1 hPa absolute accuraccy, and temperature with ±1.0°C accuracy. It can be controlled both by SPI and I2C.

Do not mix it up with the BME280. That sensor can also read humidity, but it is slightly more expensive.
The BME280 ofcourse would be a perfect chip to go to if you want to avoid the DHT22 sensor. It can read temperature, humidity and barometric pressure. I just didnt have it lying around, thus couldnt try.

If you are no fan of the DHT11/22 consider the I2C HTU21D, or theSi7021 (replaced by the HTU21D).
If you are only interested in say temperature and not in humidity, the BPM280 is the best choice and you can omit the DHT22. If you only want temperature, the DS18B20 is probably the best choice.

The battery

Lipo Charge module

It is hard to give recommendations for what battery to use. I am using the battery shield to which I connect a LiPo battery. That makes it all very simple but it is not the most efficient way of using the energy from a battery as the battery shield first boosts it up to 5 Volt after which the Wemos makes 3V3 Volt from it.
Another easy way is to use a Lipo battery with a lowdrop 3V3 regulator and a cheap charging module (pictured top). You could combine the charging module with a small solar cell (with a 5-6 Volt max output). The 100k resistor in the  circuit sketch should go directly to the V+batt, to monitor the battery voltage. The choice for the 100k resistor is explained here.  If for power efficiency you decide to use a bare ESP8266 instead, one has the opportunity to increase the resistors of the voltage divider to come to a smaller current through these resistors