//--------------------------------------------------------------------------------------------------------------------------//
// Setting up the Adafruit_MPU6050 library for the accelerator chip
//--------------------------------------------------------------------------------------------------------------------------//

// Check the other guide in the .docx as to how to INSTALL the necessary library //

// Must be included for most things! //
#include <Arduino.h> // Only include once of course.
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>

// Create instance of the sensor library //
Adafruit_MPU6050 mpu;

void setup() 
{
    Serial.begin(115200); // For Serial communication, check if the right bit-per-second rate is selected!
                          // If you want to change said bit-per-second, look in the .ini file for information.
                          // How do you know the one selected does not work / there's something wrong in the .ini file?
                          // Check the terminal, if that is the case everything printed is Unicode gibberish.
    
    while(!Serial) delay(10); // Wait until the Serial communication is set up and initialized.
    Serial.println("Starting..."); 

    if(!mpu.begin()) // Exception for the case of the mpu not starting up
    {
        // If this is the case, check the wiring and whether or not the right pins are connected.
        // Another issue that could lead to this is too little or too much current going through the chip.
        Serial.println("Failed to find MPU6050 chip.");
        while(1)
        {
            delay(10);
        }
    }
    Serial.println("MPU6050 has been found.");

    mpu.setAccelerometerRange(MPU6050_RANGE_8_G); // Set to the range of your choice for the accelerator values
                                                  // depending on the range you want your read in values to vary in.
    Serial.println("Accelerator range set to: ");
    switch(mpu.getAccelerometerRange()) // Check setting and print for insight.
    {
        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;
    }

    delay(100);

    // What is the difference between "void setup()" and "void loop()"? Why put all this in here? //
    // The setup fuction is only initialized once, and though that's true for the entire lifetime of the programm,
    // the started services continue to run in here on this threat, allowing the loop to be executed simultaniously.
    // Mind, and that's IMPORTANT!!, that you should refer from using "while(1)" in this function as much as possible.
    // (I'm aware there is one in here in this project, but only because it is handled correctly and carefully.)
}

// Put your variables here for testing, otherwise I'd recommend putting it in a class //
float _x_accel = 0; // x acceleration
float _y_accel = 0; // y acceleration
float _calc = 0; // for calculations

void loop() 
{
    // NOTICE! You might wonder why this looks different to the earlier commit.
    // This is a better example to understand what's going on, run it to find out how to read in the meassuremnts.

    // Get new sensor events with the readings //
    sensors_event_t _a, _g, _temp;
    mpu.getEvent(&_a, &_g, &_temp);
    // "_a" == acceleration
    // "_g" == gyroscope values
    // "_temp" == temperature

    // Reading acceleration //
    Serial.print("Acceleration X: "); // Note that all the values are in "m/s^2" for further calculations!
    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"); 
    // You can of course use those values to calculate the position in 3D if so needed.
    // For that, please read into it and try to write it yourself.

    // Reading rotation from the gyroscope //
    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");
    // Rotation in directions of x, y and z, as for acceleration as well as you can see.
    // If you're getting confused as to what is what IRL, look at the top of
    // the MPU sensor to see the small directions symboles for reorientation.  

    // Reading in temperature //'
    Serial.print("Temperature: ");
    Serial.print(_temp.temperature);
    Serial.println(" degC");
    // Mind that it's read in in Celcius, if needed for further calculations.
}

// Little side information //
// If you are wondering why there are two pins called "XDA" and "XCL", educate yourself on it, but you
// won't need those most likely.

// Tecnically, you only need the library asset "Wire.h" for all of this and not the whole Adafruit library.
// But then again, that's a harder, and not exactly better way to use this sensor if not all too familiar with the
// syntax of C++, but if you'd want to, try it out!
// I've left a ".txt" file in this "src" folder that has the code tackling the second option.
// Try it out if you'd like, or go with the method described in here. Your choice.

// And done! //
// Mind that everything in this loop repeats itself over and over, only stopping until the programm fails to execute or
// the current is cut. If you'd like to restart everything, press the little button titled "RST" or "BOOT" (if the first does nothing) on the ESP.