1、粉尘传感器 GP2Y10是一款光学空气质量传感器,设计用来感应空气中的尘埃粒子,其内部对角安放着红外线发光二极管和光电晶体管,使得其能够探测到空气中尘埃反射光,即使非常细小的如烟草烟雾颗粒也能够被检测到,通常在空气净化系统中应用。该传感器具有非常低的电流消耗(最大20mA,典型值11mA),可使用高达7VDC。该传感器输出为模拟电压,其值与粉尘浓度成正比。
2、可测量0.8微米以上的微小粒子,感知烟草产生的花粉,房屋粉尘等,体积小,重量轻,便于安装,广泛应用于空气清新机,换气空调,换气扇等产品。输出电压与粉尘浓度的比值如下图:
根据曲线图可以列出部分电压与粉尘浓度的对应值,如下:
V | 0.5846 | 1.1544 | 1.7173 | 2.3153 | 2.9730 | 3.5229 |
mg/m3 | 0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 |
根据以上对应值可以求出粉尘浓度mg/m3与电压V的计算公式,如下(根据Excel生成的公式):
mg/m3 = 0.1686 * V - 0.09856
根据传感器数据手册介绍,传感器的采集周期为10ms,LED灯亮时间为0.32ms,传感器采集时间为0.28ms。如下图:
3、Sensor_Dust.c 文件
// 传感器初始化
void GP2Y10_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);
// 初始化传感器LED灯控制引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOA , &GPIO_InitStruct);
GP2Y10_LED_OFF(); // 初始化传感器LED灯为关
GPIO_InitTypeDef GPIO_InitStruct; // 定义 GPIO 初始化结构体变量
ADC_InitTypeDef ADC_InitStruct; // 定义 ADC初始化结构体变量
DMA_InitTypeDef DMA_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); // 使能 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); // 使能 ADC1 时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; // 模拟输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; // ADC通道引脚
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化
ADC_DeInit(ADC1); // 复位 ADC
ADC_StructInit(&ADC_InitStruct); // 使用默认值填充 ADC_InitStruct成员
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; // 数据对齐
ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; // 禁止触发检测,使用软件触发
ADC_InitStruct.ADC_ScanDirection = ADC_ScanDirection_Upward; // 启动向上扫描模式 (from CHSEL0 to CHSEL17)
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; // 12 位模式
ADC_Init(ADC1,&ADC_InitStruct); // ADC 初始化
ADC_ChannelConfig(ADC1,ADC_Channel_1,ADC_SampleTime_239_5Cycles); // 配置ADC注入通道0及周期采样时间
ADC_GetCalibrationFactor(ADC1); // 校准 ADC
ADC_Cmd(ADC1,ENABLE); // ADC 使能
ADC_StartOfConversion(ADC1); // 开始 ADC1 转换
DMA_DeInit(DMA1_Channel1); // 复位
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_BufferSize = 1; // 整体的数据个数
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; // 指定外设为发送源
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; // 关闭两个存储区互相访问
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_Value; // 存储区基地址
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 存储区每次接收两个字节
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; // 存储区地址自增
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // 开启循环模式
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // 外设地址
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设每次传输两个字节
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不自增
DMA_InitStruct.DMA_Priority = DMA_Priority_High; // 设置通道转换优先级
DMA_Init(DMA1_Channel1, &DMA_InitStruct); // 初始化
ADC_DMARequestModeConfig(ADC1,ADC_DMAMode_Circular); // 使能ADC的DMA循环转换模式
DMA_Cmd(DMA1_Channel1, ENABLE); //DMA 使能
ADC_DMACmd(ADC1, ENABLE); // ADC DMA 使能
ADC_StartOfConversion(ADC1); // 开始 ADC1 转换
}
/***********************************
* V mg/m3 *
* 0.5846 0 *
* 1.1544 0.1 *
* 1.7173 0.2 *
* 2.3153 0.3 *
* 2.9730 0.4 *
* 3.5229 0.5 *
* mg/m3 = 0.1686 * V - 0.09856 *
**********************************/
// 计算粉尘浓度
float GP2Y10_Value(void)
{
GP2Y10_LED_ON();
SYSTICK_DelayUs(GP2Y10_SAMP_TIME);
float v = LIMIT(ADC_Value * 3.3f / 4095, 0.5846f, 3.5229f);
SYSTICK_DelayUs(GP2Y10_LEDON_TIME - GP2Y10_SAMP_TIME);
GP2Y10_LED_OFF();
SYSTICK_DelayUs(GP2Y10_PULSE_PERIOD - GP2Y10_LEDON_TIME);
return (v * 0.1686f - 0.09856f);
}
4、Sensor_Dust.h文件
#ifndef _SENSOR_DUST_H_
#define _SENSOR_DUST_H_
#include "stm32f0xx.h"
#define LIMIT(x, min, max) ( (x) < (min) ? (min) : ( (x) > (max) ? (max) : (x) ) ) // 限幅函数
#define GP2Y10_LED_ON() GPIO_ResetBits(GPIOA , GPIO_Pin_0) // 传感器LED灯开
#define GP2Y10_LED_OFF() GPIO_SetBits(GPIOA , GPIO_Pin_0) // 传感器LED灯关
#define GP2Y10_SAMP_TIME 280 // 传感器采样时间280us
#define GP2Y10_LEDON_TIME 320 // LED灯开持续时间
#define GP2Y10_PULSE_PERIOD 10000 // 传感器测量脉冲一个周期的时间
void GP2Y10_Init(void);
float GP2Y10_Value(void);
#endif
5、主函数
int main()
{
GP2Y10_Init(); // 传感器初始化
USART1_Init(); // 串口初始化
SYSTICK_Init(1); // 滴答定时器时间
while(1)
{
printf("Dust Concentration is :%f mg/m3\n",GP2Y10_Value()); // 计算粉尘浓度并通过串口打印
SYSTICK_DelayMs(50);
}
}