首页 > 其他分享 >STM32使用光敏传感器计算光照度Lux,而不是仅仅打印个电压值或者电阻值

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

时间:2023-01-11 17:35:30浏览次数:399  
标签:光照强度 DMA 光敏电阻 光照度 Lux STM32 lux 电阻值


最近项目中用到了光敏电阻。搜索资料,发现很多人都使用光敏电阻,只是用了AD读取了电压值,或者算出了电阻值,就发送给上位机或者服务器,美其名曰获取了光照度。

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

搜索一番,也没找到用光敏电阻计算Lux的方法,于是自己做了一些研究,分享一下。

 

计算光敏电阻值

相信STM32的ADC读者应该会用,教程也一抓一大把,在此不表。接下来先计算电阻值。我的光敏电阻电路图如下:

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

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

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

y/1500=5/(x+2500)

STM32的ADC精度为12位,则最大值为4096。采集到的AD值与电压成线性对应关系,系统中最高的电压值为3.3V的电源电压,它与4096对应。假设PA6感受到的电压y对应的AD值为z,则:

y/z=3.3/4096

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

x=10240000/(1.1×z)-2500

使用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;
}
}

现象是能够打印出光敏电阻值。

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

 

 

从电阻值到光照度

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

场所/环境

光照强度(lux)

场所/环境

光照强度(lux)

晴天室内

100~1000

办公室/教室

300~500

阴天室内

5~50

餐厅

10~30

月圆夜室外

0.2

距60W台灯60cm

300

精确测量光照强度是比较困难的一件事情,使用简陋的光敏电阻测量光照强度则精度更难以保障。本节的重点是解决问题的思路,如何用较简单的方法获取相对准确的光照度。配套电路板中使用的光敏电阻型号为GL5528,它的主要参数如表

项目

最大电压

最大功耗

环境温度

光谱峰值

10Lux时亮电阻

暗电阻

 

γ值

上升时间

下降时间

单位

V

mW

nm

0.6

ms

ms

GL5528

500

500

-30~+70

560

10~20

2

0.6

20

30

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

γ=lg⁡(R10/R100)

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

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

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

f(x)=(4e+0.4)×x^(-0.6021)

拟合过程如图。

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

 

 

编写代码算出光照度

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

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

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

//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的值。

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

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

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

关注公众号“yummy说电子”,后台回复关键字“光敏电阻”,获取配套源码、拟合数据与MATALAB代码。

 

标签:光照强度,DMA,光敏电阻,光照度,Lux,STM32,lux,电阻值
From: https://blog.51cto.com/u_12001544/6002420

相关文章

  • 从自定义的库函数到STM32官方标准库
      在​​上一节​​的基础上,进一步改写代码,再引入官方标注库函数。虽然官方标准库慢慢式微,有一些别的库可能会取代它,但是并不妨碍我们继续拿官方库来写代码,吸取里边好的写......
  • STM32掌机教程2,掌机的原理
    打地鼠的逻辑  打地鼠的逻辑很简单:我点亮某个LED,然后开始计时。如果在规定的时间内按下了LED对应的按键,那么加分,点亮下一个LED。按错按键,或者规定时间内没有按下,则减命,点......
  • STM32掌机教程3,工程模板与带灯按键测试
    我们需要“脚手架”  关于代码,我想体现出这么一个过程:我是如何一步一步修改代码的。我认为,从学习的角度来考虑,直接看最终的代码没有什么意义。写代码就像工人盖房子,盖房......
  • STM32自带GB2312字库显示汉字
      本文介绍如何把字库文件写入单片机的flash中,然后无需再提取字模,即可实现单片机显示中文字符的功能。下载字库到单片机flash中的指定位置  在​​上一篇博客​​中,最后......
  • STM32HAL库定时器中断关闭的方法
    本文可以用于解决这个问题:定时器中断上电后莫名其妙开启,或者首先触发一次。STM32HAL库在定时器初始化并开启以后,也是会默认开启中断。如不需要默认就开启中断可以用一下代......
  • HAL库教程2:使用STM32CubeMX新建一个工程
    安装STM32CubeMX  安装STM32CubeMX之前,电脑中要有java运行时环境(JRE),否则会报错:  双击JavaSetup8u201.exe即可安装JRE。在安装过程中,需要在线下载一些资源,所以应当保持......
  • HAL库教程1:STM32Cube的介绍
      使用STM32HAL库已经有了一段时间,觉得相比于标准库,好用了不少。加上STM32CubeMX图形化配置工具的加持,个人认为可以极大提升开发效率。其实关于HAL库的教程已经很多了,关于......
  • HAL库教程7:STM32的时钟系统
      STM32的时钟系统比较复杂,不像51单片机,可能只有一个时钟。原因:1、外设多,不同的外设有不同的时钟要求;2、功耗原因,速度越快,功耗越大,抗电磁干扰能力越弱。此处以STM32F405......
  • 进阶阶段——STM32学习笔记(一)
    进阶阶段——STM32学习笔记(1)前言由于套件放在学校,待等假期结束后才能做实验0STM32简介注意:STM32的标准工作电压为3.3V,若用5V供电,需要用(电平转换电路)稳压芯片降压至3.3......
  • STM32 - 中断
    1.中断定义(Event)中断(Interrupt):指当出现需要时,CPU暂时暂停当前程序的执行,转而执行处理新情况的程序的处理过程。即在程序运行过程中,系统出现了一个必须由CPU立即处理......