Linux下用树莓派DS18B20温度传感器读取温度并上传至服务端

news2024/11/25 22:25:42

目录

一、DS18B20温度传感器

二、逻辑分析

三、实战操作

1、服务端

2、客户端

3、运行结果


一、DS18B20温度传感器

        DS18B20是比较常用到的温度传感器,采用单总线控制。是美国DALLAS半导体公司继DS1820之后最新推出的一种改进型智能温度传感器。关于该温度传感器的具体介绍可以看这里-DS18B20。

        以下是连接DS18B20的基本步骤:

(1)DS18B20有三个引脚:VCC(电源)、GND(地)和DQ(数据引脚),DQ引脚连接到微控制器的输入引脚,用于数据通信。

(2)DS18B20通过1-wire协议与主控制器通信,树莓派需要相应的1-wire库或者驱动程序。

(3)读取DS18B20获取的温度值,并进行相应温度转换和计算

二、逻辑分析

        我使用的是树莓派4B,DS18B20将踩到的的温度值存放在 /sys/bus/w1/devices/28-0317320a8aff/w1_slave 文件中(不同的传感器型号“28-”处会略有不同),在终端使用命令 cat   /sys/bus/w1/devices/28-0317320a8aff/w1_slave即可看到文件内容,如下图所示:

  前面那些数据我们不管他,可以看到“t=11250”,这个就是我这个设备上的实时温度(11.25℃)。了解到这些之后,我们来捋一捋代码里面要用什么样的方式来读取这个温度,并显示出来。

(1)socket编程,建立客户端与服务端的通信。对socket网络编程不熟悉的同学可以看《APUE学习之socket网络编程》。

(2)由于每个DS18B20的产品序列号不一样,那么温度保存文件的路径也就会不一样,我们没办法直接调用read来读取文件的内容。那该怎么办呢?用opendir()和readdir()的组合,打开每个设备都一样的默认路径(/sys/bus/w1/devices/),并读取路径下的内容。

(3)当打开上面的路径之后,因为型号的原因,大家的路径将有所不同,我们可以找出“28-”开头的的文件夹,并将其名称保存到一个缓存区中,然后用这个缓存区的内容来更新目标路径。

(4)用open()和read()读取目标路径的内容,找出其中“t=”的部分,并记录下来。随后上传至客户端。

三、实战操作

题目要求:

(1)利用网络socket编程,编写一个服务端和一个客户端,实现通信;

(2)使用树莓派DS18B20温度传感器每10秒采集一次温度,并上传至服务端。

代码如下:

1、服务端

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <ctype.h>

#define BACKLOG          13     /*令listen最大监听数为13*/
#define PORT            8888    /*监听8888号端口*/

int main(int argc,char *argv[])
{
        int                     fd = -1;
        int                     client_fd = -1;
        int                     rv = -1;
        struct sockaddr_in      server_addr;
        struct sockaddr_in      client_addr;
        socklen_t               client_len = sizeof(client_addr);
        char                    buf[1024];

        if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
        {
                printf("Socket failure:%s\n",strerror(errno));
        }

        memset(&server_addr,0,sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(PORT);
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        if((bind(fd,(struct sockaddr *)&server_addr,sizeof(server_addr)))<0)
        {
                printf("bind failure:%s\n",strerror(errno));
                return -2;
        }

        listen(fd,BACKLOG);
        printf("\nWaitting for client...\n");


        if((client_fd=accept(fd,(struct sockaddr *)&client_addr,&client_len))<0)
        {
                printf("Accept failure:%s\n",strerror(errno));
                return -3;
        }
        printf("Connected with client [%d]\n",client_fd);
        while(1)
        {

                memset(&buf,0,sizeof(buf));

                if((rv=read(client_fd,buf,sizeof(buf))) <= 0)
                {
                        printf("Read failure or get disconnect:%s\n",strerror(errno));
                        return -4;
                }

                printf("read %d Byte data from client [%d] :%s\n",rv,client_fd,buf);

                if(write(client_fd,buf,rv)<0)
                {
                        printf("Write failure:%s\n",strerror(errno));
                        return -5;
                }

        }

        close(client_fd);
        close(fd);

}
                                         

2、客户端

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define PORT    8888            
#define IP      "127.0.0.1"

int get_temperature(float *temp);       /*该函数用于ds18b20采集温度*/

int main(int argc,char *argv[])
{

        int                     fd = -1;
        int                     rv = -1;
        struct sockaddr_in      servaddr;
        socklen_t               len = sizeof(servaddr);
        int                     r = -1;
        char                    t[16];
        float                   temp;
        char                    buf[128];

        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd < 0)
        {
                printf("create sockfd failure:%s\n",strerror(errno));
                return -1;
        }
        printf("create socket_fd [%d] successfully!\n",fd);

        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port   = htons(PORT);
        inet_aton(IP,&servaddr.sin_addr);



        if((rv = connect(fd,(struct sockaddr*)&servaddr,len)) < 0)
        {
                printf("client connect failure:%s\n",strerror(errno));
                return -2;
        }
                printf("client connect successfully!\n");
        while(1)
        {

                if((r = get_temperature(&temp)) < 0)
                {
                        printf("get temperature failure:%s\n",strerror(errno));
                        return -7;
                }
                printf("get temperature successfully and temperature is %.2f!\n",temp);

                memset(t,0,sizeof(t));
                sprintf(t,"%.2f",temp);

                if((write(fd,t,sizeof(t))) < 0)
                {
                        printf("write failure:%s\n",strerror(errno));
                        return -8;
                }
                printf("write bytes:%s\n",t);

                if((rv = read(fd,buf,sizeof(buf))) <= 0)
                {
                        printf("read failure or get disconnect:%s\n",strerror(errno));
                        return -9;
                }
                printf("read [%d] bytes:%s\n",rv,buf);

                sleep(10);
        }

        close(fd);
        return 0;

}

int get_temperature(float *temp)
{

        int             fd = -1;
        int             found = 0;
        char            w1_path[64] = "/sys/bus/w1/devices/";
        DIR             *dirp = NULL;
        struct dirent   *direntp = NULL;
        char            chip_sn[32];
        char            buf[128];
        char            *ptr;

        if( !(dirp = opendir(w1_path)) )
        {
                printf("open directory failure:%s\n",strerror(errno));
                return -3;
        }

        while( direntp = readdir(dirp) )
        {

                if( strstr(direntp->d_name,"28-") )
                {
                        strncpy(chip_sn,direntp->d_name,sizeof(chip_sn));
                        found = 1;      /*found用于确保是否能找到温度存储的文件*/
                }
        }
        if( !found )
        {
                printf("can not find ds18b20 directory!\n");
                return -4;
        }

        strncat(w1_path,chip_sn,sizeof(w1_path)-strlen(w1_path));               /*更新文件路径*/
        strncat(w1_path,"/w1_slave",sizeof(w1_path)-strlen(w1_path));

        closedir(dirp);


        fd = open(w1_path,O_RDONLY);    /*打开文件*/
        if(fd < 0)
        {
                printf("open file failure:%s\n",strerror(errno));
                return -5;
        }


        lseek(fd,0,SEEK_SET);           /*不设置文件偏移量可能造成读不到任何内容*/
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));

        ptr = strstr(buf,"t="); /*找到t=字符串*/
        if(NULL == ptr)
        {
                printf("can not find t= string\n",strerror(errno));
                return -6;
        }

        ptr += 2;       /*将指针ptr移至t=后的温度值处*/
        *temp = atof(ptr)/1000;         /*进行温度转换和相应计算*/

        close(fd);

        return 0;

}

3、运行结果

服务端:

客户端:

         到这里,这道问题就已经成功解决了!加油,相信你自己,你一定是最棒的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1405402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode刷题笔记题解(C++):LCR 153. 二叉树中和为目标值的路径

思路&#xff1a;利用回溯的思想&#xff0c;回溯的退出条件为当前节点为空&#xff0c;是符合路径的判断条件为路径和为目标值且叶子节点包含了&#xff0c;代码如下&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *…

Elasticsearch 常用信息

简述 本文针对 Elasticsearch&#xff08;简称ES&#xff09;集群6.x版本出现故障时&#xff0c;可通过提供的命令进行排查。 1、集群健康状态 集群健康状态状态说明red不是所有的主要分片都可用。表示该集群中存在不可用的主分片。可以理解为某个或者某几个索引存在主分片丢失…

Vue2:全局事件总线

一、场景描述 之前我们学习了&#xff0c;通过props实现父子组件之间的通信。通过自定义组件&#xff0c;实现了子给父传递数据。 那么&#xff0c;兄弟关系的组件&#xff0c;如何通信了&#xff1f;任意组件间如何通信了&#xff1f; 这个时候&#xff0c;就要学习全局事件总…

测试工程师必看!测试用例设计全解析,让你彻底掌握

测试工程师在入行时&#xff0c;都会接触到一个名词——测试用例&#xff0c;都知道测试用例是干什么用的&#xff0c;提到设计测试用例的方法&#xff0c;大部分测试工程师都会侃侃而谈&#xff1a;等价类法、边界值法、判定表法、正交分解法……这些方法说起来都如数家珍&…

8-Python 工匠:使用装饰器的技巧

Python 工匠&#xff1a;使用装饰器的技巧 前言 这是 “Python 工匠”系列的第 8 篇文章。[查看系列所有文章] 装饰器 (Decorator) 是 Python 里的一种特殊工具&#xff0c;它为我们提供了一种在函数外部修改函数的灵活能力。它有点像一顶画着独一无二 符号的神奇帽子&#x…

仰暮计划|“说是操场,那就是个土坡,我们在那儿上边种种树啊,拔拔草,有的时候还会有同学来喂喂羊啥的,这都是我们的娱乐”

我是1948年农历二月份在河南省许昌市五女店镇的一个乡村里边出生的。从我记事的时候&#xff0c;中华人民共和国就已经成立了。当时是好多年&#xff0c;经历了三大改造呀、生产队呀、大队呀&#xff0c;乱七八糟的很多&#xff0c;估计你们现在这些孩子们啊&#xff0c;都没有…

浪花 - 更新队伍信息

一、接口设计 1. 请求路径&#xff1a;/team/update 2. 请求参数&#xff1a;TeamUpdateRequest 有些数据不允许修改&#xff0c;封装一个请求类&#xff0c;只存放允许修改的参数列表 package com.example.usercenter.model.request;import lombok.Data;import java.io.Se…

9款最新文生图模型汇总!含华为、谷歌、Stability AI等大厂创新模型(附论文和代码)

2023年真是文生图大放异彩的一年&#xff0c;给数字艺术界和创意圈注入了新鲜血液。从起初的基础图像创作跃进到现在的超逼真效果&#xff0c;这些先进的模型彻底变革了我们制作和享受数字作品的途径。 最近&#xff0c;一些大公司比如华为、谷歌、还有Stability AI等人工智能巨…

软件工程实验报告(完整)

博主介绍&#xff1a;✌全网粉丝喜爱、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦&#xff01; &#x1f345;附上相关C语言版源码讲解&#x1f345; &#x1f44…

c语言编译链接

目录 目录 前言 一.c语言的编译链接 1.翻译环境 编译阶段可以分为预处理&#xff0c;编译&#xff0c;汇编三个阶段 预处理阶段 编译阶段 词法分析 语法分析 语义分析 汇编阶段 链接阶段 2.运行环境 二.预处理详解 #define定义常量 #define定义宏 宏和函数的对比 #和##运算符…

ETL概念

ETL ETLELT 技术原理ETL 模式应用场景常见工具ETL未来发展方向 ETL 在BI项目中ETL会花掉整个项目至少1/3的时间&#xff0c; ETL设计的好坏直接关接到BI项目的成败。ETL(Extract-Transform-Load) : 用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&…

VS2019配置Reshaper

参考VisualStudio神级插件。一JetBrains Resharpera2023.3.2学习版 拉到下面下载主程序&#xff0c;下载就点下一步就好了 然后不要打开VS2019&#xff0c;再按上面的地址下载学习补丁&#xff0c;下载好如图&#xff1a; 查看ReadMe 我们已经装好Reshaper了&#xff0c;然后点…

gmpy2与一些python库在vscode下没有自动补全的一种缓解方案

经过一定的研究&#xff0c;该问题的原因初步判断是gmpy2这个库天生没有把补全的函数doc说明附在pip包中。且因gmpy2是由C编译而来&#xff0c;以dll或so的形式作为动态链接库给python调用&#xff0c;这意味着无法从源码薅到可用的源码注释。 接下来先讲解决方案&#xff0c;再…

el-table样式错乱解决方案

bug&#xff1a; 图片的椭圆框住的地方&#xff0c;在页面放大缩小之后就对不齐了。 原因&#xff1a; 主要原因是当你对页面放大缩小的时候&#xff0c;页面进行了重构&#xff0c;页面的宽高及样式进行了变化&#xff0c;但是在这个更新的过程中&#xff0c;table的反应并没…

Python爬虫之协程

Python爬虫之协程 为什么要用协程 协程声明 await aiohttp aiofiles 案例修改 案例完整代码 为什么要用协程 轻量级&#xff1a;协程是轻量级的执行单元&#xff0c;可以在同一个线程中并发执行。相比于多线程或多进程&#xff0c;创建和切换协程的开销更小。高效利用资源&…

78.网游逆向分析与插件开发-背包的获取-背包类的C++还原与获取物品名称

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;77.网游逆向分析与插件开发-背包的获取-物品类的C还原-CSDN博客 码云地址&#xff08;ui显示角色数据 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&…

影响ETL数据传输性能的9大因素及主流ETL应对策略

前言 现在很多企业在选择ETL工具时都特别关注ETL的数据传输性能&#xff0c;而有很多开源ETL工具都说自已是性能如何如何快&#xff0c;而事实上数据传输性能是不是这些工具说的那样快呢&#xff1f; 数据传输性能受制于哪些因素呢&#xff1f;企业在自身数据库性能受制的情况…

Redis(七)复制

文章目录 是什么功能配置配主库不配从库权限细节 案例配置文件修改 一主二仆固定配置文件主从问题命令操作手动指定 薪火相传反客为主复制原理和工作流程存在问题 是什么 https://redis.io/docs/management/replication/ 就是主从复制&#xff0c;master以写为主&#xff0c;S…

农业气象站的工作原理!

TH-NQ8农业气象站的工作原理是基于传感器技术、数据采集技术、数据传输技术和数据处理技术等多个环节相互配合而实现的。 首先&#xff0c;农业气象站通过各种传感器对不同的气象指标进行实时监测和记录。传感器的种类有很多&#xff0c;包括温度传感器、湿度传感器、风速传感…

3dmax渲不出模型是什么原因---模大狮模型网

3DMax无法渲染模型可能有多种原因。以下是一些常见的问题和解决方法&#xff1a; 材质设置错误&#xff1a;检查模型的材质设置是否正确&#xff0c;包括纹理贴图的路径、UV映射是否正确等。确保材质的属性设置正确&#xff0c;如颜色、反射率、透明度等。 灯光设置问题&#…