Thanks Jeff and Pam for suggestions. No luck so far, though!
Here are more details I should have mentioned the first time around:
Arduino Uno R3 SMD
SparkFun MPU6050 breakout board
Connections:
VDD — Arduino 3.3v
GND — Arduino GND
INT — Arduino digital pin 2
FSYNC — unconnected
SCL — Arduino SCL dedicated pin
SDA — Arduino SDA dedicated pin
VIO — Arduino 3.3v
CLK — unconnected
ASCL — unconnected
ASDA — unconnected
MPU6050_raw sketch modified by putting …
accelgyro.setSleepEnabled(false);
… after the line which has accelgyro.testConnection() in it.
Example serial output:
Initializing I2C devices…
Testing device connections…
MPU6050 connection failed
a/g: 0 0 0 0 0 0
a/g: 0 0 0 0 0 0
a/g: 0 0 0 0 0 0
a/g: 0 0 0 0 0 0
a/g: 0 0 0 0 0 0
etc.
It looks like AD0 is grounded on the SparkFun board. I have
not modified the board.
Tried SCL/SDA on A5/A4; got same result.
Don’t know if the Arduino Uno R3 SMD has internal pull up
resistors on SCL/SDA. The SparkFun board has 10k pull up
resistors on those lines.
I appreciate any more suggestions you may have.
Thanks,
Riccati
From the MPU-6000/MPU-6050 Register Map and Descriptions:
-
Section 4.28, Register 107 – Power Management 1 PWR_MGMT_1, pages 40 to 41:
Note:
When using SPI interface, user should use DEVICE_RESET (register 107) as well as SIGNAL_PATH_RESET (register 104) to ensure the reset is performed properly. The sequence used should be:- Set DEVICE_RESET = 1 (register PWR_MGMT_1)
- Wait 100ms
- Set GYRO_RESET = ACCEL_RESET = TEMP_RESET = 1 (register SIGNAL_PATH_RESET)
- Wait 100ms
-
Section 4.26, Register 104 – Signal Path Reset SIGNAL_PATH_RESET, page 37:
Note: This register does not clear the sensor registers. The reset initializes the serial interface as well.
-
Section 3, Register Map, page 8:
The reset value is 0x00 for all registers other than the registers below.
- Register 107: 0x40.
- Register 117: 0x68.
This means that the PWR_MGMT_1 register defaults to sleep mode after a reset so it needs to be rewritten to disable sleep mode after commanding a reset.
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();
}
In the following code I’ve:
-
Modified
readGyro()
to implement 3 states (Request, Wait, and Read) and returntrue
when 6 bytes have been read from the MPU-6050. -
Added Blink Without Delay to
loop()
to see whether the MCU freezes which requires changing the ADO pin from pin 13 (the built-in led) to another pin, i.e. pin 12. -
Added several
Serial.print()
statements for debugging to see where things go wrong. -
Tweaked the code in response to comments.
#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.
}
Update based upon RowanP’s answer
While concentrating on the software issues I missed a crucial piece of information from the other datasheet (MPU-6000/MPU-6050 Product Specification), i.e. the electrical characteristics in Sections 6.3 and 6.4 on pages 14 and 15 showing a Vdd range of 2.375 V to 3.46 V:
6.4 Electrical Specifications, Continued
This will require level shifters on the signals between the 3.3 V MPU-6050 and the 5 V Arduino.
Loading
The problem
There is a bug in the MPU6050 component that prevents using some boards (see https://community.home-assistant.io/t/mpu6050-communication-with-mpu6050-failed/268114 and https://community.home-assistant.io/t/communication-with-mpu6050-failed/270449).
However, using this custom component works with all boards, including the problematic ones.
customGyro.h
#include "esphome.h" class MPU6050 : public PollingComponent { public: Sensor *temperature = new Sensor(); Sensor *gyroscope = new Sensor(); Sensor *accelerometer = new Sensor(); float accelgyro_temperature = 0, accelgyro_accel = 0, accelgyro_gyro = 0; const uint8_t MPU_addr = 0x68; // I2C address of the MPU-6050 MPU6050() : PollingComponent(1000) { } void setup() override { Wire.begin(); // default at power-up: // Gyro at 250 degrees second // Acceleration at 2g // Clock source at internal 8MHz Wire.beginTransmission(MPU_addr); Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); } void update() override { // This is the actual sensor reading logic. int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; Wire.beginTransmission(MPU_addr); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) accelgyro_accel = (sqrt((float)AcX * AcX + (float)AcY * AcY + (float)AcZ * AcZ) / 32768.) * 2.; // [G] accelgyro_gyro = (sqrt((float)GyX * GyX + (float)GyY * GyY + (float)GyZ * GyZ) / 32768.) * 250.; // [deg/s] accelgyro_temperature = Tmp / 340. + 36.53; //equation for temperature in degrees C from datasheet temperature->publish_state(accelgyro_temperature); gyroscope->publish_state(accelgyro_gyro); accelerometer->publish_state(accelgyro_accel); } };
YAML
esphome:
includes:
- customGyro.h
sensor:
- platform: custom
lambda: |-
auto mlx = new MPU6050();
App.register_component(mlx);
return {mlx->temperature, mlx->gyroscope, mlx->accelerometer};
sensors:
- name: "IMU temperature"
unit_of_measurement: °C
accuracy_decimals: 2
- name: "IMU gyroscope"
unit_of_measurement: "deg/s"
accuracy_decimals: 4
- name: "IMU accelerometer"
unit_of_measurement: "G"
accuracy_decimals: 4
What is version of ESPHome has the issue?
v1.20.0
What type of installation are you using?
Home Assistant Add-on
What platform are you using?
ESP32
Component causing the issue
The affected component is https://github.com/esphome/esphome/blob/dev/esphome/components/mpu6050/mpu6050.cpp
Offline
Зарегистрирован: 21.04.2022
Использую Visual Studio — Platformio
Хочу повторить проект из этого источника : https://habr.com/ru/post/575662/
После того как я скачал исходники, была проблема с библиотеками. В плане того, что их не было в проекте. После установки пачки библиотек из этого репозитория (https://github.com/pkourany/I2CDEV_MPU6050?utm_source=platformio&utm_med…)
Выходит такая ошибка
In file included from src\main.cpp:4:0:
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h: In member function ‘uint8_t MPU6050::dmpInitialize()’:
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:504:21: warning: variable ‘mpuIntStatus’ set but not used [-Wunused-but-set-variable]
uint8_t mpuIntStatus = getIntStatus();
^~~~~~~~~~~~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:354:13: warning: unused variable ‘hwRevision’ [-Wunused-variable]
uint8_t hwRevision = readMemoryByte();
^~~~~~~~~~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:362:13: warning: unused variable ‘otpValid’ [-Wunused-variable]
uint8_t otpValid = getOTPBankValid();
^~~~~~~~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h: In member function ‘uint8_t MPU6050::dmpGetAccel(int32_t*, const uint8_t*)’:
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:587:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << + packet[31]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:587:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << + packet[31]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:588:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] << + packet[35]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:588:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] << + packet[35]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:589:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << + packet[39]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:589:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << + packet[39]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h: In member function ‘uint8_t MPU6050::dmpGetQuaternion(int32_t*, const uint8_t*)’:
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:611:30: warning: left shift count >= width of type [-Wshift-count-overflow]
data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << + packet[3]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:611:50: warning: left shift count >= width of type [-Wshift-count-overflow]
data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << + packet[3]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:612:30: warning: left shift count >= width of type [-Wshift-count-overflow]
data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << + packet[7]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:612:50: warning: left shift count >= width of type [-Wshift-count-overflow]
data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << + packet[7]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:613:30: warning: left shift count >= width of type [-Wshift-count-overflow]
data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << + packet[11]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:613:50: warning: left shift count >= width of type [-Wshift-count-overflow]
data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << + packet[11]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:614:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << + packet[15]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:614:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << + packet[15]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h: In member function ‘uint8_t MPU6050::dmpGetGyro(int32_t*, const uint8_t*)’:
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:644:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << + packet[19]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:644:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << + packet[19]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:645:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << + packet[23]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:645:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << + packet[23]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:646:31: warning: left shift count >= width of type [-Wshift-count-overflow]
data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << + packet[27]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:646:52: warning: left shift count >= width of type [-Wshift-count-overflow]
data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << + packet[27]);
^~
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h: In member function ‘uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t, uint8_t*)’:
.pio\libdeps\nanoatmega328\MPU6050\src/MPU6050_6Axis_MotionApps20.h:738:29: warning: value computed is not used [-Wunused-value]
if (processed != 0) *processed++;
^~~~~~~~~~~~
src\main.cpp: At global scope:
src\main.cpp:78:44: warning: large integer implicitly truncated to unsigned type [-Woverflow]
volatile unsigned long ticksPerPulseLeft = UINT64_MAX;
^~~~~~~~~~
src\main.cpp:79:45: warning: large integer implicitly truncated to unsigned type [-Woverflow]
volatile unsigned long ticksPerPulseRight = UINT64_MAX;
^~~~~~~~~~
src\main.cpp: In function ‘bool mpuUpdate()’:
src\main.cpp:170:27: error: ‘class MPU6050’ has no member named ‘dmpGetCurrentFIFOPacket’; did you mean ‘dmpProcessFIFOPacket’?
if (mpuInterrupt && mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) {
^~~~~~~~~~~~~~~~~~~~~~~
dmpProcessFIFOPacket
src\main.cpp: In function ‘long unsigned int getTicksPerPulse(float)’:
src\main.cpp:183:12: warning: large integer implicitly truncated to unsigned type [-Woverflow]
return UINT64_MAX;
^~~~~~~~~~
*** [.pio\build\nanoatmega328\src\main.cpp.o] Error 1
В ошибках пишет: класс «MPU6050» не содержит члена «dmpGetCurrentFIFOPacket»