资讯详情

STM32使用光敏传感器计算光照度Lux,而不是仅仅打印个电压值或者电阻值

最近在项目中使用了光敏电阻。搜索资料,发现很多人只使用光敏电阻。AD读取电压值或计算电阻值后,发送给上位机或服务器,称为获得光照度。

搜索,也没有找到用光敏电阻计算Lux所以我做了一些研究来分享。

计算光敏电阻值

相信STM32的ADC读者应该能够使用,教程也很多,这里没有表。接下来,计算电阻值。我的光敏电阻电路图如下:

其中PA6接单片机AD采集引脚,最大只能输入3.6V光敏电阻的电压为5V,所以设计了R1与R保证两个分压电阻PA6的电压不超过3.6V。

光敏电阻的电阻值为xΩ,PA6的电压为y,以下公式:

STM32的ADC精度为12位,最大值为4096。收集到的AD系统中最高电压值为3.3V与4096对应的电源电压。PA6感觉到电压y对应的电压AD值为z,则:

联立两式,消去y,获得关于x的表达式:

使用ADC得到z后,光敏电阻的值可以根据上面的公式计算。

使用了我的代码DMA获取多通道AD取100个数据计算平均值滤波器,然后打印电阻值代码如下:

//main.c  main()   while (1)   {     if(DMA_Flag)     {       for(int i=0;i<ADC_CHANNEL_CNT;i  )         printf("CH%d value = %d \n",i 2,ADC1_AVG_Buf[i] );       uint32_t PhotoResistor = (uint32_t)(10240000/(1.1*ADC1_AVG_Buf[4]) - 2500);       ////串口打印采样结果       printf("The AD value is %d,the PhotoResistor is %d .\r\n",ADC1_AVG_Buf[4],PhotoResistor);       printf("The DMA count is %d .\r\n",DMA_CNT);       DMA_Flag = 0;     }   } 

光敏电阻值可以打印出来。

从电阻值到光照度

光敏电阻的电阻值以前已经计算过,可以分为光强度等级,但光强度仍然无法计算。光强是指单位面积上接受可见光的能量,简称照明和单位勒克斯(Lux或lx)。常见环境的光强值如表所示

场所/环境

光照强度(lux)

场所/环境

光照强度(lux)

晴天室内

100~1000

办公室/教室

300~500

阴天室内

5~50

餐厅

10~30

月圆夜室外

0.2

距60W台灯60cm

300

准确测量光强度是一件困难的事情,使用简单的光敏电阻来测量光强度更难保证。本节的重点是解决问题的想法,以及如何以更简单的方法获得相对准确的光照度。支撑电路板中使用的光敏电阻型号为,其主要参数如表所示

项目

最大电压

最大功耗

环境温度

光谱峰值

10Lux时亮电阻

暗电阻

γ值

上升时间

下降时间

单位

V

mW

nm

0.6

ms

ms

GL5528

500

500

-30~ 70

560

10~20

2

0.6

20

30

其中的γ值表示10Lux电阻值与100Lux对比电阻值。

将γ=0.6带入,可得R10/R100≈4。即R10=4×R100,对于R10与R1关系仍成立:R1=4×R10。手册中给出了一个对数坐标系的图,光照强度与Lux的对应关系并非一条直线,而是一个范围。为了简便计算,取范围中稍微靠下的一条直线,直线中包含(1,40),(10,10),(100,2.5)这三个点。

手册中给出的1到100范围太小了,常用光照度可到达1000Lux,因此要通过现有的关系推算出光照度与电阻值的关系式。虽然看上去光照度与电阻值的对应关系是一条直线,但是要注意坐标系是对数坐标系,不能套用一元一次方程。在MATLAB中拟合,拟合过程如图7-19所示。可得关系式为:

拟合过程如图。

 

 

编写代码算出光照度

在单片机内,用带指数的关系式计算,计算速度会很慢。可以使用查表法,无需计算,只遍历数组得到结果。根据拟合得到的函数,可以推导出Lux从1到1000,各自对应的电阻值,共1000对。观察数据,可以发现在Lux比较大的时候,对应的电阻值过于接近。此处仅要求粗略计算,无需这么多数据。将电阻值的个位数舍去,并删除重复电阻值,可得到281对数据。

定义新的结构体数据如下。

  //ADC.h
typedef struct
{
  unsigned short ohm;   //光敏电阻值
  unsigned short lux;   //流明
}PhotoRes_TypeDef;
//ADC.c
//GL5528光敏电阻的阻值与流明对应的关系
const  PhotoRes_TypeDef GL5528[281]=
{
{40000, 1},{26350, 2},{20640, 3},{17360, 4},{15170, 5},
{13590, 6},{12390, 7},{11430, 8},{10650, 9},{9990, 10},
{9440, 11},{8950, 12},{8530, 13},{8160, 14},{7830, 15},
......
{720, 773},{710, 791},{700, 809},{690, 829},{680, 849},
{670, 869},{660, 891},{650, 914},{640, 937},{630, 961},
{620, 987},
};


当得到电阻值以后,遍历数据,算出光照度,代码如下。

//ADC.c
/**
  * @brief 通过电阻值算出光照度
  * @param 光敏电阻值
  * @retval None
  */    
unsigned short GetLux(uint32_t PhotoResistor)
{
  unsigned short lux = 0;
  //查表法,根据电阻值得出光照度
  for(int i = 0 ; i < 281 ; i++)
  {
    if (PhotoResistor > GL5528[i].ohm)
    {
      lux = GL5528[i].lux;
      break;
    }
  }
  return lux;
}

主函数中,打印光照度:

//main.c main() while(1)
    if(DMA_Flag)
    {
      unsigned short lux = 0;
      for(int i=0;i<ADC_CHANNEL_CNT;i++)
        printf("CH%d value = %d \n",i+2,ADC1_AVG_Buf[i] );
      uint32_t PhotoResistor = (uint32_t)(10240000/(1.1*ADC1_AVG_Buf[4]) - 2500);
      //从电阻值计算光照度
      lux = GetLux(PhotoResistor);
      //串口打印采样结果
      printf("The AD value is %d,the PhotoResistor is %d .\r\n",ADC1_AVG_Buf[4],PhotoResistor);
      printf("The Lux is %d .\r\n",lux);
      printf("The DMA count is %d .\r\n",DMA_CNT);
      DMA_Flag = 0;
    }


下载程序,观察现象,应该看到如图7-19所示的现象,说明算出了Lux的值。

当然,这个计算结果也不会很精确,毕竟光照度与电阻的关系也不是一一对应的。聊胜于无吧。

 

标签: 12v光敏传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台