1、实验介绍
光照传感器用于检测光照强度,其工作原理是将检测光照强度值并将其转化为电压值,目前在智能家居,智慧城市,智慧农业,智慧工厂等物联网领域被大量使用。
本实验的主要结果是通过I2C总线控制光强度传感器AP3216C对环境光强度及物体接近情况进行测量并获取环境光强度及是否有物体靠近,然后通过OLED显示屏将读取到的光强度、接近程度、红外信息显示在HaaS EDU K1的屏幕上。
HaaS EDU K1搭载了丰富实用的传感器,开发者可以使用这些传感器针对实际场景需求开发自己的应用。
2、涉及的知识点
- AP3216C光照与接近传感器原理
- OLED绘图
3、实验准备
3.1、硬件
开发用电脑一台
HaaS EDU K1开发板一个 (开发板内置AP3216C传感器)
USB2TypeC 数据线一根
3.2、软件
"光照信息屏"功能已经包含在edu_demo应用中,并且包含在发布版本中。
3.2.1、固件版本
固件版本:V1.0.0
3.2.2、代码路径
git clone https://gitee.com/alios-things/AliOS-Things.git -b dev_3.1.0_haas
3.2.3、编译
进入代码的顶层目录如AliOS-Things进行编译。直接编译application/example/目录下的edu_demo应用。
两种方法进行编译
命令行方式
aos make distclean
aos make edu_demo@haaseduk1 -c config
aos make
AliOS Studio IDE方式
3.2.4、烧录
见开发环境章节
3.3、上手把玩
实验运行结果如下:
室内自然灯光下
用手机闪光灯照射屏幕上方的透明孔位
屏幕前没有遮挡情况下
拿物体靠近屏幕上方的透明孔位
3.4、实际应用场景(产品)介绍
目前光强度传感器及接近传感器在以下日常生活、工业生产等环境中都有非常广泛的应用。
- 家庭智能灯系统
检测到光强度低于一定亮度之后,触发信号控制客厅自动开灯
检测到光强度低于一定亮度之后,有人体靠近则自动打开夜灯/灯带
- 智能路灯
智慧路灯安装光强度传感器后可以自动的感知环境强度,从而做到智能开关,保证交通安全的同时节省了系统能源
- 智能手机/平板/电视等
智能手机、平板、电视等消费类电子需要感知环境光温度并根据环境光温度自动调节屏幕亮度,给使用者最佳的视觉体验的同时也降低了系统的功耗
智能手机上都存在的距离传感器还可以在通话过程中检测到听筒靠近头部的时候自动熄灭屏幕,防止误触碰
智能手机还会用距离传感器与其它感应器实现反转手机静音及解锁/锁屏等操作
这些是我们日常生活中最常见的几个应用场景。
光强度传感器是一种光电传感器,光电传感器拥有更广泛的应用范围,比如烟雾报警系统、工厂烟尘检测系统、条形码扫描仪、产品计数器、转速检测系统等等。
4、硬件介绍
4.1、电路原理图
AP3216芯片位于屏幕上方,是通过OLED扩展接口和HaaS EDU K1主板连接,最终连接到HaaS1000的I2C1通道。
4.2、AP3216C传感器介绍
AP3216C外观如下图
4.2.1、AP3216C芯片特性
- 7-bit地址模式,地址:0x1E
- 支持I2C接口Fast Mode (400kbps)
- 支持多种连续测量/单次测量及光强度、接近指标单独测试及组合测试
- 内置温度补偿电路
- 工作温度范围:-30°C到+80°C
- 光强度传感器
16-bit有效线性输出
4种动态可选范围
- 接近传感器
10-bit有效线性输出
4.2.2、AP3216C内部框图
AP3216C主要包含如下几部分。
- 光亮度敏感元件
- 接近度敏感元件
- ADC数模转换模块
- 内部逻辑控制电路(包含条件触发中断功能)
- I2C总线控制器
- 红外LED发射二极管
4.2.3、AP3216C工作模式
根据AP3216C的datasheet说明,在正常工作时,它共有3种工作模式:
- ALS模式
在这种模式下,AP3216C只对光强度进行量测 - PS+IR模式
在这种模式下,AP3216C只对接近程度进行量测 - ALS+PS+IR模式
在这种模式下,AP3216C会同时对光强度及接近程度进行量测
三种模式均支持单次量测也支持循环量测,其量测稳定时间如下:
4.2.4、AP3216C中断模式
AP3216C提供中断检测功能,MCU可以设定ALS及PS中断触发门限及持续时间阈值。在环境亮度及接近程度到达门限值后持续时间超出持续时间阈值之后,会向INT管脚发送中断通知MCU进行处理。
本案例中未使用中断模式。
4.2.5、AP3216C工作流程
AP3216C的典型工作流程如下:
对AP3226C进行复位之后,设定工作模式(连续/单次测量,ALS/PS/IR组合设定),之后等待硬件测量稳定时间,再发起读取测量值的过程。
其中,复位及模式设定是对AP3216C的System Configuration寄存器进行操作,datasheet中对System Configuration寄存器定义及描述如下:
- 复位操作
参考datasheet的描述,是通过I2C 向地址为0x00的寄存器写入0x4 (对应二进制的100)。
- 模式设定
ALS only连续测量模式:是通过I2C 向地址为0x00的寄存器写入0x4 (对应二进制的100)。
PS/IR only连续测量模式:是通过I2C 向地址为0x00的寄存器写入0x1 (对应二进制的001)。
ALS+PS/IR连续测量模式:是通过I2C 向地址为0x00的寄存器写入0x2 (对应二进制的010)。
ALS only单次测量模式:是通过I2C 向地址为0x00的寄存器写入0x5 (对应二进制的101)。
PS/IR only单次测量模式:是通过I2C 向地址为0x00的寄存器写入0x6 (对应二进制的110)。
ALS+PS/IR单次测量模式:是通过I2C 向地址为0x00的寄存器写入0x7 (对应二进制的111)。
- 读取测量结果
ALS、PS、IR值可以通过如下寄存器的值来获取。寄存器地址及所读取数值详细解析方法请参考下表:
4.2.6、ALS光强度解析
通过读取ALS数据寄存器(0x0C和0x0D)得到16bit的ADC count数据之后,需要根据ALS Configuration寄存器的ALS Gain栏位将ADC count数据根据芯片手册的说明转换成以lux为单位的亮度值。如下图所示:
4.2.7、PS/IR数据解析
PS Data寄存器详细定义如下:
PS 有效位数为10bit。
OBJ bit在有物体靠近的时候被设置成1,否则设置为0。
IR_OF bit被设置成1代表PS值无效(高强度红外光的情况下会出现)
IR数据有效位数同样为10bit,也有一个IR_OF来标识IR/PS数据是否有效。
AP3216C判断物体靠近和远离的动作是通过两组PS 高低阈值寄存器和PS Data寄存器进行比对,PS Data高于PS High Threshold之后,则判定为物体远离;PS Data低于PS Low Threshold之后,则视为物体靠近。
PS Low Threshold计算方法:Value(Reg_0x2B) * 4 + Value(Reg_0x2A)
PS High Threshold计算方法:Value(Reg_0x2D) * 4 + Value(Reg_0x2C)
4.2.8、PS中断模式说明
在开启了AP3216C的中断模式,为了避免靠近物体抖动带来频繁触发中断的情况,在PS Data高于PS High Threashold或低于PS Low Threshold之后,需要等待一个PS persist时间,如果PS persist时间之内,PS Data状态没有发生变化,则触发中断。
PS Persist的时间可以通过配置PS Configuration寄存器的bit 0:1。
4.3、OLED显示屏介绍
OLED在电场的作用下,阳极产生的空穴和阴极产生的电子就会发生移动,分别向空穴传输层和电子传输层注入,迁移到发光层。当二者在发 光层相遇时,产生能量激子,从而激发发光分子最终产生可见光。
OLED驱动芯片的详细说明请参考“OLED”章节中的描述。
4.4、I2C总线技术
HaaS EDU K1上AP3216C和HaaS1000通过I2C1接口进行通信。
I2C总线是飞利浦公司在80年代为了让CPU可以连接低速周边设备而设计的。外接传感器是I2C总线最典型的应用场景。目前I2C Spec已经发展到了6.0版本。可以通过https://www.nxp.com.cn/docs/en/user-guide/UM10204.pdf进行下载
I2C采用多主从结构,I2C主设备基于地址对I2C从设备进行寻址,采用8-bit数据传输模式,支持7-bit/10-bit地址模式。I2C总线对I2C传输开始/结束/数据传输/ACK机制/时钟同步/冲突仲裁等进行了详细的定义。这里就不再赘述。
5、软件介绍
HaaS EDU K1的edk_demo 应用程序中包含多个应用案例,所有的案例软件设计都遵循HaaS EDK应用架构的设计思想。其设计思想可以参考“HaaS EDK主系统框架”中的“添加新应用”小节的说明。
简单来说,所有的子应用页面都需要实现MENU_TYP结构体。
光照信息屏应用代码位于:appliciation/example/edu_demo/k1_apps/light_meter/light_meter.c中。
MENU_TYP lightmeter = {
"lightmeter",
&lightmeter_cover,
&lightmeter_tasks,
NULL,
&lightmeter_child_list};
在HaaS EDU K1上电之后,按K1或K2键左右切换应用的时候,如果切换到光照信息屏页面再到退出该页面的过程中,lightmeter下面的API会依此被呼叫:
- lightmeter_init
- lightmeter_uninit
5.1、软件流程
软件流程图如下所示。
在进入光照信息屏页面后,启动名为lightmeter_task的task,周期性的读取ALS/PS/IR数据并判断物体靠近标志之后将相关数据按照一定的规则打印到OLED屏幕上。
5.2、代码实现
5.2.1、光照信息屏页面
代码位置:appliciation/example/edu_demo/k1_apps/light_meter/light_meter.c
详细代码及注释如下:
#include <stdio.h>
#include <stdlib.h>
#include "lightmeter.h"
#include "aos/kernel.h"
#include "ap3216c.h"
MENU_COVER_TYP lightmeter_cover = {MENU_COVER_NONE};
MENU_TASK_TYP lightmeter_tasks = {
lightmeter_init,
lightmeter_uninit};
MENU_LIST_TYP lightmeter_child_list = {NULL, 0};
MENU_TYP lightmeter = {
"lightmeter",
&lightmeter_cover,
&lightmeter_tasks,
NULL,
&lightmeter_child_list};
int lightmeter_init(void)
{
printf("lightmeter_init begin\n");
ap3216c_init();
printf("lightmeter_init done\n");
OLED_Clear();
OLED_Refresh_GRAM();
aos_task_new("lightmeter_task", lightmeter_task, NULL, 1000);
printf("aos_task_new lightmeter_task \n");
return 0;
}
void lightmeter_task(void)
{
uint16_t tmp[3];
uint8_t als[20];
uint8_t ps[20];
uint8_t ir[20];
while (1)
{
tmp[0] = ap3216c_read_ambient_light();
tmp[1] = ap3216c_read_ir_data();
tmp[2] = ap3216c_read_ps_data();
sprintf(als, "ALS: %d", tmp[0]);
sprintf(ir, "IR : %d", tmp[1]);
OLED_Clear();
OLED_Icon_Draw(20, 14, &icon_lighter_32_32, 0);
OLED_Show_String(64, 6, als, 12, 1);
OLED_Show_String(64, 20, ir, 12, 1);
if ((tmp[2] >> 15) & 1)
OLED_Show_String(64, 36, "near !", 16, 1);
else
OLED_Show_String(64, 40, "far !", 16, 1);
OLED_Icon_Draw(2, 24, &icon_skip_left, 0);
OLED_Icon_Draw(122, 24, &icon_skip_right, 0);
OLED_Refresh_GRAM();
aos_msleep(150);
}
}
int lightmeter_uninit(void)
{
aos_task_delete("lightmeter_task");
printf("aos_task_delete lightmeter_task \n");
return 0;
}
5.2.2、AP3216C驱动
代码位置:components/peripherals/sensor/drv/drv_als_ps_ir_liteon_ap3216c.c
以ap3216C初始化和读取ALS数值为例,详细代码及注释如下:
void ap3216c_init(void)
{
#if 1
i2c_dev.port = 1;
i2c_dev.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT;
i2c_dev.config.freq = I2C_BUS_BIT_RATES_100K;
i2c_dev.config.mode = I2C_MODE_MASTER;
i2c_dev.config.dev_addr = AP3216C_ADDR;
hal_i2c_init(&i2c_dev);
#endif
reset_sensor();
aos_msleep(100);
ap3216c_set_param(AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS);
aos_msleep(150); // delay at least 150ms
ap3216c_int_Config();
ap3216c_int_init();
}
uint16_t ap3216c_read_ambient_light(void)
{
uint16_t brightness = 0; // default error data
uint16_t read_data;
uint8_t range;
read_data = (uint16_t )read_low_and_high(AP3216C_ALS_DATA_L_REG, 1);
ap3216c_get_param(AP3216C_ALS_RANGE, &range);
if (range == AP3216C_ALS_RANGE_20661)
{
brightness = 0.36 * read_data; //sensor ambient light converse to reality
}
else if (range == AP3216C_ALS_RANGE_5162)
{
brightness = 0.089 * read_data; //sensor ambient light converse to reality
}
else if (range == AP3216C_ALS_RANGE_1291)
{
brightness = 0.022 * read_data; //sensor ambient light converse to reality
}
else if (range == AP3216C_ALS_RANGE_323)
{
brightness = 0.0056 * read_data; //sensor ambient light converse to reality
}
return brightness;
}
static uint32_t read_low_and_high(uint8_t reg, uint8_t len)
{
uint32_t data;
uint8_t buf = 0;
read_regs( reg, len, &buf); // 读低字节
data = buf;
read_regs( reg + 1, len, &buf); // 读高字节
data = data + (buf << len * 8); // 合并数据
return data;
}
static void read_regs(uint8_t reg, uint8_t len, uint8_t *buf)
{
hal_i2c_mem_read(&i2c_dev, i2c_dev.config.dev_addr, reg, 1, buf, len, 100);
}
这里的hal_i2c_mem_read的实现和AP3216C datasheet上面读取寄存器的描述相匹配。
- MCU I2C 主设备先将寄存器地址通过I2C写操作发给AP3216C从设备
- MCUI2C 主设备发起读操作从AP3216C从设备读取寄存器的值
AP3216C寄存器读取的整个I2C传输过程中,详细数据传输过程如下图所示:
读取AP3216C的PS和IR寄存器的过程和读取ALS的过程中I2C的传输过程完全一致,这里就不再赘述。
6、开发者技术支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/