MPU6050 Gyroscope Interfacing with ESP32

Overview of MPU6050 Gyroscope

MPU6050 Gyroscope

 

MPU6050 sensor module is an integrated 6-axis Motion tracking device.

It has a 3-axis Gyroscope, 3-axis Accelerometer, Digital Motion Processor, and a Temperature sensor, all in a single IC.

It can accept inputs from other sensors like a 3-axis magnetometer or pressure sensor using its Auxiliary I2C bus.

If an external 3-axis magnetometer is connected, it can provide complete 9-axis Motion Fusion output.

A microcontroller can communicate with this module using the I2C communication protocol. Various parameters can be found by reading values from addresses of certain registers using I2C communication.

Gyroscope and accelerometer reading along X, Y, and Z axes are available in 2’s complement form. The temperature reading is also available in signed integer form.

Gyroscope readings are in degrees per second (dps) unit; Accelerometer readings are in g unit, and Temperature reading is in degrees Celsius.

For more information about MPU6050 Sensor Module and how to use it, refer the topic MPU6050 Sensor Module in the sensors and modules section.

 

MPU6050 Hardware Connection with ESP32

ESP32 interfaced with MPU6050

 

 

Read Accelerometer, Gyroscope and Temperature using MPU6050 and ESP32

Here we are using adafruit MPU6050 libraries for to read Accelerometer, Gyroscope, and Temperature parameters from the MPU6050 module and display them on the Web Server and Arduino Serial Monitor. We will need to install the Adafruit MPU6050 library using the Arduino Library Manager.

 

Open the Arduino IDE and navigate to Sketch ► Include Library ► Manage Libraries…

 

The library Manager window will pop up. Now enter MPU6050 into the search box and click Install on the Adafruit MPU6050 option to install version 2.2.0 or higher.

 

Now open the example of MFRC522. To open it navigate to File ► Examples ► Adafruit MPU6050 Library ► basic reading

 

Code for Basic Readings of MPU6050 using ESP32

// Basic demo for accelerometer readings from Adafruit MPU6050

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    Serial.println("+- 250 deg/s");
    break;
  case MPU6050_RANGE_500_DEG:
    Serial.println("+- 500 deg/s");
    break;
  case MPU6050_RANGE_1000_DEG:
    Serial.println("+- 1000 deg/s");
    break;
  case MPU6050_RANGE_2000_DEG:
    Serial.println("+- 2000 deg/s");
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }

  Serial.println("");
  delay(100);
}

void loop() {

  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 to see the output.

 

MPU6050 Output on Serial Monitor

 

Let’s understand the code

First initialize the required library.

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Create the mpu object of Adafruit_MPU6050 as below

Adafruit_MPU6050 mpu;

 

In setup function

We have initiated the serial communication with a 115200 Baud rate.

Serial.begin(115200);

Begin the I2C communication and check the chip ID using mpu.begin() function, if correct then soft-reset the chip and wait for the sensor calibration.

if (!mpu.begin()) {
   Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }

Before using this device you need to set the measurement ranges of MPU6050 using the below three functions. 

mpu.setAccelerometerRange(MPU6050_RANGE_8_G);

This function is used to set the accelerometer range.

The acceptable ranges are:

  • MPU6050_RANGE_2_G – Set the range for ±2g (default)
  • MPU6050_RANGE_4_G – Set the range for ±4g
  • MPU6050_RANGE_8_G – Set the range for ±8g
  • MPU6050_RANGE_16_G – Set the range for ±16g

 

mpu.setGyroRange(MPU6050_RANGE_500_DEG);

This function is used to set the gyroscope range.

The acceptable ranges are:

  • MPU6050_RANGE_250_DEG – Set the range for 250 degrees-per-second (default)
  • MPU6050_RANGE_500_DEG – Set the range for 500 degrees-per-second 
  • MPU6050_RANGE_1000_DEG – Set the range for 1000 degrees-per-second 
  • MPU6050_RANGE_2000_DEG – Set the range for 2000 degrees-per-second

 

mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

This function is used to set the digital low pass filter bandwidth.

The acceptable bandwidths are:

  • MPU6050_BAND_260_HZ, – Set 260 Hz bandwidth (Docs imply this disables the filter)
  • MPU6050_BAND_184_HZ, – Set 184 Hz bandwidth
  • MPU6050_BAND_94_HZ, – Set 94 Hz bandwidth
  • MPU6050_BAND_44_HZ, – Set 44 Hz bandwidth
  • MPU6050_BAND_21_HZ, – Set 21 Hz bandwidth
  • MPU6050_BAND_10_HZ, – Set 10 Hz bandwidth
  • MPU6050_BAND_5_HZ, – Set 5 Hz bandwidth

 

In loop function

In the loop function, we will read the acceleration, rotation, and temperature and display them on the serial monitor.

First, create a sensors_event_t object to hold results. 

sensors_event_t is a user defined datatype (Structures in C) that contains data from the mpu sensor from a specific moment in time.

sensors_event_t a, g, temp;

getEvent()function is used to read a new set of values from mpu sensor, convert them to the appropriate SI units and scale, and then assign the results to a mpu sensor object.

mpu.getEvent(&a, &g,&temp);

Now print the result on the serial monitor.

Serial.print("Acceleration X: ");
Serial.print(a.acceleration.x);
Serial.print(", Y: ");
Serial.print(a.acceleration.y);
Serial.print(", Z: ");
Serial.print(a.acceleration.z);
Serial.println(" m/s^2");

Serial.print("Rotation X: ");
Serial.print(g.gyro.x);
Serial.print(", Y: ");
Serial.print(g.gyro.y);
Serial.print(", Z: ");
Serial.print(g.gyro.z);
Serial.println(" rad/s");

Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degC");

 

Read Accelerometer, Gyroscope, and Temperature using MPU6050 over ESP32 Web Server 

Now let’s take another example to display the same readings of the MPU6050 Gyroscope on the web server using ESP32 and  Arduino IDE.

Before uploading the code make sure you have added your SSID and Password as follows.

const char* ssid = "*Your SSID*";         /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/

Code for MPU6050 Web Server using ESP32

#include <WiFi.h>
#include <WebServer.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include "html.h"

Adafruit_MPU6050 mpu;

WebServer server(80);

const char* ssid = "*Your SSID*";         /*Enter Your SSID*/
const char* password = "*Your Password*"; /*Enter Your Password*/

float x_acceleration, y_acceleration, z_acceleration;
float x_gyro, y_gyro, z_gyro;
float tempe;

void MainPage() {
  String _html_page = html_page;              /*Read The HTML Page*/
  server.send(200, "text/html", _html_page);  /*Send the code to the web server*/
}

void Web_MPU6050() {
  String data = "[\""+String(x_acceleration)+"\",\""+String(y_acceleration)+"\",\""+String(z_acceleration)+"\",\""+String(x_gyro)+"\",\""+String(y_gyro)+"\",\""+String(z_gyro)+"\",\""+String(tempe)+"\"]";
  server.send(200, "text/plane", data);
}

void setup(void){
  Serial.begin(115200);                 /*Set the baudrate to 115200*/
  WiFi.mode(WIFI_STA);                  /*Set the WiFi in STA Mode*/
  WiFi.begin(ssid, password);
  Serial.print("Connecting to ");
  Serial.println(ssid);
  delay(1000);                         /*Wait for 1000mS*/
  while(WiFi.waitForConnectResult() != WL_CONNECTED){Serial.print(".");} /*Wait while connecting to WiFi*/
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("Your Local IP address is: ");
  Serial.println(WiFi.localIP());       /*Print the Local IP*/
 

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    Serial.println("+- 250 deg/s");
    break;
  case MPU6050_RANGE_500_DEG:
    Serial.println("+- 500 deg/s");
    break;
  case MPU6050_RANGE_1000_DEG:
    Serial.println("+- 1000 deg/s");
    break;
  case MPU6050_RANGE_2000_DEG:
    Serial.println("+- 2000 deg/s");
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }

  Serial.println("");
  delay(100);

  server.on("/", MainPage);             /*Display the Web/HTML Page*/
  server.on("/read_Web_MPU6050", Web_MPU6050); /*Display the updated Distance value(CM and INCH)*/
  server.begin();                       /*Start Server*/
  delay(1000);                          /*Wait for 1000mS*/
 
}

void loop(void){
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);
 
  x_acceleration = a.acceleration.x;
  y_acceleration = a.acceleration.y;
  z_acceleration = a.acceleration.z;
  x_gyro = g.gyro.x;
  y_gyro = g.gyro.y;
  z_gyro = g.gyro.z;
  tempe = temp.temperature;
 
  /* Print out the values */
  Serial.print("Acceleration X: ");
  Serial.print(x_acceleration);
  Serial.print(", Y: ");
  Serial.print(y_acceleration);
  Serial.print(", Z: ");
  Serial.print(z_acceleration);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(x_gyro);
  Serial.print(", Y: ");

  Serial.print(y_gyro);
  Serial.print(", Z: ");
  Serial.print(z_gyro);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(tempe);
  Serial.println(" degC");

  Serial.println("");
  delay(500);

  server.handleClient();
}

 

  • Now upload the code. (While uploading the code make sure your ESP32 board is in the boot mode.)
  • After uploading the code open the serial monitor and set the baud rate to 115200 then reset the ESP32 board and check the IP address as shown in the below image

 

 

Output on the webserver

  • Next, open any mobile browser and type the IP address, which is shown on the serial monitor, and hit the enter button. 
  • If all are ok, then the web page will start showing current acceleration, gyro readings, and temperature on the web server like in the below image.

Note: make sure your ESP32 and mobile are connected to the same router/server, if they are connected to the same router or server then only you will be able to visible the web page.

 

Let’s Understand the code

To understand this code, please refer to the basics guide of “How to create the ESP32 Server”.

Once you get the basics of ESP32 server creation, it will be very simple to understand the code.

This code starts with important header files and libraries, In WiFi.h file contains all ESP32 WiFi related definitions, here we have used them for network connection purposes. 

The WebServer.h file supports handling the HTTP GET and POST requests as well as setting up a server. In the html.h file contains all the web page code, Wire.h allows you to communicate with I2C device i.e MPU6050 and then add the Adafruit_Sensor and Adafruit_MPU6050 library file.

#include <WiFi.h>
#include <WebServer.h>
#include "html.h"
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Let’s define HTTP port i.e., Port 80 as follows

WebServer server(80);

Create an mpu object of Adafruit_MPU6050

Adafruit_MPU6050 mpu;

 

Setup Function

In the setup function, first we set the WiFi as an STA mode and connect to the given SSID and password

WiFi.mode(WIFI_STA);          /*Set the WiFi in STA Mode*/
WiFi.begin(ssid, password);
Serial.print("Connecting to ");
Serial.println(ssid);
delay(1000);                  /*Wait for 1000mS*/
while(WiFi.waitForConnectResult() != WL_CONNECTED){Serial.print(".");}

After successfully connecting to the server print the local IP address on the serial window.

Serial.print("Your Local IP address is: ");
Serial.println(WiFi.localIP());     /*Print the Local IP*/

 

Handling Client Requests and Serving the Page

To handle the client request, we use server.on() function.

It takes two parameters, The first is requested URL path, and the second is the function name, which we want to execute.

As per the below code, when a client requests the root (/) path, the “MainPage()” function executes. 

Also, when a client requests the “/read_Web_MPU6050” path, The Web_MPU6050() function will be called.

server.on("/", MainPage);           /*Client request handling: calls the function to serve HTML page */
server.on("/read_Web_MPU6050", Web_MPU6050);/*Display the updated Distance value(CM and INCH)*/ 

Now start the server using server.begin() function.

server.begin();                     /*Start Server*/

 

Functions for Serving HTML

We have defined the complete HTML page in a file named “html.h” and added it to the header file. With the following function, we are sending the complete page to the client via server.send() function.

While sending, we are passing the first parameter “200” which is the status response code as OK (Standard response for successful HTTP requests). 

Second parameter is the content type as “text/html“, and the third parameter is html page code.

void MainPage() {
  String _html_page = html_page;              /*Read The HTML Page*/
  server.send(200, "text/html", _html_page);  /*Send HTM page to Client*/
}

Now in the below function only we are sending the updated acceleration, gyro, and temperature values to the web page.

void Web_MPU6050() {
  String data = "[\""+String(x_acceleration)+"\",\""+String(y_acceleration)+"\",\""+String(z_acceleration)+"\",\""+String(x_gyro)+"\",\""+String(y_gyro)+"\",\""+String(z_gyro)+"\",\""+String(tempe)+"\"]";
  server.send(200, "text/plane", data);
}

 

Loop Function

Now to handle the incoming client requests and serve the relevant HTML page, we can use handleClient() function. It executing relevant server.on() as a callback function although it is defined in void setup()

So, it continuously serves the client requests.

server.handleClient();

 

HTML Page Code

/*
  ESP32 HTML WebServer Page Code
  http:://www.electronicwings.com
*/

const char html_page[] PROGMEM = R"RawString(
<!DOCTYPE html>
<html>
  <style>
    body {font-family: sans-serif;}
    h1 {text-align: center; font-size: 30px;}
    p {text-align: center; color: #4CAF50; font-size: 30px;}
  </style>

<body>
  <h1>MPU6050 with ESP32 Web Socket </h1>
  <p>Acceleration X = <span id="x_acceleration">0</span> m/s&sup2</p>
  <p>Acceleration Y = <span id="y_acceleration">0</span> m/s&sup2</p>
  <p>Acceleration Z = <span id="z_acceleration">0</span> m/s&sup2</p><br>
 
  <p>Gyro X = <span id="x_gyro">0</span> rad/s</p>
  <p>Gyro Y = <span id="y_gyro">0</span> rad/s</p>
  <p>Gyro Z = <span id="z_gyro">0</span> rad/s</p><br>
 
  <p>Temperature = <span id="temp">0</span> &#8451;</p>

<script>
  setInterval(function() {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        const text = this.responseText;
        const myArr = JSON.parse(text);
       document.getElementById("x_acceleration").innerHTML = myArr[0];
        document.getElementById("y_acceleration").innerHTML = myArr[1];
       document.getElementById("z_acceleration").innerHTML = myArr[2];
       document.getElementById("x_gyro").innerHTML = myArr[3];
       document.getElementById("y_gyro").innerHTML = myArr[4];
       document.getElementById("z_gyro").innerHTML = myArr[5];
       document.getElementById("temp").innerHTML = myArr[6];
      }
    };
    xhttp.open("GET", "read_Web_MPU6050", true);
    xhttp.send();
  },100);
</script>
</body>
</html>
)RawString";

 

Let’s understand the code step by step

All html pages start with the <!DOCTYPE html> declaration, it is just information to the browser about what type of document is expected.

<!DOCTYPE html>

The html tag is the container of the complete html page which represents on the top of the html code.

<html>

Now here we are defining the style information for a web page using the <style> tag. Inside the style tag we have defined the font name, size, color, and test alignment. 

<style>
   body {font-family: sans-serif;}
   h1 {text-align: center; font-size: 30px;}
   p {text-align: center; color: #4CAF50; font-size: 40px;}
</style>

 

Inside the body, we are defining the document body, in below we have used headings, and paragraphs if you want you can add images, hyperlinks, tables, lists, etc. also.

On the web page, we are displaying the heading of the page, and inside a paragraph three accelerations i.e. x, y, and z acceleration, three gyro i.e. x, y, and z gyro readings, and then display temperature values. 

Now accelerations, gyro, and temperature values updates under the span id which is manipulated with JavaScript using the id attribute.

<h1>MPU6050 with ESP32 Web Socket </h1>
<p>Acceleration X = <span id="x_acceleration">0</span> m/s&sup2</p>
<p>Acceleration Y = <span id="y_acceleration">0</span> m/s&sup2</p>
<p>Acceleration Z = <span id="z_acceleration">0</span> m/s&sup2</p><br>
 
<p>Gyro X = <span id="x_gyro">0</span> rad/s</p>
<p>Gyro Y = <span id="y_gyro">0</span> rad/s</p>
<p>Gyro Z = <span id="z_gyro">0</span> rad/s</p><br>
 
<p>Temperature = <span id="temp">0</span> &#8451;</p>

Now, this is the javascript that comes under the <script> tag, this is also called a client-side script.

<script>

 

In setInterval() method we are calling the function at every 50mS intervals.

setInterval(function() {},50);

here we are creating the html XMLHttpRequest object

var xhttp = new XMLHttpRequest();

The xhttp.onreadystatechange event is triggered every time the readyState changes and the readyState holds the status of the XMLHttpRequest.

Now in the below code, the ready state is 4 means the request finished and response is ready and the status is 200 which means OK.

xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const myArr = JSON.parse(this.responseText);

 

Now here is the main thing, we are updating the acceleration, gyro, and temperature values in html page using x_acceleration,  y_acceleration, z_acceleration, x_gyro, y_gyro, z_gyro, and temp id.

document.getElementById("x_acceleration").innerHTML = myArr[0];
document.getElementById("y_acceleration").innerHTML = myArr[1];
document.getElementById("z_acceleration").innerHTML = myArr[2];
document.getElementById("x_gyro").innerHTML = myArr[3];
document.getElementById("y_gyro").innerHTML = myArr[4];
document.getElementById("z_gyro").innerHTML = myArr[5];
document.getElementById("temp").innerHTML = myArr[6];

Here we used the AJAX method to send the updated values to the server without refreshing the page.

In the below function we have used the GET method and sent the read_Web_MPU6050 function which we defined in the main code asynchronously. 

xhttp.open("GET", "read_Web_MPU6050", true); 

Send the request to the server using xhttp.send(); function.

xhttp.send();

 

Close the script

</script>

Close the body

</body>

Close the html

</html>

Components Used

MPU6050 Gyroscope and Accelerometer
MPU6050 (Gyroscope + Accelerometer + Temperature) is a combination of 3-axis Gyroscope, 3-axis Accelerometer and Temperature sensor with on-chip Digital Motion Processor (DMP). It is used in mobile devices, motion enabled games, 3D mice, Gesture (motion command) technology etc
1
ESP32 WROOM
WiFi Development Tools - 802.11 ESP32 General Development Kit, embeds ESP32-WROOM-32E, 4MB flash.
1

Downloads

ESP32_MPU6050_Serial_Output Download
ESP32_MPU6050_WebServer Download
Ad