蜜袋鼯 第④贴 RSL10-SENSE-GEVK 玩耍BHI160,步数、运动识别?不用处理,直接获取!!
[复制链接]
本帖最后由 justd0 于 2021-6-27 01:42 编辑
本是周末是要被想出游的家人拉出去当司机,奈何计划有变,于是终于有了自己的周末空闲时间~~撒花啊!
蜜袋鼯 第③贴 上一贴写了 由于官方对RSL10-SENSE-GEVK开发板进行了硬件升级,替换了光照度传感器而导致的相应例程无法使用,故写了个写了个驱动代码分享给大家。
本帖主要内容:
1、介绍姿态传感器、磁力计传感器背景及功能。
2、修改RSL10-SENSE-GEVK官方例程,读取加速度、角速度、磁力计、重力等数据。
3、修改例程中的BHI160应用层配置,将该传感器的特殊数据读取出来,例如:步数检测、运动状态识别等,此处得圈下@w494143467 ,没记错的话你项目里要用它来做运动识别的话,传感器已经实现了,你就不用自己算了哈~~
正文开始:
按照我的项目计划(哦,忘记写了,下一贴写下项目的计划内容吧),还需要运动信息,比如角速度、旋转圈数等,而这些数据可以由开发板上的BHI160传感器获取到。
在玩板之前,本以为这个传感器就是个普通的六轴姿态传感器,
但查了下资料之后才发现,这可是大名鼎鼎的博世 的 姿态传感器啊!
你可能会问博世是啥?跟普通的姿态传感器有啥区别啊。。
哈哈,我也有这个疑问来的,在我看完他的datasheet之后,不得不说这传感器很牛b。
从他官网上的简介可以看到,这个小传感器不仅仅是三轴加速度计、三轴角速度计这么简单,
他在内部就对原始数据进行了处理,能够输出
“加速度计、重力、线性加速度、陀螺仪、陀螺仪未校准、游戏旋转矢量、计步器、步数检测器、
有效运动识别(significant motion)、倾斜检测器、拾取识别、唤醒识别、手势识别、站立、
跑步、骑自行车、开车的活动识别”
而且传感器还能串联一个其他类别的传感器,例如地磁计,就又可以输出
“地磁场、未校准磁场、方向矢量、旋转矢量、地磁旋转矢量”
在官网的下方还可以看到博世已经给提供了这个传感器的使用例程,还有固件?
固件什么鬼,点开看下,原来用传感器串联他家自己传感器的时候,都不用自己配置信息了,直接按照固件烧进去就行了,如下图的BMM150,这不正是RSL10-SENSE-GEVK开发板上的磁力计传感器么~~
另外博世还给提供了详细的驱动库和示例代码,感兴趣的可以去看下
那么回来再看RSL10-SENSE-GEVK开发板的电路图上,就是采用的博世的BHI160+BMM150方案
我们直接打开SDK中的sense_bhi160来先体验下,copy下工程,然后看下例程里面是怎么个逻辑,
我画了个流程图,可以看到这个例程还是很好理解的,
初始化了必要组件之后,初始化了下BHI160传感器,并对它初始化过程做了个计时。
接下来就是注册了三组数据的回调处理函数,以便获取传感器数据更新值。
然后编译下载到开发板,我们通过Jlink RTT viewer 就可以看到数据了,
下图中可以看到,BHI160初始化的时间显示的是805ms
感兴趣的同学可以进入到初始化函数中看下,可以看到用这么久时间进行初始化,其实都是前面说的给BHI160烧写了BMM150的配置程序那个过程。
用RTT viewer看log数据就是一堆的打印信息,如下图所示,
但实时刷新的时候,根本看不清数据是啥。。。
那么我们可以借助jscope来看下数据变化,接下来只要定义个全局变量,
把传感器数据传出来,jscope就可以监控到变化的数据。
代码修改如下:
main.c
//定义数据结构,实例化数据
typedef struct
{
float x;
float y;
float z;
}Data_t;
Data_t orientation;
Data_t acc;
Data_t gyro;
........
/** Converts measured orientation data into degrees.
*
* GREEN LED will be turned on if board heading is within 10 degrees of
* magnetic north (<=10 or >=350).
*/
void ao_vector_cb(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
orientation.x = data->data_vector.x / 32768.0f * 360.0f;
orientation.y = data->data_vector.y / 32768.0f * 360.0f;
orientation.z = data->data_vector.z / 32768.0f * 360.0f;
if (orientation.x > 350.0f || orientation.x < 10.0f)
{
LED_On(LED_GREEN);
}
else
{
LED_Off(LED_GREEN);
}
//printf("Orientation: h=%.1f p=%.1f, y=%.1f (%d)\r\n", h, p, y, data->data_vector.status);
}
/** Converts measured linear acceleration data based on sensors dynamic range
* and prints it to debug terminal.
*
* Also turns on RED LED if total acceleration applied to the board is over 1g.
*/
void la_vector_cb(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
/* Linear Acceleration sensor values are scaled using dynamic range. */
uint16_t dyn_range = BHI160_NDOF_GetAccelDynamicRange();
acc.x = data->data_vector.x / 32768.0f * dyn_range;
acc.y = data->data_vector.y / 32768.0f * dyn_range;
acc.z = data->data_vector.z / 32768.0f * dyn_range;
if (fabsf(acc.x) + fabsf(acc.y) + fabsf(acc.z) >= 1.0f)
{
LED_On(LED_RED);
}
else
{
LED_Off(LED_RED);
}
// printf("Linear Accel: x=%.2f g, y=%.2f g, z=%.2f g\r\n", x, y, z);
}
void gyro_vector_cb(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
uint16_t dyn_range = BHI160_NDOF_GetGyroDynamicRange();
gyro.x = data->data_vector.x / 32768.0f * dyn_range;
gyro.y = data->data_vector.y / 32768.0f * dyn_range;
gyro.z = data->data_vector.z / 32768.0f * dyn_range;
if (fabsf(gyro.z) > 45.0f)
{
LED_On(LED_BLUE);
}
else
{
LED_Off(LED_BLUE);
}
// printf("Rate of Rotation: x=%.2f , y=%.2f /s, z=%.2f \r\n", x, y, z);
}
然后,打开jscope,新建个project,
在配置界面的specify target device中输入rsl10
elf file中选择工程编译目录下的sense_bhi160.elf
如下图所示,就可以点ok了
然后在下面添加我们定义的全局变量,点击start就可以看到数据变化了,如下图。
但各位看下下图中的数据,是存在明显的锯齿的,也就是刷新频率很低。
这个问题我们可以看下 注册回调函数的那个api,其中最后一个参数,便是设置采样率的,
他的数值代表的是频率,数值越大更新速度越快,
当然了,功耗也会相对高一点点,这里我们把它设置为1000hz,看看效果,代码修改如下所示:
main.c
int main(void)
{
.......
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_ORIENTATION, &ao_vector_cb, 1000);
ASSERT_DEBUG(retval == BHY_SUCCESS);
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_LINEAR_ACCELERATION, &la_vector_cb, 1000);
ASSERT_DEBUG(retval == BHY_SUCCESS);
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_RATE_OF_ROTATION, &gyro_vector_cb, 1000);
ASSERT_DEBUG(retval == BHY_SUCCESS);
.......
}
编译并烧录,在看下jscope的数据图,就变的连贯很多了。
在传感器数据回调注册的函数中我们还可以看到第一个参数,是选择需要的数据类型的,
改变这个参数就可以获取传感器的不同类型数据了,这里可看到库中给的定义,列写了五种数据,包括姿态角度、重力、线性加速度、角速度、磁场强度数据,可以分别改动下看看数据是怎样的。
至此,这个例程的功能我们就体验完了。
但本帖还没完。。。。。
就像开头所说的,BHI160传感器支持的数据可不止上面例程库中给列写的那几个,
在看了芯片的datasheet之后,发现还支持
“游戏旋转矢量、计步器、步数检测器、有效运动识别(significant motion)、
倾斜检测器、拾取识别、唤醒识别、手势识别、站立、跑步、骑自行车、开车的活动识别”这些数据。
看下RSL10的工程,其实也是引用了博世提供的SDK的,如下图:
在回看下上面传感器数据的枚举变量中
定义的变量其实就是这些支持的功能
那么也就是说,我们需要哪个数据,只要在BHI160_NDOF_Sensor这个枚举体中再定义下,
按照例程的方式,就可以直接使用啦。
只是这些不同类型的数据,会有对应的数据格式,这个格式可以参考BHI160的数据手册中定义的来,
如上面Table14 virtual sensor ID 表中VS data type中定义的数据类型,
再看下面这张图中的data values 使用就行了。
下面以行走步数和活动识别来举例,
因为步数更新和活动识别都是传感器内部实现的,
我们读取数据的频率就可以降低些,以1hz频率更新
这里用RTT viewer来打印,
把例程自带的三个原始数据的回调注册的打印给注释掉了,防止顶掉我们想要的数据显示
并实现行走步数和活动识别的回调和相应处理,实现代码如下:
main.c
void step_counter_cb(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
bhy_data_scalar_u16_t step_data;
step_data.data = data->data_scalar_u16.data;
printf("Step counter is %d\r\n", step_data.data);
}
void activity_recognition_cb(bhy_data_generic_t *data, bhy_virtual_sensor_t sensor)
{
bhy_data_scalar_u16_t act_data;
static uint16_t last_act;
act_data.data = data->data_scalar_u16.data;
if(act_data.data != last_act)
{
switch (act_data.data)
{
case 0x0000:
break;
case 0x0001:
printf("Still activity ended. \r\n");
break;
case 0x0002:
printf("Walking activity ended. \r\n");
break;
case 0x0004:
printf("Running activity ended. \r\n");
break;
case 0x0008:
printf("On Bicycle activity ended \r\n");
break;
case 0x0010:
printf("In Vehicle activity ended. \r\n");
break;
case 0x0020:
printf("Tilting activity ended. \r\n");
break;
case 0x0040:
break;
case 0x0080:
break;
case 0x0100:
printf("Still activity start. \r\n");
break;
case 0x0200:
printf("Walking activity start. \r\n");
break;
case 0x0400:
printf("Running activity start. \r\n");
break;
case 0x0800:
printf("On Bicycle activity start \r\n");
break;
case 0x1000:
printf("In Vehicle activity start. \r\n");
break;
case 0x2000:
printf("Tilting activity start. \r\n");
break;
case 0x4000:
break;
case 0x8000:
break;
default:
break;
}
}
last_act = act_data.data;
}
int main(void)
{
.......
/* Enable desired virtual sensor outputs. */
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_ORIENTATION, &ao_vector_cb, 1000);
ASSERT_DEBUG(retval == BHY_SUCCESS);
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_LINEAR_ACCELERATION, &la_vector_cb, 1000);
ASSERT_DEBUG(retval == BHY_SUCCESS);
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_RATE_OF_ROTATION, &gyro_vector_cb, 1000);
ASSERT_DEBUG(retval == BHY_SUCCESS);
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_STEP_COUNTER, &step_counter_cb, 1);
ASSERT_DEBUG(retval == BHY_SUCCESS);
retval = BHI160_NDOF_EnableSensor(BHI160_NDOF_S_ACTIVITY_RECOGNITION, &activity_recognition_cb, 1);
ASSERT_DEBUG(retval == BHY_SUCCESS);
........
}
活动识别的数据具体定义可以参考芯片数据手册中的描述:
然后我们烧录,并用RTT viewer可以看到我模拟走路的步数被有效的记录了下来,
这相比自己用原始数据来计算出来,功耗、效果方面都会好很多了。
本文就先到这了,以上用到的数据手册我放到下面连接了,各位随意取用。
bst-bmm150-ds001.pdf
(7.29 MB, 下载次数: 3)
bst-bhi160b-ds000.pdf
(10.24 MB, 下载次数: 3)
|