Переполнение 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.
Я не очень-то разбираюсь... Есть идеи? Возможно ли вообще сделать это таким образом?
@Jakub Jon, 👍1
Обсуждение3 ответа
Предположение: программный последовательный порт известен своей способностью вмешиваться в работу прерываний. На самом деле, я думаю, что общее правило — не использовать прерывания и программный последовательный порт.
Используемый вами код MPU — классический код Джеффа Роуберга, использующий прерывания.
Честно говоря, есть вещи, которые можно сделать так, чтобы случайный перелив не вызывал проблем, но это слишком сложно объяснить здесь, извините.
В моём случае я, пожалуй, буду использовать Arduino для управления микропроцессором, а сам Arduino и GPS-модуль подключу к Raspberry Pi, чтобы он объединил эти два устройства. Возможно, вы сможете сделать то же самое и с более мощной Arduino, если у неё есть два (или более) последовательных порта UART, но у меня нет опыта работы с ними.
Если вы можете увеличить скорость последовательной передачи данных GPS, попробуйте это, это действительно помогает (что противоречит здравому смыслу).
Вот вам ответ.
GPS продолжает отправлять данные и заполнять входной буфер микроконтроллера. Используйте функцию прослушивания и считывайте один серийный номер ПО за раз.
Если вы используете прослушивание, то одновременно будет работать только один последовательный порт, и вы можете поменять их местами.
У меня была та же проблема, и это решило ее.
Просто откройте фиктивный последовательный порт, и когда вам понадобится GPS, слушайте последовательный порт GPS и не забывайте слушать фиктивный порт после считывания GPS.
Ещё раз, пожалуйста, не добавляйте подписи к своему посту. Я их удалил. Спасибо!, @Anonymous Penguin
Когда я пытаюсь прочитать данные по отдельности, это работает, но вместе они зависают каждую секунду (вероятно, чтение данных 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. Я использовал её в скетче выше вместе с отладочной распечаткой.
- GPS-модуль uBlox Neo 6M не отвечает
- Как очистить буфер FIFO на MPU6050?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Как отправить данные из Arduino Uno с SIM900 GPRS в Firebase
- Понимание того, почему следует избегать «String» и альтернативных решений
- Объяснение кода MPU6050
- Ошибка инициализации GPS DFRobot [Arduino Uno, SIM808]
- Изменение адреса I2C MPU-6050
Похоже, как только вы получите от GPS хотя бы один символ, вы перейдете в режим ожидания полного сообщения в блокирующей функции сбора, которая может привести к невозможности опустошения буфера MPU FIFO. Вместо этого, возможно, стоит собирать символы по одному из GPS, продолжая следить за MPU, и обращаться к GPS только после получения полного сообщения., @Chris Stratton