MPU6050 libary asynchron verwenden

Hallo zusammen,

bei meinem Projekt 4 DC Motoren gleichmässig antreiben hab ich zwei Gyroskope (MPU6050) verbaut. Ich hab die auch schon mit einer eigenen Klasse grob in meine Steuerung eingebaut (Code folgt).
Ich hatte erst einmal die Möglichkeit die ganze Steuerung überhaupt zu testen und da hat sich der Arduino immer wieder "aufgehängt", ich bin mir sehr sicher, dass einer der Gyroskope den µC blockiert. Da ich da draußen im Funkloch Deutschland bin, hab ich da kein Internet und muss deswegen etwas "vorarbeiten".
Ich könnte zwar einfach die Gyroskope noch mal auskommentieren, aber morgen hätte ich ein paar Stunden Zeit was zu machen, da will ich dann die Gyroskope (zum nivilieren) auch mit einbauen, wenn noch Zeit übrig ist.
Bei meinen Tests daheim hab ich schon festgestellt, dass die Libary MPU6050 (https://github.com/ElectronicCats/mpu6050/) scheinbar als Standardeinstellung synchrone Kommunikation hat. I²C selber ist ja ein asynchroner Bus, also müsste sich das ja ändern lassen.
Da ich selber aber weder viel Ahnung von I²C, noch MPU6050 oder C++ hab, wollte ich hier um Hilfe fragen.
Ich hab mir die Lib (https://github.com/ElectronicCats/mpu6050/blob/master/src/MPU6050.cpp) schon durchgeschaut und hab mir zwei Zeilen rausgeschrieben:

  • 834 MPU6050::setWaitForExternalSensorEnabled()
  • 1404 MPU6050::setInterruptDrive()

Ich würde es jetzt mal blöd verstehen, dass ich mit ersterem deaktiviere, dass der Code blockiert wird, wenn auf eine Antwort gewartet wird und bei zweiteren wird bei einer Antwort ein Interrupt aktiviert...? Ja, Nein, Vielleicht? Ich hab keine Ahnung..

Meine Gyro-Klasse:
gyroskop.h

#pragma once

#include "Wire.h"
#include "MPU6050.h"

class Gyroskop
{
  private:
    // Members
    MPU6050 _gyro;

    uint8_t _address;

    int16_t _ax, _ay, _az;                              // actuel Values Accel
    int16_t _gx, _gy, _gz;                              // actuel Values Motion

    int16_t _y_offset;                                  // Offset of y accel for balance
    int16_t _z_offset;                                  // Offset of z accel for balance
    static const int16_t _y_tolerance = 250;            // Tolerance for y balance
    static const int16_t _z_tolerance = 250;            // Tolerance for z balance

    static const byte _count_last_values = 50;          // How many Values for average
    int16_t _last_y[_count_last_values] = {0};          // last y Values
    int16_t _last_z[_count_last_values] = {0};          // last z Values
    byte _num_last_value = 0;                           // last posistion in array
    
    int16_t _y_real;                                    // real average y accel
    int16_t _z_real;                                    // real average z accel
    int16_t _y;                                         // y accel with offset
    int16_t _z;                                         // z accel with offset

  public:
    // Comands
    Gyroskop(uint8_t address);
    void begin();
    void run();

    // Setter
    void setYOffset(int16_t offset);
    void setZOffset(int16_t offset);

    // Getter
    int16_t getYValue();
    int16_t getYRealValue();
    bool getYOkay();
    bool getYLeftUp();
    int16_t getZRealValue();
    int16_t getZValue();
    bool getZOkay();
    bool getFrontUp();
};

gyroskop.cpp

#include "gyroskop.h"

Gyroskop::Gyroskop(uint8_t address)
{
  _address = address;
  _gyro = MPU6050(address);
}

void Gyroskop::begin()
{
  Wire.begin();
  Serial.print("Initializing Gyroskop Sensor ");
  Serial.print(_address);
  Serial.println();
  _gyro.initialize();
  Serial.print("Testing device connection ");
  Serial.print(_address);
  Serial.println();
  Serial.print(_gyro.testConnection() ? "Gyro connection successful " : "Gyro connection failed ");
  Serial.print(_address);
  Serial.println();
}

void Gyroskop::run()
{
  _gyro.getMotion6(&_ax, &_ay, &_az, &_gx, &_gy, &_gz);
  
  _last_y[_num_last_value] = _ay;
  _last_z[_num_last_value] = _az;

  _num_last_value = (_num_last_value < _count_last_values) ? (_num_last_value + 1) : 0;

  long y_sum;
  long z_sum;
  int16_t y_min = 20000;
  int16_t y_max;
  int16_t z_min = 20000;
  int16_t z_max;
  byte counter_y;
  byte counter_z;
  
  for (byte i = 0; i < _count_last_values; i++)
  {
    if (_last_y[i] != 0)
    {
      y_sum += _last_y[i];

      y_min = (y_min > _last_y[i]) ? _last_y[i] : y_min;
      y_max = (y_max < _last_y[i]) ? _last_y[i] : y_max;

      counter_y++;
    }

    if (_last_z[i] != 0)
    {
      z_sum += _last_z[i];

      z_min = (z_min > _last_z[i]) ? _last_z[i] : z_min;
      z_max = (z_max < _last_z[i]) ? _last_z[i] : z_max;

      counter_z++;
    }
  }
  
  _y_real = (y_sum - y_min - y_max)/(counter_y - 2);
  _z_real = (z_sum - z_min - z_max)/(counter_z - 2);
  _y = (_y_real - _y_offset);
  _z = (_z_real - _z_offset);
}

void Gyroskop::setYOffset(int16_t offset)
{
  _y_offset = offset;
}

void Gyroskop::setZOffset(int16_t offset)
{
  _z_offset = offset;
}

int16_t Gyroskop::getYValue()
{
  return _y;
}

int16_t Gyroskop::getYRealValue()
{
  return _y_real;
}

bool Gyroskop::getYOkay()
{
  bool return_ = false;

  if ((_y < _y_tolerance)
    && (_y > _y_tolerance * -1))
  {
    return_ = true;
  }

  return return_;
}

bool Gyroskop::getYLeftUp()
{
  bool return_ = false;

  if (_y  >= _y_tolerance)
  {
    return_ = true;
  }
  
  return return_;
}

int16_t Gyroskop::getZValue()
{
  return _z;
}

int16_t Gyroskop::getZRealValue()
{
  return _z_real;
}

bool Gyroskop::getZOkay()
{
  bool return_ = false;

  if ((_z < _z_tolerance)
    && (_z > _z_tolerance * -1))
  {
    return_ = true;
  }

  return return_;
}

bool Gyroskop::getFrontUp()
{
  bool return_ = false;

  if (_z  >= _z_tolerance)
  {
    return_ = true;
  }
  
  return return_;
}

Kann mir jemand auf die Sprünge helfen, ob ich da in der richtigen Richtung oder komplett auf'm Holzweg bin..?
Bzw. wäre es für meinen "einfachen" Fall auch einfacher, wenn ich nicht die MPU6050 lib nutze, sondern nur selbst direkt die Sensoren ausles und des asynchron gestalte?

Vielen Dank und
liebe Grüße

Fipschen

Hallo,
ich habe Dein Post gestern schon gelesen, hab ich aber bedeckt gehalten da ich eigentlich nicht mitbekommen habe um was es hier geht. Nun habe ich festgestellt das es anderen auch noch so geht, es liegt also ehr an Deinem Post als an meinem Verständnis.
Deine Frage ob die Lib blokiert würde ich erst mal mit nein beantworten. Dazu gibt es doch bestimmt ein Beispiel, das kannst Du Duch erst mal minimal testen.

Da Du von Motoren sprichst könnte theoretisch EMV noch die Ursache für einen Hänger sein. Eventuell mag der I2C Bus die so nicht, oder der Bus ist nicht richtig abgeschlossen. Ursachen kann es da viele geben.

Heinz

Hallo Heinz,

danke für deine Antwort.

Dann nochmal die Kurzfassung des ganzen Projekts:
Ich hab n selbstgebauten Aufbau für meinen Anhänger. Der Spaß wiegt voll geladen ca. 1.300 kg. Ich hab 4 Schubstangenmotoren, mit welchen ich den Aufbau anheben kann, um ihn vom Anhänger zu nehmen.
Letztes Jahr ist mir die Steuerung der Motoren abgesoffen (war eine reine Relaissteuerung), weshalb ich eine neue gebaut hab, die mit nem Arduino und H-Brücken läuft.
Da der Aufbau auch gerade stehen muss, dass sich die Türen nicht verklemmen und aufgehen, hab ich zwei Gyroskope (MPU6050) eingebaut (eins vorne, eins hinten), mit welchen sich der Aufbau automatisch nivilieren soll.
Als ich das letzte mal die Kiste auf- und abgeladen hab, hab ich nur im Handbetrieb gesteuert und dabei hat sich immer wieder der Arduino aufgehangen, also hat auf kein Stopp mehr reagiert, es hat nur Strom abschalten geholfen. Hier ist ganz stark meine Vermutung, dass der Arduino auf den I²C wartet und deshalb den Stopp-Taster nicht "hört".
Gestern hatte ich auch den Gegentest: Ich hab die Gyroskope komplett auskommentiert, da hatte ich dann das Problem nicht.
Um jetzt den Bogen zurück zu schlagen: Ich vermute, dass die oben verlinkte MPU6050-Lib den Code blockiert, solang sie auf ne Antwort wartet.
Würde die EMV von den Motoren den I²C stören, könnte das den µC wirklich "aufhängen"? Ich dachte bisher, dass dann nur "Müll" über den Bus kommt.
Angeschlossen müsste der Bus richtig sein, sonst könnte ich ja die Gyroskope nicht auslesen, oder? Denn das funktioniert. :thinking:

Liebe Grüße

Fipschen

Dir ist schon klar, für welche Entfernungen I2C entworfen wurde?

Hallo,
Ahh das Thema, ich kann mich erinnern :wink:
das kannst Du doch recht einfach mal testen.
Im laufenden Betrieb einfach mal den I2C abklemmen. Nun was hast Du denn für Pullup Widerstände eingebaut am Bus. I2C ist für kleine Entfernungen, 0,5m ist max so üblich.

Frage warum hast Du denn 2 Gyros drin ? einer sollte doch reichen um den Anhänger im Wasser zu halten. ?
ich würde da auch ehr andere Sensoren nutzen und eventuell die Längen messen. So genau muss das ja nicht sein.
Haben die Linearantriebe keine Potis eingebaut. Manchmal ist das der Fall.
ich könnte mir Linearpotis vorstellen oder auch 4 Lochstreifen aus Blech und 4 Initiatoren die an dem Lochstreifen, Gitterstreifen vorbei fahren. 1cm Auflösung wird da doch reichen. Dann kannst Du von jedem die Impulse zählen und über die Differenzen die Geschwindigkeit des jeweiligen Antriebs ändern, so das im Wesentlichen Gleichstand vorliegt. Mit dem Endschalter bringst Du die Zähler wieder auf Null.
Heinz

Relativ kurz, ja.. frag mich nicht mehr wo, hab ich aber auch gelesen, dass 10 M kein großes Problem sind (zum Beispiel: https://www.mikrocontroller.net/articles/I2C_als_Hausbus). Daheim lief der auch stundenlang mit 4 M Leitung einwandfrei.

Hatte ich ja auch oben verlinkt :grimacing:

Klar, an die Idee hab ich natürlich wieder nicht gedacht, den mal abzuklemmen :man_facepalming:
Die Länge is aktuell nicht ganz 4 M, daheim ging das über Stunden problemfrei.

Weil mein Aufbau nicht verwindungsfrei ist. Damit vorne und hinten gerade wird. Hätte ich nur einen vorne, hinten oder in der Mitte würde sich die ganze Geschichte verdrehen.

Das ist ja generell auch das Thema aus dem andren Thread, den ich noch am Leben halte.
Ich vermute mal, du willst darauf hinaus, dass die Schubstangen gleich weit ausfahren. Das hilft mir nicht viel, ich mit dem Ding öfter auf unebenen Untergründen steh, weshalb ich eben nivilieren muss. Als Beispiel: Am Schießplatz von meinem Verein stehn die linken Räder ca. 15 cm weiter unten als rechts, weil der Weg so schief ist :grimacing:

Liebe Grüße

Fipschen

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.