Переполнение FIFO - одновременное чтение IMU MPU6090 и GPS uBlox NEO-6M

Пытаюсь прочитать данные с uBlox NEO-6m (мне нужна только скорость, только часть кода):

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = 7, TXPin = 4;
static const uint32_t GPSBaud = 9600;

float gps_speed = 0;

// Объект TinyGPS++
TinyGPSPlus gps;

// Последовательное подключение к устройству GPS
SoftwareSerial ss(RXPin, TXPin);

void setup(){
ss.begin(GPSBaud);
}

void loop(){
if (ss.available())
    {
      gps.encode(ss.read());
      gps_speed = gps.speed.kmph();

    }
}

И в то же время я считываю данные с MPU6090, используя этот код (в нем встроен код GPS):

http://nevit.blogspot.de/2014/07/arduino-mpu-6050-pitch-roll-with-2.html

Когда я пытаюсь прочитать данные по отдельности, это работает, но вместе они зависают каждую секунду (вероятно, чтение данных GPS), а последовательный монитор MPU6050 отправляет ошибку переполнения FIFO.

Я пытался снизить частоту передачи данных микропроцессора со 100 Гц до 20 Гц, но это не сработало. Я использую Arduino UNO.

Я не очень-то разбираюсь... Есть идеи? Возможно ли вообще сделать это таким образом?

, 👍1

Обсуждение

Похоже, как только вы получите от GPS хотя бы один символ, вы перейдете в режим ожидания полного сообщения в блокирующей функции сбора, которая может привести к невозможности опустошения буфера MPU FIFO. Вместо этого, возможно, стоит собирать символы по одному из GPS, продолжая следить за MPU, и обращаться к GPS только после получения полного сообщения., @Chris Stratton


3 ответа


0

Предположение: программный последовательный порт известен своей способностью вмешиваться в работу прерываний. На самом деле, я думаю, что общее правило — не использовать прерывания и программный последовательный порт.

Используемый вами код MPU — классический код Джеффа Роуберга, использующий прерывания.

Честно говоря, есть вещи, которые можно сделать так, чтобы случайный перелив не вызывал проблем, но это слишком сложно объяснить здесь, извините.

В моём случае я, пожалуй, буду использовать Arduino для управления микропроцессором, а сам Arduino и GPS-модуль подключу к Raspberry Pi, чтобы он объединил эти два устройства. Возможно, вы сможете сделать то же самое и с более мощной Arduino, если у неё есть два (или более) последовательных порта UART, но у меня нет опыта работы с ними.

Если вы можете увеличить скорость последовательной передачи данных GPS, попробуйте это, это действительно помогает (что противоречит здравому смыслу).

,

0

Вот вам ответ.

GPS продолжает отправлять данные и заполнять входной буфер микроконтроллера. Используйте функцию прослушивания и считывайте один серийный номер ПО за раз.

Если вы используете прослушивание, то одновременно будет работать только один последовательный порт, и вы можете поменять их местами.

У меня была та же проблема, и это решило ее.

Просто откройте фиктивный последовательный порт, и когда вам понадобится GPS, слушайте последовательный порт GPS и не забывайте слушать фиктивный порт после считывания GPS.

,

Ещё раз, пожалуйста, не добавляйте подписи к своему посту. Я их удалил. Спасибо!, @Anonymous Penguin


2

Когда я пытаюсь прочитать данные по отдельности, это работает, но вместе они зависают каждую секунду (вероятно, чтение данных GPS), а последовательный монитор MPU6050 отправляет ошибку переполнения FIFO.

Да, нужно быть внимательным к структуре цикла и «блокировке» для «ожидания» нового отчёта скорости GPS. SoftwareSerial также блокирует всё остальное в течение времени получения каждого символа.

Просто проверьте наличие символов GPS и обновите скорость, если получено полное предложение, а затем выполните «другие действия» (например, используйте данные инерциального измерительного блока). Вот версия вашего примера для NeoGPS:

#include "NMEAGPS.h"
#include <NeoSWSerial.h>

static const int RXPin = 7, TXPin = 4;
static const uint32_t GPSBaud = 9600;

float gps_speed = 0;

NMEAGPS gps;

// Последовательное подключение к устройству GPS
NeoSWSerial ss(RXPin, TXPin);

void setup(){
  Serial.begin( 9600 );
  ss.begin(GPSBaud);
}

void loop(){

  // Считывайте символы GPS и проверяйте, доступно ли новое исправление
  if (gps.available( ss )) {
    gps_fix fix = gps.read();

    // Исправление доступно раз в секунду, но GPS может не знать
    // значение скорости, возможно, из-за спутникового приема
    // плохо или устройство только запускается. Проверьте правильный флаг.

    if (fix.valid.speed) {

      // Обновите gps_speed. Другие части вашего
      // программа может использовать его, когда захочет.
      gps_speed = fix.speed_kph();
      Serial.println( gps_speed );
    }
  }

}

NeoGPS меньше и быстрее других библиотек, и ее можно настроить на анализ только тех полей, которые вы действительно используете.

Ваш исходный скетч использует 6884 байта программного пространства и 349 байт ОЗУ.
Версия NeoGPS может занимать всего 4802 байта памяти и 150 байт оперативной памяти. Значительная экономия!

Для библиотеки программного последовательного порта я бы рекомендовал использовать AltSoftSerial на контактах 8 и 9, если есть возможность переместить GPS. Это гораздо эффективнее и не блокирует прерывания на долгое время: SoftwareSerial блокирует примерно на 1 мс, а для 16-мегагерцовой Arduino — навсегда. Вероятно, это мешает прерываниям IMU.

Если вам не удаётся переместить GPS на контакты 8 и 9, попробуйте другую библиотеку, которую я поддерживаю, NeoSWSerial. Она гораздо эффективнее SoftwareSerial и работает с любыми двумя контактами. NeoSWSerial лучше работает с кодом прерывания IMU, но на неё всё равно могут повлиять проблемы, если код прерывания IMU выполняется слишком долго. NeoSWSerial не должен влиять на код прерывания IMU. Я использовал её в скетче выше вместе с отладочной распечаткой.

,