Gebruik MPU-9250 9-DOF Gyro

Hardware geleverd door Arduino
Gebruikers-avatar
Berichten: 39
Geregistreerd: 04 Dec 2016, 22:32

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor ruud-572 » 06 Feb 2017, 11:26

Nog niet besteld, wilde eerst nog even jouw/jullie mening afwachten...
Software engineer industriële automatisering

Advertisement

Gebruikers-avatar
Berichten: 1651
Geregistreerd: 06 Aug 2016, 01:03

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor Koepel » 06 Feb 2017, 18:42

Kleine test met goed resultaat (blauw = Roll, rood = Pitch, beide in graden).

Afbeelding

De nadruk ligt nu niet op de dynamische 3D beweging, maar op de statische tilting angle. Als ik de sensor 45 graden houd, dan geeft hij inderdaad ook zo'n 45 graden aan. Er zit een flink filter op, de nieuwe waarden van de sensor worden maar voor 1% toegevoegd.
Wanneer je een nieuwe sensor hebt, kijk dan eens wat dit bij jou doet.
Code: Alles selecteren
// Waterpas
// --------
// The most simple "spirit level" or "bubble level" or "angle measurement".
// No calibration, no selftest, no offset compensation.
// Not fully 3D, only for about maximum 45 tilting.
// With Arduino IDE 1.8.1, Arduino Mega 2560 + I2C level shifter + MPU-6050 / MPU-9250
//

// Tilt Sensing calculation:
//   NXP Freescale Application Note AN3461
//   The calculation seems to be called a "Farrell equation".
//   Discussion here:
//      http://stackoverflow.com/questions/3755059/3d-accelerometer-calculate-the-orientation
// Code based on: MPU-6050 Short Example Sketch
//   http://playground.arduino.cc/Main/MPU-6050#short
//

#include<Wire.h>

const int MPU_addr = 0x68; // I2C address of MPU-6050 / MPU-9250

float x, y, z;  // the acceleration


void setup()
{
  Serial.begin( 9600);
  while( !Serial);    // For Leonardo/Micro/M0
  Serial.println( "Started");
 
  Wire.begin();
 
  init_sensor();
}


void loop()
{
  int16_t xi, yi, zi;
  get_accel( xi, yi, zi);

  // Very simple filter for now.
  // Perhaps a moving average is better
  x = 0.99 * x + 0.01 * float( xi);
  y = 0.99 * y + 0.01 * float( yi);
  z = 0.99 * z + 0.01 * float( zi);

  // Calculate the Roll and Pitch
  float Roll = atan2( y, z) * 180.0 / M_PI;
  float Pitch = atan2( x, sqrt( y*y + z*z)) * 180.0 / M_PI;

  // Update display with slower rate.
  static int count;
  count++;
  if( count >= 40)
  {
    count = 0;
//    Serial.print( "Roll=");
    Serial.print( Roll, 3);
    Serial.print( ", ");
//    Serial.print( "Pitch=");
    Serial.println( Pitch, 3);
  }

  delay(10);
}


void init_sensor()
{
  Wire.beginTransmission( MPU_addr);
  Wire.write(0x6B);     // PWR_MGMT_1 register
  Wire.write(0);        // set to zero (wakes up the MPU-6050 / MPU-9250)
  Wire.endTransmission();
}


void get_accel(int16_t & AcX, int16_t & AcY, int16_t & AcZ)
{
  Wire.beginTransmission( MPU_addr);
  Wire.write( 0x3B);    // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission();
  Wire.requestFrom( MPU_addr, 6);  // request only the accel 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)
}

Gebruikers-avatar
Berichten: 39
Geregistreerd: 04 Dec 2016, 22:32

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor ruud-572 » 07 Feb 2017, 12:27

Klinkt goed, ga ik zeker proberen. Bedankt!
Software engineer industriële automatisering

Gebruikers-avatar
Berichten: 39
Geregistreerd: 04 Dec 2016, 22:32

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor ruud-572 » 07 Feb 2017, 22:02

Met jouw sketch lijkt het allemaal prima te werken (met de oude/verdachte sensor)...

Ik vraag me alleen af of en hoe ik dit moet ijken? Wanneer de sensor horizontaal ligt heb ik een afwijking van ong. 2.2° op de pitch. De waarden zijn verder wel heel stabiel, en komt ook steeds weer terug op de uitgangswaarden.
Software engineer industriële automatisering

Berichten: 2363
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor shooter » 07 Feb 2017, 22:39

ach met 2.2 graden val je echt niet uit bed hoor, maar wil wel eens zien of 45 graden ook een beetje klopt haha, ofwel mooi werk man.
paul deelen
shooter@home.nl

Gebruikers-avatar
Berichten: 1651
Geregistreerd: 06 Aug 2016, 01:03

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor Koepel » 07 Feb 2017, 23:04

De offset heb ik met de ruwe waarden van de sensor gedaan, en niet na de berekening met de Roll en Pitch. Ik weet niet of het ene beter is dan het andere.

Natuurlijk komen de waarden terug op hun oude waarden, want er zit geen dynamische berekening in. Het is puur de waarde van de accelerometer die de zwaartekracht meet.

Misschien zou het kunnen dat jouw gyro of magnetometer beschadigd is, maar dat de accelerometer het nog wel doet. Wanneer je de sensor (de chip) helemaal waterpas legt, dan is 2.2 graden volgens mij buiten de specificaties. Dus misschien heeft ook de accelerometer een optater gekregen.

Wanneer je op 'c' drukt in de seriële monitor, gevolgd door 'Enter', dan gaat hij de offset bepalen, en die wordt opgeslagen in EEPROM.
Met een 'w' veeg je de EEPROM schoon, om het verschil te zien.

Nu nog een duur-test en een temperatuur-test, om te zien hoe betrouwbaar de waarden van de accelerometer zijn :geek:

Het is zo uit de losse pols neergeschreven, alleen maar om te kijken of het ook werkt. Dus het kan mooier en er kan nog een foutje(s) in zitten.

Code: Alles selecteren
// Waterpas 2
// ----------
// The most simple "spirit level" or "bubble level" or "angle measurement".
// No selftest, no calibration, only basic offset compensation.
// Not fully 3D, only for about maximum 45 tilting.
// With Arduino IDE 1.8.1, Arduino Mega 2560 + I2C level shifter + MPU-6050 / MPU-9250
// February 2017, Public Domain
//

// Tilt Sensing calculation:
//   NXP Freescale Application Note AN3461
//   The calculation seems to be called a "Farrell equation".
//   Discussion here:
//      http://stackoverflow.com/questions/3755059/3d-accelerometer-calculate-the-orientation
// Code based on: MPU-6050 Short Example Sketch
//   http://playground.arduino.cc/Main/MPU-6050#short
//

#include <Wire.h>
#include <EEPROM.h>
const int MPU_addr = 0x68; // I2C address of MPU-6050 / MPU-9250

float x, y, z;  // the acceleration
int16_t x_offset, y_offset, z_offset;
const uint16_t MARKER_ID = 0x23A2;   // a marker and a version for the EEPROM data


void setup()
{
  Serial.begin( 9600);
  Wire.begin();
 
  while(!Serial);    // For Leonardo/Micro/M0

  Serial.println();
  Serial.println(F( "Waterpas 2"));
  Serial.println(F( "Warning: this sketch is Quick and Dirty"));
  Serial.println(F( "Command 'c' to calibrate the offsets."));
  Serial.println(F( "Command 'w' to wipe the EEPROM."));

  uint16_t marker;
  EEPROM.get( 0, marker);
  EEPROM.get( 2, x_offset);
  EEPROM.get( 4, y_offset);
  EEPROM.get( 6, z_offset);   // z-axis offset is not used at the moment

  if( marker != MARKER_ID)
  {
    Serial.println(F( "The level is not offset compensated yet."));
    x_offset = 0;
    y_offset = 0;
    z_offset = 0;
  }

  Serial.print(F( "Offset (raw) x, y = "));
  Serial.print( x_offset);
  Serial.print(F( ", "));
  Serial.println( y_offset);

  init_sensor();

  // Start the filter with measured values.
  // This is to make the output accurate, right from the first sample.
  int16_t xi, yi, zi;
  get_accel( xi, yi, zi);
  x = float( xi - x_offset);
  y = float( yi - y_offset);
  z = float( zi);
}


void loop()
{
  if( Serial.available())
  {
    char c = Serial.read();
    if( isprint( c))
    {
      switch( c)
      {
      case 'c':
        Calibrate();

        // Reset the filter, after the calibration.
        // Assuming the angle is close to zero degrees now.
        x = 0.0;
        y = 0.0;
       
        break;
      case 'w':
        Serial.println(F( "EEPROM data wiped."));
        for( int i=0; i<8; i++)
        {
          EEPROM.write( i, 0xFF);
        }
        // Clear the offset as well.
        x_offset = 0;
        y_offset = 0;
        z_offset = 0;
        break;
      }
    }
  }
 
  int16_t xi, yi, zi;
  get_accel( xi, yi, zi);

  xi -= x_offset;
  yi -= y_offset;
  // z-axis is not used with offset ! It is pointing up.

  // Dampen the binary values of the sensor with a filter.
  // Very simple filter for now.
  // Perhaps a moving average is better ?
  // Perhaps filtering the Roll and Pitch is better ?
  x = 0.99 * x + 0.01 * float( xi);
  y = 0.99 * y + 0.01 * float( yi);
  z = 0.99 * z + 0.01 * float( zi);

  // Calculate the Roll and Pitch
  float Roll = atan2( y, z) * 180.0 / M_PI;
  float Pitch = atan2( x, sqrt( y*y + z*z)) * 180.0 / M_PI;

  // Update display with slower rate.
  static int count;
  count++;
  if( count >= 40)
  {
    count = 0;
//    Serial.print( "Roll=");
    Serial.print( Roll, 3);
    Serial.print( ", ");
//    Serial.print( "Pitch=");
    Serial.println( Pitch, 3);
  }

  delay(10);
}


void init_sensor()
{
  Wire.beginTransmission( MPU_addr);
  Wire.write(0x6B);     // PWR_MGMT_1 register
  Wire.write(0);        // set to zero (wakes up the MPU-6050 / MPU-9250)
  Wire.endTransmission();
}


void get_accel(int16_t & AcX, int16_t & AcY, int16_t & AcZ)
{
  Wire.beginTransmission( MPU_addr);
  Wire.write( 0x3B);    // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission();
  Wire.requestFrom( MPU_addr, 6);  // request only the accel 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)
}


void Calibrate()
{
  const int num_samples = 1000;
 
  Serial.println(F( "Calibrating, please wait"));

  // Use long variables for averaging
  long xl = 0;
  long yl = 0;
  long zl = 0;
 
  for( int i=0; i<num_samples; i++)
  {
    int16_t xi, yi, zi;
    get_accel( xi, yi, zi);
    xl += long( xi);
    yl += long( yi);
    zl += long( zi);
    delay(1);
  }

  // Store the average offset in the global variables and in EEPROM.
  x_offset = int( xl / num_samples);
  y_offset = int( yl / num_samples);
  z_offset = int( zl / num_samples);

  EEPROM.put( 0, MARKER_ID);
  EEPROM.put( 2, x_offset);
  EEPROM.put( 4, y_offset);
  EEPROM.put( 6, z_offset);

  Serial.println(F( "Done"));
}

Gebruikers-avatar
Berichten: 39
Geregistreerd: 04 Dec 2016, 22:32

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor ruud-572 » 07 Feb 2017, 23:54

Het goede nieuws: je sketch werkt prima! Nogmaals dank.

Maar zowel de roll als pitch loopt langzaam weg, die sensor zal dus wel stuk zijn... :(
Software engineer industriële automatisering

Gebruikers-avatar
Berichten: 1651
Geregistreerd: 06 Aug 2016, 01:03

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor Koepel » 08 Feb 2017, 00:22

Hoeveel graden in hoeveel tijd bij welke temperatuur ?
Ik dacht te zien dat bij mij de waarden 0.5 graden waren veranderd na een kwartier, maar dat was op een zachte ondergrond.
Wat doet bijvoorbeeld je telefoon met een waterpas app ?

Gebruikers-avatar
Berichten: 39
Geregistreerd: 04 Dec 2016, 22:32

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor ruud-572 » 08 Feb 2017, 00:25

Nou, zomaar 2 graden in 10 minuten of zo? Echt veel... Het is uiteraard pas bruikbaar als ie volledig stabiel en betrouwbaar is!
Software engineer industriële automatisering

Gebruikers-avatar
Berichten: 1651
Geregistreerd: 06 Aug 2016, 01:03

Re: Gebruik MPU-9250 9-DOF Gyro

Berichtdoor Koepel » 08 Feb 2017, 12:25

Om het echt goed te testen heb ik een Arduino M0 met 8GB usb kaartje. Dan zou ik over meerdere dagen kunnen loggen met de temperatuur erbij. Voor mijn eigen project is een graad afwijking geen probleem, dus ik vind het zo goed genoeg getest.

Dit is met de sketch "Waterpas 2" met de sensor vastgeklemd op een stenen ondergrond. Ik heb het niet op temperatuur laten komen en ben meteen gaan meten. Na anderhalf uur gaan de waarden nog wat op en neer. Ik zag de Roll maximaal 0.149 zijn, maar daarna zakt het weer onder de 0.100.
Vervolgens zette ik een raam open voor koude tocht over de sensor. Dat maakt een groot verschil. Dan gaat de Pitch opeens 0.3 graden afwijken. Ik heb niet in de datasheet gekeken wat de temperatuur doet.

Ik had er een Android tablet naast liggen met een waterpas App. Die was echter zo onstabiel, daar is weinig van te zeggen.

plain code
MPU-9250                             
Roll Pitch
min max min max
start -0.005 0.023 0.009 0.018
na half uur 0.024 0.054 -0.026 0.012
na uur 0.088 0.108 0.026 0.050
na anderhalf uur 0.106 0.126 0.040 0.060
raam open -0.058 0.036 0.291 0.325

VorigeVolgende

Terug naar Arduino hardware

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 2 gasten