智能移动探测器

操作系统 云服务/平台 技术难度 关注领域
RTOS Gizwits Cloud 中级 Healthcare,Sensors

 

任务目标

主要是将ADXL345传感器连接到Gokit开发板提供的SPI接口,以收集三轴加速度值信息,当轴加速度值变化超出设定范围时,LED亮起。

 

所需材料/所需清单/工具

  • BG96

  • Gokit4

  • ADXL345 sensor

  • Led

  • Dupoint line

源码/示例/可执行的应用程序

  • Source Code

附加资料

  • 智能移动探测器视频(网盘密码:g95y)

搭建/在组装说明

使用的零件

以下是此项目中使用的项目。

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荣誉技术大使”是Qualcomm开发者社区对开发者用户技术能力与影响力的认证体现,该荣誉代表Qualcomm社区对用户贡献的认可与肯定。

立即申请

Qualcomm 解决方案

 

招贤纳士

Qualcomm在中国的业务发展迅速,每年提供大量的技术岗位,分布在北京,上海,深圳等地。Qualcomm开发者社区是开发者藏龙卧虎之地,Qualcomm中国HR特别设立了招聘通道,欢迎开发者同学踊跃报名。