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

目录

一、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、运行结果

服务端:

客户端:

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring为啥不推荐使用@Autowired注解?

引言 使用IDEA开发时&#xff0c;同组小伙伴都喜欢用Autowired注入&#xff0c;代码一片warning&#xff0c;看着很不舒服&#xff0c;Autowired作为Spring的亲儿子&#xff0c;为啥在IDEA中提示了一个警告&#xff1a;Field injection is not recommended 想搞清楚这个问题之…

Unity3d C#实现三维场景中图标根据相机距离动态缩放功能

前言 如题的需求&#xff0c;其实可以通过使用UI替代场景中的图标来实现&#xff0c;不过这样UI的处理稍微麻烦&#xff0c;而且需要在图标上添加粒子特效使用SpriteRender更方便快捷。这里就根据相机离图标的位置来计算图标的缩放大小即可。这样基本保持了图标的大小&#xf…

【51单片机】IO 扩展(串转并)--74HC595

0、前言 参考&#xff1a; 普中 51 单片机开发攻略 第12章 【51单片机入门教程-2020版 程序全程纯手打 从零开始入门】 https://www.bilibili.com/video/BV1Mb411e7re/?p21&share_sourcecopy_web&vd_source77e36f24add8dc77c362748ffb980148 nop()是什么语句&#…

LLM:RoPE - 开源代码中的实现 (下)

本文着重学习一下开源代码中关于RoPE的实现:ChatGLM-6B、ChatGLM2-6B、LLAMA 回顾一下RoPE位置编码: 1:对于 token 序列中的每个词嵌入向量,首先计算其对应的 query 和 key 向量 2:然后对每个 token 位置都计算对应的旋转位置编码 3:接着对每个 token 位置的 query 和 …

防御保护---信息安全概述

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 本章要求 了解信息安全的基本内容了解信息安全的脆弱性及安全攻击了解信息安全要素及整体安全解决方案 一.信息安全概述 信息安全概述 信息安全是指保护信息免受未经授权的访问、使用、披露、…

简单但全面了解一下webSocket

文章目录 webSocket是一种协议&#xff0c;设计用于提供低延迟、双全工和长期运行的连接什么是实时通信&#xff1f; webSocket之前的世界webSocket的优势为什么需要心跳机制&#xff1f;webSocket的限制 webSocket是一种协议&#xff0c;设计用于提供低延迟、双全工和长期运行…

宠物互联网医院系统

在数字时代&#xff0c;宠物医疗迎来了一场革新&#xff0c;动物互联网医院系统以其先进的技术和智能的特性成为宠物护理的领军者。本文将介绍宠物互联网医院系统的一些关键技术和代码示例&#xff0c;揭示这一科技奇迹的实现原理。 1. 远程医疗服务的实现 远程医疗服务是宠…

Neos的渗透测试靶机练习——DarkHole-2

DarkHole-2 一、实验环境二、开始渗透1. 搜集信息2. git文件泄露3. SQL注入4. 提权 三、总结 一、实验环境 虚拟机软件&#xff1a;VirtualBox 攻击机&#xff1a;kali linux&#xff08;网卡初始为仅主机模式&#xff0c;要有安全意识&#xff09; 靶机&#xff1a;DarkHole-…

IMX6ULL|input子系统(按键实验)

一.input子系统 input子系统是Linux对输入设备提供的统一驱动框架。如按键、键盘、触摸屏和鼠标等输入设备的驱动方式是类似的&#xff0c;当出现按键、触摸等操作时&#xff0c;硬件产生中断&#xff0c;然后CPU直接读取引脚电平&#xff0c;或通过SPI、I2C等通讯方式从设备的…

C#,入门教程(35)——哈希表(Hashtable)的基础知识与用法

上一篇&#xff1a; C#&#xff0c;入门教程(34)——关于函数的参数之引用&#xff08;ref&#xff09;的一点知识与源程序https://blog.csdn.net/beijinghorn/article/details/125411351 有一段故事&#xff1a; King Log The frogs in the lake had an easy life doing ex…

npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED

npm install时报错code CERT_HAS_EXPIRED 一、报错情况二、解决方案 一、报错情况 一直用的好好的&#xff0c;突然今天发现npm install 出问题了&#xff0c;具体报错如下&#xff1a; npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to…

不要为了学习而学习

经常有朋友问我&#xff1a; 老师&#xff0c;从您这里学了很多方法&#xff0c;也一直想要改变自己&#xff0c;但总是没办法坚持下去&#xff0c;怎么办&#xff1f; 这个问题&#xff0c;我也很无奈啊。毕竟我也没办法飞到你身边&#xff0c;手把手把每一步都教给你。&…

MySQL-B-tree和B+tree区别

B-tree&#xff08;平衡树&#xff09;和Btree&#xff08;平衡树的一种变种&#xff09;是两种常见的树状数据结构&#xff0c;用于构建索引以提高数据库的查询性能。它们在一些方面有相似之处&#xff0c;但也有一些关键的区别。以下是B-tree和Btree的主要区别&#xff1a; …

你知道Mysql的架构吗?

msyql分为server曾和存储引擎层 server层包括了连接器(管理连接&#xff0c;权限验证)、查询缓存&#xff08;命中直接返回结果&#xff09;、分析器&#xff08;词法分析&#xff0c;语法分析&#xff09;、优化器&#xff08;执行计划生成&#xff0c;索引选择&#xff09;、…

【揭秘】ScheduledThreadPoolExecutor全面解析

内容摘要 ScheduledThreadPoolExecutor能够高效地管理和复用线程资源&#xff0c;避免了大量线程的创建和销毁开销&#xff0c;从而提升了系统性能&#xff0c;同时&#xff0c;它提供了灵活的任务调度机制&#xff0c;支持延迟执行和固定频率执行&#xff0c;满足了各种复杂场…

idea创建公用依赖包项目

创建parent项目 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/…

linux之安装配置VM+CentOS7+换源

文章目录 一、centos07安装二、CentOS 07网络配置2.1解决CentOS 07网络名不出现问题此博主的论文可以解决2.2配置&#xff08;命令: 【ip a】也可查看ip地址&#xff09; 三、使用链接工具链接CentOS进行命令控制四、换软件源 一、centos07安装 1、在vmvare中新建虚拟机 2、下…

【K8S 云原生】K8S之HPA自动扩缩容、命名空间资源限制、容器抓包

目录 一、HPA概述 1、概念 2、两个重要的组件&#xff1a; 3、HPA的规则&#xff1a; 4、pod的副本数扩容有两种方式&#xff1a; 4.1、手动扩缩容&#xff0c;修改副本数&#xff1a; 4.2、自动扩缩容HPA 二、实验部署&#xff1a; 1、部署HPA 2、实现自动扩缩容 三…

【多商户开源-BSD- Fecmall 电商平台】

关于Fecmall Fecmall 关于&#xff0c;Fecmall介绍 Fecbbc开源BSD多商户系统&#xff0c;真正开源&#xff0c;商用免费授权的多商户系统 Fecmall系统简介&#xff1a; 全称为Fancy ECommerce Shop&#xff0c; 着重于电商架构的研发优化&#xff0c;全新定义商城的架构体系&…

【RF FILTER 仿真】滤波器 Ansys Electronics not ADS

第一&#xff0c;声明 全网搜索&#xff0c;用这个HFSS继承的介绍非常少&#xff0c;并且没有什么指导意义。所以有必要写一下&#xff0c;就像之前的xpedition,总要挑战一下吧。本文仅仅和大家学习研究&#xff0c;对比ADS体会一下差别。 第二&#xff0c;记录直接开始&…