电容式土壤湿度传感器基于电容变化原理工作。传感器探头由两块平行金属电极构成,中间的介质为土壤。空气的介电常数约为1,而水的介电常数约为80,远大于空气和干燥土壤。
当土壤含水量增加时,水分填充了土壤颗粒间的空隙,导致电极间的等效介电常数增大,传感器的电容值随之增大。内部振荡电路将电容变化转换为频率变化,再经过滤波处理后输出与湿度成反比的模拟电压信号。
特点:不易受腐蚀、寿命长、响应稳定。输出电压越低表示土壤越湿,电压越高表示土壤越干。
电阻式土壤湿度传感器基于电阻变化原理工作。传感器探头带有两根金属插脚,直接插入土壤中。土壤作为导体,其电阻值取决于含水量和离子浓度。
当土壤含水量增加时,水中溶解的离子增多,导电能力增强,土壤的电阻值减小。传感器内部将电阻变化分压后输出与湿度成反比的模拟电压信号。
特点:结构简单、成本低,但金属探头易受电化学腐蚀,长期使用可能影响精度。输出电压越低表示土壤越湿,电压越高表示土壤越干。
| 对比项 | 电容式 | 电阻式 |
|---|---|---|
| 检测原理 | 介电常数变化 | 电阻值变化 |
| 输出电压与湿度 | 反比(湿→低压) | 反比(湿→低压) |
| ADC值范围(湿) | 约1900以下 | 约2730以下 |
| ADC值范围(干) | 约3300以上 | 约4095 |
| 抗腐蚀性 | 强 | 弱 |
| 寿命 | 长 | 较短 |
| STM32引脚 | PA0 (ADC1_IN0) | PA1 (ADC1_IN1) |
ADC1同时采集两路传感器信号,使用扫描模式+DMA循环传输,无需CPU干预即可持续更新数据
根据不同传感器的输出特性,分别采用线性映射和比例缩放算法将ADC原始值转换为0~100%湿度值
0.96寸OLED屏幕每50ms刷新一次,同时显示电容式、电阻式湿度值及数字触发状态
传感器板载比较器输出数字信号(PA4),可直接判断湿度是否超过设定阈值,无需ADC参与
| 引脚 | 名称 | 功能 | STM32连接 |
|---|---|---|---|
| GND | 电源地 | 接地 | GND |
| VCC | 电源正极 | 5V供电 | 5V |
| AOUT | 模拟输出 | 湿度模拟电压 | PA0 (ADC1_IN0) |
| 引脚 | 名称 | 功能 | STM32连接 |
|---|---|---|---|
| VCC | 电源正极 | 5V供电 | 5V |
| GND | 电源地 | 接地 | GND |
| DOUT | 数字输出 | 阈值触发信号 | PA4 (GPIO_INPUT) |
| AOUT | 模拟输出 | 湿度模拟电压 | PA1 (ADC1_IN1) |
| 引脚 | 名称 | 功能 | STM32连接 |
|---|---|---|---|
| SCL | I2C时钟 | OLED时钟线 | PB15 |
| SDA | I2C数据 | OLED数据线 | PB14 |
ADC1配置为扫描模式+连续转换,启用2个规则通道(Channel 0和Channel 1),采样时间设置为239.5个时钟周期以确保精度。数据右对齐,软件触发启动转换。DMA将转换结果自动搬运至内存数组,无需CPU干预。
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/* ADC1通用配置 */
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; // 扫描模式:多通道自动扫描
hadc1.Init.ContinuousConvMode = ENABLE; // 连续转换
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
hadc1.Init.NbrOfConversion = 2; // 2个转换通道
HAL_ADC_Init(&hadc1);
/* 配置通道0 - 电容式土壤湿度传感器 (PA0) */
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/* 配置通道1 - 电阻式土壤湿度传感器 (PA1) */
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}PA4配置为输入模式(无上下拉),用于读取电阻式土壤湿度传感器板载比较器的数字输出信号。当土壤湿度超过设定阈值时,DOUT输出低电平(0),反之输出高电平(1)。
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/* 配置PA4为输入模式 - 传感器数字输出(DOUT) */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}DMA1通道1配置为外设到内存模式,半字(16位)数据对齐,内存地址自增(MINC_ENABLE)以将两个通道的ADC值依次存入AD_Value数组。DMA模式为循环模式(DMA_CIRCULAR),确保ADC数据持续自动刷新。
/* ADC1 GPIO配置: PA0->ADC1_IN0, PA1->ADC1_IN1 */
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA配置 */
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; // 外设→内存
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; // 外设地址不增
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; // 内存地址自增
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR; // 循环模式
HAL_DMA_Init(&hdma_adc1);
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);系统启动后依次初始化GPIO、DMA、ADC1,然后执行ADC校准(HAL_ADCEx_Calibration_Start),初始化OLED显示屏,最后启动ADC+DMA转换。此后AD_Value数组将由DMA自动维护,主循环只需读取计算即可。
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init(); // GPIO初始化
MX_DMA_Init(); // DMA初始化
MX_ADC1_Init(); // ADC1初始化
HAL_ADCEx_Calibration_Start(&hadc1); // ADC校准
OLED_Init(); // OLED初始化
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, 2); // 启动ADC+DMA while (1)
{
// 电容式土壤湿度传感器 - 线性映射
soil_1 = AD_Value[0] < 1900 ? 100 : (AD_Value[0] > 3300 ? 0 : (3300 - AD_Value[0]) * 100 / 1400);
// 电阻式土壤湿度传感器 - 比例缩放
soil_2 = (100 - AD_Value[1] / 4095.0 * 100) * 3;
if(soil_2 > 100) soil_2 = 100; // 限幅
if(HAL_GetTick() - Time_Now >= 50) // 50ms刷新一次
{
OLED_Clear();
OLED_Printf(0, 0, OLED_8X16, "电容式:%d%%", soil_1);
OLED_Printf(0, 32, OLED_8X16, "电阻式:%d%%", soil_2);
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0)
OLED_Printf(0, 48, OLED_8X16, "土壤湿度:是");
else
OLED_Printf(0, 48, OLED_8X16, "土壤湿度:否");
OLED_Update();
Time_Now = HAL_GetTick();
}
}电容式:ADC值越低→湿度越高(反比关系)
电阻式:ADC值越低→湿度越高(反比关系)
PA4:数字输出,低电平=湿度触发
刷新:每50ms更新OLED显示