NodeMCU V3 и MPU6050 странные значения
Я новичок на этой платформе, поэтому, пожалуйста, если я сделаю что-то против обычных правил, пожалуйста, дайте мне знать, чтобы я мог учиться. Теперь моя проблема: у меня есть NodeMCU V3, подключенный к MPU6050. Используя свой Arduino Uno, я действительно получаю разумные значения порядка 0 градусов, когда устройство плоское. Используя тот же код и ту же настройку, я получаю очень странные значения порядка 45 градусов, когда устройство плоское. Я попробовал сделать следующее:
- С помощью сканера I2C я получаю действительный адрес.
- Тестирование с Arduino Uno значения правильные.
- GY 521 breakout использует 3V3 datalines с 2k2 pull ups. Линии данных короткие. Например, на том же макете.
- GY 521 имеет на борту регулятор напряжения на 5 В, поэтому я питаю устройство 5 В, чтобы преодолеть проблему падения напряжения.
- Я пытался растянуть функцию stretchClock, но безуспешно.
Я читал о людях с подобной проблемой, но не мог найти решения. Кто-нибудь может мне помочь? Аполигии. Было бы удобнее прикрепить мой код: '' /* * Пример скетча I2C для ESP8266 */
#include <Wire.h>
const int DevID = 0x68;
const int PWR_MGT1_REG = 0x6B;
const int DataReg_AX = 0x3B;
const int DataReg_AY = 0x3D;
const int DataReg_AZ = 0x3F;
const int AccConfigReg = 0x1C;
const int GyrConfigReg = 0x1B;
const int SelfTestReg = 0x0D;
const int TempReg = 0x41;
const int DataReg_GX = 0x43;
const int DataReg_GY = 0x45;
const int DataReg_GZ = 0x47;
const int CalibrationConfigAcc = 0xF0;//set this value for calibration
const int CalibrationConfigGyr = 0xE0;//set this value for calibration
const int NormalConfigAcc = 0x00;//set this value for calibration 2G
const int NormalConfigGyr = 0x00;//set this value for calibration 250dps
/*
int16_t Acc_X;
int16_t Acc_Y;
int16_t Acc_Z;
*/
float Acc_X, accAngleX, accAngleY, Yaw_Angle;
float Acc_Y;
float Acc_Z;
//double Acc_X, accAngleX, accAngleY, Yaw_Angle;
//double Acc_Y;
//double Acc_Z;
int8_t X_selfTest;
int8_t Y_selfTest;
int8_t Z_selfTest;
int8_t Acc_X_Y_Z_selfTest;
int16_t Temp;
/*
int16_t Gyro_X;
int16_t Gyro_Y;
int16_t Gyro_Z;
*/
float Gyro_X;
float Gyro_Y;
float Gyro_Z;
int16_t Gyro_X_selfTest;
int16_t Gyro_Y_selfTest;
int16_t Gyro_Z_selfTest;
//int SDApin = 3;//create I2C pinouts for ESP8266;
//int SCLpin = 4;
unsigned long elapsedTime, previousTime, currentTime;
void setup() {// put your setup code here, to run once:
Serial.begin(115200);
Wire.begin ();
// Wire.setClock(400000);
// Wire.setClockStretchLimit(40000);
Wire.beginTransmission(DevID);
Wire.write(PWR_MGT1_REG);
Wire.write(0x0);// wake up the sensor
Wire.endTransmission();
CalibrationProcedure();// enter calibration procedure
}
void loop() {// put your main code here, to run repeatedly:
previousTime = currentTime;
currentTime = millis();
elapsedTime = (currentTime - previousTime) / 1000;
Wire.beginTransmission(DevID);
Wire.write(DataReg_AX);
Wire.endTransmission();
Wire.requestFrom(DevID, 14);
if (Wire.available() == 14) {
Acc_X = ((Wire.read() << 8) | (Wire.read())) / 16384.0;// divide by 16384 for 2G setting according to datasheet
Acc_Y = ((Wire.read() << 8) | (Wire.read())) / 16384.0;
Acc_Z = ((Wire.read() << 8) | (Wire.read())) / 16384.0;
Temp = (Wire.read() << 8) | (Wire.read());
Gyro_X = ((Wire.read() << 8) | (Wire.read())) / 131.0; // divide by 131.0 according to datasheet for setting 250 dps
Gyro_Y = ((Wire.read() << 8) | (Wire.read())) / 131.0;
Gyro_Z = ((Wire.read() << 8) | (Wire.read())) / 131.0;
delay(500);
}
//The formulas below have been extracted from another program and uses mathematical
//values for calulation of pitch roll and yaw. For the moment only pitch is calibrated
//The next purpose of this program is follow a calibration procedure to take approx 200 samples
//and average the total value to correct the pitch roll and yaw value
accAngleX = (atan(Acc_Y / sqrt(pow(Acc_X, 2) + pow(Acc_Z, 2))) * 180 / PI);
accAngleY = (atan(-1 * Acc_X / sqrt(pow(Acc_Y, 2) + pow(Acc_Z, 2))) * 180 / PI);
Yaw_Angle = Yaw_Angle + Gyro_Z * elapsedTime;
float Gyro_X_axis = (float)Gyro_X / 131.0;
float Gyro_Y_axis = (float)Gyro_Y / 131.0;
float Gyro_Z_axis = (float)Gyro_Z / 131.0;
float Temperature = (Temp / (340.0)) + 36.53;
//Serial.print(" Accelero X \t" );
//Serial.print(Acc_X);
//Serial.print(" Accelero Y \t" );
//Serial.print(Acc_Y);
//Serial.print(" Accelero Z \t");
//Serial.print(Acc_Z);
//Serial.println("");
//Serial.print(" Gyro X \t" );
//Serial.print(Gyro_X);
//Serial.print(" Gyro Y \t" );
//Serial.print(Gyro_Y);
//Serial.print(" Gyro Z \t");
//Serial.print(Gyro_Z);
//Serial.print(" Temperature \t");
//Serial.println(Temperature);
//Serial.println(Temp);
Serial.println ("Angle X");
Serial.println(accAngleX);
Serial.println ("Angle Y");
Serial.println (accAngleY);
Serial.println("Yaw Angle");
Serial.println(Yaw_Angle);
delay(500);
}
void CalibrationProcedure() {
Serial.println("Keep sensor steady until calibration process is complete!");
Wire.beginTransmission(DevID);
Wire.write(AccConfigReg);//8 g
Wire.write(CalibrationConfigAcc);
Wire.endTransmission();
delay(250);
Wire.beginTransmission(DevID);
Wire.write(GyrConfigReg);
Wire.write(CalibrationConfigGyr);//250 deg/s
Wire.endTransmission();
delay(500);
Serial.println("Selftest enabled, reading data...");
Wire.beginTransmission(DevID);
Wire.write(SelfTestReg);
Wire.endTransmission();
Wire.requestFrom(DevID, 4);
if (Wire.available() <= 4) {
X_selfTest = Wire.read();
Y_selfTest = Wire.read();
Z_selfTest = Wire.read();
Acc_X_Y_Z_selfTest = Wire.read();
delay(500);
}
//extracting factory trim values after self test
//unsigned integers for accelero variables
uint8_t XA_selfTest;
uint8_t YA_selfTest;
uint8_t ZA_selfTest;
//unsigned integers for gyro variables
uint8_t GX_selfTest;
uint8_t GY_selfTest;
uint8_t GZ_selfTest;
//Factory Trim variables
float FTGX;
float FTGY;
float FTGZ;
float FTAX;
float FTAY;
float FTAZ;
float SelfTestPercentage_GX;
float SelfTestPercentage_GY;
float SelfTestPercentage_GZ;
float SelfTestPercentage_AX;
float SelfTestPercentage_AY;
float SelfTestPercentage_AZ;
GX_selfTest = X_selfTest & 0x1F; // 0x1F is a bit mask to extract the first 5 bits. unsigned format
GY_selfTest = Y_selfTest & 0x1F;
GZ_selfTest = Z_selfTest & 0x1F;
XA_selfTest = (X_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x30) >> 4; //shift the first 3 bits and extract bits with a mask depending on the LSB postion in the last received mixed byte
YA_selfTest = (Y_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x0C) >> 2;
ZA_selfTest = (Z_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x03);
Serial.println ("XA_selfTest");
Serial.println (X_selfTest, HEX);
Serial.println("YA_selfTest");
Serial.println(Y_selfTest, HEX);
Serial.println("ZA_selfTest");
Serial.println(Z_selfTest, HEX);
Serial.println("Acc_X_Y_Z_selfTest");
Serial.println(Acc_X_Y_Z_selfTest, HEX);
//calculate the factory trim settings
FTGX = (25.0 * 131.0) * (pow(1.046, ((float)GX_selfTest - 1.0)));// Factortrim Gyro X
FTGY = (-25.0 * 131.0) * (pow(1.046, ((float)GY_selfTest - 1.0)));// Factortrim Gyro Y
FTGZ = (25.0 * 131.0) * (pow(1.046, ((float)GZ_selfTest - 1.0)));// Factortrim Gyro Z
FTAX = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)XA_selfTest - 1.0) / 30.0)));
FTAY = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)YA_selfTest - 1.0) / 30.0)));
FTAZ = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)ZA_selfTest - 1.0) / 30.0)));
Serial.println("Selftest ended...please copy data");
Serial.println(" GX trim value\t" );
Serial.println(FTGX);
Serial.println(" GY trim value\t" );
Serial.println(FTGY);
Serial.println(" GZ trim value\t");
Serial.println(FTGZ);
Serial.println(" AX trim value\t" );
Serial.println(FTAX);
Serial.println(" AY trim value\t" );
Serial.println(FTAY);
Serial.println(" AZ trim value\t");
Serial.println(FTAZ);
SelfTestPercentage_GX = 100.0 + 100.0 * ((float)GX_selfTest - FTGX) / FTGX;
Serial.println("SelfTestPercentage");
Serial.println(SelfTestPercentage_GX);
SelfTestPercentage_GY = 100.0 + 100.0 * ((float)GY_selfTest - FTGY) / FTGY;
Serial.println("SelfTestPercentage");
Serial.println(SelfTestPercentage_GY);
SelfTestPercentage_GZ = 100.0 + 100.0 * ((float)GZ_selfTest - FTGZ) / FTGZ;
Serial.println("SelfTestPercentage");
Serial.println(SelfTestPercentage_GZ);
SelfTestPercentage_AX = 100.0 + 100.0 * ((float)XA_selfTest - FTAX) / FTAX;
Serial.println("SelfTestPercentage Acclero x, y, z");
Serial.println(SelfTestPercentage_AX);
SelfTestPercentage_AY = 100.0 + 100.0 * ((float)YA_selfTest - FTAY) / FTAY;
Serial.println("SelfTestPercentage Acclero x, y, z");
Serial.println(SelfTestPercentage_AY);
SelfTestPercentage_AZ = 100.0 + 100.0 * ((float)ZA_selfTest - FTAZ) / FTAZ;
Serial.println("SelfTestPercentage Acclero x, y, z");
Serial.println(SelfTestPercentage_AZ);
// get data outputs with self test enabled
Wire.beginTransmission(DevID);
Wire.write(DataReg_AX);
Wire.endTransmission();
Wire.requestFrom(DevID, 14);
if (Wire.available() <= 14) {
Acc_X = (Wire.read() << 8) | (Wire.read());
Acc_Y = (Wire.read() << 8) | (Wire.read());
Acc_Z = (Wire.read() << 8) | (Wire.read());
Temp = (Wire.read() << 8) | (Wire.read());
Gyro_X = (Wire.read() << 8) | (Wire.read());
Gyro_Y = (Wire.read() << 8) | (Wire.read());
Gyro_Z = (Wire.read() << 8) | (Wire.read());
delay(500);
}
//print values with self test enabled
Serial.println("Self test enabled values");
Serial.println(" Accelero X " );
Serial.println(Acc_X);
Serial.println(" Accelero Y " );
Serial.println(Acc_Y);
Serial.println(" Accelero Z ");
Serial.println(Acc_Z);
Serial.println(" Gyro X " );
Serial.println(Gyro_X);
Serial.println(" Gyro Y " );
Serial.println(Gyro_Y);
Serial.println(" Gyro Z ");
Serial.println(Gyro_Z);
delay(500);
//setup the device for normal OPS
Wire.beginTransmission(DevID);
Wire.write(AccConfigReg);
Wire.write(NormalConfigAcc);
Wire.endTransmission();
delay(50);
Wire.beginTransmission(DevID);
Wire.write(GyrConfigReg);
Wire.write(NormalConfigGyr);
Wire.endTransmission();
delay(50);
//request data with self test not enabled
Wire.beginTransmission(DevID);
Wire.write(DataReg_AX);
Wire.endTransmission();
Wire.requestFrom(DevID, 14);
if (Wire.available() <= 14) {
Acc_X = (Wire.read() << 8) | (Wire.read());
Acc_Y = (Wire.read() << 8) | (Wire.read());
Acc_Z = (Wire.read() << 8) | (Wire.read());
Temp = (Wire.read() << 8) | (Wire.read());
Gyro_X = (Wire.read() << 8) | (Wire.read());
Gyro_Y = (Wire.read() << 8) | (Wire.read());
Gyro_Z = (Wire.read() << 8) | (Wire.read());
delay(500);
//print values with self test not enabled
Serial.println("Self test not enabled values");
Serial.println(" Accelero X " );
Serial.println(Acc_X);
Serial.println(" Accelero Y " );
Serial.println(Acc_Y);
Serial.println(" Accelero Z ");
Serial.println(Acc_Z);
Serial.println(" Gyro X " );
Serial.println(Gyro_X);
Serial.println(" Gyro Y " );
Serial.println(Gyro_Y);
Serial.println(" Gyro Z ");
Serial.println(Gyro_Z);
delay(5000);
}
}
'''
@sanrays10, 👍0
Обсуждение1 ответ
Некоторое время назад у меня была такая же проблема.Я смог получить хорошие результаты, используя пример, приведенный для ESP8266 в самой библиотеке MPU6050.Вы можете внести необходимые изменения, начиная с этого скетча.Надеюсь, это поможет.
Вот ссылка на github для библиотеки https://github.com/ElectronicCats/mpu6050
Спасибо! Моей целью было писать с помощью библиотеки Wire.h. Но в справочных целях я постараюсь его использовать. Я сообщу вам о результате!, @sanrays10
Кажется, это работает, если я использую очень стандартный выходной файл и реализацию моих формул. Но мне действительно интересно, почему? Используют ли они другую библиотеку I2C? Что я упускаю?, @sanrays10
смотрите мой ответ выше....Не знаете, была ли у вас такая же проблема?, @sanrays10
Да, у меня была та же проблема.Что происходит, когда вы пытаетесь снять показания с акселерометра и гироскопа, как вы это сделали, так это то, что все ваши показания не фильтруются.Таким образом, такие вещи, как дрейф гироскопа, вступают в игру и оказывают значительное влияние на выход.Но библиотека создана таким образом, что полученные вами необработанные значения проходят через буфер FIFO, а также цифровой процессор движения на вашем MPU6050. Эти два устройства эффективно объединят данные датчиков и сведут к минимуму ошибки.Я обнаружил, что лучший способ получить показания-это использовать библиотеку, но у нее также есть некоторые недостатки., @AfiJaabb
Ну, в моем случае разделение после считывания данных и битового сдвига не работало. Если вы прокомментируете это, не стесняйтесь попробовать. Я не использую никакие регистры FIFO и т. Д. Я просто играл с I2C. Спасибо за ваш вклад!, @sanrays10
- Как подключить MPU9250 к NodeMCU с помощью SPI или I2C Slave?
- Протокол I2C не работает должным образом
- ESP8266 не работает с MPU 6050 по проводной библиотеке и I2C
- LILYGO TTGO T-Display не может обнаружить акселерометр, гироскоп и датчик температуры MPU 6050
- Отправка и получение различных типов данных через I2C в Arduino
- Как выбрать альтернативные контакты I2C на ESP32?
- NodeMCU с RFID RC522 и LCD-модулем интерфейса I2C вместе
- Альтернативы библиотеке Wire для I2C
Ты сказал, что получаешь хорошие ценности, а потом сказал, что получаешь плохие. Что меняется между ними? Как вы думаете, размещение кода и проводки будет разумным? Или ты думаешь, что умнее заставить нас догадаться о том, что ты сделал?, @Delta_G
Прости! Я приложил свой код. Единственное изменение, которое я в основном сделал, это преобразование того же кода из Uno в NodeMCU с помощью стандартных контактов I2C. Когда устройство плоское, Uno считывает 0 градусов, что правильно. Но с NodeMCU я получаю значения 45 градусов, прыгая вверх и вниз., @sanrays10
Ага, значит, тут замешан НодеМКУ? Почему вы не упомянули об этом в вопросе? Вы не думали, что это может быть важно?, @Delta_G
Я записал это в своем вопросе, верно? На случай, если это было неясно, извините., @sanrays10
Я говорил о том, что "использование одного и того же кода и одной и той же настройки" подразумевает одну и ту же плату. Это меня смутило., @Delta_G
Ах да, извините за путаницу. Надеюсь, моя проблема немного прояснилась. Я использую один и тот же код для uno и NodeMCU. который прекрасно компилируется, и я действительно получаю данные с обеих плат. Однако узловой микроконтроллер дает мне неверные значения. Я перепробовал несколько датчиков I2C, и они, похоже, имеют одну и ту же проблему. Может ли кто-нибудь объяснить, чего мне не хватает?, @sanrays10
Работает ли I2C на NodeMCU так же, как и на Arduino? Принимает ли он тот же код?, @Delta_G
Да, с аппаратной точки зрения это точно. На прошлой неделе я получил NodeMCU и программирую его с помощью Arduino IDE. В том числе те же библиотеки и т. Д. Ты это имеешь в виду?, @sanrays10
Да, я никогда не делал I2C на NodeMCU, но я делал много других вещей, и мне кажется довольно типичным использовать другую библиотеку или делать по крайней мере некоторые вещи по-другому на другой платформе для большинства из них. Поэтому я подумал, не проверяли ли вы что-нибудь на I2C для NodeMCU, чтобы узнать, есть ли какие-то особые соображения или вы просто перенесли код., @Delta_G
Правда. Это похоже на реализацию "штуковины" с проволокой.h библиотека. Но я не могу понять, почему или что., @sanrays10
Думаю, я нашел решение. Division /16384 как-то не работает на этой платформе. Если я выполняю формулу с исходными значениями, она работает...Масштабирование значений в соответствии с регистровыми значениями, по-видимому, является следующей задачей..., @sanrays10
Отдел работает. Вероятно, у вас проблема с типом переменной. - Какая линия?, @Delta_G
О, я вижу линию. Также может быть проблема с последовательностью. У вас нет никакого контроля над порядком двух вызовов wire.read(). Вы должны сделать эти два чтения в двух строках., @Delta_G
Это был вопрос последовательности, я думаю. Странно, что я не смог заметить это на UNO, хотя!, @sanrays10
Компилятор получает свой выбор там. Если вы хотите, чтобы вещи шли в определенном порядке, то убедитесь, что между ними есть точка последовательности. Я никогда не могу вспомнить, что все это значит, поэтому я просто иду на разделение на две строки кода, и я знаю, что это сработает., @Delta_G