MPU6050 не выдает выход
Мне нужна помощь, чтобы мой MPU 6050 действительно предоставил мне данные. На данный момент моя программа считывает только 0 с гироскопа, и когда я перемещаю его, все значения становятся равными -1, и программа просто останавливается, пока я не закрою и снова не открою последовательный монитор. Я знаю, что этот вопрос уже задавался несколько раз, но я уже рассматривал каждый из этих вопросов и перепробовал все исправления, перечисленные там, но ни одно из них не сработало. Сканер I2C действительно находит датчик на 0x68, но это единственное, что работает. Это все совершенно новые платы, которые я получил пару дней назад.
Я перепробовал все библиотеки и все примеры скетчей, которые смог найти. Я перешел на 2 новые платы. Я даже попытался просмотреть таблицу данных для MPU 6050 и напрямую прочитать/записать регистры, но все равно не получил никаких результатов. Последовательный монитор либо остается пустым, показывает только 0 или-1, либо просто выдает мне значения мусора, которые меняются случайным образом. Пожалуйста, помогите мне.
Я подключил датчик следующим образом (в настоящее время я использую Arduino Uno):
VCC ==> 5 В>
GND ==> GND
SCL ==> A5
ПДД ==> А4>
AD0 ==> цифровой 13 (установлен на НИЗКИЙ уровень)>
И код, который я использую, таков:
#include <Wire.h>
const int addressPin = 13;
int gyroX, gyroY, gyroZ;
void setup() {
Wire.begin();
Serial.begin(9600);
//designating pins as I/O
pinMode(addressPin, OUTPUT);
//setting IMU address to 0x68 (LOW)
digitalWrite(addressPin, LOW);
initializeSensor();
}
void loop() {
readGyro();
Serial.print(gyroX);
Serial.print(" ");
Serial.print(gyroY);
Serial.print(" ");
Serial.println(gyroZ);
}
void initializeSensor() {
//performing full device reset, disables temperature sensor, disables SLEEP mode
Wire.beginTransmission(0x68);
Wire.write(0x6B);
Wire.write(0b10001000);
Wire.endTransmission();
//writing to gyro config register
Wire.beginTransmission(0x68);
Wire.write(0x1B);
Wire.write(0b00001000);
Wire.endTransmission();
}
void readGyro() {
//requesting data from gyro data registers
Wire.beginTransmission(0x68);
Wire.write(0x43);
Wire.endTransmission();
Wire.requestFrom(0x68, 6);
gyroX = Wire.read()<<8|Wire.read();
gyroY = Wire.read()<<8|Wire.read();
gyroZ = Wire.read()<<8|Wire.read();
}
P.S. Несколько недель назад я опубликовал вопрос об устройствах I2C, и в нем я сказал, что мне удалось успешно считывать данные с датчика, но позже я узнал, что это были номера мусора. :(
@Tobias Guo, 👍3
Обсуждение3 ответа
Лучший ответ:
Из карты регистра MPU-6000/MPU-6050 и описаний:
Раздел 4.28, Регистрация 107 – Управление питанием 1 PWR_MGMT_1, страницы 40-41:
Примечание:
При использовании интерфейса SPI пользователь должен использовать DEVICE_RESET (регистр 107), а также SIGNAL_PATH_RESET (регистр 104), чтобы убедиться, что сброс выполнен правильно. Используемая последовательность должна быть:- Установить DEVICE_RESET = 1 (зарегистрировать PWR_MGMT_1)
- Подождите 100 мс
- Установить GYRO_RESET = ACCEL_RESET = TEMP_RESET = 1 (зарегистрировать SIGNAL_PATH_RESET)
- Подождите 100 мс
Раздел 4.26, Регистр 104 – Сброс пути сигнала SIGNAL_PATH_RESET, страница 37:
Примечание: Этот регистр не очищает регистры датчиков. Сброс также инициализирует последовательный интерфейс.
Раздел 3, Карта регистрации, страница 8:
Значение сброса равно 0x00 для всех регистров, кроме приведенных ниже.
- Регистрация 107: 0x40.
- Регистрация 117: 0x68.
Это означает, что регистр PWR_MGMT_1 по умолчанию переходит в спящий режим после сброса, поэтому его необходимо перезаписать, чтобы отключить спящий режим после команды сброса.
void initializeSensor()
{
//
// Perfrom full reset as per MPU-6000/MPU-6050 Register Map and Descriptions, Section 4.28, pages 40 to 41.
//
// performing full device reset, disables temperature sensor, disables SLEEP mode
Wire.beginTransmission(0x68); // Device address.
Wire.write(0x6B); // PWR_MGMT_1 register.
Wire.write(0b10001000); // DEVICE_RESET, TEMP_DIS.
Wire.endTransmission();
delay(100); // Wait for reset to complete.
Wire.beginTransmission(0x68); // Device address.
Wire.write(0x68); // SIGNAL_PATH_RESET register.
Wire.write(0b00000111); // GYRO_RESET, ACCEL_RESET, TEMP_RESET.
Wire.endTransmission();
delay(100); // Wait for reset to complete.
// Disable SLEEP mode because the reset re-enables it. Section 3, PWR_MGMT_1 register, page 8.
Wire.beginTransmission(IMUAddress); // Device address.
Wire.write(0x6B); // PWR_MGMT_1 register.
Wire.write(0b00001000); // SLEEP = 0, TEMP_DIS = 1.
Wire.endTransmission();
}
В следующем коде я написал:
Изменено
readGyro (), чтобы реализовать 3 состояния (Запрос, ожидание и чтение) и возвращать значениеtrue, когда из MPU-6050 было считано 6 байт.Добавлено Мигание без задержки в
loop (), чтобы увидеть, зависает ли MCU, для чего требуется изменить вывод ADO с вывода 13 (встроенный светодиод) на другой вывод, т. Е. вывод 12.Добавлено несколько
последовательных инструкций.print()для отладки, чтобы увидеть, где что-то идет не так.Изменил код в ответ на комментарии.
#include <Wire.h>
const byte IMUAddress = 0x68; // Added for readability and maintainability.
const byte addressPin = 12; // Changed from 13 to 12 because 13 is built-in LED.
int gyroX, gyroY, gyroZ;
void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.println(F("\n\nMPU-6050 Test\n"));
// Designating pins as I/O.
pinMode(addressPin, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT); // Added LED for heartbeat signal.
// Setting IMU address to 0x68 (LOW).
digitalWrite(addressPin, IMUAddress & 1); // Added bit mask of bit 0.
initializeSensor();
}
void loop()
{
//
// TASK 1: Blink without delay to indicate that MCU hasn't frozen.
//
const unsigned int INTERVAL = 250;
unsigned long current_timestamp = millis();
static unsigned long previous_timestamp = current_timestamp;
static bool led_state = false;
if (current_timestamp - previous_timestamp >= INTERVAL)
{
led_state = !led_state;
digitalWrite(LED_BUILTIN, led_state);
previous_timestamp += INTERVAL;
}
//
// TASK 2: Read gyro.
//
if (readGyro())
{
Serial.print(gyroX);
Serial.print(F(" "));
Serial.print(gyroY);
Serial.print(F(" "));
Serial.println(gyroZ);
}
}
void initializeSensor()
{
//
// Perform full reset as per MPU-6000/MPU-6050 Register Map and Descriptions, Section 4.28, pages 40 to 41.
//
Serial.print(F("Performing full reset of MPU-6050..."));
Wire.beginTransmission(IMUAddress); // Device address.
Wire.write(0x6B); // PWR_MGMT_1 register.
Wire.write(0b10001000); // DEVICE_RESET, TEMP_DIS.
Wire.endTransmission();
delay(100); // Wait for reset to complete.
Wire.beginTransmission(IMUAddress); // Device address.
Wire.write(0x68); // SIGNAL_PATH_RESET register.
Wire.write(0b00000111); // GYRO_RESET, ACCEL_RESET, TEMP_RESET.
Wire.endTransmission();
delay(100); // Wait for reset to complete.
Serial.println(F(" Done."));
// Disable SLEEP mode because the reset re-enables it. Section 3, PWR_MGMT_1 register, page 8.
Serial.print(F("Disabling sleep mode of MPU-6050..."));
Wire.beginTransmission(IMUAddress); // Device address.
Wire.write(0x6B); // PWR_MGMT_1 register.
Wire.write(0b00001000); // SLEEP = 0, TEMP_DIS = 1.
Wire.endTransmission();
Serial.println(F(" Done."));
//
// Writing to gyro config register.
//
Serial.print(F("Configuring gyro of MPU-6050..."));
Wire.beginTransmission(IMUAddress); // Device address.
Wire.write(0x1B); // GYRO_CONFIG register.
Wire.write(0b00001000); // +/-500 deg/s.
Wire.endTransmission();
Serial.println(F(" Done."));
}
typedef enum State
{
Request,
Wait,
Read
};
bool readGyro()
{
static State state = State::Request;
switch (state)
{
case State::Request:
// Request data from gyro data registers.
Serial.print(F("Requesting data from gyro..."));
Wire.beginTransmission(IMUAddress); // Device address.
Wire.write(0x43); // GYRO_XOUT_H register.
Wire.endTransmission(false); // Restart connection, i.e. keep alive.
Wire.requestFrom(IMUAddress, 6); // GYRO_XOUT_H, GYRO_XOUT_L, GYRO_YOUT_H, GYRO_YOUT_L, GYRO_ZOUT_H, GYRO_ZOUT_L.
Serial.println(F(" Done."));
state = State::Wait;
Serial.print(F("Waiting for data from gyro..."));
break;
case State::Wait:
// Wait for data to arrive into buffer.
if(Wire.available() < 6)
{
//Serial.print(F("."));
Serial.print(F(" "));
Serial.print(Wire.available()); // Added to show bytes received.
}
else
{
Serial.print(F(" "));
Serial.print(Wire.available()); // Added to show bytes received.
Serial.println(F(" Done."));
state = State::Read;
}
break;
case State::Read:
// Read data from gyro registers.
Serial.print(F("Reading gyro data..."));
gyroX = Wire.read() << 8 | Wire.read();
gyroY = Wire.read() << 8 | Wire.read();
gyroZ = Wire.read() << 8 | Wire.read();
Serial.println(F(" Done."));
state = State::Request;
return true; // Indicate data was received.
break;
}
return false; // Indicate no data received yet.
}
Обновление основано на ответе Роуанпа
Сосредоточившись на проблемах программного обеспечения, я пропустил важную часть информации из другой спецификации (Спецификация продукта MPU-6000/MPU-6050), т. Е. Электрические характеристики в разделах 6.3 и 6.4 на страницах 14 и 15, показывающие диапазон Vdd от 2,375 В до 3,46 В:

6.4 Электрические характеристики, Продолжение

Для этого потребуются переключатели уровней сигналов между 3,3 В MPU-6050 и 5 В Arduino.
Спасибо за помощь! Я просмотрел контрольный список, который дал мне Роуэн, и исправил все, что, по моему мнению, могло быть неправильным, включая переключение на вывод 3,3 В для питания Uno. Я также использовал ваш код, и, похоже, он по-прежнему выдает только 0 секунд, но когда я поворачиваю датчик вокруг оси y, код застревает в состоянии :: Ожидание и печатает только периоды (но индикатор сердцебиения не останавливается). У тебя есть какие-нибудь идеи, почему?, @Tobias Guo
@TobiasGuo, как уже говорили другие, чип может быть поврежден из-за питания 5 В. Хотя 5 В находится в пределах абсолютного максимального значения 6 В, это выходит за рамки рекомендуемого рабочего напряжения. У вас есть переключатели уровней на SCL, SDA и ADO? Попробуйте заменить печать периода на " Serial.println(Wire.available ());", чтобы узнать, сколько байтов ему удается прочитать., @tim
@TobiasGuo, вы также можете распечатать и проверить возвращаемое значение каждого [Wire.endTransmission()](https://www.arduino.cc/en/Reference/WireEndTransmission)., @tim
@TobiasGuo, у тебя получилось? Я заметил из вашего вопроса о значениях акселерометра , что вы изменили код, т. е. отключили СПЯЩИЙ режим без выполнения сброса, потому что сброс повторно включает СПЯЩИЙ режим (раздел 3, регистр PWR_MGMT_1, стр. 8), и использовали функцию keep-alive с " Wire.endTransmission(false)` перед запросом данных., @tim
Я еще не пробовал этого. Я работал над поиском некоторых переключателей уровней для подключения к другим контактам на MPU, поэтому я еще не смог протестировать код. Я отвечу другим комментарием, как только у меня будет, и дам вам знать, как идут дела! Еще раз спасибо за помощь!, @Tobias Guo
@TobiasGuo, вот [простой двунаправленный уровень shifter](https://www.falstad.com/circuit/circuitjs.html?ctz=CQAgjCAMB0l3BWcMBMcUHYMGZIA4UA2ATmIxAUgoqoQFMBaMMAKADMQ8AWPcDQzjxCYUIbKLDQkMSChYAnEBgSiRSlXwFUw8SApDEuXTQaPCMo7bpYB3TuPOjlqi1FvqXownl5q5dvEJjNUNg1z07UMdkfGi5ACUPE2dwFF4qKi4qbGhsKHyYBBZEqLB+U2MwNIKQLOoMqCl3FLKBbl5WtztvXmxsNqE+rXd2sX6Y3vG9AHNBSYHe7wKWAGcJ6J1YofyINgBDABsVulWQHrGBc7VtEH2jk4APM7BiYUJLrleiV8rRAGUAMIAGVYTx0Dm+yEInlqqRAgKBcieGBeBnIxDwSE2sJQxgAQgBLBgAEwJ8joAGMAC4EgD2ADtDgAdFYHOgANzoBxZKwAFgS2FS6PIWLTYUF8lkMfVYNJhLC8gjWGKPpLINKuNBSBjmAhvDxCBhIHkZHAIFQvGJ4cC5EA). Нажмите переключатели., @tim
Спасибо! Похоже, это решило проблему! Я также перешел на использование библиотеки I2Cdev, и это помогло упростить процесс связи с датчиками, но теперь мои MPU фактически выдают мне правильный вывод!, @Tobias Guo
Некоторое время назад, выясняя свои собственные трудности с I2C, я провел некоторое исследование и перечислил все режимы сбоев и методы тестирования, которые я мог придумать в отношении I2C. Смотрите, что протокол I2C работает неправильно. Сейчас я регулярно просматриваю список, чтобы отметить то, что мне нужно проверить, чтобы новое соединение I2C заработало, обычно это что-то простое (скрещенные пальцы). У вас есть доступ к осциллографу?
(Править) Этот старый пост, похоже, описывает аналогичную проблему (только получение нулей) MPU6050 не работает. Все пришли к единому мнению, что 3,3 В MPU6050 был подключен к 5 В UNO, сжигая чип MPU6050. Это очень похоже на вашу ситуацию.
Спасибо, что связали этот контрольный список. Я пробегусь по нему, чтобы посмотреть, не пропустил ли я что-нибудь или есть ли что-нибудь еще, что я могу сделать, чтобы исправить это. У меня сложилось впечатление, что вывод VCC на MPU 6050 был разработан для работы с источником питания 5 В, но, возможно, я ошибался. Я обязательно попробую переключиться на источник питания 3,3 В!, @Tobias Guo
Какой модуль вы используете? Я использую модуль DFRobots 6DOF (https://wiki.dfrobot.com/6_DOF_Sensor-MPU6050__SKU_SEN0142_) и он отлично работает с питанием 5 В. Вы также можете попробовать взглянуть на это (https://www.fpaynter.com/2019/10/basic-arduino-mpu6050-gy-521-test/) и соответствующие статьи о MP6050 на моем веб-сайте (fpaynter.com), @user3765883
Я вернулся и проверил свое последнее использование модуля MPU6050, и, несмотря на ссылку, которую я опубликовал в своем ответе, я согласен с @user3765883, модули, которые у меня были, также устойчивы к 5 В. У меня нет схемы, но при ближайшем рассмотрении модуля на борту есть регулятор мощности с маркировкой 4A20. В зависимости от конкретного модуля, который вы используете, я думаю, что предыдущая ссылка о чипе MPU6050 с напряжением 3,3 В может быть отвлекающим маневром!, @RowanP
Итак, есть свидетельства по крайней мере двух различных типов модулей, находящихся в обращении. Один с регулятором мощности от 5 до 3,3 В и один без. Видишь https://forum.arduino.cc/t/mpu6050-eagle-files-out-of-date/633197, @RowanP
Я использовал 5 В от моего Arduino для питания MPU6050, и все было в порядке. Проверьте: https://www.instructables. com/How-to-Make-a-Robot-Car-Drive-Straight-and-Turn-Ex/ с очень похожим кодом.
Кроме того, я обычно избегаю контакта 13, так как он выполняет какую-то особую дополнительную функцию, в отличие от контактов 2–12.
- Изменение адреса I2C MPU-6050
- Использование MPU-6050 без I2C
- Почему Wire.write дважды?
- Несколько устройств I2C, подключенных к одному Arduino Uno?
- Мультиплексор Adafruit MPU-6050 и adafruit I2C
- Использование 2 GY521(mpu6050) с Arduino Uno R3
- запрос члена "X" в чем-то, кроме структуры или союза
- MPU-6050 с Arduino – вскрытие
Было бы хорошо дать ссылку на вопросы, по которым вы перепробовали все решения, чтобы люди точно знали, чего не следует повторять. Если вы можете, проверьте сигналы с помощью оптического прицела. Одной из потенциальных разниц между сканером I2C и библиотеками является запрашиваемая тактовая частота., @timemage