最近接到一个内部的项目,要求设计一个工厂在线检测关键设备开工率的检测模块,也就是检测设备的利用率,正好收到了CC2541的开发套件,该套件包含
• 1 × CC2540 USB dongle
• 1 × CC2541 Keyfob board
• 1 × Keyfob plastic case
• 1 × CC Debugger with cables
• 1 × CR2032 Battery
仔细研究了一下,只需要在网上购买一个带I2C接口的电流检测模块就可以搭建一个简易的设备工作状态的简易模块了,说干就干。初步设计的基于CC2541开发套件的电流检测模块的框图如下:
由于电流检测模块INA219的供电电压为3-5.5V,使用CC2541的纽扣电池供电显然不合适,所以需要额外增加以一个电池供电,手上有一些手机的锂电池,索性直接用手机的电池供电。模块之间使用杜邦线连接起来就有个如下的Demo.
这里说明一下CC2541上各个功能模块的作用。
1、 Buzzer蜂鸣器,用于设备故障或人为移动,改动的报警
2、 加速度计BMA250,用于检测设备是否有移动或检测模块是否被拆装或移动。
3、 TEST接口,使用IIC接口连接剑流检测模块INA219,该模块具备业界最高的精确度以及最小型的尺寸,不仅能监控分流电阻器上的压降,感测分流供电电压,同时还可计算电源。该器件采用 SOT23 封装,该模块的供电单独采用4.3V的锂电池供电。
4、 按键用于手动发送设备数据,以及自检,BLE广播功能。
有了方案,下面就开始开发吧。
首先需要把CC2541的开发板Keyfob上的基本功能熟悉,如电池电量电测,加速度检测,蜂鸣器报警。这个可以参考开发套件附带的说明书或笔者撰写的另外一篇评测基本功能的文章。
【文章链接】https://e2echina.ti.com/question_answer/wireless_connectivity/bluetooth/f/103/t/179713
由于该项目的第一步实际调试是基于PC机的,所以仍然需要利用BTool工具来测试和调试,从手册上实际查找得知,获取keyfob板上加速度计BMA250的数据,仍然需要先打开数据通告功能。需要先发送0x0034(handle)+0x01:00 打开加速度计功能,然后再打开加速度计的数据上报功能,发送0x003B(handle) + 0x01:00,然后就可以实时读取加速度计的数据,一读取X轴为例,发送0x003A,这时候晃动keyfob板子,就可以实时看到X轴的加速度值得变化。
到此加速度计的功能可以实现了,由于keyfob开发板上的加速度计BMA250使用的是SPI接口,I2C接口是单独引出来,在TEST接口上,可以利用开发套件附带的JTAG线和转接板连接到TEST接口上,就可以顺利连接电流检测模块。在开发套件附带的keyfobdemo程序中添加和INA219通讯程序即可。在这里列出该通讯子程序,以供大家参考。
1、编写并添加INA219驱动
写一个INA219.c(存放在“……\BLE-CC254x-1.5.0.16\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************
//name: INA219.c
//introduce: INA219驱动源文件
//author: @ttkx
//changetime: 2019.09.03
//email: wang_wensong@163.com
//******************************************************************************
#include "INA219.h"
#include "GUA_sensor.h"
#include "hal_i2c.h"
/*********************宏定义************************/
//Slave address
#define "INA219_DEV_ADDR 0x40 //0 1000000(最高位无用、INA219的地址配置脚A1和A0接GND)
// INA219 register addresses
#define INA219_REG_ADDR_CURRENT 0x00
#define INA219_REG_ADDR_CONFIG 0x01
/* Register length */
#define CURRENT_REG_LEN 2
/*********************内部函数************************/
static UINT8 INA219_Config(UINT8 *p_Data, UINT8 nWrite_Read);
//******************************************************************************
//name: INA219_Init
//introduce: INA219初始化
//parameter:
//return: TURE:初始化成功,FALSE:初始化不成功
//author: @ttkx
//email: wang_wensong@163.com
//changetime: 2019.09.03
//******************************************************************************
UINT8 INA219_Init(void)
{
UINT8 nRet = TRUE;
UINT8 bConfig_Data_Read[2] = {0};
UINT8 bConfig_Data_Write[2] = {0x70, 0xA0};
//开启iic模块、记录下从机地址、配置频率为100KHz
HalI2CInit(INA219_DEV_ADDR, i2cClock_100KHZ);
//读配置寄存器
nRet = INA219_Config(bConfig_Data_Read, INA219_REGISTER_READ);
if(nRet == FALSE)
{
return(FALSE);
}
//写配置寄存器,开启电流检测功能
nRet = INA219_Config(bConfig_Data_Write, INA219_REGISTER_WRITE);
if(nRet == FALSE)
{
return(FALSE);
}
//读配置寄存器
nRet = INA219_Config(bConfig_Data_Read, INA219_REGISTER_READ);
if(nRet == FALSE)
{
return(FALSE);
}
return(TRUE);
}
//******************************************************************************
//name: INA219_Config
//introduce: 读写INA219的配置寄存器的值
//parameter: pData:数据, nWrite_Read:
//return: none
//author: @ttkx
//email: wang_wensong@163.com
//changetime: 2019.09.03
//******************************************************************************
static UINT8 INA219_Config(UINT8 *pData, UINT8 nWrite_Read)
{
switch(nWrite_Read)
{
case INA219_REGISTER_READ:
if(HalSensorReadReg(INA219_REG_ADDR_CONFIG, pData, CURRENT_REG_LEN))
{
return(TRUE);
}
else
{
return(FALSE);
}
break;
case INA219_REGISTER_WRITE:
if(HalSensorWriteReg(INA219_REG_ADDR_CONFIG, pData, CURRENT_REG_LEN))
{
return(TRUE);
}
else
{
return(FALSE);
}
break;
default:
return(FALSE);
break;
}
}
//******************************************************************************
//name: INA219_Current_Read
//introduce: 读写INA219的电流值
//parameter: pData:读缓冲区
//return: TURE:读取成功,FALSE:读取失败
//author: @ttkx
//email: wang_wensong@163.com
//changetime: 2019.09.03
//******************************************************************************
UINT8 INA219_Current_Read(UINT8* pData)
{
if(HalSensorReadReg(INA219_REG_ADDR_CURRENT, pData, CURRENT_REG_LEN))
{
return(TRUE);
}
else
{
return(FALSE);
}
}
2)写一个头文件INA219.h(存放在“……\BLE-CC254x-1.5.0.16\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************
//name: INA219.h
//introduce: INA219驱动的头文件
//author: @ttkx
//changetime: 2019.09.03
//email: wang_wensong@163.com
//******************************************************************************
#ifndef INA219_H
#define INA219_H
/*********************宏定义************************/
#ifndef UINT8
typedef unsigned char UINT8;
#endif
#ifndef UINT16
typedef unsigned short UINT16;
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define INA219_REGISTER_READ 0
#define INA219_REGISTER_WRITE 1
/*********************外部函数************************/
extern UINT8 INA219_Init(void);
extern UINT8 INA219_Current_Read(UINT8 *pData);
#endif
3)编写传感器控制的驱动
写一个GUA_sensor.c(存放在“……\BLE-CC254x-1.5.0.16\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************
//name: GUA_sensor.c
//introduce: 传感器控制的源文件
//author: @ttkx
//changetime: 2019.09.03
//email: wang_wensong@163.com
//******************************************************************************
#include "GUA_sensor.h"
#include "hal_i2c.h"
/*********************内部变量************************/
static uint8 buffer[24];
//******************************************************************************
//name: HalSensorInit
//introduce: 传感器初始化
//parameter: dev_addr:设备地址
//return: none
//author: @ttkx
//email: wang_wensn@163.com
//changetime: 2019.09.03
//******************************************************************************
void HalSensorInit(uint8 dev_addr )
{
HalI2CInit(dev_addr, i2cClock_100KHZ);
}
//******************************************************************************
//name: HalSensorReadReg
//introduce: 传感器读函数
//parameter: 寄存器addr:地址, pBuf:读缓冲区, nBytes数据长度
//return: TURE:读成功,FALSE:读不成功
//author: @ttkx
//email: wang_wensong@163.com
//changetime: 2019.09.03
//******************************************************************************
bool HalSensorReadReg(uint8 addr, uint8 *pBuf, uint8 nBytes)
{
uint8 i = 0;
/* Send address we're reading from */
if (HalI2CWrite(1,&addr) == 1)
{
/* Now read data */
i = HalI2CRead(nBytes,pBuf);
}
return i == nBytes;
}
//******************************************************************************
//name: HalSensorWriteReg
//introduce: 传感器写函数
//parameter: 寄存器addr:地址, pBuf:写缓冲区, nBytes数据长度
//return: TURE:写成功,FALSE:写不成功
//author: @ttkx
//email: wang_wensong@163.com
//changetime: 2019.09.03
//******************************************************************************
bool HalSensorWriteReg(uint8 addr, uint8 *pBuf, uint8 nBytes)
{
uint8 i;
uint8 *p = buffer;
/* Copy address and data to local buffer for burst write */
*p++ = addr;
for (i = 0; i < nBytes; i++)
{
*p++ = *pBuf++;
}
nBytes++;
/* Send address and data */
i = HalI2CWrite(nBytes, buffer);
return (i == nBytes);
}
写一个GUA_sensor.h(存放在“……\BLE-CC254x-1.5.0.16\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************
//name: GUA_sensor.h
//introduce: 传感器控制的头文件
//author: @ttkx
//changetime: 2019.09.03
//email: wang_wensong@163.com
//******************************************************************************
#ifndef GUA_SENSOR_H
#define GUA_SENSOR_H
#ifdef __cplusplus
extern "C"
{
#endif
/*********************头文件************************/
#include "hal_types.h"
/*********************外部函数************************/
void HalSensorInit(uint8 dev_addr );
bool HalSensorReadReg(uint8 addr, uint8 *pBuf, uint8 nBytes);
bool HalSensorWriteReg(uint8 addr, uint8 *pBuf, uint8 nBytes);
#ifdef __cplusplus
}
#endif
#endif
仅仅是搭建了一个实现基本调试验证功能的Demo,后续还有许多工作要做。如手机或PC极端的监控软件,基于实际工况环境需要开发适配的工程样机来进一步调试,需要研究BLE HUB功能,以适应多个监测终端的情况,还有就是配对和绑定功能的研究。这次时间有些紧,先分享到这里,后续在和大家分享吧。有什么问题,欢迎大家留言,讨论。多谢!