"Segway" mit MPU-6050

Hi Leute,

da mein Englisch nicht reicht erstelle ich hier ein neues topic.

Ich hab mir eine Art Miniatur-Segway mit 2 gecrackten Servos gebastelt deren
Motoren ich direkt über einen 293´er ansteuere.
Ich möchte versuchen das Gerät mit dem MPU-6050 Gyroskop Sensor in Balance zu halten.

Aber ich finde keine ordentliche Beschreibung in deutsch von dem Teil und auch
keinen sketch wie denn der Arduino den Sensor auslesen kann.

Kann mir wer weiter helfen ?

Gruß Wolfgang

Hier findest Du eine Arduino-Bibliothek für den Chip: i2cdevlib/Arduino/MPU6050 at master · jrowberg/i2cdevlib · GitHub

In den Beispielen gibt "MPU6050_raw" einfach die Daten des Sensors aus.

Weia - sketches mit mehreren hundert Zeilen :frowning:
Das wird nicht einfach.

Merci

Soo,

jetzt hab ich tagelang herum gesucht um für den GY 521 einen einfachen sketch zu finden aber nix gescheites gefunden.
Meine Idee ist es den Gyrosensor auszulesen und mit einem einfachen Vergleich der Neigungswerte zB von der Y Achse
einen Motor anzusteuern der versucht das Ding im Gleichgewicht zu halten.

Also hab ich versucht den hier zu adaptieren ( die ganze Parametrierung hab ich hier weg gelassen damit das Ding nicht zu lang wird )

void setup()
{      
  pinMode(t5Pin, OUTPUT);
  digitalWrite(t5Pin, LOW);
  pinMode(t6Pin, OUTPUT);
  digitalWrite(t6Pin, LOW);
  pinMode(t3Pin, OUTPUT);
  digitalWrite(t3Pin, LOW);
  pinMode(t4Pin, OUTPUT);
  digitalWrite(t4Pin, LOW);
  int error;
  uint8_t c;


  Serial.begin(9600);
  Serial.println(F("InvenSense MPU-6050"));
  Serial.println(F("June 2012"));

  // Initialize the 'Wire' class for the I2C-bus.
  Wire.begin();


  // default at power-up:
  //    Gyro at 250 degrees second
  //    Acceleration at 2g
  //    Clock source at internal 8MHz
  //    The device is in sleep mode.
  //

  error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
  Serial.print(F("WHO_AM_I : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);

  // According to the datasheet, the 'sleep' bit
  // should read a '1'. But I read a '0'.
  // That bit has to be cleared, since the sensor
  // is in sleep mode at power-up. Even if the
  // bit reads '0'.
  error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1);
  Serial.print(F("PWR_MGMT_2 : "));
  Serial.print(c,HEX);
  Serial.print(F(", error = "));
  Serial.println(error,DEC);


  // Clear the 'sleep' bit to start the sensor.
  MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
}


void loop()
{
  int error;
  double dT;
  accel_t_gyro_union accel_t_gyro;


  Serial.println(F(""));
  Serial.println(F("MPU-6050"));

  // Read the raw values.
  // Read 14 bytes at once, 
  // containing acceleration, temperature and gyro.
  // With the default settings of the MPU-6050,
  // there is no filter enabled, and the values
  // are not very stable.
  error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
  Serial.print(F("Read accel, temp and gyro, error = "));
  Serial.println(error,DEC);


  // Swap all high and low bytes.
  // After this, the registers values are swapped, 
  // so the structure name like x_accel_l does no 
  // longer contain the lower byte.
  uint8_t swap;
#define SWAP(x,y) swap = x; x = y; y = swap

  SWAP (accel_t_gyro.reg.x_accel_h, accel_t_gyro.reg.x_accel_l);
  SWAP (accel_t_gyro.reg.y_accel_h, accel_t_gyro.reg.y_accel_l);
  SWAP (accel_t_gyro.reg.z_accel_h, accel_t_gyro.reg.z_accel_l);
  SWAP (accel_t_gyro.reg.t_h, accel_t_gyro.reg.t_l);
  SWAP (accel_t_gyro.reg.x_gyro_h, accel_t_gyro.reg.x_gyro_l);
  SWAP (accel_t_gyro.reg.y_gyro_h, accel_t_gyro.reg.y_gyro_l);
  SWAP (accel_t_gyro.reg.z_gyro_h, accel_t_gyro.reg.z_gyro_l);


  // Print the raw acceleration values

  Serial.print(F("accel x,y,z: "));
  Serial.print(accel_t_gyro.value.x_accel, DEC);
  Serial.print(F(", "));
  Serial.print(accel_t_gyro.value.y_accel, DEC);
  Serial.print(F(", "));
  Serial.print(accel_t_gyro.value.z_accel, DEC);
  Serial.println(F(""));


  // The temperature sensor is -40 to +85 degrees Celsius.
  // It is a signed integer.
  // According to the datasheet: 
  //   340 per degrees Celsius, -512 at 35 degrees.
  // At 0 degrees: -512 - (340 * 35) = -12412

  Serial.print(F("temperature: "));
  dT = ( (double) accel_t_gyro.value.temperature + 12412.0) / 340.0;
  Serial.print(dT, 3);
  Serial.print(F(" degrees Celsius"));
  Serial.println(F(""));


  // Print the raw gyro values.

  Serial.print(F("gyro x,y,z : "));
  Serial.print(accel_t_gyro.value.x_gyro, DEC);
  Serial.print(F(", "));
  Serial.print(accel_t_gyro.value.y_gyro, DEC);
  Serial.print(F(", "));
  Serial.print(accel_t_gyro.value.z_gyro, DEC);
  Serial.print(F(", "));
  Serial.println(F(""));


  if ((accel_t_gyro.value.x_accel, DEC) < 500 )

  {
    drivev();
    delay(10);
  }

  else if ((accel_t_gyro.value.x_accel, DEC) > 500 )

  {
    driver();
    delay(10);
  }

}


// --------------------------------------------------------
// MPU6050_read
//
// This is a common function to read multiple bytes 
// from an I2C device.
//
// It uses the boolean parameter for Wire.endTransMission()
// to be able to hold or release the I2C-bus. 
// This is implemented in Arduino 1.0.1.
//
// Only this function is used to read. 
// There is no function for a single byte.
//
int MPU6050_read(int start, uint8_t *buffer, int size)
{
  int i, n, error;

  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);
  if (n != 1)
    return (-10);

  n = Wire.endTransmission(false);    // hold the I2C-bus
  if (n != 0)
    return (n);

  // Third parameter is true: relase I2C-bus after data is read.
  Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true);
  i = 0;
  while(Wire.available() && i<size)
  {
    buffer[i++]=Wire.read();
  }
  if ( i != size)
    return (-11);

  return (0);  // return : no error
}


// --------------------------------------------------------
// MPU6050_write
//
// This is a common function to write multiple bytes to an I2C device.
//
// If only a single register is written,
// use the function MPU_6050_write_reg().
//
// Parameters:
//   start : Start address, use a define for the register
//   pData : A pointer to the data to write.
//   size  : The number of bytes to write.
//
// If only a single register is written, a pointer
// to the data has to be used, and the size is
// a single byte:
//   int data = 0;        // the data to write
//   MPU6050_write (MPU6050_PWR_MGMT_1, &c, 1);
//
int MPU6050_write(int start, const uint8_t *pData, int size)
{
  int n, error;

  Wire.beginTransmission(MPU6050_I2C_ADDRESS);
  n = Wire.write(start);        // write the start address
  if (n != 1)
    return (-20);

  n = Wire.write(pData, size);  // write data bytes
  if (n != size)
    return (-21);

  error = Wire.endTransmission(true); // release the I2C-bus
  if (error != 0)
    return (error);

  return (0);         // return : no error
}

// --------------------------------------------------------
// MPU6050_write_reg
//
// An extra function to write a single register.
// It is just a wrapper around the MPU_6050_write()
// function, and it is only a convenient function
// to make it easier to write a single register.
//
int MPU6050_write_reg(int reg, uint8_t data)
{
  int error;

  error = MPU6050_write(reg, &data, 1);

  return (error);
}

void allOff()
{
  digitalWrite(t5Pin, LOW);
  digitalWrite(t6Pin, LOW);
  digitalWrite(t3Pin, LOW);
  digitalWrite(t4Pin, LOW);
}

void drivev()
{
  digitalWrite(t5Pin, HIGH); 
  digitalWrite(t3Pin, HIGH);     
} 

void driver()
{
  digitalWrite(t4Pin, HIGH); 
  digitalWrite(t6Pin, HIGH);    
}

Das Problem ist nun, dass der Motor nur in eine Richtung dreht, egal wie ich das Ding neige.
Irgendwie liest er die Werte da nicht richtig aus.
Kann man die überhaupt so einsetzen wie ich das mit der if-else Schleife mache ?

Gruß Wolfgang

Hast Du die Werte einfach mal ausgegeben und geschaut, was Du bekommst, wenn Du in die eine oder andere Richtung neigst? Den Fehler in Deinem Code zu finden, ist sehr schwierig, wir wissen nicht einmal, wie Du den Sensor montiert hast, geschweige denn, wie der restliche Aufbau ist.

Jepp, der sketch sorgt dafür dass die 3 Achswerte im Serial Monitor ablesbar sind.
Daher dachte ich kann die ausgelesenen Werte in die if else Schleife einbinden.
Das klappt aber nicht - da passiert nix.

  else if ((accel_t_gyro.value.x_accel, DEC) > 500 )

Da wird nicht viel passieren, denn DEC ist immer kleiner als 500. Schreib das mal so:

  if (accel_t_gyro.value.x_accel < 500 ) {
    drivev();
  } else if (accel_t_gyro.value.x_accel > 500) {
    driver();
  }
  delay(10);