樹莓派與DS18B20獲取環境溫度(Linux)
- 前言
- 一、硬體準備
- 1.1 樹莓派4B
- 1.2 DS18B20溫濕度傳感器
- 1.4 專案展示效果
- 二、軟體準備
- 2.1 Vim(Linux)
- 2.2 SecureCRT(window)
- 三、操作和原始碼展示
- 四、總結
注:本文系湛江市嶺南師范學院物聯網俱樂部原創部分訓練專案,轉載請保留宣告,
前言
在上次的教程中已經教大家如何使用檔案IO系統呼叫、檔案夾作業系統呼叫和檔案拷貝,這些知識點將會在本次小專案中發揮得淋漓盡致,對于極客們,樹莓派是上等的DIY神器;對于專案開發者,樹莓派也不失為一種省時、省力的明智選擇,很多愛好者在玩樹莓派,所以其開源的資料比較多,好多東西我們可以拿來即用,不用重復造輪子,下面,請跟我我學習一下怎么在樹莓派上用C語言讀取ds18b20的溫度值,
一、硬體準備
1.1 樹莓派4B


1.2 DS18B20溫濕度傳感器

1.4 專案展示效果

二、軟體準備
2.1 Vim(Linux)
sudo apt-get install vim
2.2 SecureCRT(window)
參考鏈接:https://blog.51cto.com/linuxguest/392248
三、操作和原始碼展示
a)接線

b)升級內核(如果版本太老,可能無法正常讀ds18b20)
sudo apt-get update
sudo apt-get upgrade
c)掛載設備驅動,確認設備是否生效
sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices/
ls

①每個DS18B20溫度傳感器的序列號不同,以下代碼雖然可以快速讀取溫度,并且邏輯也不難,但是非常局限,原始碼初級版本:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#define buffsize 1024
int main(void)
{
float temp;
int i_num,j_num;
int fd=-1;
int rv=-1;
char message_buff[buffsize];
char temp_buff[5];
fd=open("/sys/bus/w1/devices/28-3c01d075b607/w1_slave",O_RDONLY);
if(fd < 0)
{
perror("打開檔案失敗\n");
return 0;
}
while(1)
{
lseek(fd,0,SEEK_SET);
memset(message_buff,0,sizeof(message_buff));
rv=read(fd,message_buff,sizeof(message_buff));
if(rv < 0)
{
printf("Read data from file failure:%s\n",strerror(errno));
continue;
}
if(rv >= 0)
{
printf("Read %d bytes data from files:%s\n",rv,message_buff);
break;
}
}
for(i_num=0;i_num<sizeof(message_buff);i_num++)
{
if(message_buff[i_num]=='t')
{
for(j_num=0;j_num<sizeof(temp_buff);j_num++)
{
temp_buff[j_num]=message_buff[i_num+2+j_num];
}
}
}
temp=(float)atoi(temp_buff)/1000;
printf("%.3f℃\n",temp);
goto cleanup;
cleanup:
close(fd);
return 0;
}
效果圖:

②如果想做到樹莓派讀取任意一個DS18B20溫度傳感器的值,但是以下這份原始碼難度稍微高點,需要用到結構體指標、strstr()、strcpy()和strncat()這幾個知識點,原始碼高級版本如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int DS18B20_get_temperature(float *temp);
#define buffsize 1024
int main(int argc,char *argv[])
{
float TEMP;
if(DS18B20_get_temperature(&TEMP) < 0)
{
printf("error:DS18B20 get temprature failure\n");
return 1;
}
printf("DS18B20 get temperature failure:%f ℃\n",TEMP);
return 0;
}
int DS18B20_get_temperature(float *temp)
{
char w1_path[50] = "/sys/bus/w1/devices/";
char w2_path[15] = "/w1_slave";
char chip[20];
DIR *dirp;
struct dirent *direntp;
int found = 0;
int i_num,j_num;
int fd=-1;
int rv=-1;
char message_buff[buffsize];
char temp_buff[5];
if(!temp)
{
return -1;
}
if((dirp=opendir(w1_path))==NULL)//dirp指向w1_path路徑下的檔案夾
{
printf("opendir error:%s\n",strerror(errno));
return -2;
}
printf("opendir sucess!\n");
while((direntp=readdir(dirp))!=NULL)//direntp為結構體指標,指向dirp指向w1_path路徑下的檔案夾
{
if(strstr(direntp->d_name,"28-"))//這里是將結構體里面的d_name,指向dirp指向w1_path路徑下的檔案夾“28-”這個檔案夾,這個時候可以獲取DS18B20的序列號
{
strcpy(chip,direntp->d_name);//這里是將結構體里面d_name所代表的序列號給chip
found = 1;
break;
}
}
closedir(dirp);
if(!found)
{
printf("Can not find ds18b20 in %s\n",w1_path);
return -3;
}
strncat(w1_path,chip,strlen(chip));
printf("w1_path:%s\n",w1_path);
strncat(w1_path,w2_path,strlen(w2_path));
printf("w1_path:%s\n",w1_path);
fd=open(w1_path,O_RDONLY);
if(fd < 0)
{
perror("打開檔案失敗\n");
return 0;
}
lseek(fd,0,SEEK_SET);
memset(message_buff,0,sizeof(message_buff));
rv=read(fd,message_buff,sizeof(message_buff));
if(rv < 0)
{
printf("Read data from file failure:%s\n",strerror(errno));
}
if(rv >= 0)
{
printf("Read %d bytes data from files:%s\n",rv,message_buff);
}
for(i_num=0;i_num<sizeof(message_buff);i_num++)
{
if(message_buff[i_num]=='t')
{
for(j_num=0;j_num<sizeof(temp_buff);j_num++)
{
temp_buff[j_num]=message_buff[i_num+2+j_num];
}
}
}
*temp=(float)atoi(temp_buff)/1000;
printf("%.3f℃\n",*temp);
goto cleanup;
cleanup:
close(fd);
return 0;
}
效果圖:

提示:
(1)strstr()
描述
C 庫函式 char *strstr(const char *haystack, const char *needle) 在字串 haystack 中查找第一次出現字串 needle 的位置,不包含終止符 '\0',
宣告
下面是 strstr() 函式的宣告,
char *strstr(const char *haystack, const char *needle)
引數
haystack -- 要被檢索的 C 字串,
needle -- 在 haystack 字串內要搜索的小字串,
回傳值
該函式回傳在 haystack 中第一次出現 needle 字串的位置,如果未找到則回傳 null,
(2)strcpy()
描述
C 庫函式 char *strcpy(char *dest, const char *src) 把 src 所指向的字串復制到 dest,
需要注意的是如果目標陣列 dest 不夠大,而源字串的長度又太長,可能會造成緩沖溢位的情況,
宣告
下面是 strcpy() 函式的宣告,
char *strcpy(char *dest, const char *src)
引數
dest -- 指向用于存盤復制內容的目標陣列,
src -- 要復制的字串,
回傳值
該函式回傳一個指向最終的目標字串 dest 的指標,
(3)strncat()
描述
C 庫函式 char *strncat(char *dest, const char *src, size_t n) 把 src 所指向的字串追加到 dest 所指向的字串的結尾,直到 n 字符長度為止,
宣告
下面是 strncat() 函式的宣告,
char *strncat(char *dest, const char *src, size_t n)
引數
dest -- 指向目標陣列,該陣列包含了一個 C 字串,且足夠容納追加后的字串,包括額外的空字符,
src -- 要追加的字串,
n -- 要追加的最大字符數,
回傳值
該函式回傳一個指向最終的目標字串 dest 的指標,
四、總結
學習總是從簡單到難,寫代碼也是如此,先實作一個功能,再去實作下一個功能,然后進行整合,最后進行優化,一份優質的原始碼由此誕生,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/289384.html
標籤:其他
上一篇:決策樹可視化
