//--------------------------------------------------------------------------------------------------------------------------//
// This is the seconed way to use the MPU sensor:
//--------------------------------------------------------------------------------------------------------------------------//

// Include the library you want to use: //
#include "Wire.h" 

// Define the address to the chip: //
#define MPU6050_ADDR 0x68 // Alternatively set AD0 to HIGH  --> Address = 0x69

// Set up some variables //
int16_t _accX; // Acceleration
int16_t _accY; 
int16_t _accZ; 
int16_t _gyroX; // Gyro
int16_t _gyroY; 
int16_t _gyroZ;
int16_t _tRaw; // Raw register values (accelaration, gyroscope, temperature)

// Another for specific use (in this case, convertion) //
char _result[7]; // Temporary variable used in convert function

// Prototype to function at the end //
char* toStr(int16_t _character);

void setup() 
{
  Serial.begin(115200); // Mind the Bit per second rate you selected here if blindly copying!

  // Start service //
  Wire.begin();
  Wire.beginTransmission(MPU6050_ADDR);
  
  // Set up register //
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // wake up!
  Wire.endTransmission(true);
}

void loop() 
{
  // Begin exchange with the sensor //
  Wire.beginTransmission(MPU6050_ADDR);

  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false); // The parameter indicates that the Arduino will send a restart. 
                               // As a result, the connection is kept active.
  Wire.requestFrom(MPU6050_ADDR, 14, true); // request a total of 7*2=14 registers
  
  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same int16_t variable //
  _accX = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  _accY = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  _accZ = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  _tRaw = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
  _gyroX = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
  _gyroY = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
  _gyroZ = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
  
  // Printing the read in values in a String fromat //
  Serial.print("AcX = "); 
  Serial.print(toStr(accX));

  Serial.print(" | AcY = "); 
  Serial.print(toStr(accY));

  Serial.print(" | AcZ = "); 
  Serial.print(toStr(accZ));
  
  // from data sheet: //
  Serial.print(" | tmp = "); Serial.print((tRaw + 12412.0) / 340.0);
  Serial.print(" | GyX = "); Serial.print(toStr(gyroX));
  Serial.print(" | GyY = "); Serial.print(toStr(gyroY));
  Serial.print(" | GyZ = "); Serial.print(toStr(gyroZ));
  Serial.println();
  
  delay(1000); // NOTE! This is just for demonstration purposes.
               // The function "delay({insert wanted value in ms})" stops your ENTIRE programm,
               // not allowing the ESP to do ANYTHING until the delay is canceled after the listed milliseconds have passed.
               // If possible, avoid using it at all.
}

// Function to convert the incoming values to String (for printing purposes) //
char* toStr(int16_t _character) 
{
  // Formats "int16_t" to "String" (Attention! Not "std::string", the two are)
  //                           (two seperate classes and are not the same.)

  sprintf(_result, "%6d", _character);
  return _result;
}

// Note that all the values are purely raw. Further computing is required for them to actually be of use.
// This is a more watered down version as to how to do this, but let's be real, you really won't need to make everything
// harder if this delivers all you need.

// If there is interest on how to do this on an even lower and detailed level, talk to me and I'll try to explain.