旧乡故客
发表于: 昨天 16:16 | 显示全部楼层

电子元器件产品技术的更新迭代速度快,惯性测量单元也是如此。TDK公司作为国际上领先的惯性测量单元生产设计提供商,发布了多款产品,从之前MPU6050、ICM-20602,到ICM-42688、ICM-45686等,性能越来越强。ICM-45686作为TDK InvenSense公司最新推出的一款超高性能六轴MEMS运动传感器,采用独特的BalancedGyro技术,可实现极佳的抗震和温度稳定性性能,并提供超低功耗。该传感器包括片上嵌入式APEX运动功能:计步器、倾斜和轻击检测、自由落体检测、超低功耗运动唤醒和运动检测。


在本篇帖子中,我们将主要介绍使用NUCLEO-G070开发板通过SPI方式读取YBX-ICM45686模块的数据,实现读取加速度计和陀螺仪的原始数据。


所需的组件

●  NUCLEO-G070开发板

●  YBX-ICM45686六轴惯性测量单元模块(淘宝链接

●  连接跳线

●  USB线缆

●  STM32CubeMX工具

●  友善串口调试助手


YBX-ICM45686六轴惯性测量单元模块

YBX-ICM45686模块是一板科技推出的模块扩展板,采用TDK InvenSense 6轴MEMS运动传感器ICM-45686。该运动传感器是一款高性能双接口 (UI + AUX) 六轴MEMS运动跟踪器件。ICM-45686支持此IMU类中最低的陀螺仪和加速度传感器噪声,并且具有最高的温度、冲击或弯曲引起的偏移稳定性,以及对带外振动引起的噪声的免疫力。其他业界领先的功能包括用于手势识别、活动分类和计步器的片上APEX运动处理引擎,以及可编程数字滤波器和嵌入式温度传感器。


该模块加速度传感器同时支持SPI和I2C接口方式,板载电源LDO,支持3.3V和5V电源输入。

YBX-ICM45686六轴惯性测量单元模块.jpg


硬件连接

YBX-ICM45686传感器模块连接到NUCLEO-G070RB的SPI1接口,对应的引脚分别是PA5(SCK)、PA6(MISO)和PA7(MOSI),片选引脚CSB连接到PB0。模块的VCC连接到+5V引脚,GND引脚连接到NUCLEO-G070RB的任意GND引脚。

YBX-ICM45686模块通过SPI接口与STM32 Nucleo的硬件连接.jpg

使用跳线按照以上示例图连接模块和开发板。


STM32CubeMX工具配置

STM32CubeMX工具是ST提供的一个免费的软件配置工具,它提供了一些工程模板,可以快速创建基于MCU、开发板以及示例程序的工程。使用该工具,我们可以快速新建一个基于NUCLEO-G070开发板的工程。


首先打开STM32CubeMX工具,点击ACCESS TO BOARD SELECTOR,在弹出的界面中找到NUCLEO-G070RB开发板,然后点击右上角的Start Project。


在Pinout布局中,已经初始化好RCC、Debug、UART2、LED等外设。

我们使用SPI1外设连接传感器模块,设置SPI1的模式为Full Duplex Master,将A5、PA6和PA7分别设为SPI1_SCK、SPI1_MISO和SPI1_MOSI。然后将PB0定义为CS输出。然后根据手册中的SPI时序图,设置SPI通讯的参数。

注意,SPI的时钟频率不能超过12MHz

STM32CubeMX配置参数.jpg


最后,生成基于Keil MDK的工程文件。


驱动文件

TDK提供了基于ICM-45686的驱动文件和示例代码,可以在Github进行下载:motion.mcu.icm45686.driver。也可以在TDK的官网页面下载。


代码

TDK的驱动文件中包含多个示例代码,我们选择基于basic_read_registers代码进行移植,该代码采用API函数直接读取寄存器的方式采集数据,中断标志位置位时读取数据。以下是代码:

  1. printf("\nICM45686 SPI Test\n");
  2.   printf("Bolgen Studio\n");

  3.   /* Initialize MCU hardware */
  4.   rc |= setup_mcu();
  5.   SI_CHECK_RC(rc);

  6.   INV_MSG(INV_MSG_LEVEL_INFO, "###");
  7.   INV_MSG(INV_MSG_LEVEL_INFO, "### Example Read registers (using basic API)");
  8.   INV_MSG(INV_MSG_LEVEL_INFO, "###");

  9.   /* Reset commands interface states */
  10.   print_si  = 1;
  11.   print_lsb = 0;
  12.   accel_en  = 1;
  13.   gyro_en   = 1;
  14.   use_ln    = 1;

  15.   rc |= setup_imu();
  16.   SI_CHECK_RC(rc);

  17.   /* Reset timestamp and interrupt flag */
  18.   int1_flag      = 0;
  19.   int1_timestamp = 0;

  20.   uint64_t              timestamp;
  21.   inv_imu_sensor_data_t d;
  22.   float                 accel_g[3];
  23.   float                 gyro_dps[3];
  24.   float                 temp_degc;
  25.   inv_imu_int_state_t   int_state;
  26.         
  27.   /* USER CODE END 2 */

  28.   /* Infinite loop */
  29.   /* USER CODE BEGIN WHILE */
  30.   while (1)
  31.   {
  32.     /* USER CODE END WHILE */

  33.     /* USER CODE BEGIN 3 */

  34.     /* Retrieve timestamp */
  35.     timestamp = int1_timestamp;

  36.     /* Read interrupt status */
  37.     rc |= inv_imu_get_int_status(&imu_dev, INV_IMU_INT1, &int_state);
  38.     SI_CHECK_RC(rc);

  39.     if (int_state.INV_UI_DRDY)
  40.     {
  41.       rc |= inv_imu_get_register_data(&imu_dev, &d);
  42.       SI_CHECK_RC(rc);

  43.       /*
  44.        * Convert data to SI units
  45.        * Accel and gyro data are coded as 16-bits signed (max_lsb = 2^(16-1) = 32768) with
  46.        * the configured FSR (4 g and 2000 dps, see `setup_imu()` function).
  47.        * Temperature is coded as 16-bits signed with a scale factor of 128 and an offset
  48.        * of 25 ?.
  49.        */
  50.       accel_g[0]  = (float)(d.accel_data[0] * 4 /* gee */) / 32768;
  51.       accel_g[1]  = (float)(d.accel_data[1] * 4 /* gee */) / 32768;
  52.       accel_g[2]  = (float)(d.accel_data[2] * 4 /* gee */) / 32768;
  53.       gyro_dps[0] = (float)(d.gyro_data[0] * 2000 /* dps */) / 32768;
  54.       gyro_dps[1] = (float)(d.gyro_data[1] * 2000 /* dps */) / 32768;
  55.       gyro_dps[2] = (float)(d.gyro_data[2] * 2000 /* dps */) / 32768;
  56.       temp_degc   = (float)25 + ((float)d.temp_data / 128);

  57.       /* Print data in SI units */
  58.       if (print_si)
  59.       {
  60.         char accel_str[40];
  61.         char gyro_str[40];
  62.         char temp_str[20];

  63.         if (accel_en && (discard_accel_samples == 0) &&
  64.             (d.accel_data[0] != INVALID_VALUE_FIFO) &&
  65.             (d.accel_data[1] != INVALID_VALUE_FIFO) &&
  66.             (d.accel_data[2] != INVALID_VALUE_FIFO))
  67.           snprintf(accel_str, 40, "Accel:% 8.2f % 8.2f % 8.2f g", accel_g[0],
  68.                    accel_g[1], accel_g[2]);
  69.         else
  70.           snprintf(accel_str, 40, "Accel:       -        -        -  ");

  71.         if (gyro_en && (discard_gyro_samples == 0) &&
  72.             (d.gyro_data[0] != INVALID_VALUE_FIFO) &&
  73.             (d.gyro_data[1] != INVALID_VALUE_FIFO) &&
  74.             (d.gyro_data[2] != INVALID_VALUE_FIFO))
  75.           snprintf(gyro_str, 40, "Gyro:% 8.2f % 8.2f % 8.2f dps", gyro_dps[0],
  76.                    gyro_dps[1], gyro_dps[2]);
  77.         else
  78.           snprintf(gyro_str, 40, "Gyro:       -        -        -    ");

  79.         snprintf(temp_str, 20, "Temp: % 4.2f degC", temp_degc);

  80.         INV_MSG(INV_MSG_LEVEL_INFO, "SI  %10llu us   %s   %s   %s", timestamp,
  81.                 accel_str, gyro_str, temp_str);
  82.       }

  83.       /* Print LSB data. */
  84.       if (print_lsb)
  85.       {
  86.         char accel_str[40];
  87.         char gyro_str[40];
  88.         char temp_str[20];

  89.         if (accel_en && (discard_accel_samples == 0) &&
  90.             (d.accel_data[0] != INVALID_VALUE_FIFO) &&
  91.             (d.accel_data[1] != INVALID_VALUE_FIFO) &&
  92.             (d.accel_data[2] != INVALID_VALUE_FIFO))
  93.           snprintf(accel_str, 40, "Accel:% 8d % 8d % 8d", (int)d.accel_data[0],
  94.                    (int)d.accel_data[1], (int)d.accel_data[2]);
  95.         else
  96.           snprintf(accel_str, 40, "Accel:       -        -        -");

  97.         if (gyro_en && (discard_gyro_samples == 0) &&
  98.             (d.gyro_data[0] != INVALID_VALUE_FIFO) &&
  99.             (d.gyro_data[1] != INVALID_VALUE_FIFO) &&
  100.             (d.gyro_data[2] != INVALID_VALUE_FIFO))
  101.           snprintf(gyro_str, 40, "Gyro:% 8d % 8d % 8d", (int)d.gyro_data[0],
  102.                    (int)d.gyro_data[1], (int)d.gyro_data[2]);
  103.         else
  104.           snprintf(gyro_str, 40, "Gyro:       -        -        -");

  105.         snprintf(temp_str, 20, "Temp: % 6d", (int)d.temp_data);

  106.         INV_MSG(INV_MSG_LEVEL_INFO, "LSB %10llu us   %s     %s       %s", timestamp,
  107.                 accel_str, gyro_str, temp_str);
  108.       }

  109.       if (accel_en && discard_accel_samples)
  110.         discard_accel_samples--;

  111.       if (gyro_en && discard_gyro_samples)
  112.         discard_gyro_samples--;
  113.     }

  114.     rc |= get_uart_command();

  115.     si_sleep_ms(1000);
  116.     /* USER CODE END 3 */
  117.   }
复制代码

输出结果

使用USB线缆给NUCLEO-G070开发板上电,然后将代码上传至开发板,打开友善串口调试助手,选择正确的端口号,设置波特率115200,在串口中应该能显示数据:

输出结果.jpg


以上就是NUCLEO-G070开发板读取YBX-ICM45686模块的全部内容,如果有任何疑问,请随时在本帖下面回复。


跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 22 | 回复: 26



手机版|

GMT+8, 2025-7-19 04:15 , Processed in 0.078349 second(s), 10 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表