8750|3

1382

帖子

2

TA的资源

五彩晶圆(初级)

楼主
 

ROHM传感器套件测评(二): 五个I2C接口传感器 [复制链接]

本帖最后由 cruelfox 于 2017-3-25 16:30 编辑

上一篇:ROHM传感器套件测评(一): 测试平台,霍尔传感器

  这个套件的8个传感器中有5个是I2C接口的数字传感器:

  在 SensorShield 底板上,有5个位置可以插I2C传感器小板。不过因为工作电压范围不一致,不能全插上去一起用。这5个传感器都是自带AD转换的,所以直接输出数字量了,加上可配置能力,适应性更强。比如,在不需要采集数据的时候可以关闭内部功能以节省电力。

  加速度传感器 KX022-1020
  这大概是这套传感器中配置最为复杂的一个。它是一个三轴加速度传感器,也就是能感知三维空间空间中的加速度方向。关于这个测量结果的物理意义我需要说明一下,因为两天前我自己也没想清楚:为什么加速度计放在地上不动,也测出来有加速度(大小是一个g,重力加速度的值),而不是加速度为0 ? 它明明就没有运动嘛。倘若把加速度计连同附属电路装置抛向空中,必然读出加速度是0,尽管这个时候它是向地面加速的。和人们的直观感受完全相反啊!实际是这样:运动是相对的,参照系不同,速度就不同(中学物理讲的是以静止或者匀速运动物体为参照,但是怎么定义静止呢?);加速度也会随参照系而变,因为是速度的微分(例子:伽利略实验,两个铁球同时着地)。当以地球表面自由落体的物体为参照时,这个加速度计的测量值就可以被解释了:放在桌上不动,它就有一个竖直向上的加速度。
  对于加速度计,引力是不能让它产生测量值的;人也一样,人其实不能直接感受到引力的存在。或许看我这段话的朋友要反驳了:没有引力存在我不就一蹦飞上天了么?注意,人蹦起来离开地面时候是失重的,比如蹦极的时候闭上眼睛其实并不知道引力在什么方向。反而是我们站着、坐着或者躺着的时候,受到地面、椅子或者床的向上的拖着的力——身体切实感受到了,却习以为常而被忽略了。所以结论是:人站在地球上,和坐在原离太阳系正以9.8m/s/s加速的宇宙飞船里,感受到的“重力”是一样的。

  回到说这个传感器,其内部在AD转换之后的数字部分还有DSP和FIFO buffer,才把数据送到接口电路,这是比直接读取AD转换值更高级的功能。在手册中对DSP的功能有描述,我没有工夫来详细研究了。KX022-1020 具有16-bit数字分辨率,最大每秒1600次转换输出的能力,最大正负8g的量程,对消费类一般运动检测(不是碰撞冲击)的话应该够用了。我没有惯性传感器的实际应用经验,就不作多的评价。作为类似手机重力方向感应的倾角检测应用的话,这个加速度计是足够。接口它是支持SPI和I2C的,SPI支持的速率更高,但是套件中只提供了I2C的连接方式。

  KX022 有57个8位的寄存器,好在简单的测试只配CNTL1, CNTL2之后就可以读数了。

  1. void test_KX022(char slave_addr)
  2. {
  3.     uint8_t buf[256];

  4.     i2c_w1rn(slave_addr,0x0f,buf,1);    // check WHOAMI
  5.     if(buf[0]==0x14)
  6.         uart_wstr("\r\nKX022 detected.");
  7.     else
  8.     {
  9.         uart_wstr("\r\nNo response.");
  10.         return;
  11.     }

  12.     buf[0]=0x18;    // CNTL1,2
  13.     buf[1]=0x60;    // set RES, DRDYE
  14.     buf[2]=0x00;
  15.     i2c_write_n(slave_addr, buf, 3);
  16.     _delay_ms(100);
  17.     uart_wstr("\r\nConfigured mode");

  18.     buf[0]=0x18;    // CNTL1
  19.     buf[1]=0xE0;    // operating mode
  20.     i2c_write_n(slave_addr, buf, 2);
  21.     uart_wstr("\r\nACC operating");
  22.     _delay_ms(100);

  23.     for(;;)
  24.     {
  25.         _delay_ms(10);
  26.         i2c_w1rn(slave_addr,0x13,buf,1); // read INS2
  27.         if(buf[0] & 0x10)
  28.         {
  29.             int16_t acc[3];
  30.             i2c_w1rn(slave_addr,0x06,(uint8_t *)acc,6); // read data
  31.             uart_wstr("\r\nXYZ: ");
  32.             print_i16(acc[0]);
  33.             uart_wstr(",");
  34.             print_i16(acc[1]);
  35.             uart_wstr(",");
  36.             print_i16(acc[2]);
  37.         }
  38.     }
  39. }
复制代码



  在小板上丝印标注了加速度的XYZ敏感方向。若SensorShield水平放置,Z轴是向上的。

  本测试是正负2g的量程范围,每秒50次转换输出。板子平放时候串口输出:

大约是z方向正向(向上)的一个g加速度,符合前面的推断。因为没有严格水平,加速度方向没有严格在z方向上。倒过来朝下扣着,则Z读数应该变成负的:

侧着竖起来放看一下结果:

还是蛮好玩的。至于自由落体,现在这样拖着USB线就没法测试了(需要做个电池供电,把数据存到SD卡或者无线发送出来......)

  RGB颜色传感器 BH1745
  这是一个接收可见光的传感器,所以封装是透明的。

  我先谈下我对“颜色”的理解。眼睛只所以能感受颜色,是因为有光进入了眼睛,刺激到了视网膜上的感光细胞。我们说一个不发光的物体,比如一块布料是什么颜色的,是指它的反射光。但是反射光必然又和入射光有关系,比如,在红光灯照射下,绿色的物体也只能反射红光。所以日常生活中谈论物体的颜色还有一个假设前提,就是在自然光下。但是,这还是定性讨论,自然光还没有定义呢。太阳光是具有连续光谱的,在人眼可见部分光谱的能量分布也和自然环境相关。一般笼统地把太阳光称为七种颜色的光组成,事实上并非七种单一波长的光组成。人眼能识别颜色,是因为视网膜上有3种视锥细胞,对不同波长有不同的敏感度:

这好比人眼睛有三种色彩传感器。于是,有同色异谱现象(不同的光谱分布可能产生同样的颜色感知),有了现在的RGB三基色系统来重现(模拟)自然界的色彩。

  ROHM这个 BH1745NUC 传感器的颜色敏感曲线和人眼是有所不同的

除了RGB输出,还有一个"Clear color"通道。寄存器表比前面的加速度计要简单了

  测试程序:
  1. void test_BH1745NUC(char slave_addr)
  2. {
  3.     uint8_t buf[256];

  4.     i2c_w1rn(slave_addr,0x92,buf,1);    // check ID
  5.     if(buf[0]==0xE0)
  6.         uart_wstr("\r\nBH1745NUC detected.");
  7.     else
  8.     {
  9.         uart_wstr("\r\nNo response.");
  10.         return;
  11.     }

  12.     buf[0]=0x41;
  13.     buf[1]=0x00;    // default, 160ms
  14.     buf[2]=0x10;    // RGBC EN
  15.     buf[3]=0x02;
  16.     i2c_write_n(slave_addr, buf, 4);
  17.     uart_wstr("\r\nWrite CONTROL1,2,3");

  18.     for(;;)
  19.     {
  20.         i2c_w1rn(slave_addr,0x42,buf,1); // MODE_CONTROL2
  21.         if(buf[0] & 0x80)   // VALID
  22.         {
  23.             uint16_t *d=(uint16_t *)buf;
  24.             i2c_w1rn(slave_addr,0x50,buf,8);    // read RGBC
  25.             uart_wstr("\r\nRGBC: ");
  26.             uart_wdec(d[0]);
  27.             uart_wstr(", ");
  28.             uart_wdec(d[1]);
  29.             uart_wstr(", ");
  30.             uart_wdec(d[2]);
  31.             uart_wstr(", ");
  32.             uart_wdec(d[3]);
  33.             uart_wstr(" ");
  34.         }
  35.     }
  36. }
复制代码

  我用一块PCB板将传感器盖住,在室内环境下可以实现读数全为0. 在我的工作桌上(灯头是七年半前制作的,四只Cree XR-E Q3 5C串联),输出结果

而放到被太阳光照射的地方(隔着窗玻璃,空气还有雾霾),可以发现光更强

调整一下板子的角度,让太阳光接近垂直照射到传感器上,数值应该是更大的:

在太阳光下阅读,对人眼的刺激就太大了。光过强也不好。我的另一盏LED台灯(前年制作的,用了较新的,且色温更低的LED)下:

这个LED的红色成分明显加强了,是更接近白炽灯的。但家中已没有白炽灯了,无法测试对比数据。


  另外一个用AA电池的LED小灯下,LED距离传感器比较近测量:

这个的蓝光成分就高了,作为照明用眼睛也不舒适。应急用不要紧。


  把传感器靠在我现在的显示器屏幕上,显示白色区域:

  最后玩一个,3mm的高亮度红色LED,距离传感器十几mm照射:


  作为能定量分析光照颜色的传感器,BH1745NUC 在环境监测、智能家居方面可以发挥优势。直接作为视力保护的照明条件评估,我认为也是个理想的应用。

  接近和环境光传感器 RPR-0521RS

  这是一个复合传感器,把光传感器功能和红外LED结合在一起,做成了反射式的接近检测传感器加环境光(可见光和红外)传感器。用手册中的这个图可以说明它的原理和用途:

检测需要的灵敏度和阈值是需要设置后才能用的(比如需要产生中断输出). 寄存器表如下,和前一个颜色传感器的风格一致。

  我的测试程序:
  1. void test_RPR0521(char slave_addr)
  2. {
  3.     uint8_t buf[256];

  4.     i2c_w1rn(slave_addr,0x92,buf,1);    // check ID
  5.     if(buf[0]==0xE0)
  6.         uart_wstr("\r\nRPR0521 detected.");
  7.     else
  8.     {
  9.         uart_wstr("\r\nNo response.");
  10.         return;
  11.     }

  12.     buf[0]=0x41;
  13.     buf[1]=0xC7;    // enable ALS, PS, 100ms/400ms
  14.     buf[2]=0x00;    // ALS Gain x1
  15.     buf[3]=0x20;    // PS Gain x4
  16.     i2c_write_n(slave_addr, buf, 4);
  17.     uart_wstr("\r\nWrite CONTROL regs");

  18.     buf[0]=0x4A;
  19.     buf[1]=0x06;    // unlatched
  20.     i2c_write_n(slave_addr, buf, 2);
  21.     uart_wstr("\r\nWrite INTERRUPT reg");

  22.     buf[0]=0x51;
  23.     buf[1]=0xfe;
  24.     buf[2]=0xff;
  25.     i2c_write_n(slave_addr, buf, 3);
  26.     uart_wstr("\r\nWrite ALS TL");

  27.     for(;;)
  28.     {
  29.         i2c_w1rn(slave_addr,0x4a,buf,1); // INTERRUPT
  30.         if(buf[0] & 0x40)   // ALS status
  31.         {
  32.             uint16_t *d=(uint16_t *)buf;
  33.             i2c_w1rn(slave_addr,0x44,buf,6);    // read PS,ALS
  34.             uart_wstr("\r\nPS: ");
  35.             uart_wdec(d[0]);
  36.             uart_wstr(", ALS: ");
  37.             uart_wdec(d[1]);
  38.             uart_wstr(", ");
  39.             uart_wdec(d[2]);
  40.             uart_wstr(" ");
  41.         }
  42.     }
  43. }
复制代码


  在我的工作桌上,没有遮挡的情况下输出结果:

似乎这个环境光检测的“红外”通道对可见光也是有感应的。
  拿一张纸片,平放在传感器上放10cm处,挡住灯光照射

接近检测稍有所响应(GAIN=4x),环境光检测可以看到明显变化了。距离再减到5cm

这个距离下接近检测是可靠的了。这也是手册中的测量条件。 环境光检测数进一步缩小。若距离更近,接近检测的数值会迅速增大。

  我设想RPR-0521RS作为接近传感的用途是近距离的手势控制,或者机械装置里的近距离位置反馈。作为人体接近危险区域的报警用途之类则不合适,距离太短了。我上面的测试中接近传感的测量间隔是400ms,检测手势的速度不够。不过它是可以配置为最短10ms检测一次的,应该可以用。

  气压传感器 BM1383GLV

  气压传感器的意义很直观,它封装里面的传感器和外面空气是相通的(壳上有个小孔),测量空气压强。在平常接触到的电子设备中,大概是血压计用得最多,此外它也被用来间接测量海拔高度。

  BM1383GLV这个型号的手册我下载不到,ROHM网站的链接一直是Access denied错误。我只能找到 BM1383AGLV 型号的手册,可能是改进型,但是区别有多少不得而知。根据描述,这俩都是内建温度补偿的气压传感器。我只好以 BM1383AGLV 为参照,写程序的时候发现寄存器操作有误再把Rohm网站上能下载的Arduino程序找来参考。

  测试程序(因为没有把DRDY检测弄成功,就改为延时100ms后读取一次结果了):
  1. void test_BM1383GLV(char slave_addr)
  2. {
  3.     uint8_t buf[256];

  4.     i2c_w1rn(slave_addr,0x0f,buf,2);    // check ID
  5.     if(buf[1]==0x31)
  6.         uart_wstr("\r\nBM1383GLV detected.");
  7.     else
  8.     {
  9.         uart_wstr("\r\nNo response.");
  10.         return;
  11.     }

  12.     buf[0]=0x12;
  13.     buf[1]=0x01;    // POWER DOWN REG (active)
  14.     i2c_write_n(slave_addr, buf, 2);
  15.     _delay_ms(10);
  16.     uart_wstr("\r\nLeave power down");

  17.     buf[0]=0x13;
  18.     buf[1]=0x01;    // RESET REG (active)
  19.     i2c_write_n(slave_addr, buf, 2);
  20.     _delay_ms(10);
  21.     uart_wstr("\r\nLeave reset");

  22.     buf[0]=0x14;
  23.     buf[1]=0xda;    // Average 64, DRDY enable, continuous ?? not sure
  24.     i2c_write_n(slave_addr, buf, 2);
  25.     _delay_ms(10);
  26.     uart_wstr("\r\nConfigured mode");

  27.     for(;;)
  28.     {
  29.         uint32_t p=0;

  30.         _delay_ms(100);
  31.         uart_wstr("\r\n");
  32.         i2c_w1rn(slave_addr,0x1c,buf,3); // read data
  33.         *(uint8_t *)(&p)=buf[2];
  34.         *((uint8_t *)(&p)+1)=buf[1];
  35.         *((uint8_t *)(&p)+2)=buf[0];
  36.         p>>=2;
  37.         uart_wstr("Pressure counts: ");
  38.         uart_wdec(p);
  39.     }
  40. }
复制代码


  测量结果,这个数值除以2048就是百帕(hPa)单位的值。

估测数据的波动在0.1个百帕量级。那么对气压敏感程度如何?我拿出我的笔记本电脑来测试了,带着Nucleo, SensorShield边测边走。我住在4楼,走到楼下看测量数据已经有明显的变化了:

  外面气温低,可能温度也影响了结果,也可能气压本来就跟温度有关。再上楼梯到4楼,在门外看看:

排除温度的变化,气压测量结果的确是有高度反映的。回到屋内稍暖和了一下,再看读数:

稍微有点变化。用气压测海拔本来就有精度范围的吧。不知道用这个传感器换算高度结果靠谱不。

  三轴磁场传感器 BM1422GMV

  这又是一个三轴传感器,测量磁场的方向和强度。主要的应用是电子罗盘,也就是测量地磁场来实现方向导航。在 BM1422GMV 内部集成了3个磁阻元件,经过AD转换输出12或14位的数据。

  寄存器表:

  工作流程图:

  按照流程图写的测试程序:
  1. void test_BM1422GMV(char slave_addr)
  2. {
  3.     uint8_t buf[256];

  4.     i2c_w1rn(slave_addr,0x0d,buf,3);    // check ID
  5.     if(buf[0]==0x01 &&buf[1]==0x01 &&buf[2]==0x41)
  6.         uart_wstr("\r\nBM1422GMV detected.");
  7.     else
  8.     {
  9.         uart_wstr("\r\nNo response.");
  10.         return;
  11.     }

  12.     buf[0]=CNTL1;
  13.     buf[1]=0xC0;    // Power enable, 14-bit, continuous mode
  14.     i2c_write_n(slave_addr, buf, 2);
  15.     uart_wstr("\r\nSet CNTL1");

  16.     buf[0]=CNTL4;
  17.     buf[1]=0x0;
  18.     buf[2]=0x0;
  19.     i2c_write_n(slave_addr, buf, 3);
  20.     uart_wstr("\r\nSet CNTL4");

  21.     buf[0]=CNTL2;
  22.     buf[1]=0x08;    // DREN
  23.     i2c_write_n(slave_addr, buf, 2);
  24.     uart_wstr("\r\nSet CNTL2");

  25.     buf[0]=CNTL3;
  26.     buf[1]=0x40;    // FORCE
  27.     i2c_write_n(slave_addr, buf, 2);
  28.     uart_wstr("\r\nSet CNTL2");

  29.     for(;;)
  30.     {
  31.         i2c_w1rn(slave_addr,STA1,buf,1);
  32.         if(buf[0] & 0x40)
  33.         {
  34.             int16_t *d=(int16_t *)buf;
  35.             i2c_w1rn(slave_addr,DATAX,buf,6);   // read DATAX,Y,Z
  36.             uart_wstr("\r\nDATA: ");
  37.             print_i14(d[0]);
  38.             uart_wstr(", ");
  39.             print_i14(d[1]);
  40.             uart_wstr(", ");
  41.             print_i14(d[2]);
  42.             uart_wstr(" ");
  43.         }
  44.     }
  45. }
复制代码



  然而,测量结果很奇怪。首先是沿敏感轴改变方向后数值并不是变成反号,其次读数不是很稳定,还有换用不同的插座位置时读数也有差别。第一个问题我试图用设定Offset来校正,失败,未得到合适的结果。在默认的参数下,某个摆放朝向是这样的测量结果:

X轴方向不变,Y, Z轴都变成反方向再测:

看起来好象有个负的offset在里面,但这个误差也太大了。我怀疑是否是板子上的电流产生的磁场造成的干扰,但是现在没有办法去检验。最后一图上X轴数据的突然跳变也无法解释……


  遗憾,作为地磁测量,我还没法把BM1422用起来。





此帖出自传感器论坛

最新回复

i2c_w1rn这个函数是怎么写的呢?   详情 回复 发表于 2024-7-5 15:33
点赞 关注(1)
 
 

回复
举报

2774

帖子

8

TA的资源

版主

沙发
 
来学习一下,ROHM的东西精度还是不错的!
此帖出自传感器论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
欢迎大牛9月11-13号来上海国际传感器技术博览会参观
此帖出自传感器论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 

i2c_w1rn这个函数是怎么写的呢?

此帖出自传感器论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表