Проблема с библиотекой MPU6050
У меня есть любопытство. В чем разница между добавлением файла заголовка непосредственно в arduino IDE и файла заголовка внутри другого h-файла. Например:
#include "MPU6050_6Axis_MotionApps20.h"
void setup()
{
}
void loop()
{
}
Последнее не вызвало у меня никаких проблем, но когда я создаю h-файл и добавляю в этот h-файл эту библиотеку, это выдает ошибку:
ARDUINO:
#include "Prueba.h"
void setup()
{
}
void loop()
{
}
Пруэба.ч
//#ifndef Prueba_H
//#define Prueba_H
//#define LIBRARY_VERSION 1.0.0
#include "MPU6050_6Axis_MotionApps20.h"
class Prueba
{
public:
Prueba();
};
//#endif
Часть кода ошибки выглядит следующим образом:
C:\Users\linco\Documents\Arduino\libraries\MPU6050-0.2.1\src\MPU6050.cpp:1679:9: note: implicit this pointer type mismatch
uint8_t MPU6050::getIntStatus() {
^
C:\Users\linco\Documents\Arduino\libraries\MPU6050-0.2.1\src\MPU6050.h:438:7: note: type 'struct MPU6050' itself violates the C++ One Definition Rule
class MPU6050 {
^
C:\Users\linco\Documents\Arduino\libraries\MPU6050-0.2.1\src/MPU6050.h:438:7: note: the incompatible type is defined here
class MPU6050 {
^
C:\Users\linco\Documents\Arduino\libraries\MPU6050-0.2.1\src\MPU6050.cpp:1679:9: note: 'getIntStatus' was previously declared here
uint8_t MPU6050::getIntStatus() {
^
C:\Users\linco\Documents\Arduino\libraries\MPU6050-0.2.1\src\MPU6050.cpp:1679:9: note: code may be misoptimized unless -fno-strict-aliasing is used
collect2.exe: error: ld returned 1 exit status
exit status 1
Кто-нибудь может мне это объяснить?
Заранее благодарю.
@PartnerTech, 👍2
Обсуждение1 ответ
Лучший ответ:
▲ 1
Ну, я не знаю точно, почему это работает, но основываюсь на этом вопросе так. Чтобы решить эту проблему, я должен добавить ключевое слово 'inline' в каждое определение метода в MPU6050_6Axis_MotionApps20.h Вот так:
inline uint8_t MPU6050::dmpInitialize() {
// сброс устройства
DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
reset();
delay(30); // подождите после сброса
// отключить спящий режим
setSleepEnabled(false);
// получить аппаратную ревизию MPU
setMemoryBank(0x10, true, true);
setMemoryStartAddress(0x06);
Serial.println(F("Checking hardware revision..."));
Serial.print(F("Revision @ user[16][6] = "));
Serial.println(readMemoryByte(), HEX);
Serial.println(F("Resetting memory bank selection to 0..."));
setMemoryBank(0, false, false);
// проверить действительность OTP bank
DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
DEBUG_PRINT(F("OTP bank is "));
DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!"));
// настройка странных подчиненных устройств (?)
DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F..."));
setSlaveAddress(0, 0x7F);
DEBUG_PRINTLN(F("Disabling I2C Master mode..."));
setI2CMasterModeEnabled(false);
DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)..."));
setSlaveAddress(0, 0x68);
DEBUG_PRINTLN(F("Resetting I2C Master control..."));
resetI2CMaster();
delay(20);
DEBUG_PRINTLN(F("Setting clock source to Z Gyro..."));
setClockSource(MPU6050_CLOCK_PLL_ZGYRO);
DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled..."));
setIntEnabled(1<<MPU6050_INTERRUPT_FIFO_OFLOW_BIT|1<<MPU6050_INTERRUPT_DMP_INT_BIT);
DEBUG_PRINTLN(F("Setting sample rate to 200Hz..."));
setRate(4); // 1 кГц / (1 + 4) = 200 Гц
DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]..."));
setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L);
DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz..."));
setDLPFMode(MPU6050_DLPF_BW_42);
DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec..."));
setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
// загрузить код DMP в банки памяти
DEBUG_PRINT(F("Writing DMP code to MPU memory banks ("));
DEBUG_PRINT(MPU6050_DMP_CODE_SIZE);
DEBUG_PRINTLN(F(" bytes)"));
if (!writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) return 1; // Сбой
DEBUG_PRINTLN(F("Success! DMP code written and verified."));
// Установите делитель скорости FIFO в памяти встроенного ПО DMP
unsigned char dmpUpdate[] = {0x00, MPU6050_DMP_FIFO_RATE_DIVISOR};
writeMemoryBlock(dmpUpdate, 0x02, 0x02, 0x16); // Давайте запишем данные dmpUpdate в образ прошивки, у нас есть 2 байта для записи в банк 0x02 со смещением 0x16
//записать начальный адрес MSB в регистр
setDMPConfig1(0x03);
//записать начальный адрес LSB в регистр
setDMPConfig2(0x00);
DEBUG_PRINTLN(F("Clearing OTP Bank flag..."));
setOTPBankValid(false);
DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
setMotionDetectionThreshold(2);
DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
setZeroMotionDetectionThreshold(156);
DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
setMotionDetectionDuration(80);
DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
setZeroMotionDetectionDuration(0);
DEBUG_PRINTLN(F("Enabling FIFO..."));
setFIFOEnabled(true);
DEBUG_PRINTLN(F("Resetting DMP..."));
resetDMP();
DEBUG_PRINTLN(F("DMP is good to go! Finally."));
DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)..."));
setDMPEnabled(false);
DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer..."));
dmpPacketSize = 42;
DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time..."));
resetFIFO();
getIntStatus();
return 0; // успех
}
inline bool MPU6050::dmpPacketAvailable() {
return getFIFOCount() >= dmpGetFIFOPacketSize();
}
inline uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]);
data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]);
data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]);
return 0;
}
inline uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[28] << 8) | packet[29];
data[1] = (packet[32] << 8) | packet[33];
data[2] = (packet[36] << 8) | packet[37];
return 0;
}
inline uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
v -> x = (packet[28] << 8) | packet[29];
v -> y = (packet[32] << 8) | packet[33];
v -> z = (packet[36] << 8) | packet[37];
return 0;
}
inline uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]);
data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]);
data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]);
data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]);
return 0;
}
inline uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[0] << 8) | packet[1]);
data[1] = ((packet[4] << 8) | packet[5]);
data[2] = ((packet[8] << 8) | packet[9]);
data[3] = ((packet[12] << 8) | packet[13]);
return 0;
}
inline uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
int16_t qI[4];
uint8_t status = dmpGetQuaternion(qI, packet);
if (status == 0) {
q -> w = (float)qI[0] / 16384.0f;
q -> x = (float)qI[1] / 16384.0f;
q -> y = (float)qI[2] / 16384.0f;
q -> z = (float)qI[3] / 16384.0f;
return 0;
}
return status; // возвращаемое значение int16, указывает на ошибку, если эта строка достигнута
}
inline uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]);
data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]);
data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]);
return 0;
}
inline uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[16] << 8) | packet[17];
data[1] = (packet[20] << 8) | packet[21];
data[2] = (packet[24] << 8) | packet[25];
return 0;
}
inline uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) {
// TODO: приспособить различные схемы отправляемых данных (СЕЙЧАС поддерживается только по умолчанию)
if (packet == 0) packet = dmpPacketBuffer;
v -> x = (packet[16] << 8) | packet[17];
v -> y = (packet[20] << 8) | packet[21];
v -> z = (packet[24] << 8) | packet[25];
return 0;
}
inline uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) {
// избавьтесь от компонента гравитации (+1g = +8192 в стандартном пакете DMP FIFO, чувствительность 2g)
v -> x = vRaw -> x - gravity -> x*8192;
v -> y = vRaw -> y - gravity -> y*8192;
v -> z = vRaw -> z - gravity -> z*8192;
return 0;
}
inline uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) {
// поворот измеренного 3D вектора ускорения в исходное состояние
// система отсчета , основанная на кватернионе ориентации
memcpy(v, vReal, sizeof(VectorInt16));
v -> rotate(q);
return 0;
}
inline uint8_t MPU6050::dmpGetGravity(int16_t *data, const uint8_t* packet) {
/* +1g corresponds to +8192, sensitivity is 2g. */
int16_t qI[4];
uint8_t status = dmpGetQuaternion(qI, packet);
data[0] = ((int32_t)qI[1] * qI[3] - (int32_t)qI[0] * qI[2]) / 16384;
data[1] = ((int32_t)qI[0] * qI[1] + (int32_t)qI[2] * qI[3]) / 16384;
data[2] = ((int32_t)qI[0] * qI[0] - (int32_t)qI[1] * qI[1]
- (int32_t)qI[2] * qI[2] + (int32_t)qI[3] * qI[3]) / (2 * 16384);
return status;
}
inline uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
return 0;
}
inline uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) {
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); //
data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // тета
data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi
return 0;
}
#ifdef USE_OLD_DMPGETYAWPITCHROLL
inline uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
// рыскание: (около оси Z)
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
// тангаж: (нос вверх/вниз, вокруг оси Y)
data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
// крен: (наклон влево/ вправо, вокруг оси X)
data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z));
return 0;
}
#else
inline uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
// рыскание: (около оси Z)
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
// тангаж: (нос вверх/вниз, вокруг оси Y)
data[1] = atan2(gravity -> x , sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
// крен: (наклон влево/ вправо, вокруг оси X)
data[2] = atan2(gravity -> y , gravity -> z);
if (gravity -> z < 0) {
if(data[1] > 0) {
data[1] = PI - data[1];
} else {
data[1] = -PI - data[1];
}
}
return 0;
}
#endif
inline uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) {
return 0;
}
inline uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) {
uint8_t status;
uint8_t buf[dmpPacketSize];
for (uint8_t i = 0; i < numPackets; i++) {
// считывание пакета из FIFO
getFIFOBytes(buf, dmpPacketSize);
// пакет обработки
if ((status = dmpProcessFIFOPacket(buf)) > 0) return status;
// увеличить внешнюю переменную количества процессов, если она указана
if (processed != 0) (*processed)++;
}
return 0;
}
inline uint16_t MPU6050::dmpGetFIFOPacketSize() {
return dmpPacketSize;
}
#endif
Я не знаю, почему ребята, которые создали эту библиотеку, не добавили это. Может быть, я что-то упускаю.
,
@PartnerTech
Смотрите также:
- Как использовать SPI на Arduino?
- Как очистить буфер FIFO на MPU6050?
- Подключение HX711 к трехпроводному датчику нагрузки
- Правильное использование * и & при передаче объектов в методах.
- ISO C++ запрещает принимать адрес неквалифицированной или заключенной в скобки нестатической функции-члена для формирования указателя на функцию-член
- Разница между массивом char и массивом unsigned char
- Почему MPU6050 DMP не инициализируется, но я могу получить необработанные значения ускорения от MPU6050
- Печать содержимого файла SD - карты на ЖК-дисплее
почему это закомментировано? ...
//#ifndef Prueba_H
, @jsotolaЯ пробовал и то, и другое. Прокомментировал и нет., @PartnerTech