一、项目需求
本次项目的主要需求是基于X-NUCLEO-IKS4A1 和NUCLEO-G0B1RE实现传感器选择和切换及功能的可视化的设计。
二、需求分析
需要配置好板子的引脚设置,然后利用X-NUCLEO-IKS4A1板上搭载的QVAR触摸传感器来实现传感器的选择和切换,同时需要一个能显示传感器数据的上位机,在本项目中我们选择使用matlab来实现。
三、实现方式
1、硬件介绍
NUCLEO-G0B1RE是ST公司(意法半导体)推出的一款基于STM32G0系列微控制器的评估板,属于其广受欢迎的Nucleo开发板系列。
X-NUCLEO-IKS4A1是由STMicroelectronics推出的用于搭配STM32 Nucleo的运动MEMS和环境传感器扩展板,提供了在动作检测、环境监测等IoT领域的各种传感器的参考解决方案。包括X-NUCLEO-IQS4A1主板(搭载运动MEMS和环境传感器)和可拆卸的STEVAL-MKE001A附加板(搭载Qvar滑动电极),这款扩展板具有高度的集成性和兼容性,提供了在动作检测、环境监测等IoT领域的各种传感器解决方案。
2、设计思路
根据所需任务,绘制流程图如下:
3、具体实现过程
首先按照例程配置好引脚,如下图所示:
在主函数中初始化并调用端口:
HAL_Init();
MX_MEMS_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
while (1)
{
MX_MEMS_Process();
HAL_Delay(100);
}
然后在MX_MEMS_Process()函数中加入读取传感器数据的函数:
BSP_SENSOR_LIS2DUXS12_ACC_GetAxes(&AccValue);
printf("{acc1:%ld,%ld,%ld}\n",AccValue.x,AccValue.y,AccValue.z);
BSP_SENSOR_LSM6DSV16X_ACC_GetAxes(&AccValue);
printf("{acc2:%ld,%ld,%ld}\n",AccValue.x,AccValue.y,AccValue.z);
BSP_SENSOR_LSM6DSO16IS_ACC_GetAxes(&AccValue);
printf("{acc3:%ld,%ld,%ld}\n",AccValue.x,AccValue.y,AccValue.z);
BSP_SENSOR_LSM6DSV16X_GYR_GetAxes(&GyrValue);
printf("{gyr1:%ld,%ld,%ld}\n",GyrValue.x,GyrValue.y,GyrValue.z);
BSP_SENSOR_LSM6DSO16IS_GYR_GetAxes(&GyrValue);
printf("{gyr2:%ld,%ld,%ld}\n",GyrValue.x,GyrValue.y,GyrValue.z);
BSP_SENSOR_MAG_GetAxes(&MagValue);
printf("{mag:%ld,%ld,%ld}\n",MagValue.x,MagValue.y,MagValue.z);
BSP_SENSOR_PRESS_GetValue(&PressValue);
printf("{press:%d}\n",(int)PressValue);
BSP_SENSOR_QVAR_GetValue(&QvarValue);
qvar_digital(QvarValue,&qvar_out);
printf("{one:%d}\n",(int) qvar_out);
BSP_SENSOR_TEMP_GetValue(&TempValue);
printf("{temp:%.1f}\n",(float)TempValue);
BSP_SENSOR_HUM_GetValue(&HumValue);
printf("{hum:%.1f}\n",(float)HumValue);
HAL_Delay(10);
其中,获得到的QVAR数据将通过qvar_digital()函数进行处理。下面是对qvar_digital()函数的代码分析:
首先,qvar_digital()函数使用了迟滞思想,将输入的数据进行差分:
int value_deviation=value-value_last
其中value是当前读取到的QVAR电极的电压,value_last是上一时刻读取到的QVAR电极的电压。然后,将QVAR的输入量化为1,0,-1:
if (value_deviation>=54600)
value_state_n=1;
else if(value_deviation>=23400)
value_state_n=value_state_l+1;
else if(value_deviation<=-54600)
value_state_n=-1;
else if(value_deviation<=-23400)
value_state_n=value_state_l-1;
else
value_state_n=value_state_l;
value_last= value_state_n * 32760;
其中,value_state_n是当前时刻对输入的数据进行处理后得到的返回值,value_state_l是上一时刻对输入的数据进行处理后得到的返回值。通过这个操作,可以直接识别出滑动这一行为。
然后是按键消抖程序:
if (value_state_n==value_state_l)
{
value_count+=1;
if ((value_count>=1)&&(value_state_n!=0)&&(value_state_n!=value_state_storage[0]))
{
value_count=0;
value_state_valid=1;
value_state_storage[2]=value_state_storage[1];
value_state_storage[1]=value_state_storage[0];
value_state_storage[0]=value_state_n;
}
else if((value_count>=1)&&(value_state_n==0))
{
value_count=0;
value_state_valid=1;
value_state_storage[2]=value_state_storage[1];
value_state_storage[1]=value_state_storage[0];
value_state_storage[0]=value_state_n;
}
}
else
value_count=0;
首先检查当前值value_state_n是否与上一个状态value_state_l相同,如果相同,value_count加1,用于计数连续相同状态的次数,当value_count至少为1,且当前状态value_state_n不为0,且与存储数组的第一个元素不同时:①将value_count重置为0,②将value_state_valid设置为1,③更新value_state_storage数组,将元素依次后移,并将当前状态value_state_n存储在数组的第一个位置。如果value_count至少为1,且当前状态value_state_n为0,执行的操作与上一个条件分支相同。如果value_state_n与value_state_l不相同,将value_count重置为0。
然后是动作识别框架:
if (value_state_valid)
{
value_state_valid=0;
if ((value_state_storage[2]==0)&&(value_state_storage[0]==0)&&(act_storage==0))
{
act_storage=value_state_storage[1];
act=0;
}
else if((value_state_storage[1]==-1)&&(value_state_storage[2]==1))
{
act=-1;
act_storage=0;
}
else if((value_state_storage[1]==1)&&(value_state_storage[2]==-1))
{
act=1;
act_storage=0;
}
else if((value_state_storage[2]==act_storage)&&(value_state_storage[1]==0)&&(value_state_storage[0]==0))
{
act=act_storage+act_storage;
act_storage=0;
}
else if((value_state_storage[2]*2==act_storage)&&(value_state_storage[1]==0)&&(value_state_storage[0]==0))
{
act=act_storage+act_storage;
act_storage=0;
}
else if((value_state_storage[0]==value_state_storage[2])&&(value_state_storage[0]==act_storage)&&(act_storage!=0)&&(value_state_storage[1]==0))
{
act_storage=act_storage+act_storage;
}
else if((value_state_storage[2]==0)&&(value_state_storage[0]==0)&&(act_storage!=0))
{
;
}
else
{
act=0;
act_storage=0;
}
}
else
act=0;
首先检查value_state_valid是否为真,这个变量表示状态数据是否有效。如果状态有效,首先将其设置为无效,以防止状态在本周期再次被处理,接下来是一系列的else if条件分支,每个分支都根据不同的value_state_storage数组和act_storage的值来更新act和act_storage。将为双击动作识别为±4,将点按动作识别为±2,将滑动识别为±1,无动作为0。
最后是上位机部分,使用matlab来实现,灯代表所选择的传感器,如下图所示:
触摸传感器和上位机都可对传感器进行开关,如下图“Hum”数据:
四、活动总结
感谢硬核学堂和徳捷购对本次活动的支持,通过这次活动我又学习到了很多知识,希望下次还能参加这样的活动。