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

You can build the circuit in a variety of ways. You can solder the resistor to the temperature sensor and then use some longer wires with clips to connect to the Pi. You could also solder directly to the Pi, which is a good plan for the Pi Zero, or use a prototyping board.

Once the driver is loaded and the device is recognized you will find a set of new folders in the w1/devices folder:

oneWirefolders

Most of the files have functions that are obvious from their names but there are some points of detail:

 

  • name Returns the name of the device which is the same as
    its serial number.

  • w1_slave uses the nine bytes that the device returns in a check
    sum -if the check sum is OK then the string ends with
    t= the temperature in millidegrees Celsius.

  • temperature Returns the temperature in millidegrees Celsius – the
    string is not null terminated.

  • resolution Returns the number of bits of resolution used. Writing
    a number to it sets the resolution if the device supports
    it.

  • ext_power Reads 0 if the device is parasitic powered and 1 if
    externally powered.

  • alarms Reads or writes the high and low temperatures, TH and
    TL, for the temperature alarm. The values are space
    separated and the lowest value is automatically used
    for TL.

  • eeprom Saves the current configuration if you write “save” to
    it and restores it if you write “restore”. It supports a
    limited number of writes so should be used sparingly.

 

It is also worth knowing that the device is also added to the hwmon folder and that folder is replicated in the devices folder. The reason for this is to allow integration with any hwmon software you may have – there are no advantages over using the device directly.

The 1-Wire master also has some useful files in the w1_bus_master folder:

therm_bulk_read Takes a temperature from all devices

w1_master_add Manually registers a slave device

w1_master_attempts Number of times a search was attempted

w1_master_max_slave_count Maximum number of slaves to search for

w1_master_name Name of the device (w1_bus_masterX)

w1_master_pullup 5V strong pull-up 0 enabled, 1 disabled

w1_master_remove Manually remove a slave device

w1_master_search Number of searches left to do

w1_master_slave_count Number of slaves found

w1_master_slaves Names of the slaves, one per line

w1_master_timeout Delay in seconds between searches

w1_master_timeout_us Delay in microseconds between searches

Normally a temperature conversion is triggered when you read the appropriate file but if you write trigger to the therm_bulk_read file all of the connected devices are read and the readings stored for the next time you read the device. Reading the file returns 0 if no bulk conversion is in progress, -1 if at least one device is still converting and 1 if conversion is complete but there is still data to be read from the devices.

You can set the w1_master_search to a small number if the attached devices rarely change. If your devices never change you could set it to zero and use w1_master_add to add the serial numbers.

The w1_master_timeout and w1_master_timeout_us determine the interval between searches for devices. Each time a search occurs w1_master_search is decremented and w1_master_attempts is incremented.

You can use the w1_master_slave_count and w1_master_slaves as an alternative way of discovering what devices are installed:

int getDevices(char path[][100], int *num)
{
    char buffer[500];
    int fd = open("/sys/bus/w1/drivers/w1_master_driver/
           w1_bus_master1/w1_master_slaves", O_RDONLY);
    read(fd, buffer, 500);
    close(fd);
    *num = 0;
    for (char *p = strtok(buffer, "\n"); p != NULL;
                             p = strtok(NULL, "\n"))
    {
        snprintf(path[(*num)++], 100, 
"/sys/bus/w1/devices/%s", p); } num--; }

Notice that the names are separated by newline characters and the strtok function splits the string on “/n”. You have to make sure that buffer is big enough to read all the names in one go.

A complete program that reads and displays the data of the first device connected to the 1-Wire bus is:

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
FILE *doCommand(char *cmd)
{
    FILE *fp = popen(cmd, "r");
    if (fp == NULL)
    {
        printf("Failed to run command %s \n\r", cmd);
        exit(1);
    }
    return fp;
}
void load1w(int pin)
{
    FILE *fd = doCommand("sudo dtparam -l");
    char output[1024];
    int txfound = 0;
    while (fgets(output, sizeof(output), fd) != NULL)
    {
        printf("%s\n\r", output);
        fflush(stdout);
        if (strstr(output, "w1-gpio") != NULL)
        {
            txfound = 1;
        }
    }
    pclose(fd);
    if (txfound == 0)
    {
        char cmd[100];
        snprintf(cmd, 100,
"sudo dtoverlay w1-gpio gpiopin=%d", pin); fd = doCommand(cmd); pclose(fd); } } int getDevices(char path[][100], int *num) { char buffer[500]; int fd = open("/sys/bus/w1/drivers/w1_master_driver/ w1_bus_master1/w1_master_slaves", O_RDONLY); read(fd, buffer, 500); close(fd); *num = 0; for (char *p = strtok(buffer, "\n"); p != NULL; p = strtok(NULL, "\n")) { snprintf(path[(*num)++], 100,
"/sys/bus/w1/devices/%s", p); } num--; } int getData(char path[], char name[],
char data[], int n) { char file[100]; snprintf(file, 100, "%s/%s", path, name); int fd = open(file, O_RDONLY); int c = read(fd, data, n); close(fd); data[c] = 0; return c; } int main(int argc, char **argv) { load1w(4); char path[10][100]; int num; getDevices(path, &num); printf("%d %s\n\r", num, path[0]); if (num < 1) exit(-1); char output[1024] = {0}; char file[100]; getData(path[0], "name", output, 100); printf("Name %s\n\r", output); getData(path[0], "resolution", output, 100); printf("Resolution %s\n\r", output); getData(path[0], "w1_slave", output, 100); printf("w1_slave %s\n\r", output); getData(path[0], "temperature", output, 100); printf("temperature %s\n\r", output); float temp; sscanf(output, "%f", &temp); temp = temp / 1000; printf("temperature %f C\n\r",temp); getData(path[0], "alarms", output, 100); printf("alarms %s\n\r", output); }

In Chapter But Not In This Extract

  • Netlink
  • Reading The DS18B20 Using Netlink
  • The Complete Netlink Program
  • Active Pull-Up
  • One Wire File System (OWFS)

Summary

  • The 1-Wire bus is easy to use and has good Linux support.

  • The w1-gpio driver will use any GPIO pin to implement a 1-Wire bus in software.

  • All 1-Wire devices have a unique serial number, which also codes for the type of the device.

  • You can list devices using directory operations or you can use the driver to interrogate the master.

  • The DS18B20 Temperature Sensor is a good example of a 1-Wire device.

  • The 1-Wire driver is one of the few Linux drivers that supports Netlink, a socket-based protocol that is designed to replace ioctl.

  • You can power a 1-Wire device over the line that is used for data. This only works if you use a strong pull-up in the form of a transistor.

  • If you want to make extensive use of 1-Wire devices, it might be worth looking into OWFS – the One Wire File System.

Raspberry Pi IoT In C Using Linux Drivers

By Harry Fairhead

Cdrivers360

Buy from Amazon.

Contents

  1.  Choosing A Pi For IoT

  2. C and Visual Studio Code

  3.  Drivers: A First Program

  4.  The GPIO Character Driver
         Extract: GPIO Character Driver

  5. GPIO Using I/O Control

  6.  GPIO Events

  7.  The Device Tree
        Extract: The DHT22

  8.  Some Electronics

  9.  Pulse Width Modulation
    Extract:  The PWM Driver 

  10. SPI Devices
    Extract: The SPI Driver 

  11. I2C Basics

  12. The I2C Linux Driver ***NEW!

     

  13. Advanced I2C

  14. Sensor Drivers – Linux IIO & Hwmon
      Extract: Hwmon  

  15. 1-Wire Bus
      Extract: 1-Wire And The DS18B20 

  16. Going Further With Drivers

  17. Appendix I

 <ASIN:1871962641>

<ASIN:B08W9V7TP9>

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


PlanetScale Gets Into Vector Search
02/12/2024

PlanetScale, the cloud MySQL-compatible database with advanced scaling capabilities, is now upgraded with vector storage and search.



GitHub Announces Free Copilot
19/12/2024

GitHub has launched GitHub Copilot Free, a free version of Copilot that provides limited access to selected features of Copilot and is automatically integrated into VS Code. The free tier is aimed at  [ ... ]


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info

<ASIN:187196265X>

<ASIN:1871962692>

<ASIN:1871962609>

 <ASIN:1871962617>

<ASIN:1871962455>

<ASIN:1871962463>



Last Updated ( Saturday, 27 November 2021 )