Как очистить буфер FIFO на MPU6050?
мой MPU6050 работает очень нестабильно, проблема не в том, чтобы очистить лишний буфер FIFO на MPU6050, я использую библиотеку MPU Джеффа Роуберга и согласно его примеру DMP, но без использования прерываний, вот мой модифицированный код, но я попробовал несколько методов указан в библиотеке для очистки буфера, но не работает.
Большое спасибо!
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "Wire.h"
MPU6050 mpu(0x69); //AD0=Высокий
//Управление MPU/переменные состояния
bool dmpReady = false;
uint8_t mpuIntStatus; //фактический байт состояния прерывания
uint8_t deviceStatus; //статус устройства, 0 = успех,
uint16_t packetSize; //ожидаемый размер пакета DMP (по умолчанию 42) -- ?
uint16_t fifoCount; //подсчет всех байтов, находящихся в данный момент в FIFO
uint8_t fifoBuffer[64]; // буферное хранилище FIFO
// переменные ориентации/движения
Quaternion q; // [w, x, y, z] контейнер кватернионов
VectorInt16 aa; // [x, y, z] измерения датчика ускорения
VectorInt16 aaReal; // [x, y, z] измерения датчика ускорения без гравитации
VectorInt16 aaWorld; // [x, y, z] измерения датчика ускорения мирового кадра
VectorFloat gravity; // [x, y, z] вектор гравитации
float euler[3]; // [psi, theta, phi] Контейнер углов Эйлера
float ypr[3]; // [рыскание, тангаж, крен] контейнер рыскания/тангажа/крена и вектор силы тяжести
volatile bool mpuInterrupt = false;
//void dmpDataReady() {
// mpuInterrupt = true;
//}
// поместите сюда свой код установки для однократного запуска:
void setup() {
//подключаемся к шине I2C
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 48; // Тактовая частота I2C 400 кГц (200 кГц, если процессор 8 МГц)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
//инициализируем последовательную связь
Serial.begin(115200);
while(!Serial); //обычно для задач Леонардо
//инициализируем MPU
Serial.println("Call MPU6050 Lib to initialize devices...");
mpu.initialize(); //инициализируем устройство I2C с помощью библиотеки MPU6050
//проверяем соединение
Serial.println("Tesing device connections");
Serial.println(mpu.testConnection() ? F("MPU6050 connection test successed ") : F("MPU6050 connection test failed"));
// //ждём начала, раскомментируем, если нам нужно дождаться прерывания пользователя
// Serial.println("Нажмите любую кнопку, чтобы начать");
// while (Serial.available() && Serial.read()); // пустой буфер
// пока (!Serial.available()); // ждем данных
// while (Serial.available() && Serial.read()); // снова пустой буфер
//загружаем и настраиваем DMP
Serial.println("initializing DMP");
deviceStatus = mpu.dmpInitialize(); //используем библиотеку MPU6050 для инициализации dmp
// смещения подачи
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 заводских настроек для моего тестового чипа
//убедимся, что это работает
if (deviceStatus == 0) {
Serial.println("DMP initialization success, now enable DMP for use");
//включаем DMP
mpu.setDMPEnabled(true); //используем библиотеку MPU6050 для включения DMP)
//ждём первого прерывания. в настоящее время просто оставьте значение false автоматически
mpuInterrupt == false;
// сообщаем основному циклу Llop, что можно использовать DMP, устанавливаем флаг dmpRead в значение ture
dmpReady = true;
Serial.println("DMP is ready to use.");
// получаем ожидаемый размер пакета DMP для последующего сравнения
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
//ОШИБКА! , статус устройства !=0 при инициализации DMP
Serial.print("DMP initialization failed when using MPU6050 library:");
if (deviceStatus == 1) {
Serial.println(" intial memory load failed");
} else if (deviceStatus == 2) {
Serial.println(" failed to update DMP configuration");
} else {
Serial.print(" unknow error with code: ");
Serial.println(deviceStatus);
}
}
}
int ticket = 1;
void printOnlyOnce (String message){
if (ticket == 1){
Serial.println(message);
ticket = 0 ;
} else {
return;
}
}
void loop() {
//если DMP не готов ничего не делать
if (!dmpReady) {
printOnlyOnce("MAIN LOOP: DMP disabled");
return;
} else {
//проверка переполнения
if (fifoCount == 1024) {
mpu.resetFIFO();
Serial.println("FIFO overflow");
} else {
//ждём достаточной доступной длины данных
while (fifoCount < packetSize) {
//ждём, пока наберёмся достаточно
fifoCount = mpu.getFIFOCount();
}
//читаем этот пакет из буфера FIFO
mpu.getFIFOBytes(fifoBuffer,packetSize);
//отслеживание количества FIFO, здесь доступно более одного пакета
//сбрасываем счетчик Fifo
fifoCount -= packetSize ;
Serial.println(fifoCount);
if (fifoCount > 2) {
////// очистка буфера FiFO
}
//этап отображения
// отображаем углы Эйлера в градусах
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.println(ypr[2] * 180/M_PI);
}
}
}
@Yank, 👍5
Обсуждение3 ответа
Лучший ответ:
Янк, В итоге я очищал буфер после каждого чтения. В вашем коде это будет следующая строка
//прочитаем этот пакет из буфера FIFO
mpu.getFIFOBytes(fifoBuffer,packetSize);
Я добавил
mpu.resetFIFO();
Я пришел к такому выводу после просмотра случаев переполнения. Буфер fifo добавляется к концу буфера, и когда он заполняется, а не переносится, он переполняется. Чтение, похоже, никак не удаляет данные из буфера. Очищая буфер, вы можете отбрасывать данные, но DMP выполняет за вас интеграцию с AHRS, поэтому вам действительно не нужно беспокоиться об удалении данных, поскольку вас интересуют только текущий шаг, крен, рысканье, Эйлер или что-то еще. , по крайней мере, это был мой случай. Я запускаю его на прототипе щита Arduino UNO, и он очень стабилен (с частотой по умолчанию 100 Гц). См. PiPlate/Pilot на сайте spiked3.com.
Спасибо, Spiked3! В настоящее время я тщательно его тестирую, в моей ситуации мне нужно использовать исторические данные от показаний 12 датчиков и 100% стабильную работу в течение как минимум 10 минут и вводить их в мой алгоритм машинного обучения, и я знаю, что даже если я использую прерывания, я думаю, вы просветите моя жизнь ! Сегодня днем я сообщу результаты тестирования и подтвержу их! :), @Yank
После тестирования с разными частотами и часами датчик остается стабильным без каких-либо ошибочных данных! Спасибо @Spike3, @Yank
Чтобы предотвратить проблемы с переполнением, перейдите в MPU6050_6Axis_MotionApps20.h и измените эту строку:
0x02, 0x16, 0x02, 0x00, **0x01** // D_0_22 inv_set_fifo_rate
Ценность, выделенная жирным шрифтом, является целью! Измените его на 0x03
или 0x04
или 0x05
, чтобы уменьшить частоту в Гц. Я использую 0x03
и больше не получаю значений ошибок, ненужных данных или переполнений.
На самом деле, когда я попробовал это, это даже дало мне плохие результаты. Значения, которые я прочитал, были просто очищены. Не могу проголосовать против, но это плохой подход!, @qwerty_so
Что, если мы сможем увеличить размер буфера FIFO?
uint8_t fifoBuffer[64]; // буфер хранения FIFO
Что, если я изменю это, скажем:
uint8_t fifoBuffer[1024]; // буфер хранения FIFO
а затем измените:
if ((mpuIntStatus & 0x10) || fifoCount == 16384) { // Я изменил 1024 -> 16384
// сброс, чтобы мы могли продолжить работу без ошибок
mpu.resetFIFO(); // Сбрасывает буфер FIFO, если он установлен в 1, а FIFO_EN равен 0.
Serial.println(F("FIFO overflow!"));
// в противном случае проверяем прерывание готовности данных DMP (это должно происходить часто)
}
Проверьте эти изменения.
- Проблема прерывания библиотеки MPU6050 Arduino Jeff Rowberg
- Как использовать SPI на Arduino?
- Как сбросить или отформатировать Arduino?
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как получить уникальный идентификатор для всех плат Arduino?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Элегантное решение для обновления содержимого TFT-дисплея
- Считывание нескольких поворотных энкодеров
Откуда вы знаете, что буфер FIFO — ваша проблема?, @BrettAM
привет, потому что я это проверил :), @Yank
Но какой метод тестирования вы использовали, чтобы изолировать проблему в этом буфере?, @BrettAM
Устранив один за другим другие потенциальные источники проблем до этого, у меня ушло около 8 часов :), @Yank