Arduino en MPU6050 versnellingsmeter en gyroscoop zelfstudie
In deze tutorial leren we hoe we de MPU6050 Accelerometer en Gyroscope sensor met de Arduino kunnen gebruiken. Ik zal eerst uitleggen hoe de MPU6050 werkt en hoe je de data eruit kunt lezen, daarna maken we twee praktijkvoorbeelden.
Je kunt de volgende video bekijken of de schriftelijke tutorial hieronder lezen.
Overzicht
In het eerste voorbeeld maken we met behulp van de ontwikkelomgeving Processing een 3D-visualisatie van de sensororiëntatie en in het tweede voorbeeld maken we een eenvoudig zelfstabiliserend platform of een DIY Gimbal. Op basis van de MPU6050-oriëntatie en de gefuseerde versnellingsmeter- en gyroscoopgegevens, besturen we de drie servo's die het platform waterpas houden.
Hoe het werkt
De MPU6050 IMU heeft zowel een 3-assige versnellingsmeter als een 3-assige gyroscoop geïntegreerd op een enkele chip.
De gyroscoop meet de rotatiesnelheid of veranderingssnelheid van de hoekpositie in de tijd, langs de X-, Y- en Z-as. Het maakt gebruik van MEMS-technologie en het Coriolis-effect voor het meten, maar voor meer informatie hierover kun je mijn specifieke tutorial How MEMS Sensors Work bekijken. De uitgangen van de gyroscoop zijn in graden per seconde, dus om de hoekpositie te krijgen, hoeven we alleen de hoeksnelheid te integreren.
Aan de andere kant meet de MPU6050 accelerometer acceleratie op dezelfde manier als uitgelegd in de vorige video voor de ADXL345 accelerometer sensor. Kort gezegd, het kan zwaartekrachtversnelling langs de 3 assen meten en met behulp van trigonometrie kunnen we de hoek berekenen waaronder de sensor is geplaatst. Dus als we de accelerometer- en gyroscoopgegevens fuseren of combineren, kunnen we zeer nauwkeurige informatie krijgen over de sensororiëntatie.
De MPU6050 IMU wordt ook wel een zes-assig bewegingsvolgapparaat of 6 DoF (six Degrees of Freedom) apparaat genoemd, vanwege de 6 uitgangen, of de 3 versnellingsmeteruitgangen en de 3 gyroscoopuitgangen.
Arduino en MPU6050
Laten we eens kijken hoe we de gegevens van de MPU6050-sensor kunnen aansluiten en lezen met behulp van de Arduino. We gebruiken het I2C-protocol voor communicatie met de Arduino, dus we hebben slechts twee draden nodig om hem aan te sluiten, plus de twee draden voor voeding.
U kunt de benodigde componenten voor deze Arduino-zelfstudie verkrijgen via de onderstaande links:
- MPU6050 IMU ………………………..…. Amazon / Banggood / AliExpress
- Arduino-bord ……………………….…..
- Broodplank en springdraden …………
MPU6050 Arduino-code
Hier is de Arduino-code voor het lezen van de gegevens van de MPU6050-sensor. Onder de code vindt u een gedetailleerde beschrijving ervan.
/*
Arduino and MPU6050 Accelerometer and Gyroscope Sensor Tutorial
by Dejan, https://howtomechatronics.com
*/
#include <Wire.h>
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
void setup() {
Serial.begin(19200);
Wire.begin(); // Initialize comunication
Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68
Wire.write(0x6B); // Talk to the register 6B
Wire.write(0x00); // Make reset - place a 0 into the 6B register
Wire.endTransmission(true); //end the transmission
/*
// Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
Wire.beginTransmission(MPU);
Wire.write(0x1C); //Talk to the ACCEL_CONFIG register (1C hex)
Wire.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
Wire.endTransmission(true);
// Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
Wire.beginTransmission(MPU);
Wire.write(0x1B); // Talk to the GYRO_CONFIG register (1B hex)
Wire.write(0x10); // Set the register bits as 00010000 (1000deg/s full scale)
Wire.endTransmission(true);
delay(20);
*/
// Call this function if you need to get the IMU error values for your module
calculate_IMU_error();
delay(20);
}
void loop() {
// === Read acceleromter data === //
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
//For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(MPU);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// Correct the outputs with the calculated error values
GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
GyroY = GyroY - 2; // GyroErrorY ~(2)
GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
// Print the values on the serial monitor
Serial.print(roll);
Serial.print("/");
Serial.print(pitch);
Serial.print("/");
Serial.println(yaw);
}
void calculate_IMU_error() {
// We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
// Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
// Read accelerometer values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
// Sum all readings
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;
}
//Divide the sum by 200 to get the error value
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// Read gyro values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
// Sum all readings
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;
}
//Divide the sum by 200 to get the error value
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// Print the error values on the Serial Monitor
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}
Code language: Arduino (arduino)
Codebeschrijving: Dus eerst moeten we de Wire.h-bibliotheek opnemen die wordt gebruikt voor de I2C-communicatie en enkele variabelen definiëren die nodig zijn om de gegevens op te slaan.
In het setup-gedeelte moeten we de draadbibliotheek initialiseren en de sensor resetten via het energiebeheerregister. Om dat te doen, moeten we de datasheet van de sensor bekijken van waaruit we het registeradres kunnen zien.
Als we willen, kunnen we ook het volledige bereik voor de versnellingsmeter en de gyroscoop selecteren met behulp van hun configuratieregisters. Voor dit voorbeeld gebruiken we het standaardbereik van +- 2g voor de accelerometer en het bereik van 250 graden/s voor de gyroscoop, dus ik laat dit deel van de code als commentaar achter.
// Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
Wire.beginTransmission(MPU);
Wire.write(0x1C); //Talk to the ACCEL_CONFIG register (1C hex)
Wire.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
Wire.endTransmission(true);
// Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
Wire.beginTransmission(MPU);
Wire.write(0x1B); // Talk to the GYRO_CONFIG register (1B hex)
Wire.write(0x10); // Set the register bits as 00010000 (1000deg/s full scale)
Wire.endTransmission(true);
*/
Code language: Arduino (arduino)
In het lusgedeelte beginnen we met het lezen van de versnellingsmetergegevens. De gegevens voor elke as worden opgeslagen in twee bytes of registers en we kunnen de adressen van deze registers zien in het gegevensblad van de sensor.
Om ze allemaal te lezen, beginnen we met het eerste register en met behulp van de functie requiestFrom() vragen we om alle 6 registers voor de X-, Y- en Z-assen te lezen. Vervolgens lezen we de gegevens van elk register en omdat de uitgangen twee complementair zijn, combineren we ze op de juiste manier om de juiste waarden te krijgen.
// === Read acceleromter data === //
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
//For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
Code language: Arduino (arduino)
Om outputwaarden van -1g tot +1g te krijgen, geschikt voor het berekenen van de hoeken, delen we de output met de eerder geselecteerde gevoeligheid.
Ten slotte berekenen we met behulp van deze twee formules de rol- en hellingshoeken uit de gegevens van de versnellingsmeter.
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
Code language: Arduino (arduino)
Vervolgens krijgen we met dezelfde methode de gyroscoopgegevens.
We lezen de zes gyroscoopregisters, combineren hun gegevens op de juiste manier en delen deze door de eerder geselecteerde gevoeligheid om de output in graden per seconde te krijgen.
// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(MPU);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
Code language: Arduino (arduino)
Hier kun je opmerken dat ik de uitvoerwaarden corrigeer met enkele kleine berekende foutwaarden, die ik in een minuut zal uitleggen hoe we ze krijgen. Dus omdat de output in graden per seconde is, moeten we ze nu vermenigvuldigen met de tijd om alleen graden te krijgen. De tijdwaarde wordt vastgelegd vóór elke leesiteratie met behulp van de millis()-functie.
// Correct the outputs with the calculated error values
GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
GyroY = GyroY - 2; // GyroErrorY ~(2)
GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;
Code language: Arduino (arduino)
Ten slotte fuseren we de versnellingsmeter en de gyroscoopgegevens met behulp van een complementair filter. Hier nemen we 96% van de gyroscoopgegevens omdat deze zeer nauwkeurig is en geen last heeft van externe krachten. De keerzijde van de gyroscoop is dat hij afdrijft, of dat hij na verloop van tijd fouten in de uitvoer introduceert. Daarom gebruiken we op de lange termijn de gegevens van de versnellingsmeter, in dit geval 4%, genoeg om de gyroscoopafwijkingsfout te elimineren.
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
Code language: Arduino (arduino)
Omdat we de Yaw echter niet kunnen berekenen uit de gegevens van de versnellingsmeter, kunnen we er geen complementair filter op implementeren.
Voordat we de resultaten bekijken, wil ik u eerst even uitleggen hoe u de foutcorrectiewaarden kunt krijgen. Voor het berekenen van deze fouten kunnen we de aangepaste functie berekenen_IMU_error() aanroepen terwijl de sensor zich in een vlakke, stille positie bevindt. Hier doen we 200 metingen voor alle uitgangen, we tellen ze op en delen ze door 200. Omdat we de sensor in een vlakke, stille positie houden, zouden de verwachte uitgangswaarden 0 moeten zijn. Met deze berekening kunnen we dus de gemiddelde fout van de sensor krijgen maakt.
void calculate_IMU_error() {
// We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
// Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
// Read accelerometer values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
// Sum all readings
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;
}
//Divide the sum by 200 to get the error value
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// Read gyro values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
// Sum all readings
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;
}
//Divide the sum by 200 to get the error value
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// Print the error values on the Serial Monitor
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}
Code language: Arduino (arduino)
We printen de waarden gewoon op de seriële monitor en zodra we ze kennen, kunnen we ze implementeren in de code zoals eerder getoond, voor zowel de rol- en pitchberekening als voor de 3 gyroscoopuitgangen.
Ten slotte kunnen we met de functie Serial.print de Roll-, Pitch- en Yaw-waarden op de seriële monitor afdrukken en kijken of de sensor goed werkt.
MPU6050 Oriëntatie volgen – 3D-visualisatie
Om vervolgens het voorbeeld van 3D-visualisatie te maken, hoeven we alleen deze gegevens te accepteren die de Arduino via de seriële poort in de ontwikkelomgeving Processing verzendt. Hier is de volledige verwerkingscode:
/*
Arduino and MPU6050 IMU - 3D Visualization Example
by Dejan, https://howtomechatronics.com
*/
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch,yaw;
void setup() {
size (2560, 1440, P3D);
myPort = new Serial(this, "COM7", 19200); // starts the serial communication
myPort.bufferUntil('\n');
}
void draw() {
translate(width/2, height/2, 0);
background(233);
textSize(22);
text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
// Rotate the object
rotateX(radians(-pitch));
rotateZ(radians(roll));
rotateY(radians(yaw));
// 3D 0bject
textSize(30);
fill(0, 76, 153);
box (386, 40, 200); // Draw box
textSize(25);
fill(255, 255, 255);
text("www.HowToMechatronics.com", -183, 10, 101);
//delay(10);
//println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}
// Read data from the Serial Port
void serialEvent (Serial myPort) {
// reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
data = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (data != null) {
data = trim(data);
// split the string at "/"
String items[] = split(data, '/');
if (items.length > 1) {
//--- Roll,Pitch in degrees
roll = float(items[0]);
pitch = float(items[1]);
yaw = float(items[2]);
}
}
}
Code language: Arduino (arduino)
Hier lezen we de binnenkomende gegevens van de Arduino en plaatsen deze in de juiste Roll, Pitch en Yaw-variabelen. In de hoofdtekenlus gebruiken we deze waarden om het 3D-object te roteren, in dit geval is dat een eenvoudig vak met een bepaalde kleur en tekst erop.
Als we de schets uitvoeren, kunnen we zien hoe goed de MPU6050-sensor is voor het volgen van de oriëntatie. Het 3D-object volgt de oriëntatie van de sensor vrij nauwkeurig en het reageert ook erg goed.
Zoals ik al zei, is de enige keerzijde dat de Yaw na verloop van tijd zal drijven omdat we het complementaire filter ervoor niet kunnen gebruiken. Om dit te verbeteren hebben we een extra sensor nodig. Dat is meestal een magnetometer die kan worden gebruikt als een langetermijncorrectie voor de gyroscoop Yaw-drift. De MPU6050 heeft echter een functie die Digital Motion Processor wordt genoemd en die wordt gebruikt voor berekeningen aan boord van de gegevens en die de Yaw-drift kan elimineren.
Hier is hetzelfde 3D-voorbeeld met de Digital Motion Processor in gebruik. We kunnen zien hoe nauwkeurig het volgen van de oriëntatie nu is, zonder de Yaw-drift. De ingebouwde processor kan ook quaternions berekenen en uitvoeren die worden gebruikt voor het weergeven van oriëntaties en rotaties van objecten in drie dimensies. In dit voorbeeld gebruiken we eigenlijk quaternionen om de oriëntatie weer te geven, die ook geen last heeft van Gimbal-lock die optreedt bij het gebruik van Euler-hoeken.
Desalniettemin is het verkrijgen van deze gegevens van de sensor iets ingewikkelder dan wat we eerder hebben uitgelegd. Allereerst moeten we een extra draad aansluiten op een Arduino digitale pin. Dat is een interrupt-pin die wordt gebruikt voor het lezen van dit gegevenstype van de MPU6050.
De code is ook een beetje ingewikkelder, daarom gaan we de i2cdevlib-bibliotheek van Jeff Rowberg gebruiken. Deze bibliotheek kan worden gedownload van GitHub en ik zal een link naar in het website-artikel opnemen.
Nadat we de bibliotheek hebben geïnstalleerd, kunnen we het MPU6050_DMP6-voorbeeld uit de bibliotheek openen. Dit voorbeeld wordt goed uitgelegd met opmerkingen voor elke regel.
Hier kunnen we selecteren wat voor soort uitvoer we willen, quaternionen, Euler-hoeken, gieren, pitch en roll, versnellingswaarde of quaternionen voor de 3D-visualisatie. Deze bibliotheek bevat ook een Processing-schets voor het voorbeeld van 3D-visualisatie. Ik heb het zojuist aangepast om de doosvorm te krijgen zoals in het vorige voorbeeld. Hier is de 3D-visualisatieverwerkingscode die werkt met het MPU6050_DPM6-voorbeeld, voor geselecteerde "OUTPUT_TEAPOT" -uitvoer:
/*
Arduino and MPU6050 IMU - 3D Visualization Example
by Dejan, https://howtomechatronics.com
*/
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch,yaw;
void setup() {
size (2560, 1440, P3D);
myPort = new Serial(this, "COM7", 19200); // starts the serial communication
myPort.bufferUntil('\n');
}
void draw() {
translate(width/2, height/2, 0);
background(233);
textSize(22);
text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
// Rotate the object
rotateX(radians(-pitch));
rotateZ(radians(roll));
rotateY(radians(yaw));
// 3D 0bject
textSize(30);
fill(0, 76, 153);
box (386, 40, 200); // Draw box
textSize(25);
fill(255, 255, 255);
text("www.HowToMechatronics.com", -183, 10, 101);
//delay(10);
//println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}
// Read data from the Serial Port
void serialEvent (Serial myPort) {
// reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
data = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
if (data != null) {
data = trim(data);
// split the string at "/"
String items[] = split(data, '/');
if (items.length > 1) {
//--- Roll,Pitch in degrees
roll = float(items[0]);
pitch = float(items[1]);
yaw = float(items[2]);
}
}
}
Code language: Arduino (arduino)
Dus hier met de functie serialEvent() ontvangen we de quaternionen die van de Arduino komen, en in de hoofdtekenlus gebruiken we ze om het 3D-object te roteren. Als we de schets uitvoeren, kunnen we zien hoe goed quaternionen zijn voor het roteren van objecten in drie dimensies.
Om deze tutorial niet te overbelasten, heb ik het tweede voorbeeld, de DIY Arduino Gimbal of het zelfstabiliserende platform, in een apart artikel geplaatst.
Voel je vrij om elke vraag met betrekking tot deze tutorial te stellen in de comments hieronder en vergeet ook niet om mijn verzameling Arduino-projecten te bekijken.
Productieproces
- Arduino RFID Lock-zelfstudie
- LCD-animatie en gaming
- Besturing van servomotor met Arduino en MPU6050
- Python3- en Arduino-communicatie
- FM-radio met Arduino en RDA8057M
- Versnelling omzetten naar hoek van MPU6050 I2C-sensor
- Tutorial Arduino-vingerafdruksensor
- Arduino-zelfstudie:minipiano
- Raspberry Pi en Arduino-laptop
- Gebaarherkenning met Accelerometer en ESP
- Arduino-zelfstudie 01:Aan de slag