Pi IoT In Python Using Linux Drivers -The DHT22
Written by Harry Fairhead & Mike James   
Monday, 15 March 2021
Article Index
Pi IoT In Python Using Linux Drivers -The DHT22
Using The Driver
The Program

If you lookup the details of the dht11 overlay in the ReadMe you will find:

Name: dht11	
Info: Overlay for the DHT11/DHT21/DHT22 
humidity/temperature sensors. Also sometimes found
with the part number(s) AM230x. Load: dtoverlay=dht11,<param>=<val> Params: gpiopin GPIO connected to the sensor's
DATA output. (default 4) 

This all very straightforward. If you add:

dtoverlay=dht11 gpiopin=4

to the config.txt file then when you reboot, the driver will be loaded and configured to use GPIO4. Change the gpiopin parameter to whichever GPIO line you are using. After a reboot the driver will be ready to use – but where are the device folders? If you look in /sys/class you won’t find any new or obvious folders, but examining the device tree listed in /proc/device-tree you will find a new device, /proc/device-tree/dht11@0. However, looking through the information listed there gives you no clue how to find and use the device folders. This is very typical of using a new device driver – its use is more than obvious to its creators, but a potential user is left out in the cold.

The key to using the dht11 device driver is to discover that it is stored in the Pi OS GitHub repository at /linux/drivers/iio/humidity/dht11.c. The iio folder is where drivers written to the Industrial I/O standard are stored. This is covered in more detail in Chapter 14, but for now we can ignore this fact and simply use it to find the device folders.

All IIO devices are stored in /sys/bus/iio/devices/ and if you look you will find /sys/bus/iio/devices/iio:device0. This corresponds to the dht11 device you have just added. Of course iio:device0 isn’t a name that is going to ensure that you have the dht11 device. A partial solution is to read the name file to discover the device name. To read the actual data you read in_temp_input for the temperature in millidegree Celsius and in_humidityrelative_input for the percentage humidity times 1000. There is no easy way to find the names of these files in the documentation, but once you have found the correct folder they are fairly obvious.

A program to read the name, temperature and humidity is:

import io
fdr = io.open("/sys/bus/iio/devices/iio:device0/name",
                                    "rb", buffering=0)
name = fdr.readline().decode("utf-8")
print("name=", name)
fdr = io.open(
"rb", buffering=0) temp = fdr.readline().decode("utf-8") print("temp=", int(temp)/1000, "C") fdr.close() fdr = io.open("/sys/bus/iio/devices/iio:device0/ in_humidityrelative_input", "rb", buffering=0) hum = fdr.readline().decode("utf-8") print("Humidity=",int(hum)/1000,"%") fdr.close()

If you run the program you will see the name dht11@0 and the temperature and humidity. In a more complete program you would check the name to make sure that it is the device you want and if there are multiple devices you would search through the top-level folder to find the device with the correct name.

Dynamic Loading Drivers

There are many problems with using drivers as part of an application and one big one is the need to configure the system to install the driver. The simplest solution is to ask the user to edit the config.txt file, but this could be a road block to your app being installed at all and then there is the possibility of user error. A better solution is to include the change in an install script. This is simple but doesn’t allow for the user or some other program changing the config.txt file so that your app no longer works. A good solution in some cases is to make use of the new dynamic overlay loading feature. This is fairly recent but it works with the latest version of Pi OS.

Instead of having to load drivers at boot time you can use the dtoverlay or dtparam commands to install and configure drivers. The only problem is that there are some cases where it doesn’t work. Essentially you have to try it out to see it if works. The overlays that are dynamically loaded form a stack and, in theory, you can only remove the overlay on the top of the stack. In practice, removing any overlay often results in a memory leak at best and a crashed system at worse.

The dtoverlay command is described in the documentation as:

dtoverlay <overlay> [<param>=<val>...]
Add an overlay (with parameters)
dtoverlay -D Dry-run(prepare overlay, but don't apply- save it as dry-run.dtbo)
dtoverlay -r [<overlay>] Remove an overlay (by name, index or the last) dtoverlay -R [<overlay>] Remove from an overlay (by name, index or all) dtoverlay -l List active overlays/params dtoverlay -a List all overlays (marking the active)
dtoverlay -h Show this usage message
dtoverlay -h <overlay> Display help on an overlay
dtoverlay -h <overlay> <param>.. Or its parameters where <overlay> is the name of an overlay or 'dtparam' for dtparams

Options applicable to most variants:

-d <dir> specify an alternate location for the overlays
(defaults to /boot/overlays or /flash/overlays -p <string> force a compatible string for the platform -v Verbose operation

The dtparam command is:

dtparam <param>=<val>… 	Add an overlay (with parameters)
dtparam -D Dry-run (prepare overlay,
but don't apply - save it
as dry-run.dtbo)
dtparam -r [<idx>] Remove an overlay (by index,
or the last)
dtparam -R [<idx>] Remove from an overlay (by index,
or all)
dtparam -l List active overlays/dtparams
dtparam -a List all overlays/dtparams
(marking the active)
dtparam -h Show this usage message
dtparam -h <param>... Display help on the listed

Options applicable to most variants:

-d <dir>   Specify an alternate location for the overlay
(defaults to /boot/overlays or /flash/overlays) -p <string> Force a compatible string for the platform
-v Verbose operation

The important thing is that you can use the -l option to discover what overlays are already loaded and hence avoid loading the same overlay again.



Last Updated ( Monday, 15 March 2021 )