Raspberry Pi IoT In C Using Linux Drivers - 1-Wire And The DS18B20
Written by Harry Fairhead   
Monday, 22 November 2021
Article Index
Raspberry Pi IoT In C Using Linux Drivers - 1-Wire And The DS18B20
Listing Devices
Folders

Listing Devices

When the driver is loaded it scans the 1-Wire bus for connected devices. It repeats the scan at intervals, so keeping the system up-to-date if you add new devices. For each device it finds, it creates a directory with the same name as the serial number of the device in /sys/bus/w1/devices/. Inside the folder are, among other things, files that let you work with the sensor. In particular there is the w1_slave file that allows you to initiate a measurement and read the result.

What we have to do is read the names of the folders in /sys/bus/w1/devices/ and extract each one and use this to construct paths to each of the w1_slave files that have been created. Usually we know the class of device we are working with by the form of its serial number. Each device has a 64-bit number that is composed of a family code that tells you the type of the device and a unique serial number:

For example, all DS18B20 Temperature Sensors have a serial number that starts with 28-. Variations on the device have different family codes:

W1_THERM_DS18S20	0x10
W1_THERM_DS1822	        0x22
W1_THERM_DS18B20	0x28
W1_THERM_DS1825	        0x3B
W1_THERM_DS28EA00	0x42

All of these are supported by the Linux driver.

Working with directories in Linux isn’t difficult, but you you need a refresher then see Applying C for the IoT with Linux, ISBN: 9781871962611. The following is the usual way to find out what devices are connected, but there is arguably a better way, see later.

First we open the devices directory:

int getDevices(char path[][100], int *num) {
    DIR *dirp;
    char name[10][50];
    struct dirent *direntp;
    if ((dirp = opendir("/sys/bus/w1/devices/")) ==
NULL) { return -1; }

Next we scan through all of the directories that this contains, looking for names that start with 28-:

    *num = 0;
    while ((direntp = readdir(dirp)) != NULL) {
        if (strstr(direntp->d_name, "28-")) {
            strncpy(name[*num], direntp->d_name, 50);
            (*num)++;
        }
    } 
    closedir(dirp);

Each one found is copied to an element of the name string array. Notice that the name array only has space for 10 devices – you could make it bigger.

Finally we construct a string array with the path to each of the w1_slave files that allow us to read each of the sensors:

 for (int i = 0; i < *num; i++) {
  snprintf(path[i],100,
"/sys/bus/w1/devices/%s/w1_slave", name[i]); } return 0; }

Notice that when the getDevices function is called it has to be supplied with a path string array of the required dimensions.

The complete function is:

int getDevices(char path[][100], int *num)
{
    DIR *dirp;
    char name[10][50];
    struct dirent *direntp;
    if ((dirp = opendir("/sys/bus/w1/devices/")) ==
NULL) { return -1; } *num = 0; while ((direntp = readdir(dirp)) != NULL) { if (strstr(direntp->d_name, "28-")) { strncpy(name[*num], direntp->d_name, 50); (*num)++; } } closedir(dirp); for (int i = 0; i < *num; i++) { snprintf(path[i], 100,
"/sys/bus/w1/devices/%s", name[i]); } return 0; }

It is also possible to arrange for an action to occur when a new device is added as outlined in the next chapter.

The DS18B20

As an example of a 1-Wire bus device the DS18B20 is a good choice as it is almost the only device anyone makes significant use of. It is low-cost, easy to use and you can use multiple devices on a single GPIO line.

The DS18B20 is available in a number of formats, but the most common makes it look just like a standard BJT (Bipolar Junction Transistor) which can sometimes be a problem when you are trying to find one. You can also get them made up into waterproof sensors complete with cable.

Device

 

probe

No matter how packaged, they will work at 3.3V or 5V.

The basic specification of the DS18B20 is:

 

  • Measures temperatures from -55°C to +125°C (-67°F to +257°F)

  • ±0.5°C accuracy from -10°C to +85°C

  • Thermometer resolution is user-selectable from 9 to 12 bits

  • Converts temperature to 12-bit digital word in 750ms (max)

 

It can also be powered from the data line, making the bus physically need only two wires - data and ground. However, this "parasitic power" mode is difficult to make work reliably and best avoided in an initial design. To supply it with enough power during a conversion, the host has to connect it directly to the data line by providing a "strong pull-up" - essentially a transistor. In normal-powered mode there are just three connections:

pinout
Ground needs to be connected to the system ground, VDD to 3.3V, and DQ to the pull-up resistor of an open collector bus.

onewirebus
While you can have multiple devices on the same bus, for simplicity it is better to start off with a single device until you know that everything is working.

layout



Last Updated ( Saturday, 27 November 2021 )