STM32、Arduino、51单片机驱动土壤湿度传感器,实时检测土壤湿度(附源码)

文章目录


一、传感器简介

模块基于电容式检测原理,通过测量土壤介电常数变化来判断土壤湿度。相比传统电阻式传感器,具有不易腐蚀、使用寿命长、抗干扰能力强的特点。模块内部采用 NE555 振荡电路、电容感应探头,输出为模拟电压信号,可直接接入 ADC 采集

二、引脚功能

引脚 功能
GND 电源地
5V 5V供电引脚,也可接3.3V,输出会低0.1V
OUT 模拟电压输出引脚,输出范围1-2V左右,对应湿度100%-0%

三、采集程序

本次实验采用的开发板分别是 arduino uno 、STM32F103RC、STC89C52

arduino uno、STM32F103 有片内 AD 资源,可直接采集土壤湿度传感器输出的模拟电压; STC89C52 无片内AD需外挂一个ADC模块,采用的是ADS1115,相关教程可参考:51 驱动 ADS1115 AD采集

arduino

.ino

c 复制代码
const int sensorPin = A0;
const float VREF = 5.0;
const int ADC_RES = 1023;

void setup() {
  Serial.begin(9600);
}

void loop() {

  int adcValue = analogRead(sensorPin);
  float voltage = adcValue * (VREF / ADC_RES);

  // 限制1~2.05V范围
  if (voltage > 2.05) voltage = 2.05;
  if (voltage <  1.0) voltage = 1.0;

  float humidity = (2.05 - voltage) * 100.0;

  Serial.print("ADC: ");
  Serial.print(adcValue);
  Serial.print("  Voltage: ");
  Serial.print(voltage, 3);
  Serial.print(" V  Humidity: ");
  Serial.print(humidity, 1);
  Serial.println(" %");
  delay(1000);
}

STM32

AD.C

c 复制代码
#include "stm32f10x.h"                  // Device header

/**
  * 函    数:AD初始化
  * 参    数:无
  * 返 回 值:无
  */
void AD_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
	
	/*设置ADC时钟*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA0引脚初始化为模拟输入
	
	/*规则组通道配置*/
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);		//规则组序列1的位置,配置为通道0
	
	/*ADC初始化*/
	ADC_InitTypeDef ADC_InitStructure;						//定义结构体变量
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;		//模式,选择独立模式,即单独使用ADC1
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//数据对齐,选择右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//外部触发,使用软件触发,不需要外部触发
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;		//连续转换,失能,每转换一次规则组序列后停止
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;			//扫描模式,失能,只转换规则组的序列1这一个位置
	ADC_InitStructure.ADC_NbrOfChannel = 1;					//通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
	ADC_Init(ADC1, &ADC_InitStructure);						//将结构体变量交给ADC_Init,配置ADC1
	/*ADC使能*/
	ADC_Cmd(ADC1, ENABLE);									//使能ADC1,ADC开始运行
	/*ADC校准*/
	ADC_ResetCalibration(ADC1);								//固定流程,内部有电路会自动执行校准
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/**
  * 函    数:获取AD转换的值
  * 参    数:无
  * 返 回 值:AD转换的值,范围:0~4095
  */
uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//软件触发AD转换一次
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//等待EOC标志位,即等待AD转换结束
	return ADC_GetConversionValue(ADC1);					//读数据寄存器,得到AD转换的结果
}

main.C

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"
#include "sys.h"
#include "usart.h"

uint16_t ADValue;			//定义AD值变量
float Voltage;				//定义电压变量
float humidity;
char HumD[10] = {0};
int main(void)
{
	SystemInit();
	AD_Init();				//AD初始化
	NVIC_Configuration();
	uart_init(9600);

	while (1)
	{
		ADValue = AD_GetValue();					//获取AD转换的值
		Voltage = (float)ADValue / 4095 * 3.3;		//将AD值线性变换到0~3.3的范围,表示电压
		if(Voltage > 2.0)
		{
			Voltage = 2.0;
		}
		if(Voltage < 1.0)
		{
			Voltage = 1.0;
		}
		humidity = (2.0 - Voltage) * 100.0;
		sprintf(HumD,"RH:%0.1F",humidity);
		Usart1_SandTXString(HumD);
		Delay_ms(500);			//延时100ms,手动增加一些转换的间隔时间
	}
}

C51

main.C

c 复制代码
#include <STC89C5xRC.H>
#include <IIC.H>
#include <uart.H>
#include <ADS1115.H>
#include <delay.H>
//整形数据转字符数组
void IntToString(unsigned char *str,unsigned int dat)//str 存放字符的数组,dat 整形数据
{
	unsigned char i = 0;
	unsigned int buf[8];
	do { //先转换成 低位在前的十进制数组 将低位高位互换
		buf[i++] = dat % 10;
		dat /= 10;
	} while (dat > 0);
	while (i-- > 0) //将数组值转换为 ASCII 码反向拷贝到接收指针上
	{
			*str++ = buf[i] + '0';
	}
	*str = '\0';
}	
void main()
{
	float Voltage=0,humidity;
	unsigned char arr[8];
	char * P = arr;
	uart_init();//波特率2400
	ADS1115_Write();
	Delay_x_ms(1000);
	while(1)
	{
		Voltage = ADS1115_Read();
		
		if(Voltage > 2.0){Voltage = 2.0;}
		if(Voltage < 1.0){Voltage = 1.0;}
		humidity = (2.0 - Voltage) * 100.0;
		
		IntToString(P,humidity);
		UART_Send(P);
		UART_SendByte('.');
		humidity = (humidity - (int)humidity)*10;//取小数
		IntToString(P,humidity);
		UART_Send(P);
		
		UART_Send("%");
		Delay_x_ms(500);
	}

}

四、实验现象

---------------------------------------------------传感器接线--------------------------------------------------

C51 :

ADS1115_SCL --- P2^0

ADS1115_SDA --- P2^1

传感器_OUT --- ADS1115_AIN0

STM32 :

传感器_OUT --- PA0

arduino :

传感器_OUT --- A0

开发板串口输出如下:

以上内容个人理解,如有不正欢迎指正,需要资料及工程可留言邮箱