ESP32通过TTL转RS485接口和风速风向变送器,检测风速风向数据(vs code附完整代码)

前言

我们学校生产实习项目之一——智能环境节点检测,我负责本模块的开发。这是我第一次遇到单片机TTL转RS485模块,其中的难点在

  • ESP32上通过ttl转rs485接口实现串口接收modbus格式的数据。
  • 编写代码以解析Modbus数据帧,提取风速和风向数据。
  • 将解析后的风速和风向数据进行处理和显示,风速单位为m/s,风向为16方位法如N(北风),NNE(东北偏北风),NE(东北风)等。
  • 将代码封装成头文件和接口函数,使用者调用函数即可实现功能。

软硬件简要介绍

一、搭建ESP32开发环境

VScode + platfromIO

1.vscode官网选择相应系统版本安装即可,我使用的是压缩包方式,下载后直接解压即可使用,无需安装

 https://code.visualstudio.com/#alt-downloads

2.相关插件的安装和配置

打开vs-code后安装所需要的插件:

下面四个直接安装即可,最后一个是vscode界面汉化插件。

 

 并下载PlatformIO插件

 

 4.安装串口监视插件 Serial Monitor:

VSCode “插件”选项中,查找“ Serial Monitor ”插件,点击安装:

 

3.使用PlatformIO进行项目的创建和编译

根据箭头选择Platformio主页打开,右侧四个选项分别为创建新项目,导入arduinoi项目以及打开Platformio项目和打开项目示例。

在此我们选择创建新项目。

 

  之后选项开发板,项目名称即可。开发板选择ESP32 Dev Module选项,项目名称和储存路径不要带中文。

 

4.外设库的下载

在使用esp32时我们会用到各种外设库,外设库的安装方法如下:

进入plat主页选择libraries进入外设库页面

 

下载Arduino库 

二、硬件介绍

1.ESP32

 大家的芯片型号不同,可能引脚分布不同,我们此次通过UART1:GPIO16、GPIO17读取转换后的RS485信号。

 2.单片机TTL转RS485模块

  • 使用MAX485芯片
  • 自动控制流向
  • 可连接多个传感器
  • 输入3.3V或者5V

接线说明   

单片机16号引脚——TXD , 17号引脚——RXD ,5V供电引脚——VCC , GUN——GUN 。

电路连接图

风向风速变送器采用RS485硬件接口,协议层兼容标准的工业Modbus-Rtu协议。被广泛应用于温室、环境保护、气象站、船舶、码头、养殖等环境的风向风速测量。

 两个传感器需要外接12V适配器电源,除了图中这样,直接连接一块12V电源(电池)也可。

代码实现 

头文件WindDet.h 及关键变量和功能函数设计

#ifndef __WINDDET_H
#define __WINDDET_H

#include <Arduino.h>

// float wspeed;
// String wdirStr;

#define TX1_PIN 16
#define RX1_PIN 17  //接16.17号引脚

// 定义风速和风向的查询命令
const uint8_t windSpeedQuery[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B};
const uint8_t windDirectionQuery[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B};

String convertWindDirection(int wdir);	// 将风向整数值转换为字符串表示的函数

void ReadWindSpeed(HardwareSerial &mySerial1);// 读取风速的函数,通过串行端口与风速传感器通信

void ReadWindDirection(HardwareSerial &mySerial2); // 读取风向的函数,通过串行端口与风向传感器通信

#endif

 代码简要设计

  1. 发送查询命令:函数ReadWindSpeedReadWindDirection分别向风速和风向传感器发送预定义的查询命令。

  2. 等待响应:使用delay函数等待传感器有足够的时间响应。

  3. 读取数据:检查串口是否有数据可读,如果有,则读取数据到缓冲区。

  4. 数据校验:检查接收到的数据长度和格式是否正确,以确保数据的完整性。

  5. 提取和处理数据:从响应数据中提取风速和风向的值,并将其转换为实际的物理量。

  6. 输出结果:通过串口输出风速和风向的值。

 

	#include "WindDet.h"
	// 读取风速的函数,通过HardwareSerial对象与风速传感器通信
	void ReadWindSpeed(HardwareSerial &mySerial1)
	{
	 // 重置事件队列,以防之前的串口事件干扰当前通信
	 mySerial1.eventQueueReset();
	 // 向风速传感器发送查询命令,请求风速数据
	 mySerial1.write(windSpeedQuery, sizeof(windSpeedQuery)); 
	 // 等待一段时间以便传感器有足够的时间响应
	 delay(1000);                                             
	 // 检查串口是否有数据可读
	 if (mySerial1.available())
	 {
	   // 定义一个缓冲区,用于存储从串口读取的数据
	   uint8_t buffer[128];                                   
	   // 从串口读取数据到缓冲区,并获取读取的字节数
	   int len = mySerial1.readBytes(buffer, sizeof(buffer)); 
	   // 校验数据格式是否正确(数据长度、设备地址、功能码)
	   if (len > 0 && len == 9 && buffer[0] == 0x01 && buffer[1] == 0x03)
	   {
	     // 从响应数据中提取风速值(风速数据格式假设为2个字节的整数)
	     int fs10 = buffer[3] * 256 + buffer[4]; 
	     // 将提取的风速值转换为实际的风速(假设原数据单位为0.1m/s)
	     float wspeed = fs10 / 10.0;                   
	     // 通过串口输出实际的风速值
	     Serial.print("Wind Speed: ");
	     Serial.print(wspeed);
	     Serial.println(" m/s");
	   }
	   else
	   {
	     // 如果数据格式不正确,输出错误信息
	     Serial.println("Failed to read wind speed");
	   }
	 }
	 else
	 {
	   // 如果没有接收到任何数据,输出无响应信息
	   Serial.println("No response for wind speed");
	 }
	}
	// 读取风向的函数,通过HardwareSerial对象与风向传感器通信
	void ReadWindDirection(HardwareSerial &mySerial2)
	{
	 // 向风向传感器发送查询命令,请求风向数据
	 mySerial2.write(windDirectionQuery, sizeof(windDirectionQuery)); 
	 // 等待一段时间以便传感器有足够的时间响应
	 delay(150);                                                    
	 // 检查串口是否有数据可读
	 if (mySerial2.available())
	 {
	   // 定义一个缓冲区,用于存储从串口读取的数据
	   uint8_t buffer[128];                                      
	   // 从串口读取数据到缓冲区,并获取读取的字节数
	   int len = mySerial2.readBytes(buffer, sizeof(buffer)); 
	   // 校验数据格式是否正确(数据长度、设备地址、功能码)
	   if (len > 0 && len == 9 && buffer[0] == 0x01 && buffer[1] == 0x03)
	   {
	     // 从响应数据中提取风向值(风向数据格式假设为2个字节的浮点数)
	     float windDir = (buffer[3] * 256 + buffer[4]) / 10; 
	     // 提取风向的整数值
	     int wdir = (buffer[5] * 256 + buffer[6]);
	     // 输出风向的数值和字符串表示
	     Serial.printf("Wind direction: %d(%.2f)\n", wdir, windDir);
	     // 将风向整数值转换为风向字符串
	     String wdirStr = convertWindDirection(wdir);   
	     Serial.print("Wind Direction: ");
	     Serial.println(wdirStr);
	   }
	   else
	   {
	     // 如果数据格式不正确,输出错误信息
	     Serial.println("Failed to read wind direction");
	   }
	 }
	 else
	 {
	   // 如果没有接收到任何数据,输出无响应信息
	   Serial.println("No response for wind direction");
	 }
	}
	// 将风向整数值转换为字符串表示的函数
	String convertWindDirection(int wdir)
	{
	 // 使用switch语句,根据风向整数值返回对应的风向字符串
	 switch (wdir)
	 {
	   case 0: return "N";   // 北
	   case 1: return "NNE"; // 北北东
	   case 2: return "NE";  // 东北
	   case 3: return "ENE"; // 东北东
	   case 4: return "E";   // 东
	   case 5: return "ESE"; // 东南东
	   case 6: return "SE";  // 东南
	   case 7: return "SSE"; // 南南东
	   case 8: return "S";   // 南
	   case 9: return "SSW"; // 南南西
       case 10: return "SW";  // 西南
       case 11: return "WSW"; // 西西南
       case 12: return "W";   // 西
       case 13: return "WNW"; // 西西北
       case 14: return "NW";  // 西北
       default: return "NNW"; // 北北西
     }
}

 

 最后采集到的风向风速信息,在串口打印输出

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值