使用手机BLE连接VEML6075的可穿戴平台紫外检测功能开发

使用手机BLE连接VEML6075的可穿戴平台紫外检测功能开发

文档编号

TN_TEMPLATE0101_A0

关键字

BLE,VEML6075,可穿戴,紫外检测

摘要

本技术笔记对使用手机BLE连接VEML6075的可穿戴平台紫外检测功能开发进行说明

Mars4zhu


目 录

1 总述 1

2 紫外线检测及其传感器VEML6075介绍 1

2.1 紫外线及其检测介绍 1

2.2 VEML6075介绍 1

3 VEML6075在FRDM-KW41Z上的移植 2

3.1 Driver例程修改 2

3.1.1 原例程运行结果与代码分析 3

3.1.2 i2c_polling_transfer例程修改适配VEML6075 4

3.2 BLE例程修改 8

4 版本历史(Revision History) 14


插图索引

图 21 紫外UVA与UVB频谱分布 1

图 22   VEML6075的命令协议格式 2

图 23   VEML6075的命令代码与寄存器描述 2

图 31   i2c_polling_transfer例程硬件连线 3

图 32 不连接I2C1(master)和I2C0(slave)接线的i2c_polling_transfer运行结果 3

图 33 连接I2C1(master)和I2C0(slave)接线的i2c_polling_transfer运行结果 4

图 34   i2c_polling_transfer例程修改后读取VEML6075紫外检测结果 8

图 35   FRDM-KW41Z和VEML6075的连线 9

图 36   BLE例程blood_pressure_sensor修改后的截图界面 12

图 37   blood_pressure_sensor例程修改后读取VEML6075并在手机App显示紫外指数截图 13


表格索引

错误!未找到目录项。

1 总述

为了评估可穿戴设备的紫外检测,使用Vishay出品的VEML6075紫外检测传感器芯片,并利用具备低功耗蓝牙BLE连接功能的开发板FRDM-KW41Z,实现从手机、平板等便携终端的BLE连接到可穿戴平台,显示紫外线指数检测结果的功能。

2 紫外线检测及其传感器VEML6075介绍

2.1 紫外线及其检测介绍

紫外线主要包括365nm波长(320-400nm,3dB带宽为350--375nm)的UVA区域和330nm波长(280--4430nm,3dB带宽为315--340nm)的UVB区域,

wpsF062.tmp

wpsF072.tmp

21 紫外UVA与UVB频谱分布

UVB波长较短伤害较大,不过仅占太阳能的0.1%,而UVA虽然波长长单个光子伤害低,但是能量丰富,占了太阳能的4.5%。

2.2 VEML6075介绍

VEML6075是一个紫外检测传感器芯片,提供标准的I2C接口,并提供多种命令来设置或读取传感器参数。其读写格式和命令列表如下:

wpsF0C1.tmp

22  VEML6075的命令协议格式

wpsF0C2.tmp

23  VEML6075的命令代码与寄存器描述

3 VEML6075在FRDM-KW41Z上的移植

FRDM-KW41Z是具备多协议无线功能的开发板,特别支持低功耗蓝牙BLE 4.2。为了实现在FRDM-KW41Z上移植VEML6075传感器,需要参照LPC824_VEML6075例程,对FRDM-KW41Z的例程进行修改。

3.1 Driver例程修改

出于简单起见,先使用i2c-river例程修改,这里选择i2c_polling_transfer例程。

3.1.1 原例程运行结果与代码分析

首先运行i2c-polling_transfer例程,注意例程运行过程前,需要分别连接I2C0和I2C1的SCL和SDA引脚。连接线如下图:

wpsF0C3.tmp

31  i2c_polling_transfer例程硬件连线

运行结果如下:

wpsF0C4.tmp

32 不连接I2C1(master)和I2C0(slave)接线的i2c_polling_transfer运行结果

wpsF0D5.tmp

33 连接I2C1(master)和I2C0(slave)接线的i2c_polling_transfer运行结果

3.1.2 i2c_polling_transfer例程修改适配VEML6075

根据VEML6075的数据手册,采用I2C1作为I2C-Master来设置和读取VEML6075的参数。

原有的LPC824_VEML6075例程的代码主体结构不需要变化,只需要修改适配最终的I2C通讯相关的代码部分,即SetupXferRecAndExecute函数。并且复制delay和delay_Long函数。

#define VEML6075_I2C_ADDR_7BIT (0x10)

#define I2C_ADDR_7BIT VEML6075_I2C_ADDR_7BIT

static uint8_t txData[16];

static uint8_t rxData[16];

static int txSize, rxSize;

void delay(unsigned int n)

{

while(n!=0){n--;}

}

void delay_Long(unsigned long n)

{

unsigned int i;

for(i=0;i<n;i++)

  delay(100);

}

/* Function to setup and execute I2C transfer request */

static void SetupXferRecAndExecute(uint8_t devAddr,

uint8_t *txBuffPtr,

uint16_t txSize,

uint8_t *rxBuffPtr,

uint16_t rxSize)

{

   memset(&masterXfer, 0, sizeof(masterXfer));

    masterXfer.slaveAddress = VEML6075_I2C_ADDR_7BIT;

    masterXfer.direction = kI2C_Write;

    masterXfer.subaddress = 0;

    masterXfer.subaddressSize = 0;

    masterXfer.data = txBuffPtr;

    masterXfer.dataSize = txSize;

    masterXfer.flags = kI2C_TransferNoStopFlag;

    I2C_MasterTransferBlocking(EXAMPLE_I2C_MASTER_BASEADDR, &masterXfer);

   memset(&masterXfer, 0, sizeof(masterXfer));

    masterXfer.slaveAddress = VEML6075_I2C_ADDR_7BIT;

    masterXfer.direction = kI2C_Read;

    masterXfer.subaddress = 0;

    masterXfer.subaddressSize = 0;

    masterXfer.data = rxBuffPtr;

    masterXfer.dataSize = rxSize;

    masterXfer.flags = kI2C_TransferRepeatedStartFlag;

    I2C_MasterTransferBlocking(EXAMPLE_I2C_MASTER_BASEADDR, &masterXfer);

}

需要注意的是在读参数的时候,整个I2C协议帧包括先写命令和再读参数两部分,两部分的I2C中间不需要STOP,即第一部分的写命令的I2C为 kI2C_TransferNoStopFlag,第二个的flags为kI2C_TransferRepeatedStartFlag。否则会出现一直停留在I2C协议帧的第二部分代码里。

Main函数的代码修改为如下:

#define DEBUGOUT PRINTF

#define printf PRINTF

int main(void)

{

    BOARD_InitPins();

    BOARD_BootClockRUN();

    BOARD_InitDebugConsole();

    PRINTF("\r\nI2C example -- MasterPolling_VEML6075\r\n");

/*2.Set up i2c master to send data to slave*/

/*

     * masterConfig.baudRate_Bps = 100000U;

     * masterConfig.enableStopHold = false;

     * masterConfig.glitchFilterWidth = 0U;

     * masterConfig.enableMaster = true;

     */

    I2C_MasterGetDefaultConfig(&masterConfig);

    masterConfig.baudRate_Bps = I2C_BAUDRATE;

    sourceClock = I2C_MASTER_CLK_FREQ;

    I2C_MasterInit(EXAMPLE_I2C_MASTER_BASEADDR, &masterConfig, sourceClock);

// 初始化VEML6075,发送0x00命令,参数为0x40

txSize = 3;

rxSize = 0;

txData[0]=0x00;

txData[1]=0x40;//0x10;

txData[3]=0x00;//0x10;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

txSize = 1;

rxSize = 2;

txData[0]=0x0C;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

/* Enter the task loop */

DEBUGOUT("Initialization OK\n");

float a = 2.22, b = 1.33, c = 2.95, d = 1.74;

while(1) {

uint16_t UVA_data, UVB_data, UVcomp1_data, UVcomp2_data, UV_id;

float UVAcalc, UVBcalc;

// 发送0x07命令,读取UVA_data寄存器的数值

txData[0]=0x07;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

UVA_data = (rxData[1] << 8) + rxData[0];

delay(100);

// 发送0x09命令,读取UVB_data寄存器的数值

txData[0]=0x09;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

UVB_data = (rxData[1] << 8) + rxData[0];

delay(100);

// 发送0x0A命令,读取UVcomp1_data寄存器的数值

txData[0]=0x0A;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

UVcomp1_data = (rxData[1] << 8) + rxData[0];

delay(100);

// 发送0x0B命令,读取UVcomp2_data寄存器的数值

txData[0]=0x0B;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

UVcomp2_data = (rxData[1] << 8) + rxData[0];

delay(100);

// 发送0x0C命令,读取UV_id寄存器的数值

txData[0]=0x0C;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

UV_id = (rxData[1] << 8) + rxData[0];

delay(100);

printf("UVA_data = %d, UVB_data = %d, UVcomp1_data = %d, UVcomp2_data = %d, UV_id = %x\n",

UVA_data, UVB_data, UVcomp1_data, UVcomp2_data, UV_id);

UVAcalc = (float)UVA_data -  a*(float)UVcomp1_data - b*(float)UVcomp2_data;

UVBcalc = (float)UVB_data -  c*(float)UVcomp1_data - d*(float)UVcomp2_data;

printf("UVAcalc = %f, UVBcalc = %f\n\n", UVAcalc, UVBcalc);

delay_Long(20000);

}

}

最终运行结果为:

wpsF0F5.tmp

34  i2c_polling_transfer例程修改后读取VEML6075紫外检测结果

3.2 BLE例程修改

项目要求实现BLE连接功能,最终在手机上显示紫外检测结果,因此在BLE例程上进行修改。为了方便显示,选择blood_pressure_sensor例程。将原例程中的模拟的心率传感数据替换为读取的紫外显示数据,最终在App中可以直观的看到数据结果(虽然App显示为心率,但是实际明白是紫外指数就行。

首先硬件连线,将VEML6075的VCC、GND以及I2C接线SCL、SDA分别于FRDM-KW41Z连接即可。

wpsF0F6.tmp

35  FRDM-KW41Z和VEML6075的连线

基本同样的代码修改,在blood_pressure_sensor.c文件中添加如下代码:

// Mars4zhu Add for VEML6075

#include "fsl_i2c.h"

// #include "pinmux.h"

#define EXAMPLE_I2C_MASTER_BASEADDR I2C1

#define I2C_MASTER_CLK_SRC I2C1_CLK_SRC

#define I2C_MASTER_CLK_FREQ CLOCK_GetFreq(I2C1_CLK_SRC)

#define I2C_BAUDRATE 100000U

#define I2C_DATA_LENGTH 32U

i2c_master_config_t masterConfig;

uint32_t sourceClock;

i2c_master_transfer_t masterXfer;

#define VEML6075_I2C_ADDR_7BIT (0x10)

#define I2C_ADDR_7BIT VEML6075_I2C_ADDR_7BIT

static uint8_t txData[16];

static uint8_t rxData[16];

static int txSize, rxSize;

void delay(unsigned int n)

{

while(n!=0){n--;}

}

void delay_Long(unsigned long n)

{

unsigned int i;

for(i=0;i<n;i++)

  delay(100);

}

/* Function to setup and execute I2C transfer request */

static void SetupXferRecAndExecute(uint8_t devAddr,

uint8_t *txBuffPtr,

uint16_t txSize,

uint8_t *rxBuffPtr,

uint16_t rxSize)

{

   memset(&masterXfer, 0, sizeof(masterXfer));

    masterXfer.slaveAddress = VEML6075_I2C_ADDR_7BIT;

    masterXfer.direction = kI2C_Write;

    masterXfer.subaddress = 0;

    masterXfer.subaddressSize = 0;

    masterXfer.data = txBuffPtr;

    masterXfer.dataSize = txSize;

    masterXfer.flags = kI2C_TransferNoStopFlag;

    I2C_MasterTransferBlocking(EXAMPLE_I2C_MASTER_BASEADDR, &masterXfer);

   memset(&masterXfer, 0, sizeof(masterXfer));

    masterXfer.slaveAddress = VEML6075_I2C_ADDR_7BIT;

    masterXfer.direction = kI2C_Read;

    masterXfer.subaddress = 0;

    masterXfer.subaddressSize = 0;

    masterXfer.data = rxBuffPtr;

    masterXfer.dataSize = rxSize;

    masterXfer.flags = kI2C_TransferRepeatedStartFlag;

    I2C_MasterTransferBlocking(EXAMPLE_I2C_MASTER_BASEADDR, &masterXfer);

}

void VEML6075_Init()

{

// 修改开发板引脚设置,I2C1功能引出到PTC2/PTC3

    BOARD_InitI2C();

// 初始化VEML6075,发送0x00命令,参数为0x40

   I2C_MasterGetDefaultConfig(&masterConfig);

    masterConfig.baudRate_Bps = I2C_BAUDRATE;

    sourceClock = I2C_MASTER_CLK_FREQ;

    I2C_MasterInit(EXAMPLE_I2C_MASTER_BASEADDR, &masterConfig, sourceClock);

txSize = 3;

rxSize = 0;

txData[0]=0x00;

txData[1]=0x40; // 800ms

txData[3]=0x00; ;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

txSize = 1;

rxSize = 2;

txData[0]=0x0C;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

}

void VEML6075_GetUV_data(uint16_t *UVA_data, uint16_t *UVB_data)

{

    txSize = 1;

rxSize = 2;

// 发送0x07命令,读取UVA_data寄存器的数值

txData[0]=0x07;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

*UVA_data = (rxData[1] << 8) + rxData[0];

delay(100);

// 发送0x09命令,读取UVB_data寄存器的数值

txData[0]=0x09;

SetupXferRecAndExecute(I2C_ADDR_7BIT, txData,txSize, rxData, rxSize);

*UVB_data = (rxData[1] << 8) + rxData[0];

delay(100);

}

然后在BleApp_Init()函数中添加VEML6075_Init();

void BleApp_Init(void)

{

/* Initialize application support for drivers */

    BOARD_InitAdc();

    VEML6075_Init();

}

最后将TimerMeasurementCallback()函数修改为读取VEML6075的紫外检测指数。

static void TimerMeasurementCallback(void * pParam)

{

uint16_t UVA_data, UVB_data;

      VEML6075_GetUV_data(&UVA_data, &UVB_data);

      bpsMeasurement_t bp;

      bp.unit = gBps_UnitInkPa_c;

      bp.systolicValue = UVA_data;

      bp.diastolicValue = UVB_data;

      bp.meanArterialPressure = (bp.systolicValue + bp.diastolicValue * 2)/3;

      Bps_RecordBloodPressureMeasurement(service_blood_pressure, &bp);

}

最后编译运行,在App中得到如下功能。必须认清App中的心率参数systolic和diastolic两个值现在分别是VEML6075传感器检测到的UVA和UVB紫外指数。

wpsF116.tmp

36  BLE例程blood_pressure_sensor修改后的截图界面

使用手机的相机LED曝光灯(手电筒功能)照射VEML6075,可以看到紫外线指数急剧增加。因此手机App成功通过BLE连接读取到了紫外检测结果。

wpsF117.tmp

37  blood_pressure_sensor例程修改后读取VEML6075并在手机App显示紫外指数截图

4 版本历史(Revision History)

版本号

发布时间

内容

A0

2017-06-30

初次编写

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值