智能移动探测器
操作系统 | 云服务/平台 | 技术难度 | 关注领域 |
---|---|---|---|
RTOS | Gizwits Cloud | 中级 | Healthcare,Sensors |
任务目标
主要是将ADXL345传感器连接到Gokit开发板提供的SPI接口,以收集三轴加速度值信息,当轴加速度值变化超出设定范围时,LED亮起。
所需材料/所需清单/工具
• BG96
• Gokit4
• Led
源码/示例/可执行的应用程序
附加资料
搭建/在组装说明
使用的零件
以下是此项目中使用的项目。
1. windows7 台式机。
2. Gokit4开发板
3. ADXL345传感器,用来检测轴加速度值。
4.led灯,当轴加速度值变化超过设定的阈值时,点亮led灯。
5.杜邦线,用来作为导线连接其他部件。
部署项目
1.根据demo的需求,结合板载资源购买合适的器件。
2. 检测器件是否可用。
3.搭建和调试硬件电路。
4.创建本地项目“demo-Smart-Motion-detector”。
5.移植相关源代码。
6.开发采集轴加速度值相关的功能。
7.联合调试。
8.上传代码到github。
工作流程
下面是测试项目的使用说明。
现在我们介绍“demo-Smart-Motion-detector”的工作流程。
gagentMain---->sensorInit---->led_init---->motion_init---->tx_timer_create
在接口“tx_timer_create”中注册一个回调函数,当时间到调用名为“userTimerCB”的回调函数。
demo-Smart-Motion-detector/main/main.c
void gagentMain( void )
{
getFreeHeap();
sensorInit();
gizwitsInit();
}
GAgent调用了名为gagentMain的函数,GAgent的主要作用是数据转发,它是设备数据,云计算和应用程序端(APP)之间的数据交互桥梁。在函数sensorInit中,做一些传感器初始化。
void sensorInit(void)
{
int32 ret = -1;
gizLog(LOG_INFO,"Sensor initialization ...\n");
led_init();
motion_init();
txm_module_object_allocate(&userTimer, sizeof(TX_TIMER));
ret = tx_timer_create(userTimer, "userTimer", userTimerCB, NULL, 1,
200, TX_AUTO_ACTIVATE);
if(ret != TX_SUCCESS)
{
gizLog(LOG_ERROR,"Failed to create UserTimer.\n");
}
}
void led_init()
{
led_gpio_config();
led_on_off(false,led_green); //init status is off
led_on_off(true,GPIO_BLUE); //init status is off
}
void motion_init()
{
adxl345_init();
}
demo-Smart-Motion-detector/driver/adxl345/adxl345.c
/*do some initialization about SPI and ADXL345 sensor.*/
void adxl345_init()
{
static uint8 data;
uint8 *data_addr;
spi_init();
data_addr = spi_reg_read(0x00); //read device id;
qapi_Timer_Sleep(10, QAPI_TIMER_UNIT_TICK, true);
data = *data_addr;
gizLog(LOG_INFO, "Device id is 0xx\n", data);
spi_reg_write(0x31, 0x2B);
spi_reg_write(0x2C, 0x08);
spi_reg_write(0x2D, 0x08);
spi_reg_write(0x2E, 0x00);
spi_reg_write(0x2F, 0x00);
spi_reg_write(0x2E, 0x02);
spi_reg_write(0x38, 0x9F);
}
demo-Smart-Motion-detector/driver/spi/spi.c
/*do SPI initialization*/
void spi_init(void)
{
/*Get a handle to an SPI instance.*/
qapi_SPIM_Open(QAPI_SPIM_INSTANCE_6_E, &spi_hdl);
/*Turn on all resources required for a successful SPI transaction.*/
qapi_SPIM_Power_On(spi_hdl);
/*spi interface config*/
/*set the spi mode, determined by slave device*/
spi_config.SPIM_Mode = QAPI_SPIM_MODE_3_E;
/*set CS low as active, determined by slave device*/
spi_config.SPIM_CS_Polarity = QAPI_SPIM_CS_ACTIVE_LOW_E;
spi_config.SPIM_endianness = SPI_LITTLE_ENDIAN;
spi_config.SPIM_Bits_Per_Word = 8;
spi_config.SPIM_Slave_Index = 0;
/*config spi clk about 1Mhz */
spi_config.Clk_Freq_Hz = 1000000;
spi_config.SPIM_CS_Mode = QAPI_SPIM_CS_KEEP_ASSERTED_E;
/*don't care, set 0 is ok.*/
spi_config.CS_Clk_Delay_Cycles = 0;
/*don't care, set 0 is ok.*/
spi_config.Inter_Word_Delay_Cycles = 0;
spi_config.loopback_Mode = 0;
}
/*used to write data to registers*/
qapi_Status_t spi_reg_write(uint8 reg, uint8 data)
{
qapi_Status_t res = QAPI_OK;
qapi_SPIM_Descriptor_t spi_desc;
int num;
tx_buf[0] = reg & 0x3f;
tx_buf[1] = data;
spi_desc.rx_buf = rx_buf;
spi_desc.tx_buf = tx_buf;
spi_desc.len = 2;
spi_status.status = 0;
spi_status.read_addr = NULL;
spi_status.len = 1;
/*used to performs a data transfer over the SPI bus */
res = qapi_SPIM_Full_Duplex(spi_hdl, &spi_config, &spi_desc, 1, qapi_spi_cb_func, &spi_status, false);
if (res != QAPI_OK)
return res;
for(num = 0; num < 100; num++)
{
gizLog(LOG_INFO,"num = %d\n", num);
if (spi_status.status == QAPI_SPI_COMPLETE)
{
gizLog(LOG_INFO,"spi write reg(0xx) = 0xx\n", reg, data);
return QAPI_OK;
}
else if (spi_status.status != 0)
{
gizLog(LOG_INFO,"spi write err\n");
return QAPI_ERROR;
}
qapi_Timer_Sleep(1, QAPI_TIMER_UNIT_TICK, true);
}
return QAPI_ERR_TIMEOUT;
}
demo-Smart-Motion-detector/main/main.c
/*”userTimerCB” is registered in the inteface named “tx_timer_create”*/
void ICACHE_FLASH_ATTR userTimerCB(void)
{
static uint8_t ctime = 0;
static uint8_t ccount = 0;
GETAXIS_ERROR_t status = 0;
static uint8_t num = 0;
int tmp_x = 0, tmp_y = 0, tmp_z = 0;
int32_t X_axis_Value = 0;
int32_t Y_axis_Value = 0;
int32_t Z_axis_Value = 0;
if (QUERY_INTERVAL < ctime)
{
ctime = 0;
status=getaxis(&X_axis_Value,&Y_axis_Value,&Z_axis_Value);
if( status != GETAXIS_OK)
{
return;
}
if(num == 0)
{
old_axis_val.X = X_axis_Value;
old_axis_val.Y = Y_axis_Value;
old_axis_val.Z = Z_axis_Value;
num += 1;
}
else
{
tmp_x = old_axis_val.X > X_axis_Value ? old_axis_val.X - X_axis_Value:X_axis_Value - old_axis_val.X;
tmp_y = old_axis_val.Y > Y_axis_Value ? old_axis_val.Y - Y_axis_Value:Y_axis_Value - old_axis_val.Y;
tmp_z = old_axis_val.Z > Z_axis_Value ? old_axis_val.Z - Z_axis_Value:Z_axis_Value - old_axis_val.Z;
gizLog(LOG_INFO, "tmp_x= %d, tmp_y = %d , tmp_z = %d\n", tmp_x, tmp_y, tmp_z);
if(tmp_x > X_AXIS_THRESHOLD || tmp_y > Y_AXIS_THRESHOLD || tmp_z > Z_AXIS_THRESHOLD)
{
led_on_off(true,led_green);
gizLog(LOG_INFO, "LED ON\n");
}
else
{
led_on_off(false, led_green);
gizLog(LOG_INFO, "LED OFF\n");
}
old_axis_val.X = X_axis_Value;
old_axis_val.Y = Y_axis_Value;
old_axis_val.Z = Z_axis_Value;
}
currentDataPoint.valueX_axis_Value = X_axis_Value;
currentDataPoint.valueY_axis_Value = Y_axis_Value;
currentDataPoint.valueZ_axis_Value = Z_axis_Value;
}
ctime++;
}
demo-Smart-Motion-detector/driver/adxl345/adxl345.c
/*used to get three axis acceleration values*/
uint8_t getaxis(int32_t *X_axis_Value, int32_t *Y_axis_Value, int32_t *Z_axis_Value)
{
qapi_Status_t res = QAPI_ERROR;
uint8_t data;
uint8_t *data_addr;
SENSOR_DATA_TypeDef axis_converted_avg;
data_addr = spi_reg_read(0x30);
if (data_addr == NULL) {
gizLog(LOG_ERROR, "read 0x30 err\n");
return GETAXIS_ERR;
}
qapi_Timer_Sleep(10, QAPI_TIMER_UNIT_TICK, true);
data = *data_addr;
if (data & 0x02)
{
res = ADXL345_READ_FIFO(&axis_converted_avg);
if (res != QAPI_OK)
return GETAXIS_ERR;
*X_axis_Value = axis_converted_avg.X;
*Y_axis_Value = axis_converted_avg.Y;
*Z_axis_Value = axis_converted_avg.Z;
return GETAXIS_OK;
}
else
{
return GETAXIS_NO_INT;
}
}
demo-Smart-Motion-detector/driver/spi/spi.c
/*used to read data from registers*/
uint8 *spi_reg_read(uint8 reg)
{
qapi_Status_t res = QAPI_OK;
qapi_SPIM_Descriptor_t spi_desc;
int num;
tx_buf[0] = reg | 0x80 & 0xbf;
tx_buf[1] = 0xff;
rx_buf [0] = 0;
rx_buf [1] = 0;
spi_desc.rx_buf = rx_buf;
spi_desc.tx_buf = tx_buf;
spi_desc.len = 2;
spi_status.status = 0;
spi_status.read_addr = NULL;
spi_status.len = 1;
res = qapi_SPIM_Full_Duplex(spi_hdl, &spi_config, &spi_desc, 1, qapi_spi_cb_func, &spi_status, false);
gizLog(LOG_INFO,"read spi end\n");
if (res != QAPI_OK)
return NULL;
return rx_buf + 1;
}
demo-Smart-Motion-detector/driver/adxl345/adxl345.c
/*used to get raw data from slave device*/
qapi_Status_t ADXL345_READ_FIFO(SENSOR_DATA_TypeDef *axis_converted_avg)
{
uint16_t axis_raw_data[10][3];
static uint8_t data_buf[6];
uint8 *data_addr;
SENSOR_DATA_TypeDef axis_converted[10];
for (uint8_t i = 0; i < 10; i++)
{
for(uint8_t m = 0; m < 6; m++) {
data_addr = spi_reg_read(0x32 + m);
qapi_Timer_Sleep(10, QAPI_TIMER_UNIT_TICK, true);
data_buf[m] = *data_addr;
}
/*x, y, z raw val*/
for(uint8_t n = 0; n < 6; n++){
gizLog(LOG_INFO, "data_buf[%d] = 0x%x\n", n, data_buf[n]);
}
axis_raw_data[i][0] = data_buf[0] | (((uint16_t)data_buf[1]) << 8);
axis_raw_data[i][1] = data_buf[2] | (((uint16_t)data_buf[3]) << 8);
axis_raw_data[i][2] = data_buf[4] | (((uint16_t)data_buf[5]) << 8);
gizLog(LOG_INFO, "dtat[%d].x = 0x%x, dtat[%d].y = 0x%x, dtat[%d].z = 0x%x\n", i, axis_raw_data[i][0], i, axis_raw_data[i][1], i, axis_raw_data[i][2]);
axis_converted[i] = ADXL345_DATA_CONVERT(axis_raw_data[i]);
}
*axis_converted_avg = ADXL345_AVERAGE(axis_converted, 10);
return QAPI_OK;
}
/*used to deal with raw data*/
SENSOR_DATA_TypeDef ADXL345_DATA_CONVERT(uint16_t *data)
{
int8_t sign = 1;
uint16_t temp = 0;
uint8_t i = 0;
uint32_t val = 0;
SENSOR_DATA_TypeDef converted_data;
for (i = 0; i < 3; i++)
{
sign = 1;
temp = data[i];
if ((temp & 0xF000) == 0xF000)
{
sign = -1;
temp = -temp;
}
if (i == 0)
{
/*calibrate out x axis offset*/
converted_data.X = ((temp & 0x0FFF) * 4) * sign;
}
else if (i == 1)
{
/*calibrate out y axis offset*/
converted_data.Y = ((temp & 0x0FFF) * 4) * sign;
}
else if (i == 2)
{
/*calibrate out z axis offset*/
converted_data.Z = ((temp & 0x0FFF) * 4) * sign;
}
}
gizLog(LOG_INFO, "converted_data.X = %d, converted_data.Y = %d, converted_data.Z = %d\n", converted_data.X, converted_data.Y, converted_data.Z);
return converted_data;
}
/*Average 10 sets of raw data*/
SENSOR_DATA_TypeDef ADXL345_AVERAGE(SENSOR_DATA_TypeDef *data, uint8_t len)
{
SENSOR_DATA_TypeDef result = {0};
uint32_t i;
for (i = 0; i < len; i++)
{
result.X += data[i].X;
result.Y += data[i].Y;
result.Z += data[i].Z;
}
result.X /= len;
result.Y /= len;
result.Z /= len;
return result;
}
1.从该github链接地址处下载代码。
2.编译代码并烧录镜像到Gokit4开发板。
3.将ADXL345传感器连接到Gokit4开发板的SPI接口上。
4.将LED的一个引脚连接到开发板的D9引脚,另一个引脚连接到vcc。
5.USB数据线连接到PC和Gokit开发板。
6.打开串口调试助手。
7.晃动ADXL345传感器,可以看到数据变化。
8.当检测到轴加速度的变化超过设定的范围,led将会被点亮。
贡献者信息
姓名 | 公司 |
---|---|
Zhen sunzhen@thundersoft.com |
Thundersoft |
Rong yangrong0925@thundersoft.com |
Thundersoft |
Jie wangjie0508@thundersoft.com |
Thundersoft |
Kou kouzw0723@thundersoft.com |
Thundersoft |
Eric yansh0810@thundersoft.com |
Thundersoft |
>>浏览更多Qualcomm硬件案例:http://qualcomm.csdn.net/m/zone/qualcomm2016/project
Qualcomm 开发者专区是 Qualcomm 联合CSDN 共同打造的面向中国开发者的技术专区。致力于通过提供全球最新资讯和最多元的技术资源及支持,为开发者们打造全面一流的开发环境。本专区将以嵌入式、物联网、游戏开发、Qualcomm® 骁龙™处理器的软件优化等技术为核心,打造全面的开发者技术服务社区,为下一代高性能体验和设计带来更多的想法和灵感。
加入 Qualcomm 开发者专区申请成为“Qualcomm荣誉技术大使”
“Qualcomm荣誉技术大使”是Qualcomm开发者社区对开发者用户技术能力与影响力的认证体现,该荣誉代表Qualcomm社区对用户贡献的认可与肯定。
立即申请招贤纳士
Qualcomm在中国的业务发展迅速,每年提供大量的技术岗位,分布在北京,上海,深圳等地。Qualcomm开发者社区是开发者藏龙卧虎之地,Qualcomm中国HR特别设立了招聘通道,欢迎开发者同学踊跃报名。