Funpack3-3:用X-NUCLEO-IKS4A1制作体感追踪器
该项目使用了X-NUCLEO-IKS4A1,实现了体感追踪器的设计,它的主要功能为:加入算法实现以下功能,计算板卡的空间姿态以及相对海拔高度变化,并且可以将数据传输到电脑上。
标签
嵌入式系统
Funpack活动
开发板
小熊熊
更新2024-07-08
38

项目描述

本项目使用了X-NUCLEO-IKS4A1上面的LSM6DSO16IS传感器来测量空间姿态,用LPS22DF传感器来测量相对海拔高度。测量到的信息通过NUCLEO-H503RB上的stlink串口传送到电脑上。

上位机使用的是Adafruit官方的网页版在线工具Adafruit WebSerial 3D Model Viewer。这个工具支持通过串口输入欧拉角或四元数信息,然后将空间姿态通过3D模型显示在页面上。工具的地址是:https://adafruit.github.io/Adafruit_WebSerial_3DModelViewer/

image.png

LSM6DSO16IS传感器是一个MEMS 3D加速度计 (±2/±4/±8/±16 g) + 3D陀螺仪 (±125/±250/±500/±1000/±2000 dps) 与ISPU(智能处理单元)。项目中将3D加速度计与3D陀螺仪的输出融合成为四元数的计算就是在传感器内部的ISPU完成的。

LSM6DSO16ISNTR

LPS22DF传感器是一个低功率和高精度MEMS压力传感器,260-1260 hPa绝对数字输出气压计。

LPS22DF MEMS Nano Pressure Sensor - STMicro | Mouser


软件流程图及各功能对应的主要代码片段及说明

image.png


项目是使用arduino进行编写的。在编写程序前,需要下载两个传感器对应的arduino库文件,相应的文件我会添加在附件中,可以在arduino ide中通过导入zip库的形式进行安装。

image.png

要想使用LSM6DSO16IS传感器内部的ISPU计算融合数据,首先要对寄存器进行配置,将程序写入ISPU。这部分程序是官方编译好的hex,单独写在sensor_fusion.h文件中。这个文件需要和主程序放在同一个文件夹下。


接下来看一下主程序,两个传感器都是通过i2c连接到单片机上,首先要初始化i2c接口和两个传感器,以及一些所需的全局变量。

#include "LSM6DSO16ISSensor.h"
#include "sensor_fusion.h"
#include <LPS22DFSensor.h>

#define INT_1 A5
#define DEV_I2C Wire
#define SerialPort Serial

LPS22DFSensor PressTemp(&DEV_I2C);
float pressure = 0, temperature2 = 0, init_height = 0, height = 0;

// Interrupts.
volatile int mems_event = 0;

LSM6DSO16ISSensor sensor(&DEV_I2C, LSM6DSO16IS_I2C_ADD_L);
ucf_line_ext_t *ProgramPointer;
int32_t LineCounter;
int32_t TotalNumberOfLine;
void INT1Event_cb();

union data {
uint8_t raw_data[16];
float_t values[4];
};


下面是设置函数,这个函数只会被运行一次,用来执行参数的配置。往ISPU中写入对应的程序也在这一步中完成。同时还需要获取上电时开发板的海拔,用来计算相对海拔时作为参考。海拔计算使用hypsometric formula

image.png

void setup() {
// Led.
pinMode(LED_BUILTIN, OUTPUT);

// Initialize serial for output.
SerialPort.begin(115200);

// Initlialize i2c.
DEV_I2C.begin();

// Initlialize components.
sensor.begin();
sensor.Enable_X();
sensor.Enable_G();

PressTemp.begin();
PressTemp.Enable();
delay(250);
PressTemp.GetPressure(&pressure);
PressTemp.GetTemperature(&temperature2);
init_height = ((pow((101.325 / (pressure / 10)), (1 / 5.257)) - 1) * (temperature2 + 273.15)) / 0.0065;

// Feed the program to ISPU
ProgramPointer = (ucf_line_ext_t *)ispu_conf;
TotalNumberOfLine = sizeof(ispu_conf) / sizeof(ucf_line_ext_t);
SerialPort.println("LSM6DSO16IS ISPU Sensor Fusion");
SerialPort.print("UCF Number Line=");
SerialPort.println(TotalNumberOfLine);

for (LineCounter = 0; LineCounter < TotalNumberOfLine; LineCounter++) {
if (ProgramPointer[LineCounter].op == MEMS_UCF_OP_WRITE) {
if (sensor.Write_Reg(ProgramPointer[LineCounter].address, ProgramPointer[LineCounter].data)) {
SerialPort.print("Error loading the Program to LSM6DSO16ISSensor at line: ");
SerialPort.println(LineCounter);
while (1) {
// Led blinking.
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
}
}
} else if (ProgramPointer[LineCounter].op == MEMS_UCF_OP_DELAY) {
delay(ProgramPointer[LineCounter].data);
}
}
SerialPort.println("Program loaded inside the LSM6DSO16IS ISPU");
// Interrupts.
pinMode(INT_1, INPUT);
attachInterrupt(INT_1, INT1Event_cb, RISING);
}

void INT1Event_cb() {
  mems_event = 1;
}


下面是主循环部分,将获取到的空间姿态和相对高度发送到串口。

void loop() {
union data quaternions;
// When the quaternion for the new sample is computed and available in the output registers an interrupt is generated.
if (mems_event) {
LSM6DSO16IS_ISPU_Status_t ispu_status;
mems_event = 0;
sensor.Get_ISPU_Status(&ispu_status);
// Check if the ISPU event is from the algo00.
if (ispu_status.ia_ispu_0) {
// Read quaternions and print them.
sensor.Read_ISPU_Output(LSM6DSO16IS_ISPU_DOUT_00_L, &quaternions.raw_data[0], 16);
SerialPort.print("Quaternion: ");
SerialPort.print(quaternions.values[3], 4);
SerialPort.print(", ");
SerialPort.print(quaternions.values[1], 4);
SerialPort.print(", ");
SerialPort.print(-quaternions.values[0], 4);
SerialPort.print(", ");
SerialPort.println(quaternions.values[2], 4);

// Read pressure and temperature.
PressTemp.GetPressure(&pressure);
PressTemp.GetTemperature(&temperature2);
height = (pow((101.325 / (pressure / 10)), (1 / 5.257)) - 1) * (temperature2 + 273.15) / 0.0065;
SerialPort.print("Relative Height: ");
SerialPort.println(height - init_height);
}
}
}

功能展示及说明

219315e76bd1196b3d2ba129b3d087c.jpg


连接Adafruit WebSerial 3D Model Viewer,可以从串口中看到数据,3D模型也可以随着板卡运动而运动。

bc5b4a71ca979b3457e6c891ad6639b.jpg

630ee79272d8bafde0a5601c0a2592a.png

对本活动的心得体会

本次活动中我使用了X-NUCLEO-IKS4A1搭配NUCLEO-H503RB使用,使用起来非常方便,可以做到即插即用。这次开发再次让我体验到STM32开发环境的友好,哪怕不是官方的开发环境,使用第三方arduino,官方都做了非常到位的适配,有齐全的库和范例对应芯片的各个功能。

附件下载
funpack3_3.zip
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号