MPU-6050 op het GY-521 of GY-80 board.

Beschrijving:
De MPU-6050 op het GY-521 board heeft een 3-assige gyro en 3-assige versnellingssensor gecombineerd met de Digital Motion Processor (DMP) waarmee de complexe 9-assige MotionFusion algoritmes verwerkt worden.

MPU-6050 specificaties:
. I2C aansluiting
. Werkt op: 3.3V
. Gyro bereik van +/-250, +/-500, +/-1000 en +/-2000dps
. Versnellingsmeter bereik van +/-2g, +/-4g, +/-8g en +/-16g
Kan worden gebruikt voor de ballancerende robot op 2 wielen.;-)
In de 'maker.pro' tutorial lees ik dat de IMU een accelorometer, een magnetometer en een altimeter heeft. De MPU 650 is een 6 DOF (degrees of freedom) of een zes assige IMU sensor. Wat betekend dat het 6 output waarden geeft. 3 Van de versnellingsmeter (accelerometer) en 3 van de gyroscoop. De MPU-6050 is gebasseerd op de MEMS (micro electronica mechanische systemen) binnen een enkele chip.
De chip gebruikt de I2C voor communicatie.
De accelerometer werkt ongeveer als een balletje in een doosje, als het doorsje beweegt wil het balletje stilliggen en rolt tegengesteld aan de richting van het bewegende doosje. Zodra het doosje vertraagt met bewegen wil het balletje doorrollen.
De wanden van het doosje worden dan van piezoelectronica voorzien zodat gemeten kan worden hoe hard het balletje tegen de wand drukt.
Druk je de piezo in dan krijg je een spanning (de electronische aansteker).
Een goede Engelstalige uitleg vind je hier.
Een gysoscoop werkt met het Coriolis systeem.Grofweg, een gewicht gaat omhoog komen als je het ronddraaid aan een touw. Als je de hoek meet tussen het stil hangen van het gewicht en het moment dat het gewicht 90 graden gestegen is, dan kan je berekeningen daarop los laten. Laat je nu 3 gewichten verschillende rondingen laat maken kan je dus 3x zoveel meten.
Gyro bereik van 250, 500, 1000 en 2000dps
Je leest met de Arduino of ESPxx al snel heel veel ruwe data waar je weinig mee kan doen.



Er is een MPU-6050 en een MPU 9150, de MPU 9150 heeft ook een digitaal compas.

verbinden:

of /CS, SDO, SCLK, SDI of SDA, SCL
ESP8266----MPU6050
---3.3V----VCC
----GND----GND
-----D2----SDA
-----D1----SCL
-----D4----INT
NC---------AD0=Aux SD0 voor ander board
NC---------XCL=Aux SCL voor ander board
NC---------XDA=Aux SDA voor ander board
library

Hardware


In 2014 kwam er een nieuwe MPU-6050 zonder extra naam of code.
De pinnen zitten aan de linker kant en in de volgorde: "VCC", "GND", "SCL", "SDA", "XDA", "XCL", "AD0", "INT".
Er zijn een paar verschillende board uitvoeringen, zo heeft de GY 80 ook nog een barometer op het board. Alle zijn bijna gelijk aan de GY-521. Er is een spanning regelaar op de print voor 3.3V.
De boards werken met I2C.
Volgens tekst zijn er twee 10k pull-up weerstanden voor de SCL en SDA aansluitingen, en ook een 330 ohm weerstand in de SCL en SDA signalen. Als ik echter het schema bekijk zijn er 2x een 4.7K die de SDA en SCL met 3.3V hoog maken, 1K weerstand voor de led en 1x 4.7K om de AD0 laag te maken.

Door de spanning regelaar kan je het board met 5V voeden en ook de I2C rechtstreeks op de Arduino aansluiten. T.a.v. de SDA en SCL twijvel ik, volgens teksten en tekeningen mag je ze rechtstreeks aan de 5V van de Arduino aansluiten. Maar volgens het schema komt er dan toch 5V van de Arduino op de MPU-6050 processor. Of zouden de 2x 330 Ohm weerstanden niet op het schema getekend staan?
Bekijk ik de datasheet dan zie ik bij punt 3 het verschil tussen de MPU 6000 en de MPU 6050, dat de Vlogic van de 6050 VDD mag zijn en bij punt 6.9 dat de processor max. 5.5V mag hebben en de SDA en SCL VDD+0.5. Bij 3.3 van de handleiding en table 1 lees ik weer dat de processor max.3.3V mag hebben.
3.2 van de handleiding geeft aan wat de verschillen zijn tussen de MPU6000 en de MPU6050. Table 5 van de handleiding geeft aan 5V voeding en op pin 2 van jumper 13 max 3.3V. Maar dat is alleen de MPU 6050 dat op het GY521 board zit.Voor de zekerheid wellicht een levelshifter er tussen.
Geen hardwarematige I2C adressering mogelijk. Voorbeeld geeft een adres aan van 0x6B.
Op playground van Arduino lees ik dat je wel iets kan regelen met de ADO, als je die naar GND brengt leest de 6050 adres 0x68 en breng de ADO naar 3.3V voor 0x69. Dat 0x69 wordt volgens Arduino playground echter zelden gebruikt.
Ik lees daar ook dat de 5V van de Arduino niet gebruikt mag worden. Heel vreemd want als de GY-521 board op 5V aangesloten mag worden, die heeft een spanningsregelaar voor de MPU650, is dan het niet mogen aansluiten voor de I2C bedoeld?

Software:
Het lezen van de ruwe data is makkelijk, het omzetten naar bruikbare data om iets aan te sturen niet.
Er is data van de sensor snelheid en data van de sensor helling hoek(t.o.v. aantrekking van de aarde).
I2C verwacht dus juiste adressering om registers te benaderen met read of write.
De X Y en Z as data wordt in een register opgeslagen, voor de X Y en Z assen zijn alle drie 2 registers beschikbaar (x0 en x1)(y0 en Y1)(z0 en z1). Die data moet in een float tussen -1 en +1, afhankelijk van de as stand t.o.v. de draaing en aantrekkingskracht van de aarde.


// MPU-6050 Short Example Sketch
// https://howtomechatronics.com/how-it-works/electrical-engineering/mems-accelerometer-gyrocope-magnetometer-arduino/
#include<Wire.h>
//--- Versnelling meter Register Adres
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x33 // Hexadecima address for the DATAX1 internal register.
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53; //Device address in which is also included the 8th bit for selecting the mode, read in this case.
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
float Xa,Ya,Za; // data uit X Y Z
//-------------------------------------------
void setup()
{
Wire.begin();
Serial.begin(9600);
Wire.beginTransmission(ADXAddress);
Wire.write(Power_Register); // PWR_CTL register;
// Enable measurement;
Wire.write(8); // Bit D3 High for measuring enable (0000 1000);
Wire.endTransmission();
}
//--------------------------------------------
void loop() {
// X-axis
Wire.beginTransmission(ADXAddress); // Begin transmission to the Sensor
//Ask the particular registers for data
Wire.write(X_Axis_Register_DATAX0);
Wire.write(X_Axis_Register_DATAX1);
Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers
Wire.requestFrom(ADXAddress,2); // Request the transmitted two bytes from the two registers
if(Wire.available()<=2) { //
X0 = Wire.read(); // Reads the data from the register
X1 = Wire.read();
/* Converting the raw data of the X-Axis into X-Axis Acceleration
- The output data is Two's complement
- X0 as the least significant byte
- X1 as the most significant byte */
X1=X1<<8;
X_out =X0+X1;
Xa=X_out/256.0; // Xa = output value from -1 to +1, Gravity acceleration acting on the X-Axis
}
// Y-Axis
Wire.beginTransmission(ADXAddress);
Wire.write(Y_Axis_Register_DATAY0);
Wire.write(Y_Axis_Register_DATAY1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2) {
Y0 = Wire.read();
Y1 = Wire.read();
Y1=Y1<<8;
Y_out =Y0+Y1;
Ya=Y_out/256.0;
}
// Z-Axis
Wire.beginTransmission(ADXAddress);
Wire.write(Z_Axis_Register_DATAZ0);
Wire.write(Z_Axis_Register_DATAZ1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2) {
Z0 = Wire.read();
Z1 = Wire.read();
Z1=Z1<<8;
Z_out =Z0+Z1;
Za=Z_out/256.0;
}
// Prints the data on the Serial Monitor
Serial.print("Xa= ");
Serial.print(Xa);
Serial.print(" Ya= ");
Serial.print(Ya);
Serial.print(" Za= ");
Serial.println(Za);
}
Met dat bovenstaande script krijg je ruwe data zoals rechts te zien is. Die data blijft dus oplopen afhankelijk van de beweging van de aarde. Helaas is dat geen vast getal bij mij. Die te lezen data blijft niet constant hetzelfde met de bovenstaande sketch, ook al laat je de sensor gewoon liggen.
Er moet dus een vertalingsslag volgen voordat je wat kan doen.
De ruwe data moet vertaad worden naar machnetische veld waarden of Gauss units. Op de database van de sensor zien we dat dat de standaard gevoelswaarde 0.92mG/digit is. Dat betekend dat we de ruwe data met 0.00092 moeten vermenigvuldigen om de aardse machnetisch veld in Gaus waarde te krijgen.

Daar moet dan de aantrekkingskracht van de aarde mee berekend worden, om die te meten is er het volgende script:

#include <Wire.h> //I2C Arduino Library

#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08

int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;

float Xm,Ym,Zm;

#define Magnetometer 0x1E //I2C 7bit address of HMC5883

void setup(){
//Initialize Serial and I2C communications
Serial.begin(9600);
Wire.begin();
delay(100);

Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Select mode register
Wire.write(0x00); // Continuous measurement mode
Wire.endTransmission();
}
void loop(){

//---- X-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX1 = Wire.read();
}

//---- Y-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY1 = Wire.read();
}

//---- Z-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ1 = Wire.read();
}

//---- X-Axis
mX1=mX1<<8;
mX_out =mX0+mX1; // Raw data
// From the datasheet: 0.92 mG/digit
Xm = mX_out*0.00092; // Gauss unit
//* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.

//---- Y-Axis
mY1=mY1<<8;
mY_out =mY0+mY1;
Ym = mY_out*0.00092;

//---- Z-Axis
mZ1=mZ1<<8;
mZ_out =mZ0+mZ1;
Zm = mZ_out*0.00092;

//Print out values of each axis
Serial.print("x: ");
Serial.print(Xm);
Serial.print(" y: ");
Serial.print(Ym);
Serial.print(" z: ");
Serial.println(Zm);

delay(50);
}

Vervolgens lees ik overal -0.24.
Omdat je uiteindelijk toch iets wil doen met de 6050 is het handig om een library te gebruiken. Er zijn 3 librarys bij Gidhub te vinden en ik gebruikte de Jarzebski accel pitch rol voorbeeld:

/*
MPU6050 Triple Axis Gyroscope & Accelerometer. Pitch & Roll Accelerometer Example.
Read more: http://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-zyroskop-i-akcelerometr-mpu6050.html
GIT: https://github.com/jarzebski/Arduino-MPU6050
Web: http://www.jarzebski.pl
(c) 2014 by Korneliusz Jarzebski
*/

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

void setup()
{
Serial.begin(115200);

Serial.println("Initialize MPU6050");

while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
}

void loop()
{
// Read normalized values
Vector normAccel = mpu.readNormalizeAccel();

// Calculate Pitch & Roll
int pitch = -(atan2(normAccel.XAxis, sqrt(normAccel.YAxis*normAccel.YAxis + normAccel.ZAxis*normAccel.ZAxis))*180.0)/M_PI;
int roll = (atan2(normAccel.YAxis, normAccel.ZAxis)*180.0)/M_PI;

// Output
Serial.print(" Pitch = ");
Serial.print(pitch);
Serial.print(" Roll = ");
Serial.print(roll);

Serial.println();

delay(10);
}
Als je nu de informatie aan de rechterzijde leest en naar de Pitch en Roll data kijkt, zie je dat er bruikbare informatie getoond wordt. - Is schuin naar achter of schuin naar rechts (als je de I2C aansluitpinnen van je af heb) en positief is naar voren of naar links. Pitcht 0 en Roll 0 is dus vlak.

Als ik in de I2C een levelshifter opneem om de eventueel te verwachte problemen tussen 3.3V van de MPU en 5V van de Nano te voorkomen, krijg ik een foutmelding. De MPU wordt niet gevonden. Haal ik de levelshifter weg dan verdwijnt de fout melding.


documenten:
Datasheet
Registers
handleiding


software:
Gidhub ElectronicCats library
Gidhub jarzebski library
Gidhub adafruit library


bronnen:
i2cdevlib library by Jeff Rowberg
howtomechatronics arduino-and-mpu6050-accelerometer-and-gyroscope-tutorial
howtomechatronics diy-arduino-gimbal-self-stabilizing-platform
github.com
maker.pro how-to-interface-arduino-and-the-mpu-6050-sensor
maker build-arduino-self-balancing-robot
hobbyelectronica.nl mpu-6050
playground.arduino mpu-6050
invensense.com mpu-6050
mpu6050-8-mpu6050-connection-failed
ebay
instructables real-segway
instructables Arduino-Nano-Segway
hackester small-segway-with-arduino