欢迎光临
我们一直在努力

STM32读取电阻式土壤湿度模块+OLED显示完整教程

前言

本篇基于 STM32F103C8T6 最小系统板,搭配电阻式土壤湿度传感器、I2C‑OLED 屏幕,实现土壤湿度采集、ADC 滤波、两点标定、OLED 屏幕数据显示。可以看到 ADC 原始值、引脚电压、相对湿度百分比、土壤干湿状态,适合单片机入门教学、课程实验。

硬件清单

  • STM32F103C8T6 最小系统板
  • 电阻式土壤湿度检测模块
  • 0.96 寸 I2C OLED 显示屏
  • 杜邦线若干

视频讲解:STM32读取电阻式土壤湿度模块+OLED显示完整教程https://www.bilibili.com/video/BV1jEbV6zEjV/?share_source=copy_web&vd_source=91b967b41a17a5686913521545a8c3fb

一、整体实现原理

土壤含水量发生改变,会直接改变土壤导电能力;土壤湿度模块把导电能力变化转化为 AO 模拟输出电压。 STM32 芯片通过 ADC 外设读取该模拟电压,经过多次采样平均滤波消除噪声,再通过两点标定算法换算出相对湿度,最终把各项数据输出到 OLED 屏幕上展示。

完整业务流程: 土壤含水情况发生变化 → 探针导电能力改变 → 模块输出 AO 模拟电压 → STM32 PA1 引脚 ADC 采集 → 16 次平均滤波得到稳定 ADC 数值 → 通过干湿标定点计算相对湿度 → OLED 显示 ADC、电压、湿度、干湿状态。

二、硬件接线说明

⚠️重点提醒:所有器件必须共地!传感器 GND、STM32 GND、OLED GND 接在一起。如果不共地,ADC 读数乱跳、数值固定不变,测量完全失效。

模块引脚STM32F103C8T6 引脚功能说明
土壤湿度模块 VCC 3.3V 传感器供电
土壤湿度模块 AO PA1 模拟信号输出,ADC1 通道 1 采集
土壤湿度模块 GND GND 公共参考地
OLED VCC 5V OLED 屏幕供电
OLED SCL PB8 I2C 时钟(软件 I2C)
OLED SDA PB9 I2C 数据(软件 I2C)
OLED GND GND 公共参考地

接线注意点

  • STM32F103 ADC 输入最大电压为 3.3V,本项目传感器使用 3.3V 供电,AO 输出不会超过 3.3V,可以直接接 PA1。如果传感器改成 5V 供电,AO 输出有可能超过 3.3V,必须增加分压限压电路,严禁直接接入 STM32 ADC 引脚。
  • 本实验没有使用模块 DO 数字输出引脚。DO 引脚是比较器输出,只能输出高低电平,仅判断是否超过电位器阈值,无法获取连续湿度变化;AO 模拟输出可以采集连续变化电压,适合学习 ADC 采集、滤波、标定算法。
  • 三、电阻式土壤湿度模块工作原理

    电阻式土壤湿度传感器依靠两根金属探针工作。探针插入土壤之后,土壤充当导电介质。

    • 土壤干燥:水分少,导电离子少,探针之间等效电阻大;
    • 土壤湿润:水分充足,导电离子变多,探针之间等效电阻变小。

    模块内部分压电路,会把电阻变化转换成 AO 引脚输出电压。市面上大部分电阻式土壤湿度模块规律:土壤越湿,AO 输出电压越低,ADC 采样数值越小。

    ⚠️注意:不同厂家模块电路设计不一样,也存在越湿 ADC 值越大的模块。本套程序兼容两种情况,只要正确填写干燥、湿润两组标定 ADC 数值即可。

    重要知识点:电阻式传感器检测本质是土壤导电能力,不是直接测量土壤含水量。土壤盐分、肥料浓度、土壤紧实度、探针接触松紧,都会干扰读数。必须经过标定,才可以得到可用的相对湿度。

    四、STM32 ADC 采集原理

    STM32F103C8T6 内置 12 位 ADC,PA1 引脚对应 ADC1 通道 1。 输入电压范围:0 ~ 3.3V;ADC 转换输出数字范围:0 ~ 4095。

    电压计算公式: 引脚电压(V) = ADC原始值 × 3.3 ÷ 4095

    工程代码内部转换为毫伏计算: voltage_mv = adc_value * 3300 / 4095;

    PA1 电压对应 ADC 数值
    0V 0
    0.60V 745
    1.65V 2048
    2.40V 2978
    3.30V 4095

    ADC 初始化主要完成:开启 GPIOA、ADC1 时钟;PA1 配置模拟输入;ADC 时钟配置 12MHz;配置单通道单次软件触发转换;设置采样时间;执行 ADC 复位与自校准,丢弃第一次无效转换结果。

    五、软件滤波处理

    ADC 采样容易受到电源噪声、接触抖动干扰,如果单次采样直接显示,OLED 屏幕数字会不停跳动。 本工程采用16 次采样取算术平均值的平均滤波算法。 平均ADC值 = 16次ADC采样总和 /16

    滤波流程:软件触发 ADC 转换,循环读取 16 次 ADC 结果,完成采样之后求平均值,换算电压,再计算湿度,最后刷新 OLED。

    平均滤波优点:抑制随机噪声,显示数据稳定;缺点:会轻微降低响应速度,本项目主循环约 200ms 刷新一次屏幕,适合实验观察。

    工程关键函数说明

    源文件函数名功能
    TR_Detection.c TR_Detection_Init() 初始化 PA1、ADC1,执行 ADC 校准
    TR_Detection.c TR_Detection_ReadAdc() 单次读取 ADC 通道 1 原始数值
    TR_Detection.c TR_Detection_ReadAdcAverage() 16 次采样平均滤波
    TR_Detection.c TR_Detection_ConvertToVoltageMv() ADC 值转换成引脚电压(毫伏)
    TR_Detection.c TR_Detection_ConvertToMoisturePercent() 两点标定换算相对湿度百分比
    TR_Detection.c TR_Detection_ReadData() 一次性读取 ADC、电压、湿度全套数据
    main.c Demo_ShowSoilData() OLED 屏幕打印全部测量数据和干湿状态

    六、两点标定算法讲解

    ❗为什么一定要标定? 不同传感器、不同土质、探针插入深度不一样,同样湿度下 ADC 读数完全不同。不能直接拿 ADC0‑4095 直接当做湿度百分比,必须设置两个参考点。

    两个标定参考点:

    • dry_raw:干燥土壤对应的 ADC 值,对应湿度 0%
    • wet_raw:充分湿润土壤对应的 ADC 值,对应湿度 100%

    常用模块(湿度越大 ADC 数值越小)计算公式: 相对湿度 = (干燥ADC值 – 当前ADC值) ×100 ÷ (干燥ADC值 – 湿润ADC值)

    同时程序会对输出做限制:结果强制限定在 0~100%。

    • 当前 ADC ≥干燥 ADC →湿度强制 0%
    • 当前 ADC ≤湿润 ADC →湿度强制 100%
    • 中间区间做线性换算

    举个例子:干燥 ADC=3000,湿润 ADC=1500,当前 ADC=2250 (3000‑2250)*100/(3000‑1500)=50%

    工程头文件默认标定参数:

    #define TR_DETECTION_DRY_ADC 4095u
    #define TR_DETECTION_WET_ADC 0u

    默认参数只是 ADC 全量程,仅用于程序跑通观察变化趋势,不是真实土壤标定结果。

    实操标定步骤

  • 探针擦拭干净,插入干燥待测土壤,保持插入深度固定;
  • 等待 OLED 上 ADC 读数稳定,记录数值作为 dry_raw;
  • 向土壤均匀加水,不要把水淋到传感器电路板;
  • 等待水分扩散,读数稳定,记录此时 ADC 值作为 wet_raw;
  • 修改头文件标定宏定义,重新编译下载;
  • 再次测试,观察湿度百分比随土壤干湿变化。
  • 也可以代码运行时动态设置标定参数:

    TR_Detection_Calibration calibration;
    calibration.dry_raw = 3000u;
    calibration.wet_raw = 1500u;
    TR_Detection_SetCalibration(&calibration);

    标定注意:标定必须使用你实际测量的土壤,探针插入深度、压紧程度前后保持一致。

    七、OLED 显示逻辑与干湿状态判断

    屏幕输出示例:

    SOIL MOISTURE
    ADC:2250/4095
    PIN:1.813 V
    MOIST:050 %
    STATE:NORMAL

    显示字段含义:

    显示内容说明
    ADC 滤波之后 ADC 平均值,范围 0‑4095
    PIN PA1 引脚计算得到模拟电压
    MOIST 两点标定计算得到相对湿度百分比
    STATE 土壤干湿状态

    状态阈值逻辑:

    • MOIST<30% → STATE:DRY(干燥)
    • 30% ≤ MOIST<70% → STATE:NORMAL(正常)
    • MOIST ≥70% → STATE:WET(潮湿)

    30%、70% 只是实验演示阈值,不是植物浇水标准,实际项目根据植物需求修改阈值。

    八、源代码章节

    包含工程关键源码,如 TR_Detection.c、TR_Detection.h、main.c 核心片段。

    main.c代码

    /*
    * STM32F103C8T6 soil-moisture teaching demonstration
    *
    * TR_Detection AO -> PA1 (ADC1 channel 1)
    * OLED SCL -> PB8
    * OLED SDA -> PB9
    */
    #include "delay.h"
    #include "sys.h"
    #include "oled.h"
    #include "TR_Detection.h"

    #define DISPLAY_UPDATE_MS 200u

    static void Demo_ShowStartup(void);
    static void Demo_ShowSoilData(const TR_Detection_Data *data);
    static u8 *Demo_GetMoistureText(u8 moisture_percent);

    int main(void)
    {
    TR_Detection_Data soil_data;

    delay_init();
    NVIC_Configuration();
    OLED_Init();
    OLED_ColorTurn(0u);
    OLED_DisplayTurn(0u);

    Demo_ShowStartup();
    TR_Detection_Init();
    delay_ms(500u);

    while (1)
    {
    if (TR_Detection_ReadData(&soil_data) == TR_DETECTION_OK)
    {
    Demo_ShowSoilData(&soil_data);
    }
    delay_ms(DISPLAY_UPDATE_MS);
    }
    }

    static void Demo_ShowStartup(void)
    {
    OLED_Clear();
    OLED_ShowString(0u, 0u, (u8 *)"SOIL MOISTURE", 16u);
    OLED_ShowString(0u, 20u, (u8 *)"AO: PA1 / ADC1", 12u);
    OLED_ShowString(0u, 36u, (u8 *)"OLED: PB8 PB9", 12u);
    OLED_ShowString(0u, 52u, (u8 *)"INITIALIZING…", 12u);
    OLED_Refresh();
    }

    static void Demo_ShowSoilData(const TR_Detection_Data *data)
    {
    OLED_Clear();

    OLED_ShowString(0u, 0u, (u8 *)"SOIL MOISTURE", 12u);

    OLED_ShowString(0u, 13u, (u8 *)"ADC:", 12u);
    OLED_ShowNum(30u, 13u, data->raw, 4u, 12u);
    OLED_ShowString(60u, 13u, (u8 *)"/4095", 12u);

    OLED_ShowString(0u, 26u, (u8 *)"PIN:", 12u);
    OLED_ShowNum(30u, 26u, data->voltage_mv / 1000u, 1u, 12u);
    OLED_ShowString(36u, 26u, (u8 *)".", 12u);
    OLED_ShowNum(42u, 26u, data->voltage_mv % 1000u, 3u, 12u);
    OLED_ShowString(60u, 26u, (u8 *)" V", 12u);

    OLED_ShowString(0u, 39u, (u8 *)"MOIST:", 12u);
    OLED_ShowNum(42u, 39u, data->moisture_percent, 3u, 12u);
    OLED_ShowString(60u, 39u, (u8 *)" %", 12u);

    OLED_ShowString(0u, 52u, (u8 *)"STATE:", 12u);
    OLED_ShowString(42u, 52u,
    Demo_GetMoistureText(data->moisture_percent), 12u);

    OLED_Refresh();
    }

    static u8 *Demo_GetMoistureText(u8 moisture_percent)
    {
    if (moisture_percent < 30u)
    {
    return (u8 *)"DRY";
    }
    if (moisture_percent < 70u)
    {
    return (u8 *)"NORMAL";
    }

    return (u8 *)"WET";
    }

    TR_Detection.c代码

    /**
    * @file TR_Detection.c
    * @brief STM32F103C8T6 土壤湿度检测模块驱动实现。
    * @note 文件编码:UTF-8。
    */

    #include "TR_Detection.h"
    #include "stm32f10x_adc.h"
    #include "stm32f10x_gpio.h"
    #include "stm32f10x_rcc.h"

    /** STM32F103 内部 ADC 为 12 位,最大转换值为 4095。 */
    #define TR_DETECTION_ADC_MAX 4095u

    /** ADC 参考电压,单位为毫伏;本工程模拟电源为 3.3V。 */
    #define TR_DETECTION_REFERENCE_MV 3300u

    /** 当前使用的干燥、湿润两点标定参数。 */
    static TR_Detection_Calibration g_calibration =
    {
    TR_DETECTION_DRY_ADC,
    TR_DETECTION_WET_ADC
    };

    /**
    * @brief 初始化土壤湿度传感器的模拟量采集接口。
    *
    * PA1 被配置为模拟输入,ADC1 工作在单次、独立转换模式。初始化末尾执行
    * STM32F1 所需的复位校准和校准,并丢弃校准后的第一次转换结果。
    */
    void TR_Detection_Init(void)
    {
    GPIO_InitTypeDef gpio_init;
    ADC_InitTypeDef adc_init;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
    RCC_APB2Periph_ADC1, ENABLE);

    /* 本工程 PCLK2 为 72MHz,六分频后 ADC 时钟为 12MHz,不超过 14MHz。 */
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    /* PA1 对应 ADC1_IN1,模拟输入模式会关闭数字输入输出电路。 */
    gpio_init.GPIO_Pin = GPIO_Pin_1;
    gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_init.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &gpio_init);

    /* 使用单通道、单次转换和软件触发,转换结果采用右对齐。 */
    ADC_DeInit(ADC1);
    adc_init.ADC_Mode = ADC_Mode_Independent;
    adc_init.ADC_ScanConvMode = DISABLE;
    adc_init.ADC_ContinuousConvMode = DISABLE;
    adc_init.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    adc_init.ADC_DataAlign = ADC_DataAlign_Right;
    adc_init.ADC_NbrOfChannel = 1u;
    ADC_Init(ADC1, &adc_init);

    /* 较长的采样时间有利于稳定采集土壤湿度模块的模拟输出。 */
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1u,
    ADC_SampleTime_239Cycles5);
    ADC_Cmd(ADC1, ENABLE);

    /* STM32F1 ADC 上电后需要依次完成复位校准和启动校准。 */
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1) != RESET)
    {
    }

    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1) != RESET)
    {
    }

    /* 丢弃校准后的第一次转换结果,避免其影响后续测量。 */
    (void)TR_Detection_ReadAdc();
    }

    /**
    * @brief 读取一次 ADC1 通道 1 的转换结果。
    * @return 12 位 ADC 原始值,范围为 0~4095。
    */
    u16 TR_Detection_ReadAdc(void)
    {
    /* 清除上一次完成标志,然后通过软件启动一次规则组转换。 */
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);

    /* 等待本次转换完成。 */
    while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)
    {
    }

    return ADC_GetConversionValue(ADC1);
    }

    /**
    * @brief 对多次 ADC 采样结果进行算术平均滤波。
    * @param times 采样次数。
    * @return 四舍五入后的 ADC 平均值;采样次数为 0 时返回 0。
    */
    u16 TR_Detection_ReadAdcAverage(u8 times)
    {
    u8 i;
    u32 sum;

    if (times == 0u)
    {
    return 0u;
    }

    sum = 0u;
    for (i = 0u; i < times; i++)
    {
    sum += TR_Detection_ReadAdc();
    }

    /* 除法前加上除数的一半,使整数计算结果按四舍五入处理。 */
    return (u16)((sum + ((u32)times / 2u)) / (u32)times);
    }

    /**
    * @brief 将 ADC 原始值换算为 PA1 引脚电压。
    * @param adc_value ADC 原始值。
    * @return 引脚电压,单位为毫伏。
    */
    u16 TR_Detection_ConvertToVoltageMv(u16 adc_value)
    {
    u32 raw;

    /* 对输入值限幅,防止错误参数造成换算结果超过参考电压。 */
    raw = adc_value;
    if (raw > TR_DETECTION_ADC_MAX)
    {
    raw = TR_DETECTION_ADC_MAX;
    }

    /* 电压 = ADC值 × 参考电压 ÷ ADC满量程,并进行四舍五入。 */
    return (u16)((raw * TR_DETECTION_REFERENCE_MV +
    TR_DETECTION_ADC_MAX / 2u) / TR_DETECTION_ADC_MAX);
    }

    /**
    * @brief 使用两点标定法将 ADC 值换算为相对土壤湿度。
    * @param adc_value ADC 原始值。
    * @return 相对湿度,范围为 0~100%。
    *
    * 函数同时兼容“湿度越高 ADC 值越小”和“湿度越高 ADC 值越大”的模块。
    * 超出干燥、湿润标定区间的输入值会被限制为 0% 或 100%。
    */
    u8 TR_Detection_ConvertToMoisturePercent(u16 adc_value)
    {
    u32 raw;
    u32 span;
    u32 position;
    u32 percent;
    u16 dry_raw;
    u16 wet_raw;

    dry_raw = g_calibration.dry_raw;
    wet_raw = g_calibration.wet_raw;
    raw = adc_value;
    if (raw > TR_DETECTION_ADC_MAX)
    {
    raw = TR_DETECTION_ADC_MAX;
    }

    /* 常见电阻式模块在湿度升高时输出电压和 ADC 值降低。 */
    if (dry_raw > wet_raw)
    {
    if (raw >= dry_raw)
    {
    return 0u;
    }
    if (raw <= wet_raw)
    {
    return 100u;
    }
    span = (u32)dry_raw – wet_raw;
    position = (u32)dry_raw – raw;
    }
    else
    {
    /* 同时支持湿度升高时 ADC 值增大的反向输出模块。 */
    if (raw <= dry_raw)
    {
    return 0u;
    }
    if (raw >= wet_raw)
    {
    return 100u;
    }
    span = (u32)wet_raw – dry_raw;
    position = raw – dry_raw;
    }

    /* 在两个标定点之间进行线性插值,并对结果进行四舍五入。 */
    percent = (position * 100u + span / 2u) / span;
    return (u8)percent;
    }

    /**
    * @brief 获取一次完整的土壤湿度测量数据。
    * @param data 用于接收 ADC、电压和湿度结果的指针。
    * @return 参数有效时返回成功,否则返回参数错误。
    */
    u8 TR_Detection_ReadData(TR_Detection_Data *data)
    {
    if (data == 0)
    {
    return TR_DETECTION_ERROR_ARGUMENT;
    }

    data->raw = TR_Detection_ReadAdcAverage(TR_DETECTION_SAMPLE_COUNT);
    data->voltage_mv = TR_Detection_ConvertToVoltageMv(data->raw);
    data->moisture_percent =
    TR_Detection_ConvertToMoisturePercent(data->raw);

    return TR_DETECTION_OK;
    }

    /**
    * @brief 设置运行时两点标定参数。
    * @param calibration 干燥点和湿润点标定值。
    * @return 标定值有效时返回成功,否则返回参数错误。
    */
    u8 TR_Detection_SetCalibration(const TR_Detection_Calibration *calibration)
    {
    /* 两个标定值必须位于 ADC 量程内,并且不能相等。 */
    if ((calibration == 0) ||
    (calibration->dry_raw > TR_DETECTION_ADC_MAX) ||
    (calibration->wet_raw > TR_DETECTION_ADC_MAX) ||
    (calibration->dry_raw == calibration->wet_raw))
    {
    return TR_DETECTION_ERROR_ARGUMENT;
    }

    g_calibration = *calibration;
    return TR_DETECTION_OK;
    }

    /**
    * @brief 读取当前两点标定参数。
    * @param calibration 用于接收标定参数的指针。
    */
    void TR_Detection_GetCalibration(TR_Detection_Calibration *calibration)
    {
    if (calibration != 0)
    {
    *calibration = g_calibration;
    }
    }

    TR_Detection.h代码

    #ifndef __TR_DETECTION_H
    #define __TR_DETECTION_H

    /**
    * @file TR_Detection.h
    * @brief 土壤湿度检测模块驱动接口。
    * @note 文件编码:UTF-8。
    *
    * 硬件连接:
    * – 土壤湿度模块 AO 接 PA1,对应 ADC1 通道 1;
    * – 土壤湿度模块 VCC 接 3.3V,GND 接系统地。
    *
    * 湿度百分比由干燥、湿润两个参考点线性换算得到。不同传感器及不同
    * 土壤环境的输出存在差异,正式使用前应记录实际干燥值和湿润值,修改
    * TR_DETECTION_DRY_ADC、TR_DETECTION_WET_ADC,或调用运行时标定接口。
    */

    #include "stm32f10x.h"

    /** 干燥参考点 ADC 值,对应相对湿度 0%。 */
    #define TR_DETECTION_DRY_ADC 4095u

    /** 湿润参考点 ADC 值,对应相对湿度 100%。 */
    #define TR_DETECTION_WET_ADC 0u

    /** 每次读取数据时的 ADC 平均采样次数。 */
    #define TR_DETECTION_SAMPLE_COUNT 16u

    /** 接口执行成功。 */
    #define TR_DETECTION_OK 0u

    /** 接口参数无效。 */
    #define TR_DETECTION_ERROR_ARGUMENT 1u

    /** 土壤湿度两点标定参数。 */
    typedef struct
    {
    u16 dry_raw; /**< 干燥参考点 ADC 值,对应 0%。 */
    u16 wet_raw; /**< 湿润参考点 ADC 值,对应 100%。 */
    } TR_Detection_Calibration;

    /** 一次完整的土壤湿度测量结果。 */
    typedef struct
    {
    u16 raw; /**< 经过平均滤波的 12 位 ADC 原始值。 */
    u16 voltage_mv; /**< PA1 引脚电压,单位为毫伏。 */
    u8 moisture_percent; /**< 标定后的相对湿度,范围为 0~100%。 */
    } TR_Detection_Data;

    /** 初始化 PA1、ADC1,并执行 ADC 校准。 */
    void TR_Detection_Init(void);

    /** 启动一次 ADC 转换并返回 12 位原始值。 */
    u16 TR_Detection_ReadAdc(void);

    /**
    * 连续读取 ADC 并返回平均值。
    * @param times 采样次数;传入 0 时直接返回 0。
    * @return 四舍五入后的 ADC 平均值。
    */
    u16 TR_Detection_ReadAdcAverage(u8 times);

    /**
    * 将 ADC 原始值换算为 PA1 引脚电压。
    * @param adc_value ADC 原始值。
    * @return 引脚电压,单位为毫伏。
    */
    u16 TR_Detection_ConvertToVoltageMv(u16 adc_value);

    /**
    * 根据当前两点标定参数换算相对湿度。
    * @param adc_value ADC 原始值。
    * @return 相对湿度,范围为 0~100%。
    */
    u8 TR_Detection_ConvertToMoisturePercent(u16 adc_value);

    /**
    * 完成平均采样、电压换算和湿度换算。
    * @param data 用于接收测量结果的非空指针。
    * @return TR_DETECTION_OK 或 TR_DETECTION_ERROR_ARGUMENT。
    */
    u8 TR_Detection_ReadData(TR_Detection_Data *data);

    /**
    * 设置运行时干燥、湿润标定值。
    * @param calibration 标定参数;两点必须不同且不能超过 4095。
    * @return TR_DETECTION_OK 或 TR_DETECTION_ERROR_ARGUMENT。
    */
    u8 TR_Detection_SetCalibration(const TR_Detection_Calibration *calibration);

    /**
    * 获取当前使用的标定参数。
    * @param calibration 用于接收标定参数的指针;空指针不会执行操作。
    */
    void TR_Detection_GetCalibration(TR_Detection_Calibration *calibration);

    #endif

    九、实物演示章节

    实验准备实物

    STM32 最小系统板、土壤湿度模块、OLED 显示屏、杜邦线、干土、清水、容器。

    演示操作步骤

  • 按照上面接线表完成接线,再次确认全部 GND 共地,检查传感器供电为 3.3V,确认接线没有短路。
  • 将程序编译下载到 STM32 开发板,上电,OLED 屏幕成功点亮,输出土壤湿度相关数据。
  • 场景 1:探针放置空气中 探针悬空,相当于干燥环境,可以观察 ADC 数值变大,电压升高,MOIST 湿度百分比变低,STATE 显示 DRY 干燥。
  • 场景 2:探针插入干燥土壤 把探针插入干土,保持稳定,等待读数稳定,记录当前 ADC 数值,这就是干燥标定点。
  • 场景 3:向土壤加水,模拟浇水 缓慢向土壤加水,不要打湿传感器电路板。等待水分渗透,观察 ADC 数值下降,电压降低,湿度百分比上升,状态从 DRY 切换 NORMAL,继续加水切换 WET。
  • 标定效果演示 把上面记录干、湿两组 ADC 数值替换代码中标定点,重新烧录。再次干湿切换,可以看到湿度百分比可以精准落在 0‑100 区间跟随土壤变化。
  • 现象异常排查

  • OLED 不亮:检查 5V 供电、SCL PB8、SDA PB9 接线,确认 I2C 设备地址是否匹配。
  • ADC 数值固定不变:检查 AO 引脚是否真正接到 PA1,确认共地,确认传感器 3.3V 供电正常。
  • 数值不停乱跳:检查地线是否接牢,增加滤波电容,确认 16 次平均滤波代码正常运行。
  • 十、传感器使用注意事项

  • 探针腐蚀问题:电阻式探针长期通电会发生电解腐蚀。课堂短时实验可以持续上电;长期野外采集项目,建议测量瞬间才给传感器供电,采集完成立刻断电,延长探针寿命。
  • 盐分肥料干扰:传感器测导电率,土壤施肥、含盐量高,相同含水量 ADC 读数会改变。更换土壤必须重新标定,不能直接复用旧标定参数。
  • 探针插入影响:插入深度、土壤空隙、压紧程度都会改变测量结果,做对比实验,探针插入条件必须统一。
  • 水分扩散需要时间:浇水之后不要立刻读数,等待水分在土壤扩散均匀。严禁水直接淋到传感器电路板。
  • 百分比只是相对值:OLED 上面湿度是两点标定得到的相对百分比,不是专业设备测量的体积含水率。如果需要高精度土壤含水率,需要称重法或者专业土壤传感器。
  • 十一、总结

    电阻式土壤湿度传感器把土壤导电能力转换为模拟电压输出;STM32 通过 ADC 外设读取模拟信号,经过多次采样平均滤波抑制噪声,使用两点标定算法,把 ADC 原始值转换成相对湿度百分比,最终在 OLED 屏幕展示 ADC、电压、湿度和干湿状态。

    赞(0)
    未经允许不得转载:171主机测评 » STM32读取电阻式土壤湿度模块+OLED显示完整教程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址