• Hallo Zusammen, Aufgrund der aktuellen Situation setzten wir die Möglichkeit aus, sich mit Gmail zu registrieren. Wir bitten um Verständnis Das RCMP Team

Praxisbericht Gyro als Neigungssensor (MPU-6050)

Kasi-Hasi

Moderator
Mitarbeiter
Da ich die Neigung von meinem Auto feststellen und entsprechend auswerten will ("Der kippt! Halt an, Junge!") hab ich mir ein Gyro-Modul gekauft, genaugenommen drei Stück für nen 10er:

https://www.amazon.de/PEMENOL-3-Ach...ŽÕÑ&keywords=MPU-6050+Modul+3-Achsen-Gyroskop



das ganze wird über den I2C-Bus angeschlossen und läuft auf 3,3V. Ich spare mir daher den Schaltplan, es sind ja nur 4 Kabel:
Gyro: Arduino:
VCC > 3,3V
GND > GND
SCL > A5 (auf dem Nano)
SDA > A4 (auf dem Nano)

Bei einem normalen Arduino sind SCL und SDA extra als Pin vorhanden, beim Nano muss man A4 und A5 nehmen.


Tja, und nu? Kurz googlen und man findet z.B. diese Seite hier:
https://www.mschoeffler.de/2017/10/...mpu-6050-breakout-board-with-the-arduino-uno/

Der Herr Schoeffler hat sich da schon was fertiges ausgedacht, damit kann man also super arbeiten. Im Beispielcode gibt er alle Werte einfach auf der seriellen Schnittstelle aus.

Ich habe das mal auskommentiert und das Script erweitet, um zwei LEDs (an D5 und D6) entsprechend der Neigung des Y-Werts zu dimmen.

Der Sensor gibt einen Wert zwischen -16.000 und +16.000 aus, 0 ist dabei "waagerecht" - bei meinem Sensor ist der wert etwa bei 500. Entweder ist mein Haus schief oder das soll so, das schwankt sowieso alles etwas.

Für die LEDs berechne ich einfach per Dreisatz den Wert von 0-255 abhängig vom Wert des Sensors, jeweils abhängig von der Neigung nach links oder rechts.

Der Sketch dazu sieht dann so aus:

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de
#include "Wire.h" // This library allows you to communicate with I2C devices.
const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.
int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data
char tmp_str[7]; // temporary variable used in convert function
char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
sprintf(tmp_str, "%6d", i);
return tmp_str;
}
void setup() {
// Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);

pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
Wire.requestFrom(MPU_ADDR, 7 * 2, true); // request a total of 7*2=14 registers

// "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
accelerometer_x = Wire.read() << 8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
accelerometer_y = Wire.read() << 8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
accelerometer_z = Wire.read() << 8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
temperature = Wire.read() << 8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
gyro_x = Wire.read() << 8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
gyro_y = Wire.read() << 8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
gyro_z = Wire.read() << 8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
/*
// print out data
Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
// the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
Serial.print(" | tmp = "); Serial.print(temperature/340.00+36.53);
Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x));
Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y));
Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z));
Serial.println();
*/
// delay
// delay(1000);
// Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
// Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
// Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
// Serial.print(" | aY_raw = "); Serial.print(accelerometer_y);
// Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
// Serial.println();

// LEDs je nach Y-Schräglage dimmen
//----------------------------------------------------------
// Spielraum des Sensors für Y-Kanal ist ca. 100-500, wenn er hochkant (also die Platine) im Breadboard steckt und dieses flach aufliegt.
// Wird der Sensor geneigt, gehen die Ausschläge bis ca +/-16500, bei 45 Grad ist er bei ca -12.000 und +10.500, zum Test wird 16.000 benutzt
// LEDs werden erst ab +/- 1.000 angesteuert (Spielraum für den Ruhepunkt)

int Y_Value = 0; // Neigungswert
int Y_Max = 16500; // Standard für Maximalwert der Neigung
int LED_ID = 0; // welche LED entsprechend angesteuert werden soll
int LED_ID_Off = 0; // welche LED entsprechend nicht angesteuert werden soll
bool show_Y = false; // Schalter, ob Neigung per LED angezeigt werden soll
int LED_Value_Int;
int DeadZone=1500; // Ruhepunkt

// Neigung nach rechts
if (accelerometer_y > DeadZone)
{
Y_Value = accelerometer_y;
LED_ID = 5; // LED an Pin 5 für rechts
LED_ID_Off=6; // Welche LED nicht leuchten soll
show_Y = true;
Y_Max = 16500;

}
// Neigung nach links
if (accelerometer_y < (DeadZone*-1))
{
Y_Value = accelerometer_y * -1; // negativen Wert invertieren
LED_ID = 6; // LED an Pin 6 für links
LED_ID_Off=5; // Welche LED nicht leuchten soll
show_Y = true;
Y_Max = 16000;
}

// Neigung über Ruhepunkt, LED ansteuern
if (show_Y == true)
{
// Serial.print(" | neigung! ");
float LED_Value;
LED_Value = (255 / (float(Y_Max) - DeadZone)) * float(Y_Value-DeadZone); //PWM-Wert ermitteln (Y_Value und Y-Max minus Ruhewert, dann per Dreisatz Wert von 0-255 ermitteln)
LED_Value_Int = (int)(LED_Value + .5); // Float in Int umwandeln und kaufmännisch runden


if(LED_Value_Int>255)
LED_Value_Int=255;
analogWrite(LED_ID, LED_Value_Int);
analogWrite(LED_ID_Off, 0);
}
else
{
analogWrite(5, 0);
analogWrite(6, 0);
}



}
(Der rote Krams ist das von mir)


Das sieht dann im Video so aus:

Das kann man jetzt weiterspinnen und z.B. eine Warn-LED ansteigend leuchten und am Ende wild blinken lassen oder die Blinker anschalten oder auch ein Ton-Signal ausgeben.

Wichtig ist natürlich, den Kipp-Wert des Fahrzeugs zu ermitteln und die Schwellwerte entsprechend anzupassen.

Da der Gyro ja alle drei Achsen im Raum überwacht, kann man also neben Seitenneigung auch die Neigung in Fahrtrichtung prüfen, also wie steil der Hang sein darf.

Und für die Basher unter uns könnte man natürlich die Unterbodenbeleuchtung anschalten, wenn die Karre gerade im Backflip ist. So als Idee :eek::cool::cool:



Der Gyro muss übrigens nicht kalibriert werden. Egal in welcher Position ich den anschalte, da kommt in gleicher Lage immer der gleiche Wert raus.
 

DFENCE

Mitglied
Und für die Basher unter uns könnte man natürlich die Unterbodenbeleuchtung anschalten, wenn die Karre gerade im Backflip ist. So als Idee :eek::cool::cool:
Könnte man erweitern, das ist ja neben dem Gyro auch nen 3 Achsen Beschleunigungsensor verbaut, kannst ja je nachnachdem wie die Karre aufschlägt ne Digitale LED Ansteuern und durch die Verschiedenen Farben darstellen mit wieviel G die Karre aufgeschlagen ist ;-) Das wäre doch mal durchaus interessant für nen Basher, oder das ganze erweitern durch nen Lidar Sensor oder Ultraschall um die Höhe der Sprünge Visuell darzustellen über Digitale LED´s

Ach da kann ma so viel lustige Spielereien mit machen :D
 

Bunyip

Mitglied
Ich habe mal eine Frage zu dem Gyro-Sensor: Wirft der jedes Mal, wenn er neu gestartet wird, für die gleiche Position den gleichen Wert aus oder muss man den nach jedem Start kalibrieren?
Noch mal anders ausgedrückt: Wenn er 3 Werte für 3 Achsen liefert und ich trenne die Stromversorgung, werden dann nach Neustart wieder die gleichen 3 Werte angezeigt, wie zuvor?

Ich habe das gelesen:

Der Sensor gibt einen Wert zwischen -16.000 und +16.000 aus, 0 ist dabei "waagerecht" - bei meinem Sensor ist der wert etwa bei 500. Entweder ist mein Haus schief oder das soll so, das schwankt sowieso alles etwas.


War das mit der 500 ein Zufall oder ist das generell "problematisch"?
 
D

Deleted member 1492

Gast
Ein solcher Sensor muss bei jedem Neustart zunächst erstmal wissen was Sache ist.
Viele können das von sich aus, dabei einfach waagerecht hinstellen.
 
D

Deleted member 1492

Gast
Wenn man Dich nach dem Aufstehen auf eine schräge Ebene stellt, kannst du zunächst auch nicht gerade gehen.
Ich verstehe jetzt nicht, wo das eigentliche Problem liegt? Jeder Sensor, egal was, muss einen "Nullpunkt" oder eine "Basis" haben.
Dazu zählt übrigens auch der Gleichgewichtssinn/die Ohren beim Menschen. Das funktioniert nach dem gleichen Prinzip.
Ohne Basisdaten, also einen festen Bezugspunkt (egal wie er beschaffen ist) geht schlicht garnix.
 

Bunyip

Mitglied
Ich könne auch sagen, Du verstehst meine Frage nicht ;)
Dann Frage ich mal anders: Wenn ich bei Sensor A festgestellt habe, dass beim Wert 500 der Sensor waagerecht ist und ich mache ihn stromlos. Ist dann beim nächsten Einschalten beim Sensor A wiederum bei 500 der Sensor waagerecht oder muss ich dann wieder neu ermitteln, bei welchem Wert der Sensor waagerecht ist?
Reicht es je Sensor diesen Wert einmalig zu ermittteln oder muss nach jedem Neustart der Wert neu ermittelt werden?
 
Top Bottom