嵌入式C与STM32技术结合ROS系统与MQTT协议在智能农业灌溉系统项目设计中的应用思路与代码示例

目录

项目概述

系统设计

硬件设计

软件设计

系统架构图

代码实现

1. STM32微控制器代码

1.1 STM32初始化代码

1.2 读取土壤湿度

1.3 MQTT数据发送

1.4 接收控制命令

1.5 主循环

2. ROS系统代码

2.1 创建ROS节点

2.2 控制水泵的逻辑

3. ROS与MQTT的集成

3.1 安装ros_mqtt

3.2 在ROS中配置MQTT

项目总结

项目总结

项目优点

后续改进方向

参考文献


项目概述

随着全球水资源短缺问题的日益严重,智能灌溉系统的开发与应用显得尤为重要。本文介绍一种基于STM32微控制器土壤湿度传感器的智能灌溉系统。该系统利用MQTT协议将数据上传至ROS(Robot Operating System)系统,进而实现自动化精准灌溉。通过实时监测土壤湿度和天气预报信息,系统能够根据设定的阈值自动控制水泵,实现水资源的节约和农作物的高效灌溉。

系统设计

硬件设计

  1. STM32微控制器:作为系统的核心,负责数据采集、处理和控制。
  2. 土壤湿度传感器:实时监测土壤的湿度状况,输出模拟或数字信号。
  3. MQTT通信模块:如ESP8266或SIM800L,用于将数据发送到ROS系统。
  4. 水泵:根据控制信号自动灌溉。
  5. 电源模块:为各个硬件组件提供稳定的电源。

软件设计

  1. STM32固件

  2. 读取土壤湿度传感器数据。
  3. 通过MQTT协议将数据发送到ROS系统。
  4. 接收ROS系统发送的灌溉控制命令。
  5. ROS系统

  6. 接收来自STM32的数据。
  7. 根据设定的阈值和天气预报信息,判断是否启动水泵。
  8. 控制水泵的开关状态。

系统架构图

代码实现

本文将详细介绍STM32和ROS系统的代码实现,包括每块代码的注释和说明。

1. STM32微控制器代码

1.1 STM32初始化代码

首先,初始化STM32微控制器及其外设。

#include "stm32f4xx_hal.h"
#include "mqtt_client.h" // MQTT客户端库

// 初始化系统
void System_Init(void) {
    HAL_Init(); // 初始化HAL库
    SystemClock_Config(); // 配置系统时钟
    MX_GPIO_Init(); // 初始化GPIO
    MX_USART2_UART_Init(); // 初始化串口
    MQTT_Init(); // 初始化MQTT客户端
}
  • HAL_Init(): 初始化硬件抽象层。
  • SystemClock_Config(): 配置系统时钟。
  • MX_GPIO_Init(): 初始化GPIO端口。
  • MX_USART2_UART_Init(): 初始化串口通信。
  • MQTT_Init(): 初始化MQTT客户端。
  • 1.2 读取土壤湿度

    读取土壤湿度传感器的值并转换为百分比。

    // 读取土壤湿度
    float Read_Soil_Moisture(void) {
        uint32_t adc_value = HAL_ADC_GetValue(&hadc1); // 获取ADC值
        float moisture_percentage = (adc_value / 4095.0) * 100; // 将ADC值转换为百分比
        return moisture_percentage; // 返回湿度值
    }
    
  • HAL_ADC_GetValue(&hadc1): 获取ADC通道的值。
  • 将ADC值转换为湿度百分比,假设ADC值范围为0-4095。
  • 1.3 MQTT数据发送

    通过MQTT将土壤湿度数据发送到服务器。

    // 发送土壤湿度数据到MQTT服务器
    void Send_Data(float moisture) {
        char message[50];
        snprintf(message, sizeof(message), "{\"moisture\": %.2f}", moisture); // 将湿度值格式化为JSON
        MQTT_Publish("farm/soil/moisture", message); // 发送MQTT消息
    }
  • 功能:将土壤湿度数据以JSON格式发送到MQTT Broker。
  • 代码说明
  • snprintf用于将浮点数moisture格式化为JSON字符串,确保在消息中包含适当的湿度值。
  • MQTT_Publish函数将格式化后的消息发送到主题"farm/soil/moisture",以便ROS系统可以接收和处理。
  • 1.4 接收控制命令

    处理接收到的MQTT消息,根据指令控制水泵的开关状态。

    // 处理接收到的MQTT消息
    void MQTT_Message_Handler(char *topic, char *message) {
        // 判断是否是水泵控制指令
        if (strcmp(topic, "farm/control/pump") == 0) {
            if (strcmp(message, "ON") == 0) {
                HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // 打开水泵
                printf("Pump is ON\n"); // 输出调试信息
            } else if (strcmp(message, "OFF") == 0) {
                HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 关闭水泵
                printf("Pump is OFF\n"); // 输出调试信息
            }
        }
    }
    
  • 功能:根据接收到的MQTT消息控制水泵的状态。
  • 代码说明
  • strcmp函数用于比较消息主题和内容。
  • HAL_GPIO_WritePin用于控制水泵的GPIO引脚,GPIO_PIN_1对应于水泵的控制引脚。
  • 输出调试信息以便于观察水泵的状态。
  • 1.5 主循环

    在主循环中,系统会定期读取土壤湿度并发送数据,同时检查是否有新的MQTT消息。

    int main(void) {
        System_Init(); // 初始化系统
        while (1) {
            float moisture = Read_Soil_Moisture(); // 读取土壤湿度
            Send_Data(moisture); // 发送数据到MQTT
    
            // 检查是否有新消息并处理
            MQTT_Check_For_Messages(); // 检查MQTT消息
            HAL_Delay(60000); // 每60秒读取一次湿度
        }
    }
    
  • 功能:主循环中定时读取土壤湿度并发送数据,同时处理MQTT消息。
  • 代码说明
  • Read_Soil_Moisture()函数用于获取当前的土壤湿度。
  • Send_Data(moisture)将湿度数据发送到MQTT Broker。
  • MQTT_Check_For_Messages()检查是否有新的MQTT消息,并调用相应的处理函数。
  • HAL_Delay(60000)使主循环每60秒执行一次。
  • 2. ROS系统代码

    接下来,我们将实现ROS系统的代码,处理从STM32接收到的土壤湿度数据,并根据设定阈值控制水泵。

    2.1 创建ROS节点

    在ROS中,我们需要创建一个节点用于接收和处理从STM32发送的土壤湿度数据,并根据设定的阈值控制水泵的状态。

    #!/usr/bin/env python
    import rospy
    from std_msgs.msg import String
    
    def callback(data):
        # 解析接收到的湿度数据
        moisture_data = data.data
        moisture = float(moisture_data.split(":")[1].strip("}"))  # 解析JSON格式数据
        control_pump(moisture)  # 根据湿度值控制水泵
    
    def control_pump(moisture):
        threshold = 30.0  # 设定的湿度阈值
        if moisture < threshold:
            publish_command("ON")  # 湿度低于阈值,启动水泵
        else:
            publish_command("OFF")  # 湿度高于阈值,停止水泵
    
    def publish_command(command):
        pub = rospy.Publisher('farm/control/pump', String, queue_size=10)  # 创建发布者
        pub.publish(command)  # 发布水泵控制命令
        rospy.loginfo("Published command: %s", command)  # 输出信息到日志
    
    if __name__ == '__main__':
        rospy.init_node('irrigation_controller', anonymous=True)  # 初始化ROS节点
        rospy.Subscriber('farm/soil/moisture', String, callback)  # 订阅湿度数据主题
        rospy.spin()  # 保持节点运行
    
  • 功能:创建一个ROS节点,接收土壤湿度数据,并根据湿度值控制水泵的开关。
  • 代码说明
  • rospy.init_node('irrigation_controller', anonymous=True): 初始化一个名为irrigation_controller的ROS节点。
  • rospy.Subscriber('farm/soil/moisture', String, callback): 订阅farm/soil/moisture主题,用于接收来自STM32的湿度数据,并在接收到数据时调用callback函数。
  • rospy.spin(): 保持节点运行,等待回调函数处理消息。
  • 2.2 控制水泵的逻辑

    control_pump函数中,我们根据读取到的土壤湿度值决定水泵的开关状态。

    def control_pump(moisture):
        threshold = 30.0  # 设定的湿度阈值
        if moisture < threshold:
            publish_command("ON")  # 湿度低于阈值,启动水泵
        else:
            publish_command("OFF")  # 湿度高于阈值,停止水泵
    
  • 功能:根据湿度值判断是否需要启动或停止水泵。
  • 代码说明
  • 定义一个湿度阈值(例如30.0%),如果湿度低于阈值,则发送"ON"命令启动水泵;如果湿度高于阈值,则发送"OFF"命令停止水泵。
  • 3. ROS与MQTT的集成

    为了让ROS能够处理MQTT消息,我们可以使用ros-mqtt库将ROS与MQTT连接。这样,ROS就可以接收来自STM32的消息,并根据逻辑处理发送控制指令。

    3.1 安装ros_mqtt

    在ROS环境中安装ros_mqtt库:

    sudo apt-get install ros-<your_ros_distro>-mqtt
    

    替换<your_ros_distro>为你的ROS版本,例如noeticmelodic

    3.2 在ROS中配置MQTT

    为了让ROS能够通过MQTT协议接收和发送消息,我们需要设置MQTT客户端,并在ROS节点中进行必要的配置。

    import paho.mqtt.client as mqtt
    
    # MQTT连接回调
    def on_connect(client, userdata, flags, rc):
        rospy.loginfo(f"Connected to MQTT Broker with result code {rc}")
        client.subscribe("farm/soil/moisture")  # 订阅湿度数据主题
    
    # MQTT消息处理回调
    def on_message(client, userdata, msg):
        rospy.loginfo(f"Received message: {msg.payload.decode()}")
        moisture_data = msg.payload.decode()  # 将消息内容解码为字符串
        callback(moisture_data)  # 调用之前定义的callback函数处理消息
    
    if __name__ == '__main__':
        rospy.init_node('irrigation_controller', anonymous=True)  # 初始化ROS节点
    
        # 配置MQTT客户端
        mqtt_client = mqtt.Client()  # 创建MQTT客户端实例
        mqtt_client.on_connect = on_connect  # 设置连接回调
        mqtt_client.on_message = on_message  # 设置消息处理回调
    
        # 连接到MQTT Broker
        mqtt_client.connect("broker.hivemq.com", 1883, 60)  # 连接到MQTT Broker
    
        # 启动MQTT客户端循环
        mqtt_client.loop_start()  # 启动阻塞循环以处理网络流量
    
        # 订阅ROS主题
        rospy.Subscriber('farm/soil/moisture', String, callback)  # 订阅湿度数据主题
    
        rospy.spin()  # 保持节点运行
        mqtt_client.loop_stop()  # 停止MQTT客户端循环
    
  • 功能:设置MQTT客户端以便与MQTT Broker连接并处理消息。
  • 代码说明
  • on_connect(client, userdata, flags, rc): 当与MQTT Broker连接成功后会调用该函数,可以在这里进行主题订阅。
  • on_message(client, userdata, msg): 当接收到MQTT消息时,该函数将被调用,可以在这里处理消息内容并调用callback函数。
  • mqtt_client = mqtt.Client(): 创建一个MQTT客户端实例。
  • mqtt_client.connect("broker.hivemq.com", 1883, 60): 连接到MQTT Broker,使用HiveMQ公共测试Broker。
  • mqtt_client.loop_start(): 启动MQTT循环,处理网络流量和消息。
  • 项目总结

    本文介绍了一种基于STM32微控制器和土壤湿度传感器的智能灌溉系统。通过MQTT协议将数据上传至ROS系统,实现了自动化精准灌溉。系统能够根据实时的土壤湿度和设定的阈值控制水泵的开关,节约水资源,提高灌溉效率。

    项目优点

    1. 精准灌溉:系统可根据实时土壤湿度调整灌溉计划,避免水资源浪费。
    2. 实时监测:通过MQTT协议,能够实时监测土壤湿度,并快速响应。
    3. 易于扩展:系统架构清晰,可根据需求增加其他传感器(如气象传感器)实现更智能的灌溉管理。

    后续改进方向

    1. 天气预报集成:集成天气预报API,进一步优化灌溉计划。
    2. 手机应用:开发手机应用,用户可以实时监控土壤湿度和水泵状态。
    3. 数据分析:收集数据进行分析,优化长期灌溉策略。

    参考文献

    1. MQTT协议简介: MQTT – The Standard for IoT Messaging
    2. ROS官方文档: Documentation – ROS Wiki
    3. STM32微控制器文档: https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html
    4. Paho MQTT Python客户端文档: Eclipse Paho | The Eclipse Foundation

    作者:极客小张

    物联沃分享整理
    物联沃-IOTWORD物联网 » 嵌入式C与STM32技术结合ROS系统与MQTT协议在智能农业灌溉系统项目设计中的应用思路与代码示例

    发表回复