Arduino 获得 Gm1020 照度计测量值
userHead Zoologist 2020-09-30 10:25:41

照度,可以理解为灯泡发出的光的数量(光通量)在某一方向以一定的强度(光强)入射到某一表面,此时可测得这一表面的照度。 

而亮度是指发光体(反光体)表面发光(反光)强弱的物理量,人眼从一个方向观察光源,在这个方向上的光强与人眼所“见到”的光源面积之比,定义为该光源单位的亮度,即单位投影面积上的发光强度,当我们站在某一位置观察受照面的时候,我们就看到了这个表面的明亮程度(亮度)。 

projectImage

以更简单直观的方式来解释: 

照度是一个客观的参量,是我们用仪器去检测在某一个面上实际到达的光的数量。 

亮度是指某一物体发射或者反射出来的光被人眼所感知的程度。 

如同前面所述,光线通过反射进入眼睛是我们“看到”的必要条件,工程师和科学家使用 “光强”来描述光线强度。国际单位是 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 自带的软件进行推导。

projectImage

Virtual SerialPort Driver 是一款串口模拟软件。我们用它在系统中模拟出2个相互连通的串口 COM1 和 COM2。从一端发送,数据会出现在另外的端口上。因此,我们一端用软件打开,另外一端用串口工具打开。串口通讯需要设置通讯参数,对于这款设备使用的参数为 “19200 BPS/ 8 Data bits/ 1 Stop bits/ No Parity/ no Flow control”。

projectImage

打开对应串口后,软件通知设备准备开始 1e 00 0000 00 00 00 1e 发送这个命令 3c 01 00 00 00 00 00 3d, 设备会开始不停发送当前的照度信息 发送这个命令 3c 02 0000 00 00 00 3e,,设备会开始停止发送当前的照度信息

projectImage
projectImage

注意: 

1. 测量界面可以在不同单位中切换,有:Lux(勒克斯) FC(尺烛光)℃(摄氏度) F(华氏度),但是设备从 USB 口发出的数据只有以 Lux 和℃为单位的; 

2. 测量范围和精度

projectImage

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..
}

照度计设备就是这个东西

projectImage

过上述的方法可以实现将 USB 照度计数据发送到电脑上,从而实现将有线设备转成无线设备的功能。在实际生产环境下,还可以通过更换无线模块达到更强的抗干扰更远的发送距离要求。 

关于作者 

Zoologist 来自 Arduino 中文社区,爱好使用 Arduino 制作各种有趣的东西。

联系我们
联系邮箱:makercarnival@hotmail.com
官方微信公众号:创客嘉年华
官方微博:上海创客嘉年华
© Copyright Zhiwei Robotics Corp. All Rights Reserved
code 上海创客嘉年华