漏水传感器(STM32)

目录

一、传感器介绍

二、传感器原理

三、RS485指令

四、程序设计

main.c文件

water485.h文件

water485.c文件

四、实验演示

五、资料获取

项目分享


哔哩哔哩视频链接:https://www.bilibili.com/video/BV1ASHf68ExN/?share_source=copy_web&vd_source=097fdeaf6b6ecfed8a9ff7119c32faf2

(资料分享见文末)

一、传感器介绍

漏水传感器主要用于检测地面、管道或设备周围是否出现积水、渗漏等情况。当探头接触到水后,模块会立即切换为报警状态,并通过 RS485接口将检测结果发送给STM32、PLC或上位机。模块采用Modbus-RTU通信协议,具有通信距离远、抗干扰能力强、便于多设备组网等特点。它适用于机房、仓库、地下室、配电柜、水泵房、厨房、卫生间、智能家居及工业自动化系统,可配合蜂鸣器、水泵、电磁阀或云平台,实现漏水报警、自动断水和远程监控。

以下是模块的参数:

|------|-------------|
| 型号 | EYK-JSK930 |
| 供电 | 9-30V |
| 波特率 | 9600 |
| 设备地址 | 0x01 |
| 检测对象 | 自来水、纯净水 |
| 检测距离 | 1000米 |
| 输出地址 | 继电器输出/RS485 |

二、传感器原理

漏水传感器通过探头上的金属电极检测水的导电性。正常干燥时,电极之间电阻较大,传感器输出正常状态;当水接触探头后,水中的离子使电极之间形成导电通路,电阻降低,内部检测电路判断发生漏水并切换为报警状态。模块随后把检测结果转换为数字数据,通过RS485接口按照Modbus-RTU协议发送给STM32。主控发送查询指令后,传感器返回状态数据,其中00表示正常,01表示漏水报警。系统可根据报警结果启动蜂鸣器、关闭电磁阀、停止水泵或上传远程平台,实现实时检测和自动联动控制。

以下是引脚描述:

|------|-------------|
| 漏水传感器 ||
| 485+ | RS485差分信号正端 |
| VCC | 模块正极 |
| GND | 模块负极 |
| 485- | RS485差分信号负端 |
| S1 | 漏水探头正极 |
| S2 | 漏水探头负极 |

|-----|-------------|
| 485转TTL模块 ||
| VCC | 电源正极 |
| TXD | 发送端 |
| RDX | 接收端 |
| GND | 电源负极 |
| A+ | RS485差分信号正端 |
| B- | RS485差分信号负端 |

三、RS485指令

查询指令:01 02 00 00 00 01 B9 CA

返回指令:01 02 01 00 A1 88

四、程序设计

1.使用STM32F103C8T6接收漏水传感器发送的采集数据

2.将解析后的漏水结果在OLED上显示

|----------|------|
| PA2 | TXD |
| PA3 | RXD |
| 5V | VCC |
| GND | GND |
| OLED_SCL | PB8 |
| OLED_SDA | PB9 |
| 调试 | 串口1 |
| A+ | 485+ |
| B- | 485- |

main.c文件

cpp 复制代码
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include "OLED.h"
#include "water485.h"
#include <stdio.h>
/*****************辰哥单片机设计******************
			STM32
 * 文件		:  漏水传感器实验                   
 * 版本		:  V1.0
 * 日期		:  2026.7.31
 * MCU		:  STM32F103C8T6
 * 接口		:  见usart2.h文件
 * IP账号	:  辰哥单片机设计(同BILIBILI|抖音|快手|小红书|CSDN|公众号|视频号等)
 * 作者		:  辰哥
 * 工作室	:  异方辰电子工作室
 * 官方网站	:  www.yfcdz.cn
**********************BEGIN***********************/		
int main(void)
{
  SystemInit();
delay_init(72);
USART1_Config();
  Water485_Init();
OLED_Init();
OLED_Clear();
    while(1)
    {
//当前状态
			  OLED_ShowChinese(8,24,0,16,1);
OLED_ShowChinese(24,24,1,16,1);
OLED_ShowChinese(40,24,2,16,1);
OLED_ShowChinese(56,24,3,16,1);
			  OLED_ShowChar(72,24,':',16,1);
        /*
         * 查询一次漏水传感器状态
         *
         * 最长等待200ms。
         */
        if(Water485_ReadState(200))
        {
            if(Water485_State == WATER485_NORMAL)
            {
//正常
OLED_ShowChinese(88,24,4,16,1);
				      OLED_ShowChinese(104,24,5,16,1);
            }
            else if(Water485_State == WATER485_ALARM)
            {
//漏水
OLED_ShowChinese(88,24,6,16,1);
				      OLED_ShowChinese(104,24,7,16,1);
            }
        }
        delay_ms(500);
    }
}

water485.h文件

cpp 复制代码
#ifndef __WATER485_H
#define __WATER485_H

#include "stm32f10x.h"

/*****************辰哥单片机设计******************
			STM32
 * 文件		:  漏水传感器.h文件                  
 * 版本		:  V1.0
 * 日期		:  2026.7.31
 * MCU		:  STM32F103C8T6
 * 接口		:  见usart2.h文件
 * IP账号	:  辰哥单片机设计(同BILIBILI|抖音|快手|小红书|CSDN|公众号|视频号等)
 * 作者		:  辰哥
 * 工作室	:  异方辰电子工作室
 * 官方网站	:  www.yfcdz.cn

**********************BEGIN***********************/		
/*
 * 漏水传感器状态
 */
typedef enum
{
    /*
     * 通信错误或没有收到正确数据
     */
    WATER485_ERROR = 0,

    /*
     * 传感器正常,没有检测到漏水
     */
    WATER485_NORMAL,

    /*
     * 检测到漏水
     */
    WATER485_ALARM

} Water485_State_t;


/*
 * 当前漏水传感器状态
 */
extern volatile Water485_State_t Water485_State;


/**
 * @brief  漏水传感器初始化
 * @param  无
 * @retval 无
 */
void Water485_Init(void);

/**
 * @brief  向漏水传感器发送状态查询指令
 * @param  无
 * @retval 无
 */
void Water485_SendQuery(void);

/**
 * @brief  处理漏水传感器返回数据
 * @param  无
 * @retval 1:收到并解析到正确数据
 *         0:没有数据或数据错误
 */
uint8_t Water485_Process(void);

/**
 * @brief  阻塞方式读取一次漏水状态
 * @param  timeout_ms:等待超时时间,单位毫秒
 * @retval 1:读取成功
 *         0:读取失败
 */
uint8_t Water485_ReadState(uint16_t timeout_ms);

/**
 * @brief  获取状态对应的字符串
 * @param  无
 * @retval 状态字符串
 */
const char *Water485_GetStateString(void);

#endif

water485.c文件

cpp 复制代码
#include "water485.h"
#include "usart2.h"
#include "delay.h"
#include "usart.h"
/*****************辰哥单片机设计******************
			STM32
 * 文件		:  漏水传感器.c文件                  
 * 版本		:  V1.0
 * 日期		:  2026.7.31
 * MCU		:  STM32F103C8T6
 * 接口		:  见usart2.h文件
 * IP账号	:  辰哥单片机设计(同BILIBILI|抖音|快手|小红书|CSDN|公众号|视频号等)
 * 作者		:  辰哥
 * 工作室	:  异方辰电子工作室
 * 官方网站	:  www.yfcdz.cn
**********************BEGIN***********************/		
/*
 * 当前漏水传感器状态
 *
 * 上电默认设置为通信错误,
 * 成功读取传感器后再更新状态。
 */
volatile Water485_State_t Water485_State = WATER485_ERROR;
/*
 * 读取地址为0x01的漏水传感器状态
 *
 * Modbus-RTU查询指令:
 *
 * 01:设备地址
 * 02:读取离散输入功能码
 * 00 00:起始地址
 * 00 01:读取1个状态
 * B9 CA:CRC16校验码,低字节在前
 */
static const uint8_t Water485_QueryCmd[8] =
{
//查询指令:01 02 00 00 00 01 B9 CA
    0x01,0x02,0x00,0x00,0x00,0x01,0xB9,0xCA
};
/**
 * @brief  计算Modbus-RTU CRC16校验值
 * @param  data:需要校验的数据地址
 * @param  len:需要校验的数据长度
 * @retval CRC16校验值
 *
 * 返回值低8位是CRC低字节,
 * 返回值高8位是CRC高字节。
 */
static uint16_t Water485_CRC16(const uint8_t *data, uint16_t len)
{
    uint16_t crc;
    uint16_t i;
    uint8_t j;
    crc = 0xFFFF;
    for(i = 0; i < len; i++)
    {
        crc ^= data[i];
        for(j = 0; j < 8; j++)
        {
            if(crc & 0x0001)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    return crc;
}
/**
 * @brief  漏水传感器初始化
 * @param  无
 * @retval 无
 */
void Water485_Init(void)
{
    /*
     * 漏水传感器默认波特率为9600
     */
    USART2_Init(9600);
    USART2_ClearRx();
    /*
     * 初始状态设置为通信错误
     */
    Water485_State = WATER485_ERROR;
}
/**
 * @brief  发送漏水状态查询指令
 * @param  无
 * @retval 无
 */
void Water485_SendQuery(void)
{
    /*
     * 每次发送查询指令前,
     * 先清空上一次接收的数据。
     */
    USART2_ClearRx();
    /*
     * 发送Modbus-RTU查询指令
     */
    USART2_SendArray(Water485_QueryCmd, sizeof(Water485_QueryCmd));
}
/**
 * @brief  处理漏水传感器返回的数据
 * @param  无
 * @retval 1:收到并解析到正确数据
 *         0:没有数据或数据错误
 *
 * 正常返回:
 * 01 02 01 00 A1 88
 *
 * 漏水报警返回:
 * 01 02 01 01 60 48
 */
uint8_t Water485_Process(void)
{
    uint8_t rx_data[USART2_RX_BUF_SIZE];
    uint16_t rx_len;
    uint16_t i;
    uint16_t crc;
    /*
     * 没有接收到完整的一帧数据
     */
    if(USART2_RX_Flag == 0)
    {
        return 0;
    }
    /*
     * 临时关闭总中断,
     * 防止复制数据时USART2中断修改缓冲区。
     */
    __disable_irq();
    //读取接收长度
    rx_len = USART2_RX_CNT;
    if(rx_len > USART2_RX_BUF_SIZE)
    {
        rx_len = USART2_RX_BUF_SIZE;
    }
    for(i = 0; i < rx_len; i++)
    {
//复制到局部数组
        rx_data[i] = USART2_RX_BUF[i];
    }
//清空接收状态
    USART2_RX_CNT = 0;
    USART2_RX_Flag = 0;
//重新开启接收中断
    __enable_irq();
//检查数据长度
    if(rx_len < 6)
    {
        Water485_State = WATER485_ERROR;
        return 0;
    }
    /*
     * 从接收缓冲区中查找正确的6字节数据帧。
     *
     * 这样即使数据前面存在少量干扰字节,
     * 也能够找到真正的返回数据。
     */
    for(i = 0; i + 6 <= rx_len; i++)
    {
        /*
         * 判断设备地址、功能码和数据长度
         */
        if((rx_data[i] == 0x01) &&
           (rx_data[i + 1] == 0x02) &&
           (rx_data[i + 2] == 0x01))
        {
            /*
             * 对前4个字节计算CRC16
             */
            crc = Water485_CRC16(&rx_data[i], 4);
            /*
             * Modbus-RTU发送CRC时低字节在前
             */
            if(((uint8_t)(crc & 0xFF) == rx_data[i + 4]) &&
               ((uint8_t)(crc >> 8) == rx_data[i + 5]))
            {
                /*
                 * 第4个字节为漏水状态:
                 *
                 * 0x00:正常
                 * 0x01:漏水报警
                 */
                if(rx_data[i + 3] == 0x00)
                {
                    Water485_State = WATER485_NORMAL;
                    return 1;
                }
                else if(rx_data[i + 3] == 0x01)
                {
                    Water485_State = WATER485_ALARM;
                    return 1;
                }
                else
                {
                    Water485_State = WATER485_ERROR;
                    return 0;
                }
            }
        }
    }
    /*
     * 没有找到正确的返回帧
     */
    Water485_State = WATER485_ERROR;
    return 0;
}
/**
 * @brief  阻塞方式读取一次漏水状态
 * @param  timeout_ms:等待超时时间,单位毫秒
 * @retval 1:读取成功
 *         0:读取超时或数据错误
 */
uint8_t Water485_ReadState(uint16_t timeout_ms)
{
    /*
     * 发送查询指令
     */
    Water485_SendQuery();
    /*
     * 在规定时间内等待传感器返回数据
     */
    while(timeout_ms > 0)
    {
        /*
         * 检查并处理接收数据
         */
        if(Water485_Process())
        {
            return 1;
        }
        delay_ms(1);
        timeout_ms--;
    }
    /*
     * 等待超时,没有收到正确返回数据
     */
    Water485_State = WATER485_ERROR;
    return 0;
}
/**
 * @brief  获取漏水状态字符串
 * @param  无
 * @retval 状态对应的字符串
 */
const char *Water485_GetStateString(void)
{
    switch(Water485_State)
    {
        case WATER485_NORMAL:
            return "NORMAL";
        case WATER485_ALARM:
            return "WATER ALARM";
        case WATER485_ERROR:
        default:
            return "COMM ERROR";
    }
}

四、实验演示

五、资料获取

项目分享

相关推荐
恶魔泡泡糖2 小时前
stm32F103C8T6标准库串口接收之多串口基础应用5
stm32·单片机·嵌入式硬件
木子单片机2 小时前
基于51单片机计步器—无线蓝牙APP上传
单片机·嵌入式硬件·51单片机·keil
智者知已应修善业2 小时前
【51单片机只有一个8*8点阵数据如何滚动起来一片595+一组IO+花样】2022-1-15
c++·经验分享·笔记·单片机·蓝桥杯·硬件架构
恒锐丰科技林技术员2 小时前
EG2123A 三相独立半桥驱动芯片解析与工程应用
经验分享·嵌入式硬件·硬件工程
硅基手札3 小时前
【Linux 内核专栏 13】快IO层
linux·服务器·嵌入式硬件
李日华大战鸡红3 小时前
滑膜观测器(学习记录)
stm32·单片机·学习·matlab·机器人
白搞电子3 小时前
ESP32-S31 项目如何制作 Windows 一键烧录包:完整镜像、esptool 与数据边界
windows·stm32·单片机
xiangw@GZ4 小时前
纽扣电池型号
嵌入式硬件
优信电子4 小时前
Raspberry Pi Pico 硬件开发 —— 第二课:MicroPython 从入门到项目实践(LED篇)
单片机·嵌入式硬件·树莓派·micropython·pico·入门教学