浅析CC2530下ZigBee协议栈中添加BH1750数字光照传感器

数字传感器

数字传感器是指将传统的模拟式传感器经过加装或改造A/D转换模块,使之输出信号为数字量(或数字编码)的传感器,主要包括:放大器、A/D转换器、微处理器(CPU)、存储器、通讯接口、温度测试电路等,在微处理器和传感器变得越来越便宜的今天,全自动或半自动(通过人工指令进行高层次操作,自动处理低层次操作)系统可以包含更多智能性功能,能从其环境中获得并处理更多不同的参数。

特点

1、先进的A/D转换技术和智能滤波算法,在满量程的情况下仍可保证输出码的稳定。

2、可行的数据存储技术,保证模块参数不会丢失。

3、良好的电磁兼容性能。

4、传感器的性能采用数字化误差补偿技术和高度集成化电子元件,用软件实现传感器的线性、零点、温漂、蠕变等性能参数的综合补偿,消除了人为因素对补偿的影响,大大提高了传感器综合精度和可靠性。

5、传感器的输出一致性误差可以达到0.02%以内甚至更高,传感器的特性参数可完全相同,因而具有良好的互换性。

6、采用A/D转换电路、数字化信号传输和数字滤波技术,传感器的抗干扰能力增加,信号传输距离远,提高了传感器的稳定性。

7、数字传感器能自动采集数据并可预处理、存储和记忆,具有唯一标记,便于故障诊断。

8、传感器采用标准的数字通讯接口,可直接连入计算机,也可与标准工业控制总线连接,方便灵活。

9, 数字传感器是将AD,EPROM,DIE(指还未封装的传感器芯片,属于裸片,大小介于cell和chip之间),封装在一块用PCB,金属块或陶瓷板上的集成。通过各种温度,压力点的校准,计算出DIE的线性,再利用AD去补偿的方法加工而成的。

应用及前景

在微处理器和传感器变得越来越便宜的今天,全自动或半自动(通过人工指令进行高层次操作,自动处理低层次操作)系统可以包含更多智能性功能,能从其环境中获得并处理更多不同的参数。尤其是MEMS(微型机电系统)技术,它使数字传感器的体积非常微小并且能耗与成本也很低。以纳米碳管或其它纳米材料制成的纳米传感器同样具有巨大的潜力 [1] 。

即使在萌芽阶段,人们仍然认为在不久的将来数字传感器对电子市场具有重要的推动作用。制作数字传感器的接口以及支持用于数字传感器网络的形式多样的通讯协议都是对技术工艺的巨大挑战。传感器的非均质特性和其操作条件的多样化也对技术工艺提出了巨大的挑战。

现在系统设计所包含的传感器和处理器越来越多。随着传感器和处理器价格的不断降低,取代机械控制结构的阈值也在不断变化。在系统中选择正确的传感器组合和处理算法可以显著地降低原材料及能耗的费用并提高系统的总体性能。目前,不断提高操作的简化程度和延长能源的使用寿命变得越来越重要,尤其是如今越来越多的传感器网络动辄就配置1000或更多的传感器节点。

项目里需要获得光照强度,之前用的是光敏电阻,但是光敏电阻实在不精确,换用BH1750数字光照传感器。网上购买后,送的资料都是单片机的,移植到ZigBee协议栈里面,时序有些问题,在网上找的一些资料,很杂乱。主要出现两个问题:一、读取不到数据;二、读取到的数据是乱的。

仔细研究之后,发现,第一个问题读不到数据,八成是延时函数有差别;第二个问题,一直以为是时序的问题,纠结了很久还是没弄好,后来突然想把数据处理的地方单独弄出来测试,结果正是这里,采集到数据,转为字符串的时候,数据类型跟所需要的数据类型有差,最大范围不同,可能每个人宏或者自定义的数据类型都不太一样,所以移植过来的时候,虽然名字一样,但是实际上定义的时候不一样,导致使用的时候不容易发现问题。

下面贴上代码。(之前在网上看到别人做的bh1750,想问他买代码,结果告诉我一个代码要我80,瞬间无语,还好自己弄出来了 ,共享给大家,也给自己提个醒,最是觉得没有问题的地方,往往就是问题所在,需时刻抱有怀疑的态度)

BH1750.h:

#ifndef __BH1750_H

#define __BH1750_H

#include 《ioCC2530.h》

#define st(x) do { x } while (__LINE__ == -1)

#define HAL_IO_SET(port, pin, val) HAL_IO_SET_PREP(port, pin, val)

#define HAL_IO_SET_PREP(port, pin, val) st( P##port##_##pin## = val; )

#define HAL_IO_GET(port, pin) HAL_IO_GET_PREP( port,pin)

#define HAL_IO_GET_PREP(port, pin) ( P##port##_##pin)

#define LIGHT_SCK_0() HAL_IO_SET(1,3,0)

#define LIGHT_SCK_1() HAL_IO_SET(1,3,1)

#define LIGHT_DTA_0() HAL_IO_SET(1,1,0)

#define LIGHT_DTA_1() HAL_IO_SET(1,1,1)

#define LIGHT_DTA() HAL_IO_GET(1,1)

#define LIGHT_SCK() HAL_IO_GET(1,3)

#define SDA_W() (P1DIR |=(1 《《 1) )

#define SDA_R() (P1DIR &=~(1 《《 1) )

#define LIGHT_INIT()

do{

P1SEL &= ~0x08;

P1DIR |=0x08;

P1_3 = 1;

P1SEL &= ~0x02;

P1DIR |= 0x02;

P1_1 = 1;

}while(0)

extern unsigned short get_light(void);

#endif // __BH1750_H

BH1750.c:

#include “BH1750.h”

#include “OnBoard.h”

void halMcuWaitUs(uint16 usec)

{

while(usec–)

{

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

asm(“nop”);

}

}

//以ms延时

void halMcuWaitMs(uint16 msec)

{

while(msec–)

halMcuWaitUs(1000);

}

void delay_us()

{

halMcuWaitUs(1);

// MicroWait(1);

}

void delay_5us()

{

halMcuWaitUs(5);

//MicroWait(5);

}

void delay_10us()

{

halMcuWaitUs(10);

//MicroWait(10);

}

void delay_nms(int n)

{

halMcuWaitMs(n);

}

/****************************/

static void start_i2c(void)

{

SDA_W() ;

LIGHT_DTA_1();//

LIGHT_SCK_1() ;//

delay_us() ;

LIGHT_DTA_0() ;

delay_us() ;

LIGHT_SCK_0() ;

delay_us() ;

//delay() ;

}

static void stop_i2c(void)

{

SDA_W() ;

LIGHT_DTA_0() ;

delay_us();

LIGHT_SCK_1() ;

delay_us();

LIGHT_DTA_1() ;

delay_us();

LIGHT_SCK_0() ;

delay_us();

}

static char i2c_send(unsigned char val)

{

int i;

char error=0;

SDA_W();

for(i=0x80;i》0;i/=2)

{

if(val&i)

LIGHT_DTA_1();

else

LIGHT_DTA_0();

delay_us();

LIGHT_SCK_1() ;

delay_us();

LIGHT_SCK_0() ;

delay_us();

}

LIGHT_DTA_1();

SDA_R();

delay_us();

//delay_us();

LIGHT_SCK_1() ;

delay_us();

if(LIGHT_DTA())

error=1;

delay_us();

LIGHT_SCK_0() ;

return error;

}

static char i2c_read(char ack)

{

int i;

char val=0;

LIGHT_DTA_1();

//SDA_R();

for(i=0x80;i》0;i/=2)

{

LIGHT_SCK_1() ;

delay_us();

SDA_R();

//SDA_W();

//LIGHT_DTA_0();

//LIGHT_DTA_0() ;

//delay_us();

if(LIGHT_DTA())

val=(val|i);

delay_us();

//SDA_R();

LIGHT_SCK_0() ;

delay_us();

}

SDA_W();

if(ack)

LIGHT_DTA_0();

else

LIGHT_DTA_1();

delay_us();

LIGHT_SCK_1() ;

delay_us();

LIGHT_SCK_0() ;

LIGHT_DTA_1();

return val;

}

unsigned short get_light(void)

{

unsigned char ack1=1;

unsigned char ack2=1;

unsigned char ack3=1;

unsigned char ack4=1;

unsigned char ack5=1;

unsigned char ack6=1;

unsigned char ack7=1;

unsigned char t0;

unsigned char t1;

unsigned short t;

P1DIR |= (1 《《 1);

delay_nms(200);

start_i2c();

ack1=i2c_send(0x46);

if(ack1)

return 255;

ack2=i2c_send(0x01);

if(ack2)

return 254;

stop_i2c(); //init

start_i2c();

ack3=i2c_send(0x46);

if(ack3)

return 253;

ack4=i2c_send(0x01);

if(ack4)

return 252;

stop_i2c();//power

start_i2c();

ack5=i2c_send(0x46);

if(ack5)

return 251;

ack6=i2c_send(0x10);

if(ack6)

return 250;

stop_i2c();

delay_nms(1500);

start_i2c();

ack7=i2c_send(0x47);

if(ack7)

return 249;

t0 = i2c_read(1);

t1 = i2c_read(0);

stop_i2c();

t = ((short)t0)《《8;

t |= t1;

return t;

}

在主函数中加入以下函数(注意,此处就是最容易忽视的地方,uint应该是unsigned int,不能是范围太小的类型):

char wan,qian,bai,shi,ge;

void conversion(unsigned int temp_data)

{

wan=(uint)temp_data/10000 ;

temp_data=temp_data%10000;

qian=(uint)temp_data/1000 ;

temp_data=temp_data%1000;

bai=(uint)temp_data/100;

temp_data=temp_data%100;

shi=(uint)temp_data/10;

temp_data=temp_data%10;

ge=(uint)temp_data;

}

调用光照获取函数,讲数据转为字符串:

uint32 w;

w = get_light()/1.2;

conversion(w);

char buf[5];

buf[0] = wan + 48;

buf[1] = qian + 48;

buf[2] = bai + 48;

buf[3] = shi + 48;

buf[4] = ge + 48;