1@page lightmeter 光照信息屏 2# 实验整体介绍 3## 背景 4光照传感器用于检测光照强度,其工作原理是将检测光照强度值并将其转化为电压值,目前在智能家居,智慧城市,智慧农业,智慧工厂等物联网领域被大量使用。 5本实验的主要结果是通过I2C总线控制光强度传感器AP3216C对环境光强度及物体接近情况进行测量并获取环境光强度及是否有物体靠近,然后通过OLED显示屏将读取到的光强度、接近程度、红外信息显示在HaaS EDU K1的屏幕上。 6HaaS EDU K1搭载了丰富实用的传感器,开发者可以使用这些传感器针对实际场景需求开发自己的应用。 7 8## 涉及的知识点 9* AP3216C光照与接近传感器原理 10* OLED绘图 11 12 13# 开发环境准备 14## 硬件 15 开发用电脑一台 16 HAAS EDU K1 开发板一块 17 USB2TypeC 数据线一根 18 19## 软件 20### AliOS Things开发环境搭建 21 开发环境的搭建请参考 @ref HaaS_EDU_K1_Quick_Start (搭建开发环境章节),其中详细的介绍了AliOS Things 3.3的IDE集成开发环境的搭建流程。 22 23### HaaS EDU K1 DEMO 代码下载 24 HaaS EDU K1 DEMO 的代码下载请参考 @ref HaaS_EDU_K1_Quick_Start (创建工程章节),其中, 25 选择解决方案: 基于教育开发板的示例 26 选择开发板: haaseduk1 board configure 27 28### 代码编译、烧录 29 参考 @ref HaaS_EDU_K1_Quick_Start (3.1 编译工程章节),点击 ✅ 即可完成编译固件。 30 参考 @ref HaaS_EDU_K1_Quick_Start (3.2 烧录镜像章节),点击 "⚡️" 即可完成烧录固件。 31 32 33 34## 上手把玩 35实验运行结果如下: 361. 室内自然灯光下: 37 38 39<div align=center> 40 <img src="https://img.alicdn.com/imgextra/i2/O1CN01DYmUrt1LmDnLgN4a4_!!6000000001341-2-tps-1200-800.png" style="zoom:50%;" /> 41</div> 42 43 442. 用手机闪光灯照射屏幕上方的透明孔位 45 46 47<div align=center> 48 <img src="https://img.alicdn.com/imgextra/i2/O1CN01ZoZ2AI1RA6WahQENe_!!6000000002070-2-tps-1200-800.png" style="zoom:50%;" /> 49</div> 50 51 523. 屏幕前没有遮挡情况下 53 54 55<div align=center> 56 <img src="https://img.alicdn.com/imgextra/i4/O1CN01qmbhY627OUpqxiQLw_!!6000000007787-2-tps-1200-800.png" style="zoom:50%;" /> 57</div> 58 59 604. 拿物体靠近屏幕上方的透明孔位 61 62 63<div align=center> 64 <img src="://img.alicdn.com/imgextra/i4/O1CN01vKgrup1kunbe8wGgJ_!!6000000004744-2-tps-1200-800.png" style="zoom:50%;" /> 65</div> 66 67 68## 实际应用场景(产品)介绍 69目前光强度传感器及接近传感器在以下日常生活、工业生产等环境中都有非常广泛的应用。 70* 家庭智能灯系统 71 * 检测到光强度低于一定亮度之后,触发信号控制客厅自动开灯 72 * 检测到光强度低于一定亮度之后,有人体靠近则自动打开夜灯/灯带 73* 智能路灯 74 * 智慧路灯安装光强度传感器后可以自动的感知环境强度,从而做到智能开关,保证交通安全的同时节省了系统能源 75* 智能手机/平板/电视等 76 * 智能手机、平板、电视等消费类电子需要感知环境光温度并根据环境光温度自动调节屏幕亮度,给使用者最佳的视觉体验的同时也降低了系统的功耗 77 * 智能手机上都存在的距离传感器还可以在通话过程中检测到听筒靠近头部的时候自动熄灭屏幕,防止误触碰 78 * 智能手机还会用距离传感器与其它感应器实现反转手机静音及解锁/锁屏等操作 79 80这些是我们日常生活中最常见的几个应用场景。 81光强度传感器是一种光电传感器,光电传感器拥有更广泛的应用范围,比如烟雾报警系统、工厂烟尘检测系统、条形码扫描仪、产品计数器、转速检测系统等等。 82 83# 硬件介绍 84## 电路原理图 85AP3216芯片位于屏幕上方,是通过OLED扩展接口和HaaS EDU K1主板连接,最终连接到HaaS1000的I2C1通道。 86 87 88<div align=center> 89 <img src="https://img.alicdn.com/imgextra/i2/O1CN013xnlcx1e1wTNimju3_!!6000000003812-2-tps-264-360.png" style="zoom:50%;" /> 90</div> 91 92 93## AP3216C传感器 94### AP3216C外观 95 96 97<div align=center> 98 <img src="https://img.alicdn.com/imgextra/i2/O1CN01w1xpIr1SPVSjxM5Ck_!!6000000002239-2-tps-514-468.png" style="zoom:50%;" /> 99</div> 100 101 102### AP3216C芯片特性 103* 7-bit地址模式,地址:0x1E 104* 支持I2C接口Fast Mode (400kbps) 105* 支持多种连续测量/单次测量及光强度、接近指标单独测试及组合测试 106* 内置温度补偿电路 107* 工作温度范围:-30°C到+80°C 108* 光强度传感器 109 16-bit有效线性输出 110 4种动态可选范围 111 * 接近传感器 112 10-bit有效线性输出 113 114### AP3216C内部框图 115AP3216C主要包含如下几部分。 1161. 光亮度敏感元件 1172. 接近度敏感元件 1183. ADC数模转换模块 1194. 内部逻辑控制电路(包含条件触发中断功能) 1205. I2C总线控制器 1216. 红外LED发射二极管 122 123 124<div align=center> 125 <img src="https://img.alicdn.com/imgextra/i4/O1CN01NZKskY1MYlmDMNUVd_!!6000000001447-2-tps-1482-754.png" style="zoom:50%;" /> 126</div> 127 128 129### AP3216C工作模式 130根据AP3216C的datasheet说明,在正常工作时,它共有3种工作模式: 1311. ALS模式 132在这种模式下,AP3216C只对光强度进行量测 1332. PS+IR模式 134在这种模式下,AP3216C只对接近程度进行量测 1353. ALS+PS+IR模式 136在这种模式下,AP3216C会同时对光强度及接近程度进行量测 137 138三种模式均支持单次量测也支持循环量测,其量测稳定时间如下: 139 140 141<div align=center> 142 <img src="https://img.alicdn.com/imgextra/i1/O1CN01cEXBbo1F4MASlldqn_!!6000000000433-2-tps-1536-306.png" style="zoom:50%;" /> 143</div> 144 145 146### AP3216C中断模式 147AP3216C提供中断检测功能,MCU可以设定ALS及PS中断触发门限及持续时间阈值。在环境亮度及接近程度到达门限值后持续时间超出持续时间阈值之后,会向INT管脚发送中断通知MCU进行处理。 148本案例中未使用中断模式。 149 150### AP3216C工作流程 151AP3216C的典型工作流程如下: 152 153 154<div align=center> 155 <img src="https://img.alicdn.com/imgextra/i3/O1CN01uNp0mF1aUYl0COe4D_!!6000000003333-2-tps-726-576.png" style="zoom:50%;" /> 156</div> 157 158 159对AP3226C进行复位之后,设定工作模式(连续/单次测量,ALS/PS/IR组合设定),之后等待硬件测量稳定时间,再发起读取测量值的过程。 160其中,复位及模式设定是对AP3216C的System Configuration寄存器进行操作,datasheet中对System Configuration寄存器定义及描述如下: 161 162 163<div align=center> 164 <img src="https://img.alicdn.com/imgextra/i2/O1CN01EuhLeU1vxViwX7u1p_!!6000000006239-2-tps-1532-408.png" style="zoom:50%;" /> 165</div> 166 167 168* 复位操作 169参考datasheet的描述,是通过I2C 向地址为0x00的寄存器写入0x4 (对应二进制的100)。 170 171* 模式设定 172ALS only连续测量模式:是通过I2C 向地址为0x00的寄存器写入0x4 (对应二进制的100)。 173PS/IR only连续测量模式:是通过I2C 向地址为0x00的寄存器写入0x1 (对应二进制的001)。 174ALS+PS/IR连续测量模式:是通过I2C 向地址为0x00的寄存器写入0x2 (对应二进制的010)。 175ALS only单次测量模式:是通过I2C 向地址为0x00的寄存器写入0x5 (对应二进制的101)。 176PS/IR only单次测量模式:是通过I2C 向地址为0x00的寄存器写入0x6 (对应二进制的110)。 177ALS+PS/IR单次测量模式:是通过I2C 向地址为0x00的寄存器写入0x7 (对应二进制的111)。 178 179* 读取测量结果 180ALS、PS、IR值可以通过如下寄存器的值来获取。寄存器地址及所读取数值详细解析方法请参考下表: 181 182 183<div align=center> 184 <img src="https://img.alicdn.com/imgextra/i1/O1CN01DSpQfM1To4JlpTvK3_!!6000000002428-2-tps-1522-834.png" style="zoom:50%;" /> 185</div> 186 187 188### ALS光强度解析 189 190通过读取ALS数据寄存器(0x0C和0x0D)得到16bit的ADC count数据之后,需要根据ALS Configuration寄存器的ALS Gain栏位将ADC count数据根据芯片手册的说明转换成以lux为单位的亮度值。如下图所示: 191 192 193<div align=center> 194 <img src="https://img.alicdn.com/imgextra/i1/O1CN01kRjroj24kX2lSRoU3_!!6000000007429-2-tps-1546-640.png" style="zoom:50%;" /> 195</div> 196 197 198### PS/IR数据解析 199PS Data寄存器详细定义如下: 200- PS 有效位数为10bit。 201- OBJ bit在有物体靠近的时候被设置成1,否则设置为0。 202- IR_OF bit被设置成1代表PS值无效(高强度红外光的情况下会出现) 203 204 205<div align=center> 206 <img src="https://img.alicdn.com/imgextra/i3/O1CN017IDLnb20pn7tOeDN1_!!6000000006899-2-tps-1522-834.png" style="zoom:50%;" /> 207</div> 208 209 210IR数据有效位数同样为10bit,也有一个IR_OF来标识IR/PS数据是否有效。 211 212 213<div align=center> 214 <img src="https://img.alicdn.com/imgextra/i1/O1CN01LpyTnk1Kq3Ubov7q8_!!6000000001214-2-tps-1546-640.png" style="zoom:50%;" /> 215</div> 216 217 218AP3216C判断物体靠近和远离的动作是通过两组PS 高低阈值寄存器和PS Data寄存器进行比对,PS Data高于PS High Threshold之后,则判定为物体远离;PS Data低于PS Low Threshold之后,则视为物体靠近。 219- PS Low Threshold计算方法:Value(Reg_0x2B) * 4 + Value(Reg_0x2A) 220- PS High Threshold计算方法:Value(Reg_0x2D) * 4 + Value(Reg_0x2C) 221 222 223<div align=center> 224 <img src="https://img.alicdn.com/imgextra/i1/O1CN01Xy2jsE1mgGGW09e5J_!!6000000004983-2-tps-1520-686.png" style="zoom:50%;" /> 225</div> 226 227 228<div align=center> 229 <img src="https://img.alicdn.com/imgextra/i4/O1CN01DHGoEZ1jt8YHQelbL_!!6000000004605-2-tps-1536-430.png" style="zoom:50%;" /> 230</div> 231 232 233<div align=center> 234 <img src="https://img.alicdn.com/imgextra/i1/O1CN01q0rVZC1rEqdf7JXre_!!6000000005600-2-tps-1516-180.png" style="zoom:50%;" /> 235</div> 236 237 238### PS中断模式说明 239在开启了AP3216C的中断模式,为了避免靠近物体抖动带来频繁触发中断的情况,在PS Data高于PS High Threashold或低于PS Low Threshold之后,需要等待一个PS persist时间,如果PS persist时间之内,PS Data状态没有发生变化,则触发中断。 240 241 242<div align=center> 243 <img src="https://img.alicdn.com/imgextra/i3/O1CN01llCSS51OmczflBnIS_!!6000000001748-2-tps-1452-492.png" style="zoom:50%;" /> 244</div> 245 246 247PS Persist的时间可以通过配置PS Configuration寄存器的bit 0:1。 248 249 250<div align=center> 251 <img src="https://img.alicdn.com/imgextra/i1/O1CN01Xy2jsE1mgGGW09e5J_!!6000000004983-2-tps-1520-686.png" style="zoom:50%;" /> 252</div> 253 254 255 256## I2C总线技术 257HaaS EDU K1上AP3216C和HaaS1000通过I2C1接口进行通信。 258I2C总线是飞利浦公司在80年代为了让CPU可以连接低速周边设备而设计的。外接传感器是I2C总线最典型的应用场景。目前I2C Spec已经发展到了6.0版本。可以通过https://www.nxp.com.cn/docs/en/user-guide/UM10204.pdf 进行下载 259I2C采用多主从结构,I2C主设备基于地址对I2C从设备进行寻址,采用8-bit数据传输模式,支持7-bit/10-bit地址模式。I2C总线对I2C传输开始/结束/数据传输/ACK机制/时钟同步/冲突仲裁等进行了详细的定义。这里就不再赘述。 260 261# 软件介绍 262HaaS EDU K1的edk_demo 应用程序中包含多个应用案例,所有的案例软件设计都遵循HaaS EDK应用架构的设计思想。其设计思想可以参考“HaaS EDK主系统框架”中的“添加新应用”小节的说明。 263简单来说,所有的子应用页面都需要实现MENU_TYP结构体。 264光照信息屏应用代码位于:solutions/eduk1_demo/k1_apps/lightmeter/lightmeter.c中。 265``` 266MENU_TYP lightmeter = { 267 "lightmeter", 268 &lightmeter_cover, 269 &lightmeter_tasks, 270 NULL, 271 &lightmeter_child_list}; 272``` 273在HaaS EDU K1上电之后,按K1或K2键左右切换应用的时候,如果切换到光照信息屏页面再到退出该页面的过程中,lightmeter下面的API会依此被呼叫: 2741. lightmeter_init 2752. lightmeter_uninit 276 277## 软件流程 278软件流程图如下所示。 279在进入光照信息屏页面后,启动名为lightmeter_task的task,周期性的读取ALS/PS/IR数据并判断物体靠近标志之后将相关数据按照一定的规则打印到OLED屏幕上。 280 281 282<div align=center> 283 <img src="https://img.alicdn.com/imgextra/i2/O1CN01zu05lV1NtD4Gl3VLg_!!6000000001627-2-tps-992-1152.png" style="zoom:50%;" /> 284</div> 285 286 287## 代码实现 288### 光照信息屏页面 289代码位置:solutions/eduk1_demo/k1_apps/lightmeter/lightmeter.c 290详细代码及注释如下: 291``` 292#include <stdio.h> 293#include <stdlib.h> 294#include "lightmeter.h" 295#include "aos/kernel.h" 296#include "ap3216c.h" 297 298/* 按照主程序框架的规则,声明页面相关相关信息(封面、初始化、反初始化、子页面等)*/ 299MENU_COVER_TYP lightmeter_cover = {MENU_COVER_NONE}; 300MENU_TASK_TYP lightmeter_tasks = { 301 lightmeter_init, 302 lightmeter_uninit}; 303MENU_LIST_TYP lightmeter_child_list = {NULL, 0}; 304MENU_TYP lightmeter = { 305 "lightmeter", 306 &lightmeter_cover, 307 &lightmeter_tasks, 308 NULL, 309 &lightmeter_child_list}; 310 311/* 页面初始化函数 */ 312int lightmeter_init(void) 313{ 314 printf("lightmeter_init begin\n"); 315 /* AP3216C 初始化函数 */ 316 ap3216c_init(); 317 printf("lightmeter_init done\n"); 318 319 /* 清空OLED屏幕 */ 320 OLED_Clear(); 321 OLED_Refresh_GRAM(); 322 323 /* 启动光照信息屏主任务 */ 324 aos_task_new("lightmeter_task", lightmeter_task, NULL, 1000); 325 printf("aos_task_new lightmeter_task \n"); 326 return 0; 327} 328 329void lightmeter_task(void) 330{ 331 uint16_t tmp[3]; 332 uint8_t als[20]; 333 uint8_t ps[20]; 334 uint8_t ir[20]; 335 336 while (1) 337 { 338 /* 从AP3216C读取ALS、PS、IR数据 */ 339 tmp[0] = ap3216c_read_ambient_light(); 340 tmp[1] = ap3216c_read_ir_data(); 341 tmp[2] = ap3216c_read_ps_data(); 342 343 /* 打印ALS/IR信息字串 */ 344 sprintf(als, "ALS: %d", tmp[0]); 345 sprintf(ir, "IR : %d", tmp[1]); 346 347 /* 将lightmeter图标及ALS/IR信息输出到屏幕 */ 348 OLED_Clear(); 349 OLED_Icon_Draw(20, 14, &icon_lighter_32_32, 0); 350 OLED_Show_String(64, 6, als, 12, 1); 351 OLED_Show_String(64, 20, ir, 12, 1); 352 353 /* 判断是否有物体靠近,并显示在屏幕上 */ 354 if ((tmp[2] >> 15) & 1) 355 OLED_Show_String(64, 36, "near !", 16, 1); 356 else 357 OLED_Show_String(64, 40, "far !", 16, 1); 358 359 /* 将左右按键标志输出到屏幕上 */ 360 OLED_Icon_Draw(2, 24, &icon_skip_left, 0); 361 OLED_Icon_Draw(122, 24, &icon_skip_right, 0); 362 363 /* 刷新屏幕数据 */ 364 OLED_Refresh_GRAM(); 365 366 /* 休眠150ms */ 367 aos_msleep(150); 368 } 369} 370 371/* 光照信息屏页面退出处理函数 */ 372int lightmeter_uninit(void) 373{ 374 /* 删除光照信息屏主任务 */ 375 aos_task_delete("lightmeter_task"); 376 printf("aos_task_delete lightmeter_task \n"); 377 return 0; 378} 379``` 380 381### AP3216C驱动 382代码位置:components/peripherals/sensor/drv/drv_als_ps_ir_liteon_ap3216c.c 383以ap3216C初始化和读取ALS数值为例,详细代码及注释如下: 384``` 385/** 386 * This function initializes ap3216c registered device driver 387 * 388 * @param no 389 * 390 * @return the ap3216c device. 391 */ 392void ap3216c_init(void) 393{ 394 /** 395 1. ap3216c连接到HaaS edu k1的I2C1端口, 所以i2c_dev的端口好需要设定为1 396 2. ap3216c为7-bit地址模式 397 3. haas1000芯片内部的I2C1作为主模式, ap3216c作为从设备 398 4. ap3216c外设定制用AP3216C_ADDR声明 399 */ 400#if 1 401 i2c_dev.port = 1; 402 i2c_dev.config.address_width = I2C_HAL_ADDRESS_WIDTH_7BIT; 403 i2c_dev.config.freq = I2C_BUS_BIT_RATES_100K; 404 i2c_dev.config.mode = I2C_MODE_MASTER; 405 i2c_dev.config.dev_addr = AP3216C_ADDR; 406 /* 呼叫hal_i2c_init对haas1000内部的I2C1控制器进行初始化 */ 407 hal_i2c_init(&i2c_dev); 408#endif 409 /* 复位ap3216c芯片, 向system configuration寄存器写入0x0对其进行软件复位 */ 410 reset_sensor(); 411 /* 等待ap3216c复位稳定时间 */ 412 aos_msleep(100); 413 /* 设置ap3216c工作在连续量测ALS/PS/IR模式 */ 414 ap3216c_set_param(AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS); 415 /* 休眠150ms等待量测到稳定值 */ 416 aos_msleep(150); // delay at least 150ms 417 418 /* 配置中断脚 和 中断数据 - 函数内部实现置空 */ 419 ap3216c_int_Config(); 420 ap3216c_int_init(); 421} 422/** 423 * This function reads light by ap3216c sensor measurement 424 * 425 * @param no 426 * 427 * @return the ambient light converted to float data. 428 */ 429uint16_t ap3216c_read_ambient_light(void) 430{ 431 uint16_t brightness = 0; // default error data 432 uint16_t read_data; 433 uint8_t range; 434 435 /*分别读取 0x0c和0x0d的值,组成16-bit的ALS ADC count */ 436 read_data = (uint16_t )read_low_and_high(AP3216C_ALS_DATA_L_REG, 1); 437 /* 读取ALS range 配置 */ 438 ap3216c_get_param(AP3216C_ALS_RANGE, &range); 439 /* 根据ALS range 配置,完成从ADC count到lux的换算 */ 440 if (range == AP3216C_ALS_RANGE_20661) 441 { 442 brightness = 0.36 * read_data; //sensor ambient light converse to reality 443 } 444 else if (range == AP3216C_ALS_RANGE_5162) 445 { 446 brightness = 0.089 * read_data; //sensor ambient light converse to reality 447 } 448 else if (range == AP3216C_ALS_RANGE_1291) 449 { 450 brightness = 0.022 * read_data; //sensor ambient light converse to reality 451 } 452 else if (range == AP3216C_ALS_RANGE_323) 453 { 454 brightness = 0.0056 * read_data; //sensor ambient light converse to reality 455 } 456 return brightness; 457} 458 459/** 460 * This function is convenient to getting data except including high and low data for this sensor. 461 * note:after reading lower register first,reading higher add one. 462 */ 463 /* 读取从reg开始的两个字节, 并对数据进行合并*/ 464static uint32_t read_low_and_high(uint8_t reg, uint8_t len) 465{ 466 uint32_t data; 467 uint8_t buf = 0; 468 469 read_regs( reg, len, &buf); // 读低字节 470 data = buf; 471 read_regs( reg + 1, len, &buf); // 读高字节 472 data = data + (buf << len * 8); // 合并数据 473 474 return data; 475} 476 477/* 读寄存器的值 */ 478static void read_regs(uint8_t reg, uint8_t len, uint8_t *buf) 479{ 480 hal_i2c_mem_read(&i2c_dev, i2c_dev.config.dev_addr, reg, 1, buf, len, 100); 481} 482 483``` 484这里的hal_i2c_mem_read的实现和AP3216C datasheet上面读取寄存器的描述相匹配。 485* MCU I2C 主设备先将寄存器地址通过I2C写操作发给AP3216C从设备 486* MCUI2C 主设备发起读操作从AP3216C从设备读取寄存器的值 487AP3216C寄存器读取的整个I2C传输过程中,详细数据传输过程如下图所示: 488 489 490<div align=center> 491 <img src="https://img.alicdn.com/imgextra/i2/O1CN012WHnPA1kGUkd87seS_!!6000000004656-2-tps-1458-976.png" style="zoom:50%;" /> 492</div> 493 494 495读取AP3216C的PS和IR寄存器的过程和读取ALS的过程中I2C的传输过程完全一致,这里就不再赘述。