照度,可以理解为灯泡发出的光的数量(光通量)在某一方向以一定的强度(光强)入射到某一表面,此时可测得这一表面的照度。
而亮度是指发光体(反光体)表面发光(反光)强弱的物理量,人眼从一个方向观察光源,在这个方向上的光强与人眼所“见到”的光源面积之比,定义为该光源单位的亮度,即单位投影面积上的发光强度,当我们站在某一位置观察受照面的时候,我们就看到了这个表面的明亮程度(亮度)。
以更简单直观的方式来解释:
照度是一个客观的参量,是我们用仪器去检测在某一个面上实际到达的光的数量。
亮度是指某一物体发射或者反射出来的光被人眼所感知的程度。
如同前面所述,光线通过反射进入眼睛是我们“看到”的必要条件,工程师和科学家使用 “光强”来描述光线强度。国际单位是 candela( “坎德拉”简写 cd),其他单位有烛光,支光。1 cd 即 1000 mcd 是指单色光源(频率 540X10^12 HZ)的光,在给定方向上(该方向上的辐射强度为(1/683)瓦特/球面度)的单位立体角发出的光通量。 这次需要读取标智科技( Benetech )出品的数字照度计的测量信息,具体型号是 GM1020。
首先从实验得知,这款设备是通过内置的 Prolific 2302 芯片来实现 USB 对串口的转接。之前我们介绍过 USB HID 设备的读取,相较而言串口和 HID 相比,从编程角度来说前者更加方便和通用,资料更加丰富,无论什么编程语言都会支持这一传统设备的编程。但是从客户使用的角度来说,USB 串口很可能需要用户安装驱动,虽然 Win10 内置了多种 USB 串口芯片的驱动,但是仍然有一些型号不支持,在使用过程中如果客户使用 Ghost 精简版也会碰到很多问题。而 HID 设备只需要 Application 即可,驱动完全内置。
设备本身没有提供数据格式之类的资料(国产设备大部分如此,提供资料的反倒是异类),但是已经确定了使用串口协议,因此这里使用 Virtual Serial Port Driver 和 GM1020 自带的软件进行推导。
Virtual SerialPort Driver 是一款串口模拟软件。我们用它在系统中模拟出2个相互连通的串口 COM1 和 COM2。从一端发送,数据会出现在另外的端口上。因此,我们一端用软件打开,另外一端用串口工具打开。串口通讯需要设置通讯参数,对于这款设备使用的参数为 “19200 BPS/ 8 Data bits/ 1 Stop bits/ No Parity/ no Flow control”。
打开对应串口后,软件通知设备准备开始 1e 00 0000 00 00 00 1e
发送这个命令 3c 01 00 00 00 00 00 3d, 设备会开始不停发送当前的照度信息
发送这个命令 3c 02 0000 00 00 00 3e,,设备会开始停止发送当前的照度信息
注意:
1. 测量界面可以在不同单位中切换,有:Lux(勒克斯) FC(尺烛光)℃(摄氏度) F(华氏度),但是设备从 USB 口发出的数据只有以 Lux 和℃为单位的;
2. 测量范围和精度
3. 例如设备发送数据 3322 00 12 01 00 b1 11。具体分析如下:
Byte[2:3]==0x0012
其中BIT[15:14]==0,读取值要乘以0.1
BIT[13:0]==0x12==18,所以这个数据表示1.8Lux
Byte[5:6]==0xb1=177,实际温度为 177*0.1=17.7℃
有了上述的知识,可以使用 USB Host Shield 实现解析 USB 照度计数据,然后将数据用蓝牙发送到电脑上。
关键代码有 2 部分:
首先是 OnInit 函数,设置通讯参数,然后发送让设备开始发送数据的命令
uint8_t PLAsyncOper::OnInit(ACM *pacm)
{
uint8_t rcode;
// Set DTR = 1
rcode =pacm->SetControlLineState(1);
if (rcode)
{
ErrorMessage<uint8_t>(PSTR("SetControlLineState"),rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate =19200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode =pacm->SetLineCoding(&lc);
if (rcode)
ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
delay(100);
uint8_t StartCMD[8] ={0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x1e};
uint8_t SndDataCMD[8]={0x3c,0x01,0x00,0x00,0x00,0x00,0x00,0x3d};
//发送起始命令
pacm->SndData(sizeof(StartCMD),&StartCMD[0]);
delay(100);
//发送数据传输命令
pacm->SndData(sizeof(SndDataCMD),&SndDataCMD[0]);
delay(100);
return rcode;
}
接下来是收取串口数据的代码
byte Waiting8Bytes=0;
void loop()
{
Usb.Task();
if(Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
uint8_t rcode;
uint8_t buf[64];
uint16_t rcvd= 64;
//接收数据
rcode =Pl.RcvData(&rcvd, buf);
if (rcode&& rcode != hrNAK)
ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
//有数据,直接处理
if( rcvd ){
for(uint16_t i=0; i < rcvd; i++ ) {
Serial.print((byte)buf,HEX); //printing on the screen
Serial.print(" ");
}
Waiting8Bytes=Waiting8Bytes+rcvd;
if(Waiting8Bytes>7) {
Serial.println("");
Waiting8Bytes=0;
}
}//if( rcvd...
}//if(Usb.getUsbTaskState() == USB_STATE_RUNNING..
}
照度计设备就是这个东西
过上述的方法可以实现将 USB 照度计数据发送到电脑上,从而实现将有线设备转成无线设备的功能。在实际生产环境下,还可以通过更换无线模块达到更强的抗干扰更远的发送距离要求。
Zoologist 来自 Arduino 中文社区,爱好使用 Arduino 制作各种有趣的东西。