简体   繁体   English

使用缓冲区和溢出缓冲区将IMU数据写入csv文件?

[英]Write IMU data to csv file using buffer and overflow buffer?

I have been trying to implement a C++ complementary filter for a LSM9DS1 IMU connected via I2C to an mbed board, but timing issues are preventing me from getting the angular rate integration right. 我一直在尝试为通过I2C连接到mbed板的LSM9DS1 IMU实现C ++互补滤波器,但是时序问题使我无法正确获得角速率集成。 This is because in my code I'm assuming that my sample rate is 100Hz, while this isn't exactly the rate at which data is being sampled due to the printf() statements I am using to display values in real time. 这是因为在我的代码中,我假设我的采样率为100Hz,但由于我要实时显示值所使用的printf()语句,这并不是精确的数据采样率。 This results in my filter outputting angles that drift/don't go back to the original value when the IMU is put back in its original position. 这导致我的滤波器的输出角度在将IMU放回其原始位置时漂移/不回到原始值。

I've been recommended to follow the following steps in order to avoid delays in my code that could disrupt my time sensitive application: 建议我按照以下步骤进行操作,以避免代码中的延迟可能破坏我的时间敏感应用程序:

  • On each iteration of the program, add the raw IMU data to a buffer 在程序的每次迭代中,将原始IMU数据添加到缓冲区中
  • When the buffer is nearly full, use an interrupt to write all the data from the buffer to a .csv file 当缓冲区快满时,请使用中断将缓冲区中的所有数据写入.csv文件
  • When/if the buffer overflows, add the remaining data to a new "overflow buffer" 当/如果缓冲区溢出,则将剩余数据添加到新的“溢出缓冲区”中
  • Empty the first buffer and refill it with the data stored in the overflow buffer, and so on 清空第一个缓冲区,并用溢出缓冲区中存储的数据重新填充,依此类推
  • Handle the filtering calculations separately by manually treating the data from the .csv file once it's all been collected, so as to avoid timing issues, and see if the output is as expected 收集完所有数据后,通过手动处理.csv文件中的数据来分别处理过滤计算,以避免计时问题,并查看输出是否符合预期

The whole buffer/overflow buffer back and forth thing really confuses me, could someone please help me clarifying how to technically achieve the above steps? 整个缓冲区/溢出缓冲区的来回交互确实使我感到困惑,有人可以帮助我阐明如何从技术上实现上述步骤吗? Thanks in advance! 提前致谢!

Edit: 编辑:

#include "LSM9DS1.h"
#define DT 1/100

void runFilter()
{
    // calculate Euler angles from accelerometer and magnetometer (_roll, 
    // _pitch,_yaw)
    calcAttitude(imu.ax, imu.ay, imu.az, -imu.my, -imu.mx, imu.mz);

    _gyroAngleX += (_rateX*DT);
    _gyroAngleY += (_rateY*DT);
    _gyroAngleZ += (_rateZ*DT);

    _xfilt = 0.98f*(_gyroAngleX) + 0.02f*_roll;
    _yfilt = 0.98f*(_gyroAngleY) + 0.02f*_pitch;
    _zfilt = 0.98f*(_gyroAngleZ) + 0.02f*_yaw;

    printf("%.2f, %.2f, %.2f \n", _xfilt, _yfilt, _zfilt);
}

in main.cpp: 在main.cpp中:

int main()
{
    init(); // Initialise IMU
    while(1) {
        readValues(); // Read data from the IMUs
        runFilter(); 
    }
 }

As Kentaro also mentioned in the comments, use a separate thread for printf and use the Mbed OS EventQueue to defer printf statements to it. 正如Kentaro在评论中也提到的那样,为printf使用一个单独的线程,并使用Mbed OS EventQueue将printf语句延迟到该线程。

EventQueue queue;
Thread event_thread(osPriorityLow);

int main() {
    event_thread.start(callback(&queue, &EventQueue::dispatch_forever));

    // after sampling
    queue.call(&printf, "%.2f, %.2f, %.2f \n", _xfilt, _yfilt, _zfilt);

However, you might still run into issues with the speed. 但是,您可能仍然会遇到速度问题。 Some general tips: 一些一般性提示:

  1. Use the highest baud rate that your development board can handle. 使用开发板可以处理的最高波特率。
  2. Use a RawSerial object over printf (which uses Serial ) to avoid claiming a mutex. printf (使用Serial )上使用RawSerial对象,以避免声明互斥量。
  3. Don't write to UART but rather write to a file (eg mount a FATFileSystem to an SD card). 不要写入UART,而是写入文件(例如,将FATFileSystem装入SD卡)。 This will be much faster. 这样会更快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM