Linux programming to realize DS18B20 to detect the temperature of raspberry pie

Posted by ramblix on Tue, 03 Mar 2020 11:04:52 +0100

Catalog

(1) Project introduction
(two) code and debugging
(3) Summary

(1) Project introduction

DS18B20 is a commonly used digital temperature sensor. Its output is a digital signal, which has the characteristics of small size, low hardware cost, strong anti-interference ability and high precision. This experiment project is based on the support of raspberry to DS18B20 1-wire Temperature Sensor (first-line protocol), and then realizes the temperature detection by programming.

DQ is digital signal input / output terminal;
GND is power ground;
VCC is the input terminal of external power supply;
The connection mode of the two ports is as follows:
The ground end of raspberry pie (pin 06) - the port connecting the GND of DS18B20;
gpio 04 end of raspberry pie (pin 07 pin) --------- the port connecting DQ of DS18B20;
3.3V end of raspberry pie (pin 01) ---- connect the VCC port of DS18B20;

(2) Code and debugging

1. Log in to the raspberry pie server remotely through SecurtCRT, and find the location of the file, as shown in the following figure in the W1? Slave file in the root directory:

First, three basic file I/O functions, open(), read(), close(), are called to read the file contents:

  int main(int argc, char **argv)
  {    
     int fd;
       
     char buf[128];
      
     fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDONLY);
      
     memset(buf,0,sizeof(buf);   //Initialize the memory of buf to avoid redundant characters in the result
     
     read(fd,buf,sizeof(buf));   
     
     printf("buf: %s\n"buf);
 
     close(fd);
 }

The operation results are as follows:

2. If we want to filter out other irrelevant characters, we need to call the strstr() function to locate "t =" this string, and then use printf() to print directly; because the temperature bit floating-point number, in order to read conveniently, we need to call the A to f() function (a:ASCII code, to: conversion, f: float type), that is, convert the ASCII code corresponding to the string to float type.
The code optimization results are as follows:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main(int argc, char **argv)
{
     int fd;
     char buf[128];
     char *ptr;
     float temp;
     
     fd=open("/sys/bus/w1/devices/28-041731f7c0ff/w1_slave",O_RDONLY);
    
     memset(buf,0,sizeof(buf);   
     
     read(fd,buf,sizeof(buf));
    
     printf("buf: %s\n"buf);
     
     ptr=strstr(buf,"t=");
     if(!ptr)
     {
         printf("can not find t=string\n");
         return -1;
     }
     
     ptr +=2;
    
     printf("ptr= %s\n",ptr);
    
     temp = atof(ptr)/1000;
    
     printf("temperature: %f\n",temp);

     close(fd);
}

The operation results are as follows:

3. In fact, the serial number of DS18b20 chip is constantly changing, but it starts with "28 -", so we need to further optimize the code, use strstr() function to match the string containing "28 -" under the path of "/ sys/bus/w1/devices /", and then use strncat() function to splice it under the path, so that no matter how the serial number of the chip changes, we can accurately locate the corresponding path

The final code is as follows:

#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
#include<dirent.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
    int           fd=-1;
    char          buf[128];
    char          *ptr = NULL;
    float         temp;
    DIR           *dirp=NULL;
    struct dirent *direntp = NULL;
    char          w1_path[32]="/sys/bus/w1/devices/";
    char          chip_sn[32];
    int           found=0;

    dirp=opendir(w1_path);
    if(!dirp)
    {
        printf("open folder %s failure:%s\n",w1_path,strerror(errno));
        return -1;
    }
    while(NULL!=(direntp=readdir(dirp)))
    {
        if(strstr(direntp->d_name,"28-"))
        {
            strncpy(chip_sn,direntp->d_name,sizeof(chip_sn));
            found=1;
        }               

    }
    closedir(dirp);
    if(!found)
    {
        printf("can not find ds18b20 chipset\n");
        return -2;
    }
    strncat(w1_path,chip_sn,sizeof(w1_path)-strlen(w1_path));

    strncat(w1_path,"w1_slave",sizeof(w1_path)-strlen(w1_path));

    printf("w1_path:%s\n",w1_path);



    fd=open("w1_path",O_RDONLY);
    if(fd<0)
    {
        printf("open file failure: %s\n",strerror(errno));
        return -3;
    }
    memset(buf,0,sizeof(buf));   

    if(read(fd,buf,sizeof(buf))<0);
    {
        printf("read data from fd=%d failure: %s\n",fd,strerror(errno));
        return -4;
    }

    printf("buf: %s\n",buf);

    ptr=strstr(buf,"t=");
    if(!ptr)
    {
        printf("can not find t=string\n");
        return -5;
    }

    ptr +=2;

    printf("ptr= %s\n",ptr);

    temp = atof(ptr)/1000;

    printf("temperature: %f\n",temp);

    close(fd);

    return 0;
}

(3) Summary

This project involves some knowledge of raspberry pie and DS18B20 hardware, but the main test is the understanding of file IO system call under Linux, and a certain programming ability of c language. If not, please give me more advice. I hope my summary can help you.

Published 1 original article, won praise 1, visited 6
Private letter follow

Topics: Programming ascii Linux C