当前位置: 首页 > article >正文

基于 STM32 和 Modbus 协议的公路隧道照明环境数据采集系统设计

一、项目概述

在现代高速公路的隧道照明系统中,实时监控环境参数(如照度、温度和湿度)是确保安全与高效运营的重要环节。本项目旨在设计一个多通道数据采集器,能够实时采集隧道内的照明及环境数据,并通过工业标准的 Modbus 协议将数据传输到上位机进行监控和分析。

技术栈关键词

  • 单片机: STM32

  • 传感器: BH1750(照度传感器),DHT11(温度湿度传感器)

  • 通信协议: Modbus

  • 数据传输: I²C(用于BH1750),单总线(用于DHT11)

二、系统架构

设计系统架构

系统架构的设计旨在满足数据采集的实时性和准确性需求。整体架构包括数据采集模块、数据处理模块和数据传输模块。STM32作为主控制器,负责协调各个模块的工作。

选择的硬件组件

  • STM32: 作为主控制器,具备强大的处理能力和丰富的外设接口。

  • BH1750: 精确的数字光照传感器,通过 I²C 协议进行通信。

  • DHT11: 低成本的温湿度传感器,通过单总线协议进行通信。

系统架构图

以下是系统架构图,清晰展示了各组件之间的关系和通信方式。

STM32 BH1750 DHT11 Modbus 发送读取照度命令 返回照度数据 发送读取温湿度命令 返回温湿度数据 发送数据到上位机 STM32 BH1750 DHT11 Modbus

三、环境搭建和注意事项

环境搭建

  1. 硬件准备:

    • STM32开发板(如STM32F103C8T6)

    • BH1750传感器模块

    • DHT11传感器模块

    • jumper线、面包板等

  2. 软件环境:

    • 开发环境: STM32CubeIDE

    • 库文件: STM32 HAL库、Modbus库、I²C库

  3. 注意事项:

  • 确保各传感器的电源电压符合要求。

  • 在连接传感器时注意I²C和单总线的引脚配置。

  • 使用外部上拉电阻确保数据传输的可靠性。

四、代码实现过程

在本节中,我们将详细介绍基于 STM32 和 Modbus 协议的公路隧道照明多通道数据采集器的代码实现过程。整个实现过程包括多个功能模块的设计与集成,我们将对每个模块的代码逻辑、工作流程、时序图等进行深入分析和说明。

1. 照度采集模块

1.1 模块概述

照度采集模块主要负责从 BH1750 传感器读取光照强度数据。BH1750 是一款高精度的数字光照传感器,支持 I²C 通信协议,具备快速响应能力,适合用于隧道照明的实时监控。

1.2 硬件连接
  • I²C 引脚配置:

  • SCL (时钟线) 连接到 STM32 的 I²C1_SCL

  • SDA (数据线) 连接到 STM32 的 I²C1_SDA

  • VCC 连接到 STM32 的 3.3V

  • GND 连接到 STM32 的 GND

1.3 代码实现

I²C 初始化

首先,我们需要初始化 I²C 总线,以便与 BH1750 进行通信。以下是 I²C 初始化的代码示例:

#include "stm32f1xx_hal.h"

I2C_HandleTypeDef hi2c1;

void MX_I2C1_Init(void) {
    hi2c1.Instance = I2C1;
    hi2c1.Init.ClockSpeed = 100000; // I²C 时钟频率
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    HAL_I2C_Init(&hi2c1);
}

读取照度数据

接下来,我们实现读取照度数据的函数。该函数会向 BH1750 发送读取命令,然后读取并返回光照强度值。

#define BH1750_ADDRESS 0x23 // BH1750 设备地址

float Read_Lux(void) {
    uint8_t cmd = 0x01; // 启动测量
    uint8_t data[2];
    
    // 发送启动命令
    HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDRESS, &cmd, 1, HAL_MAX_DELAY);
    
    // 延时等待转换
    HAL_Delay(180);
    
    // 读取数据
    HAL_I2C_Master_Receive(&hi2c1, BH1750_ADDRESS, data, 2, HAL_MAX_DELAY);
    
    // 计算照度值
    uint16_t lux = (data[0] << 8) | data[1];
    return (float)(lux / 1.2); // 转换为 lux
}

2. 温湿度采集模块

2.1 模块概述

温湿度采集模块主要负责与 DHT11 传感器进行通信,获取环境温度和湿度数据。DHT11 是一种低成本的数字温湿度传感器,适合用于环境监测。

2.2 硬件连接
  • 单总线连接:

    • DHT11 的 DATA 引脚连接到 STM32 的 GPIO 引脚(如 PA0),需要配置为输入输出模式。

    • VCC 连接到 STM32 的 3.3V

    • GND 连接到 STM32 的 GND

2.3 代码实现

DHT11 读取函数

以下是 DHT11 读取温度和湿度的函数实现,采用单总线协议进行通信。

#include "dht11.h"

// DHT11 读取温度和湿度
void Read_Temp_Humidity(float* temperature, float* humidity) {
    uint8_t data[5] = {0}; // 存储数据的数组
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // 初始化 GPIO
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_0; // 假设 DATA 引脚连接到 PA0
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 向 DHT11 发送起始信号
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 拉低信号线
    HAL_Delay(18); // 保持低电平18ms
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 拉高信号线
    HAL_Delay(20); // 等待 DHT11 反应

    // 设置信号线为输入
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // DHT11 响应信号
    while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); // 等待连接
    while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); // 等待 DHT11 拉低信号
    while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); // 等待 DHT11 拉高信号

    // 读取 40 位数据
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 8; j++) {
            while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); // 等待拉高
            HAL_Delay(30); // 等待 30us
            if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)) {
                data[i] |= (1 << (7 - j)); // 记录数据
            }
            while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)); // 等待拉低
        }
    }

    // 数据验证
    if (data[4] == (data[0] + data[1] + data[2] + data[3])) {
        *humidity = data[0]; // 湿度
        *temperature = data[2]; // 温度
    } else {
        *humidity = -1; // 错误
        *temperature = -1; // 错误
    }
}

3. 数据传输模块

3.1 模块概述

数据传输模块负责将采集到的照度、温度和湿度数据通过 Modbus 协议发送到上位机。Modbus 是一种广泛使用的通信协议,适用于工业设备之间的数据交换。

3.2 硬件连接
  • 串口连接:

    • 使用 STM32 的 USART 接口(如 USART1)连接到 Modbus 上位机。

    • TX 引脚连接到上位机的 RX,引脚连接为 RX。

3.3 代码实现

Modbus 初始化

首先,我们需要初始化 USART 以便进行数据传输。

#include "usart.h"

UART_HandleTypeDef huart1;

void MX_USART1_UART_Init(void) {
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart1);
}

Modbus 数据发送

接下来,我们实现一个函数,用于通过 Modbus 协议发送数据。

#include "modbus.h"

// 发送 Modbus 数据
void Send_Data(float lux, float temperature, float humidity) {
    uint8_t buffer[32];
    int length = snprintf((char*)buffer, sizeof(buffer),
                          "Lux: %.2f, Temperature: %.2f, Humidity: %.2f\n", lux, temperature, humidity);
    
    // 通过 USART 发送数据
    HAL_UART_Transmit(&huart1, buffer, length, HAL_MAX_DELAY);
}

4. 主程序逻辑

在主程序中,我们将整合以上模块,实现数据的周期性采集和传输。

#include "main.h"

int main(void) {
    HAL_Init(); // 初始化 HAL 库
    SystemClock_Config(); // 配置系统时钟
    // 初始化 I2C 和 USART
    MX_I2C1_Init();
    MX_USART1_UART_Init();

    // 主循环
    while (1) {
        float lux = Read_Lux(); // 读取照度
        float temperature, humidity;
        Read_Temp_Humidity(&temperature, &humidity); // 读取温湿度

        // 发送数据到上位机
        Send_Data(lux, temperature, humidity);

        // 延时一段时间(例如 1 秒)
        HAL_Delay(1000);
    }
}

http://www.kler.cn/news/319901.html

相关文章:

  • 技能深化与软实力双提升
  • TLC/TK Adv学习笔记1 - Py版本+美化
  • HarmonyOS鸿蒙开发实战(5.0)多文件下载监听应用案例实践
  • 快速排序(C语言实现)
  • linux命令记录 ss 和 lsof
  • 【Mysql多数据源实现读写分离的几种方案】
  • 【Python 基础学习笔记】文件的基础操作
  • [Redis][主从复制][中]详细讲解
  • 2024网安周 | 百度安全深度参与,探索人工智能与数字安全的融合发展之路
  • 【SQL】产品分组销售
  • 前端开发——(1)使用vercel进行网页开发
  • vue路由的基本使用
  • Linux-L14-Linux中把用户加入到管理者root中
  • 鸿蒙OpenHarmony【轻量系统芯片移植】轻量系统STM32F407芯片移植案例
  • 无人机探测:光电侦测技术详解
  • Gstreamer中,使用mp4或者flv作为视频源去推流RTP等视频流时,需要先解码在编码才能正常
  • 使用Postman工具接口测试
  • Redis常见知识点
  • arm-硬件
  • 源码编译OpenJDK 12
  • JS二叉树的深度优先、广度优先实现代码
  • Java数据库连接jdbc
  • MATLAB基础应用精讲-【数模应用】OR值
  • 牛客周赛 Round 61 (C++实现)
  • 【算法中的最优解和较优解问题】
  • 开源标注工具
  • 【Java】注解与单元测试的使用【主线学习笔记】
  • JS手写Promise以及promise.all方法
  • QQ频道机器人零基础开发详解(基于QQ官方机器人文档)[第七期]
  • Go Mail设置指南:如何提升发送邮件效率?