夏普GP2Y1010AU0F灰尘传感器在STM32平台上的使用

夏普GP2Y1010AU0F灰尘传感器STM32平台上的使用

一、传感器的概述

   GP2Y1010AUOF是日本夏普公司开发的一款光学灰尘浓度检测传感器。此传感器内部成对角分布的红外发光二极管和光电晶体管,利用光敏原理来工作。用于检测特别细微的颗粒,如香烟颗粒、细微灰尘。依靠输出脉冲的高度来判断颗粒浓度。

 


二、传感器的一些参数 

   

     

 

  

三、传感器的工作原理

 

                                                         图(1

                      

                                                            图(2

       夏普GP2Y1010AU0F灰尘传感器价格较便宜,能检测出室内空气中的灰尘和烟尘含量.并不能测出所谓的PM2.5浓度,然而现在市面上有好多红外发光二极管的传感器都称自己是PM2.5传感器,能测PM2.5的值,其实并不是,真正能测PM2.5浓度的是那种上百的激光传感器,这种红外的连PM10都测不了,只能用来玩玩,或者大概描述空气质量的等级而已,经我多次实验,发现这传感器显示的灰尘浓度与网上公布的AQI空气质量指数比较接近,跟真实的PM2.5浓度有很大的区别,这测出的灰尘浓度其实就是所有不同直径的颗粒物总和,里面包含了PM1.0,PM2.5,PM10

     其原理如2所示,传感器中心有个洞可以让空气自由流过,定向发射LED光,通过检测经过空气中灰尘折射过后的光线来判断灰尘的含量。


四、传感器与STM32的连接

 

  注:把图中的430单片机直接换成STM32就行,接线顺序跟电阻、电容的大小都不变

     在这里简单地说一下,为什么要这样接? 

1. 电阻R1和电容C1:因为V-LED和LED-GND是给红外发光二极管供电的,所以不能直接接上5V,需要串一个150欧的电阻来限流,另外为了稳定供电,还需要在给发光二极管供电的正极和负极上并一个220uf的电容。

2. 三极管:可以增加LED的驱动能力(建议加上,加上后比较稳定)

3. 电阻R2:起到限流作用,因为该传感器的最大工作电流为20mA

4. 电阻R3和R4:起分压作用(因为该传感器是5V供电,而32单片机的AD采样最大电压为3.3V)

5. 上图中的P1.2为脉冲输入脚,为传感器提供输入信号(该PWM的占空比规定为0.032)

6. 上图中的P6.5为单片机的ADC模拟输入脚,用来输出信号的

                                                   

   

                        (图1                                                                (图2

  1为脉冲输入波形,周期为10ms,高电平为0.32ms

  2为AD采样时序,由图可知,在输入上升沿到输出的峰值,时间为280us左右,就在此时进行采样,因为整个高电平持续的时间为320us,所以在打开红外发光二极管280us后采样,然后延时40us后关闭红外发光二极管,最后再延时9680us(输入波形的周期为10ms),这就实现了一次完整的工作

 

                  数据手册上面有关电压值与灰尘浓度的关系比例图

         

    由图可知,该曲线在前半部分是有一定的斜率的,大约到0.6mg/m3左右,该曲线不再增长,此时输出的电压最大为3.6V左右,但是在曲线的前半部分,是可以得出电压值与灰尘浓度的关系:Dust density = 0.17 * Output Voltage  

 

  根据技术手册可知,当空气洁净的时候,Vo的范围是0~1.5V,典型值是0.9V

      

     当空气灰尘浓度很高的时候,Vo的数值3.6V。但是该传感器输出的最大电压为3.6V,所以当灰尘浓度再增加时,我们这款传感器已经测不出了


    0.9V表示空气洁净,3.6V表示空气灰尘很多。由于空气中不可能一点灰尘都没有,所以取个正常值0.9V,换成灰尘浓度就是0.053mg/m3

当达到最大电压值3.6V时,此时的灰尘浓度为0.512mg/m3
所以我们这个传感器的范围就是0~512ug/m3这个512只是一个估算大约的值,实际情况中还是有可能超出这值的


五、主要的程序代码

 

Main.c

 

#include "stm32f10x.h"

#include "bsp_SysTick.h"

#include "bsp_usart1.h"

#include "bsp_GP2Y.h"

#include "bsp_pwm_output.h"

#include "bsp_TiMbase.h" 

#define FILTER_N 7

 

int  A[32];

volatile u32 time = 0; // ms 计时变量

 

void Delay(__IO uint32_t nCount)

{

  for(; nCount != 0; nCount--);

}

voidTIM3_Configuration(void);

void  TIM3_NVIC_Configuration(void);

 

int main(void)

{

float  calcVoltage ;

int  filter_sum, i ,j ,dust;

int filter_max, filter_min;

int filter_buf[FILTER_N];

 

SysTick_Init();

USART1_Config();

TIM3_Configuration();

TIM3_NVIC_Configuration();

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);

Adc_Init();

TIM3_PWM_Init();

 

Delay_ms(200);  //等待传感器稳定工作//

 while(1)

 {

   if(time==200)    //10ms发生一次中断,等到中断200次后,即2s//

     {

      time=0;

      for(i = 0; i < FILTER_N; i++)

    {

      GP2Y_Low;                //打开红外二极管//

      Delay_us(280);            //延时280us//  

     filter_buf[i]=Get_Adc(ADC_Channel_10);    //采样,读取AD值//  

     Delay_us(19);           //延时19us,因为这里我设了AD采样的周     期为239.5,所以AD转换一次需耗时21us,19加21再加280刚好是320us,这跟上面说的高电平持续的时间为0.32ms//

     GP2Y_High;             //关闭红外二极管//

    Delay_us(9680);         //延时9680us//

   }

          filter_max = filter_buf[0];

          filter_min = filter_buf[0];

          filter_sum = filter_buf[0];

     for(i = FILTER_N - 1; i > 0; i--)

  {

    if(filter_buf[i] > filter_max)

      filter_max=filter_buf[i];

     else if(filter_buf[i] < filter_min)

      filter_min=filter_buf[i];

      filter_sum = filter_sum + filter_buf[i];

      filter_buf[i] = filter_buf[i - 1];

     }

       i = FILTER_N - 2;

      filter_sum = filter_sum - filter_max - filter_min + i/2;          //加上i/2是为了四舍五入//

      filter_sum = filter_sum / i;

      calcVoltage=filter_sum*(3.3/ 4096)*2;   /因为上面采集到的是AD值,这里要把它转换为电压值//

  注:为什么我在公式的最后要乘以2呢?这个2是一定不能少的,因为我们将它与32单片机连接的时候,加了两个10K的电阻分压,读取到的电压值已减小了一半,但这不是实际采取到的电压,所以要在最后乘以2返回原来的电压值)

     dust=(0.17*calcVoltage-0.1)*1000;  //乘以1000单位换成ug/m3//

     if (dust<0)

      dust=0;            //限位//

     if (dust>500)        

      dust=500;

      printf("\r\n电压值:%fV\n",calcVoltage);

     printf("\r\n灰尘浓度:%dug/m3\n",dust);

 }

 }

}

以上就是主要的一些程序,由于该传感器不太稳定,输出波形抖动较大,所以在程序里我加上了数字滤波算法,我采用那种去极值取平均的中位值滤波法,在传感器工作一次时,取输出波形的连续几个的峰值,存到数组里,然后进行去掉最大值,最小值的操作,剩下的取平均

 

 六、实际操作

 

 实物连接图如下:

                                                                     

 

 把程序烧进单片机,观察其输出的值

                                  

   对比右图可知,一般室内的灰尘浓度所对应的电压值都是0.9V左右

    

 再对比一下网上公布的空气指数

 

 

对比可知,该传感器测出的值与网上公布的AQI指数比较接近

 

  我们再来看看这输入波形和输出波形

 

 

 

 

     黄色的是输入波形,蓝色的是输出波形

  (注:这图像上显示的电压值是分压后的)

   当我往传感器的中心孔里放根杜邦线时,可以看到其输出波形立马飙升,说明这传感器还是挺灵敏的

          

 

 

    当往孔里插根杜邦线或者一支笔时,测出的值立马到达最大值3.6V左右,这是对颗粒物的灵敏度,对于烟雾类型的也很敏感,我利用电烙铁焊锡时产生的烟雾,经传感器测量也能到达最大值,显示的灰尘浓度达530ug/m3.

    由于这传感器的内部存有空隙,所以当你外加烟雾给它时,会有少量的烟雾残留在内部的空隙里,才会出现为什么我把烟雾撤去之后,显示的浓度依然很大,这时你需往孔里吹口气,将里面残留的烟雾吹走,这时才恢复你室内正常的浓度,否则的话,你得等待一段时间,待里面的烟雾慢慢散去.

猜你喜欢

转载自blog.csdn.net/qq_38021919/article/details/78764764