Funpack3-3 基于NUCLEO-IKS4A1传感器扩展板的VR体感追踪器
该项目使用了STM32 IKS4A1,实现了VR体感追踪器的设计,它的主要功能为:此设备主要利用了板载的LSM6DSV16X 6轴传感器和LPS22DF气压传感器,用于实时计算和监测空间姿态以及相对海拔高度的变化。
标签
嵌入式系统
STM32
Funpack活动
IKS4A1
VR体感追踪器
安先生
更新2024-07-08
140

项目描述

本项目的核心目标是开发一款基于STM32 NUCLEO-G0B1RE开发板和X-NUCLEO-IKS4A1传感器扩展板的VR体感追踪器。

此设备主要利用了板载的LSM6DSV16X 6轴传感器和LPS22DF气压传感器,用于实时计算和监测空间姿态以及相对海拔高度的变化,并通过串口将这些数据传输至上位机。

上位机软件基于Python开发,实时显示一个立方体的三维空间变化,从而直观地展示传感器捕获的动态信息。

设计思路:

STM32 NUCLEO-G0B1RE作为主控板,具有足够的处理能力和丰富的接口,同时选择X-NUCLEO-IKS4A1扩展板作为传感器模块,因为它集成了多种MEMS传感器,能够提供所需的运动及环境数据。

软件开发分为两大部分:嵌入式系统开发和上位机接口设计。

嵌入式系统负责实时数据采集和初步处理,上位机则负责数据的进一步处理和可视化展示。

嵌入式开发采用了PlatformIO平台,这是一个开源的集成开发环境,支持多种开发板和框架,极大地简化了STM32的编程和调试过程。

硬件介绍:

  • STM32 NUCLEO-G0B1RE开发板
    • 基于32位ARM Cortex-M0+ MCU,支持
  • X-NUCLEO-IKS4A1传感器扩展板
    • 板载传感器:
    • LSM6DSO16IS:MEMS 3D加速度计 + 3D陀螺仪 与ISPU
    • LIS2MDL:MEMS 3D磁力计
    • LIS2DUXS12:超低功耗MEMS 3轴加速度计
    • 低功率和高精度MEMS绝对数字输出气压计
    • SHT40AD1B:高精度超低功耗的温湿度传感器
    • STTS22H:低电压,超低功耗,0.5°C精度的温度传感器
    • LSM6DSV16X:MEMS 3D加速度计+ 3D陀螺仪
    • 适用于高精度运动追踪和海拔高度测量。

工作流程:

  • 数据采集:从IMU(惯性测量单元)传感器中采集加速度计和陀螺仪数据。如果设备包含磁力计数据,也可以采集。
  • 传感器数据预处理:对原始传感器数据进行滤波和预处理,以去除噪声和漂移。
  • 姿态估计:使用传感器融合算法(如卡尔曼滤波器或互补滤波器)来估计设备的姿态。
  • 输出结果:生成表示姿态的四元数或欧拉角,供应用程序使用。


6轴传感器原理

LSM6DSV16X传感器包含一个3轴加速度计和一个3轴陀螺仪。

加速度计测量设备在X、Y和Z轴上的线性加速度(单位g),陀螺仪测量设备在X、Y和Z轴上的角速度(单位dps)。

传感器通过I2C总线与MCU通信,并将测量数据存储在FIFO(先进先出)缓冲区中,以便后续读取和处理。

四元数介绍

一种用来表示三维旋转的数学工具。

它由一个实部和三个虚部组成,通常表示为 q=w+xi+yj+zkq = w + xi + yj + zkq=w+xi+yj+zk,其中 www、xxx、yyy 和 zzz 是实数。

与欧拉角(Yaw, Pitch, Roll)相比,四元数在计算旋转时具有更高的精度和稳定性,特别是对于连续旋转的情况。

四元数的优点:

  • 避免万向锁问题:欧拉角在某些旋转情况下会遇到万向锁问题,而四元数不会。
  • 更高的计算效率:四元数在进行旋转插值和组合时效率更高。
  • 更稳定的姿态表示:四元数提供更平滑和连续的旋转表示。


气压计原理

LPS22DF传感器用于测量环境气压(单位hPa)。根据国际民航组织(ICAO)标准大气模型,可以通过气压计算相对高度。公式如下:

其中,Initial Pressure是初始气压值,Pressure是当前测量的气压值。通过这个公式,可以计算出设备相对于初始位置的高度变化。


环境搭建

  1. 安装PlatformIO
    • 访问PlatformIO官网下载并安装PlatformIO IDE,该IDE可以集成到VS Code等流行的代码编辑器中。
    • 安装后,在PlatformIO的主界面中创建一个新项目,选择对应的开发板型号(NUCLEO-G0B1RE),并设置合适的配置参数。
  2. 库文件依赖
    • 在项目的platformio.ini配置文件中添加必要的库依赖项,确保项目能够顺利编译和上传到开发板
[env:nucleo_g0b1re]
platform = ststm32
framework = arduino
board = nucleo_g0b1re
monitor_speed = 115200
lib_deps =
    https://github.com/stm32duino/X-NUCLEO-IKS4A1.git
    https://github.com/stm32duino/LsM6DsV16x.git
    https://github.com/stm32duino/LPS22DF.git
    https://github.com/stm32duino/LIS2MDL.git
    https://github.com/stm32duino/MotionFX.git


参考链接

https://stm32-base.org/guides/platformio.html

https://docs.platformio.org/en/latest/platforms/ststm32.html


软件流程图及代码片段


嵌入式部分流程图:




上位机流程图:


  • 传感器数据采集与发送

      // Check the number of samples inside FIFO
      if (accGyr.FIFO_Get_Num_Samples(&fifo_samples) != LSM6DSV16X_OK) {
        SerialPort.println("LSM6DSV16X Sensor failed to get number of samples inside FIFO");
        while (1);
      }

      // Read the FIFO if there is one stored sample
      if (fifo_samples > 0) {
        for (int i = 0; i < fifo_samples; i++) {
          accGyr.FIFO_Get_Tag(&tag);
          if (tag == 0x13) {
            accGyr.FIFO_Get_Rotation_Vector(&quaternions[0]);

            // Compute the elapsed time within loop cycle and wait
            elapsedTime = millis() - startTime;

            if ((long)(ALGO_PERIOD - elapsedTime) > 0) {
              delay(ALGO_PERIOD - elapsedTime);
            }
          }
        }
      }
     
      // Print Quaternion data
    SerialPort.print("Quaternion: ");
    SerialPort.print(quaternions[3], 4);
    SerialPort.print(", ");
    SerialPort.print(quaternions[0], 4);
    SerialPort.print(", ");
    SerialPort.print(quaternions[1], 4);
    SerialPort.print(", ");
    SerialPort.println(quaternions[2], 4);


        // Read pressure and temperature.
    float pressure = 0, temperature2 = 0;
    PressTemp.GetPressure(&pressure);
    PressTemp.GetTemperature(&temperature2);

    // Calculate relative altitude
      if (!initialPressureSet) {
        initialPressure = pressure;
        initialPressureSet = true;
      }
      float altitude = 44330.0 * (1.0 - pow(pressure / initialPressure, 0.1903));

      SerialPort.print("Pres: ");
      SerialPort.print(pressure, 2);
      SerialPort.print(" Temp: ");
      SerialPort.print(temperature2, 2);
      SerialPort.print(" Altitude: ");
      SerialPort.println(altitude, 2);

      delay(100);



  • 图形化显示(上位机Python)
    def project_vertex(vertex, offset_y):
        """ Project 3D vertex to 2D space """
        x, y, z = vertex
        factor = 200 / (z + 200)
        x = x * factor + width // 2
        y = -y * factor + height // 2 + offset_y
        return x, y

    def draw_cube(offset_y):
        screen.fill((0, 0, 0))

        # Project and draw cube edges
        projected_vertices = [project_vertex(vertex, offset_y) for vertex in cube_vertices]
        for i, edge in enumerate(edges):
            start, end = edge
            color = colors[i % len(colors)]
            pygame.draw.line(screen, color, projected_vertices[start], projected_vertices[end], 2)
       
        pygame.display.flip()

功能展示及说明

  • 上位机接收到的数据用于实时更新3D立方体的姿态。

心得体会

通过本项目,我深入理解了STM32的传感器数据处理和串口通信机制,同时对Python进行数据可视化的能力有了更进一步的掌握。项目过程中,PlatformIO的强大功能给我的开发工作带来了极大的便利,使我能够更专注于算法的实现和优化。希望未来能有更多机会针对不同的应用场景开发类似的嵌入式系统,进一步提升我的技术能力。

对活动的建议

建议未来的活动能增加更多关于云计算和AI的集成应用,这将有助于开发更智能的物联网设备,实现更广泛的应用场景。同时,增设更多实战演练和案例分析,能够帮助参与者更好地理解理论与实践的结合点。

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