Java采集传感器数据,亲测有效!

news2024/11/19 15:16:58

背景

先说背景

最近公司项目需要用到传感器,采集设备温湿度,倾斜角,电流…,公司采购采购了一个温湿度传感器给我们开发测试使用,如下图:

image-20231027213450647

看着还挺精致有没有。

进入正题

有了这个温湿度传感器,我们如何读取其采集到的数据呢。需要一个RS485转串口工具,下面这个蓝色的东东:

image-20231027213752928

把它接到传感器上,然后插到电脑上

image-20231027213858771

通过电脑设备管理器-端口,可以看到该设备串口号是COM3,这个参数记住下面采集数据需要。

接下来,先用工具TH11S-B Tool_V105,直接读取温湿度。

工具长这样image-20231027214139239

打开工具,

image-20231027214357841

除了串口号,其他参数基本都是固定的,也看到页面上串口号也确实是COM3,然后点击连接直接连接串口。

此时点击读取就能读到当时的温湿度值,可以看到通过串口与传感器交互的协议报文。

image-20231027214545607

读取报文01 03 00 00 00 02 C4 0B,经过搜索得知这个是ModBus-RTU协议(传感器常用协议)的报文,具体含义如下:

ChatGPT回答:

这个报文 01 03 00 00 00 02 C4 0B 是一个 Modbus RTU 协议的请求报文,它的各部分含义如下:

  1. 01:从站地址,表示要操作的 Modbus 从站的地址。在这个例子中,从站地址为 1。
  2. 03:功能码,表示请求的操作类型。在 Modbus 中,功能码 03 表示读取保持寄存器。这个功能码用于读取传感器的数据。
  3. 00 00:起始寄存器地址,指示要读取的寄存器的起始地址。在这个例子中,起始寄存器地址为 0x0000(通常是一个 16 位的寄存器地址)。
  4. 00 02:寄存器数量,表示要读取的连续寄存器的数量。在这个例子中,要读取 2 个寄存器。
  5. C4 0B:CRC 校验,用于确保报文的完整性。

这个请求报文的目的是要求 Modbus 从站(通常是传感器或其他设备)返回起始寄存器地址为 0x0000 的 2 个寄存器的数据。这些数据通常包括传感器的温度和湿度值,具体含义取决于传感器的规格和协议。所以,你需要根据你的传感器的规格和协议来解析这些数据。

具体协议不做研究,主要看看响应报文01 03 04 00 FE 02 50 9A 9F,具体含义如下:

ChatGPT回答:

这个响应报文 01 03 04 00 FE 02 50 9A 9F 是 Modbus RTU 协议的响应报文,其各部分含义如下:

  1. 01:从站地址,表示响应来自 Modbus 从站的地址。在这个例子中,从站地址为 1,与请求报文相同。

  2. 03:功能码,表示响应的操作类型。在 Modbus 中,功能码 03 表示读取保持寄存器。这个功能码用于读取传感器的数据,与请求报文相同。

  3. 04:字节数,表示响应数据的字节数。在这个例子中,有 4 个字节的数据。

  4. 00 FE:数据,表示读取到的保持寄存器数据。这里的数据是 2 个 16 位寄存器的值,以大端模式表示(高位在前,低位在后)。在这个例子中,它的十六进制值为 00 FE,对应的十进制值是 254。

  5. 02:CRC 校验,用于确保报文的完整性。

根据响应报文中的数据部分,这个特定传感器的温度值为 254。要了解确切的温度单位和规范,请参考传感器的文档或规格表。通常,温度值需要进一步处理和解释,以转换为实际的温度单位(例如摄氏度或华氏度)。

其他无需关注只需知道**00 FE(第四五字节)表示温度值,02 50(第六七字节)表示湿度值**即可,十六进制转为十进制然后直接除以十就是真实温湿度值。

00 FE:254 / 10.0 = 25.4度(温度)

02 50:592 / 10.0 = 59.2%(湿度)

代码实战

经过一些调研,要使用Java读取传感器数据,jSerialComm依赖用的比较多。

添加依赖

项目中添加依赖

       <dependency>
            <groupId>com.fazecast</groupId>
            <artifactId>jSerialComm</artifactId>
            <version>2.9.2</version>
        </dependency>

封装构建请求报文工具类

接下来构建请求报文,创建工具类与请求报文格式对应如下:

public class ModbusRTURequestBuilder {

    /**
     * @param slaveAddress 从站地址
     * @param functionCode 功能码
     * @param startAddress 起始寄存器地址
     * @param registerCount 寄存器数量
     * @return Modbus-RTU 协议请求报文
     */
    public static byte[] buildModbusRTURequest(int slaveAddress, int functionCode, int startAddress, int registerCount) {
        // 创建一个字节数组用于存储报文
        byte[] request = new byte[8];

        // 设置从机地址
        request[0] = (byte) slaveAddress;

        // 设置功能码
        request[1] = (byte) functionCode;

        // 设置起始寄存器地址(高位和低位)
        request[2] = (byte) (startAddress >> 8);
        request[3] = (byte) (startAddress & 0xFF);

        // 设置寄存器数量(高位和低位)
        request[4] = (byte) (registerCount >> 8);
        request[5] = (byte) (registerCount & 0xFF);

        // 计算CRC校验并设置到报文中
        int crc = calculateCRC(request, 6);
        request[6] = (byte) (crc & 0xFF); // 低位
        request[7] = (byte) (crc >> 8); // 高位

        return request;
    }

    private static int calculateCRC(byte[] message, int length) {
        int crc = 0xFFFF;
        for (int i = 0; i < length; i++) {
            crc ^= (message[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((crc & 1) == 1) {
                    crc = (crc >> 1) ^ 0xA001;
                } else {
                    crc = crc >> 1;
                }
            }
        }
        return crc;
    }
}

与传感器交互,解析响应报文

接下来与传感器交互,解析响应报文温湿度值

简单测试一下:

public class SerialSensorReader {
    public static void main(String[] args) {
        // 设置串口一些参数,除了串口号其他基本固定 COM3就是开头要大家记住的串口号
        SerialPort serialPort = SerialPort.getCommPort("COM3"); // 串口设备名称
        serialPort.setBaudRate(9600); // 波特率
        serialPort.setNumDataBits(8); // 数据位
        serialPort.setParity(SerialPort.NO_PARITY); // 校验位
        serialPort.setNumStopBits(1); // 停止位

        if (serialPort.openPort()) {
            // 借助工具类,构建请求报文
            byte[] requestMessage = ModbusRTURequestBuilder.buildModbusRTURequest(1, 3, 0, 2);
            // 读取温湿度
            serialPort.writeBytes(requestMessage, requestMessage.length);

            try {
                Thread.sleep(100); // 等待足够的时间以确保传感器响应
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
			// 响应数据的长度根据传感器规格进行配置(该传感器响应报文长度为9,不同传感器自行调整)
            byte[] responseData = new byte[9]; 

            // 获取响应 	
            int bytesRead = serialPort.readBytes(responseData, responseData.length);
            if (bytesRead == responseData.length) {
                // 解析温湿度数据
                int temperature = ((responseData[3] << 8) | (responseData[4] & 0xFF));
                int humidity = ((responseData[5] << 8) | (responseData[6] & 0xFF));

                System.out.println("温度: " + temperature / 10.0);
                System.out.println("湿度: " + humidity / 10.0);
            } else {
                System.out.println("未收到完整的响应数据");
            }

            serialPort.closePort();
        } else {
            System.out.println("无法打开串口");
        }
    }
}

经测试,数据没有问题:

image-20231027221424840

文章不长,也是博主一点一点搜出来、ChatGPT出来的,其中也是踩了不少坑,创作不易,请一键三连啊!(如果文章对您有用的话,不妨给我一个大大的赞,您的赞是我创作的动力。)

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

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

相关文章

【Leetcode】【每日一题】【中等】1465. 切割后面积最大的蛋糕

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/maximum-area-of-a-piece-of-cak…

Vue3+Element-Plus项目 el-table 拖拽排序实现,Vue3项目sortablejs的安装与使用

概述 技术栈&#xff1a; Vue3 Ts Vite Element-Plus 实现&#xff1a;实现 sortablejs 实现 el-tabel 的拖拽排序&#xff0c;可滚动排序&#xff0c;并实现拖拽排序的开启与关闭 文章目录 概述一、先看效果二、安装 sortablejs三、sortablejs 封装3.1 utilts 封装3.2 全局…

SpringBoot 定时任务:@EnableScheduling @Scheduled

Scheduled注解参数 cron参数 这个参数是最经常使用的参数&#xff0c;表示接收一个cron参数&#xff0c;cron它是一个表达式&#xff0c;最多接收7个参数&#xff0c;从左到右分别表示&#xff1a;秒 分 时 天 月 周 年&#xff1b;参数以空格隔开&#xff0c;其中年不是必须参…

【JAVA学习笔记】48 - 八大常用Wrapper类(包装类)

一、包装类 1.针对八种基本定义相应的引用类型一包装类 2.有了类的特点&#xff0c;就可以调用类中的方法。 黄色背景的表示父类是Number 二、包装类和基本数据的转换 演示包装类和基本数据类型的相互转换&#xff0c;这里以int和Integer演示。 1.jdk5前的手动装箱和拆箱方…

STM32 TIM(四)编码器接口

STM32 TIM&#xff08;四&#xff09;编码器接口 编码器接口简介 Encoder Interface 编码器接口 编码器接口可接收增量&#xff08;正交&#xff09;编码器的信号&#xff0c;根据编码器旋转产生的正交信号脉冲&#xff0c;自动控制CNT自增或自减&#xff0c;从而指示编码器的…

取Dataset子集(pytorch)

取Dataset子集--pytorch 1. why2. how3. example 1. why 我们在调试深度学习代码时&#xff0c;常常会遇到数据集太大&#xff0c;导致调试浪费时间的情况&#xff0c;这种情况下&#xff0c;将数据集中的一个子集拿出来用于调试代码&#xff0c;调试成功在用完整的数据集运行…

elementUI el-table实现鼠标悬浮某一行,在鼠标右侧展示提示信息

背景 el-table组件中&#xff0c;可以通过勾选某条数据来创建单据&#xff0c;但是有些数据没有权限使用&#xff0c;就需要禁用掉勾选的功能&#xff0c;然后当鼠标悬浮在这一行的时候&#xff0c;展示类似于toolTip的提示框。 除了当鼠标悬浮在某一行&#xff0c;展示类似于…

离散数学速成视频推荐(讲的不错)

【拯救者】离散数学速成(期末考研专升本) 适合人群 期末 考研 复试 转升本 月考都可以用 课程大纲 适用课本 适用于所有离散数学课本 按课本章节来&#xff0c; 抽取重点&#xff0c;翻译为人话 学习步骤&#xff1a; 每一章&#xff0c;都会【讲会考的基础&#x1f4bb;】&a…

跨平台Markdown编辑软件Typora mac中文版功能介绍

Typora mac是一款跨平台的Markdown编辑器&#xff0c;支持Windows、MacOS和Linux操作系统。它具有实时预览功能&#xff0c;能够自动将Markdown文本转换为漂亮的排版效果&#xff0c;让用户专注于写作内容而不必关心格式调整。Typora Mac版除了支持常见的Markdown语法外&#x…

通俗易懂的理解 解耦 概念

解耦&#xff08;Decoupling&#xff09;是计算机科学和软件工程中的一个概念&#xff0c;指的是降低系统中不同部分之间的依赖性&#xff0c;使系统的各个组件能够相对独立地进行开发、维护和演化。解耦的主要目标是减少组件之间的紧密耦合&#xff0c;以提高系统的灵活性、可…

Tomcat的动静分离

一、动态负载均衡 3、台虚拟机模拟&#xff1a; 代理服务器&#xff1a;51 tomcat动态页面&#xff1a;53,54 关闭防火墙和安全机制 配置代理服务器&#xff0c;由于做的是七层代理&#xff0c;所以要在http模块配置 配置前端页面 <!DOCTYPE html> <html> <…

AutoEncoding与AutoRegressive:区别,联系和应用

关于AutoEncoding&#xff08;AE&#xff09;和AutoRegressive&#xff08;AR&#xff09; 前几天看了Ilya在Simons上做的关于Generative Model的演讲&#xff0c;介绍了OpenAI现在做的一些AutoRegressive的工作&#xff0c;昨天又看到LeCun宣称Auto-Regressive LLMs are doom…

ES6新特性:变量的解构赋值

文章目录 1 数组的解构赋值1.1 基本用法1.2 交换变量的值1.3 注意事项 2 对象的解构赋值2.1 基本用法2.2 属性重命名2.3 注意事项 ES6允许按照一定模式&#xff0c;从数组和对象中提取值&#xff0c;对变量进行赋值&#xff0c;这被称为解构&#xff08;Destructuring&#xff…

【Flutter】自定义分段选择器Slider

【Flutter】ZFJ自定义分段选择器Slider 前言 在开发一个APP的时候&#xff0c;需要用到一个分段选择器&#xff0c;系统的不满足就自己自定义了一个&#xff1b; 可以自定义节点的数量、自定义节点的大小、自定义滑竿的粗细&#xff0c;自定义气泡的有无等等… 基本上满足你…

Docker实战之二

一、前言 前一篇 Docker实战之一 我们介绍了Dokcer 镜像和容器基本概念&#xff0c;这一节我们来具体制作一个镜像文件并进行快速部署&#xff0c;这个镜像文件是我们的测试环境&#xff0c;主要包含JDK1.8、Nginx、Git、Node、Gradle&#xff0c;基础镜像为CentOS&#xff0c…

进击的零跑:拿巨头的钱,把中国车打进欧洲市场

作者 | 张祥威 编辑 | 德新 造车新势力中&#xff0c;零跑属于不惹事&#xff0c;独自在角落低调发育的这一类。偶尔高调门喊一声要干掉特斯拉&#xff0c;围观的人也是笑一笑不当回事儿&#xff0c;于是又回去默默卖车。 声量一般&#xff0c;卖车还行。 行业里每次晒数据&…

开发实践|三步搞定爆款直播间小游戏

直播间小游戏引爆社交新潮流 近年来&#xff0c;直播行业迅速发展&#xff0c;特别是在抖音平台&#xff0c;直播间的吸引力已远超传统的短视频内容。而在这波直播风潮中&#xff0c;有一种玩法让我格外留意——直播间小游戏。经常刷抖音的朋友应该在直播间看到过这样的场景&a…

SIT3491ISO具有隔离功能,256 节点,全双工 RS422/RS485 芯片

SIT3491ISO 是一款电容隔离的全双工 RS-422/485 收发器&#xff0c;总线端口 ESD 保护能力 HBM 达到 15kV 以上&#xff0c;功能完全满足 EIA-422 以及 TIA/EIA-485 标准要求的 RS-422/485 收发器。 SIT3491ISO 包括一个驱动器和一个接收器&#xff0c;两者均…

为什么 Python 适合初学者?如何开始学习 Python?

与其他编程语言相比较&#xff0c;Python有着更为简单的语法&#xff0c;所以学习Python对于很多刚进入编程领域的初学者来说是一个很好的选择。 Python还是一门应用领域很广的编程语言&#xff0c;这也就意味着你可以在各种各样的工作和领域中使用它。 跟很多刚进入技术领域…

C++in/out输入输出流[IO流]

文章目录 1. C语言的输入与输出2.C的IO流2.1流的概念2.2CIO流2.3刷题常见while(cin >> str)重载强制类型转换运算符模拟while(cin >> str) 2.4C标准IO流2.5C文件IO流1.ifstream 1. C语言的输入与输出 C语言用到最频繁的输入输出方式就是scanf ()与printf()。 scanf…