MPU-6050 Arduino-opas: kytkentä, koodi ja kallistuskulmat
MPU-6050 Arduino -yhdistelmä on yksi harrastajaelektroniikan suosituimmista anturiprojekteista – ja hyvästä syystä. Haluatko rakentaa itsetasapainottavan robotin, digitaalisen vesivaa’an tai eleohjatun laitteen? Kaikki alkaa tästä pienestä, edullisesta moduulista. MPU-6050 yhdistää kolmiakselisen kiihtyvyysanturin ja kolmiakselisen gyroskoopin samalle piirille, ja se kommunikoi Arduinon kanssa yksinkertaisella I2C-väylällä. Tässä oppaassa käymme läpi MPU-6050:n kytkennän Arduino Nanoon, luemme raakadataa rekisteritasolla ja rakennamme komplementaarifiltterin kallistuskulmien laskemiseen. Lopuksi esittelemme yksinkertaisen PID-pohjaisen tasapainotuskonseptin servolla.
Kaikki tarvittavat komponentit saat alle 20 eurolla, ja projekti sopii erinomaisesti I2C-anturin ja anturitekniikan opiskeluun.
Sisällysluettelo

Mikä on MPU-6050?
MPU-6050 on InvenSensen (nykyisin TDK) valmistama 6-akselinen IMU (Inertial Measurement Unit) eli inertiamittausyksikkö. Se sisältää:
- Kiihtyvyysanturi (3 akselia) – mittaa lineaarista kiihtyvyyttä X-, Y- ja Z-suunnissa. Oletusalue ±2g, ohjelmoitavissa ±4g, ±8g tai ±16g asti.
- Gyroskooppi (3 akselia) – mittaa kulmanopeutta. Oletusalue ±250 °/s, ohjelmoitavissa ±500, ±1000 tai ±2000 °/s asti.
- Lämpötila-anturi – sisäänrakennettu, mittausalue -40 °C … +85 °C.
- DMP (Digital Motion Processor) – piirin sisäinen prosessori, joka voi laskea sensorifuusiota itsenäisesti.
Kaikki kanavat käyttävät 16-bittistä AD-muunninta, joten resoluutio on erinomainen. I2C-väylän ansiosta tarvitset vain neljä johtoa: VCC, GND, SDA ja SCL. MPU-6050:n oletusosoite on 0x68, mutta sen voi vaihtaa osoitteeksi 0x69 vetämällä AD0-pinnin ylös. Juuri tämä helppous tekee MPU-6050 Arduino -projekteista niin suosittuja aloittelijoiden keskuudessa.
Kiihtyvyysanturi vs. gyroskooppi – miksi molempia tarvitaan?
Kiihtyvyysanturi mittaa painovoimaa ja liikekiihtyvyyttä. Kun anturi on paikallaan, voit laskea kallistuskulman trigonometrialla, koska painovoima osoittaa aina alaspäin. Ongelmana on, että lukemat ovat kohinaisia ja häiriintyvät tärinästä tai liikkeestä.
Gyroskooppi Arduino -käytössä mittaa kulmanopeutta (°/s). Integroimalla kulmanopeutta ajan suhteen saat kulman muutoksen. Gyro reagoi nopeasti ja on immuuni tärinälle, mutta se ajautuu (drift) ajan myötä, koska pienetkin mittausvirheet kertautuvat integroinnissa.
Ratkaisu on yhdistää molemmat anturit komplementaarifiltterillä tai Kalman-filtterillä. Näin saat gyroskoopin nopeuden ja kiihtyvyysanturin pitkän aikavälin vakauden.
Tarvittavat komponentit
Tähän projektiin tarvitset vain kolme komponenttia:

- MPU-6050 kiihtyvyysanturi- ja gyroskooppimoduuli – 4,90 €. Moduulissa on valmiiksi juotetut piikkirimat ja sisäänrakennetut ylösvetovastukset SDA/SCL-linjoille.
- ATmega328P ’Nano’ ohjain – 9,90 €. Arduino Nano -yhteensopiva ohjain USB-C-liitännällä. I2C-pinnit: A4 (SDA) ja A5 (SCL).
- Dupont-hyppylanka 10cm (20kpl) uros-naaras – 3,90 €. Värikoodatut hyppylangat helpottavat kytkentää.
Kokonaishinta: 18,70 € – edullinen tapa päästä alkuun anturitekniikan ja I2C-väylän opiskelussa.
Tasapainotusprojektia (Koodi 3) varten tarvitset lisäksi servon, esimerkiksi MG996R metallivaihteisen servon (11,90 €).
Kytkentä Arduino Nanoon
MPU-6050:n peruskytkentä vaatii vain neljä johtoa. Moduulissa on sisäänrakennettu 3,3 V:n regulaattori, joten voit syöttää siihen 5 V suoraan Arduinon 5V-pinnistä.
| MPU-6050 | Arduino Nano | Huomio |
|---|---|---|
| VCC | 5V | Moduulin oma regulaattori hoitaa jännitteen |
| GND | GND | Yhteinen maa |
| SCL | A5 | I2C-kellosignaali |
| SDA | A4 | I2C-datasignaali |
| INT | D2 (valinnainen) | Keskeytyspinni DMP:lle |
| AD0 | GND tai NC | Low = osoite 0x68 |
| XDA, XCL | NC | Ulkoisille antureille, ei tarvita |
Varmista, että GND-yhteys on kunnossa – se on yleisin syy I2C-ongelmiin. Moduulin valmiit ylösvetovastukset hoitavat SDA- ja SCL-linjojen vetämisen, joten erillisiä vastuksia ei tarvita.
Koodi 1: Raakadatan lukeminen Wire.h-kirjastolla
Aloitetaan yksinkertaisimmasta esimerkistä: luetaan MPU-6050:n kiihtyvyys-, gyroskooppi- ja lämpötiladata suoraan rekistereistä. Käytämme Arduinon sisäänrakennettua Wire.h-kirjastoa, joka hoitaa I2C-protokollan.
Tärkeä huomio: MPU-6050 käynnistyy lepotilassa! Rekisteriin 0x6B (PWR_MGMT_1) täytyy kirjoittaa arvo 0x00, jotta anturi herää. Tämä on yleisin aloittelijan virhe.
/*
* MPU-6050 raakadatan lukeminen Arduinolla
* Kytkentä: VCC->5V, GND->GND, SCL->A5, SDA->A4
*/
#include <Wire.h>
const int MPU_ADDR = 0x68; // MPU-6050 I2C-osoite
int16_t accX, accY, accZ;
int16_t gyroX, gyroY, gyroZ;
int16_t temp;
void setup() {
Serial.begin(115200);
Wire.begin();
// Herätä MPU-6050 lepotilasta
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B); // PWR_MGMT_1 rekisteri
Wire.write(0x00); // Kirjoita 0 -> herätys
Wire.endTransmission(true);
Serial.println("MPU-6050 alustettu!");
}
void loop() {
// Lue 14 tavua alkaen rekisteristä 0x3B
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // ACCEL_XOUT_H
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 14, true);
// Yhdistä kaksi tavua 16-bittiseksi arvoksi
accX = Wire.read() << 8 | Wire.read();
accY = Wire.read() << 8 | Wire.read();
accZ = Wire.read() << 8 | Wire.read();
temp = Wire.read() << 8 | Wire.read();
gyroX = Wire.read() << 8 | Wire.read();
gyroY = Wire.read() << 8 | Wire.read();
gyroZ = Wire.read() << 8 | Wire.read();
// Muunna fysikaalisiksi arvoiksi (oletus ±2g ja ±250°/s)
float ax = accX / 16384.0; // g-voimaksi
float ay = accY / 16384.0;
float az = accZ / 16384.0;
float gx = gyroX / 131.0; // °/s
float gy = gyroY / 131.0;
float gz = gyroZ / 131.0;
float tempC = temp / 340.0 + 36.53; // °C
Serial.print("aX="); Serial.print(ax, 2);
Serial.print(" aY="); Serial.print(ay, 2);
Serial.print(" aZ="); Serial.print(az, 2);
Serial.print(" | gX="); Serial.print(gx, 1);
Serial.print(" gY="); Serial.print(gy, 1);
Serial.print(" gZ="); Serial.print(gz, 1);
Serial.print(" | T="); Serial.print(tempC, 1);
Serial.println("°C");
delay(100);
}
Raakadatan tulkinta
Anturi palauttaa 16-bittisiä etumerkillisiä kokonaislukuja (-32768 … +32767). Jotta saat fysikaaliset arvot, jaa raakadata herkkyyskertoimella:
- Kiihtyvyys (±2g): jaa luvulla 16384 → tulos g-voimana. Paikallaan Z-akselin pitäisi näyttää ~1,0 g (painovoima).
- Gyroskooppi (±250 °/s): jaa luvulla 131 → tulos asteina sekunnissa. Paikallaan kaikkien akselien pitäisi olla lähellä nollaa.
- Lämpötila: kaava on
raaka / 340.0 + 36.53→ tulos celsiusasteina.
Jos vaihdat mittausaluetta (esim. ±4g tai ±500 °/s), muista päivittää myös jakoluku koodissa!
Koodi 2: Kallistuskulmat komplementaarifiltterillä
Pelkkä raakadata ei vielä kerro, missä asennossa anturi on. Tarvitsemme sensorifuusion, joka yhdistää kiihtyvyysanturin ja gyroskoopin tiedot luotettavaksi kulma-arvioksi.
Komplementaarifiltterin periaate
Komplementaarifiltteri on yksinkertainen mutta tehokas tapa yhdistää kaksi anturitietoa:
kulma = α × (kulma + gyro × dt) + (1 - α) × kiihtyvyyskulma
Kerroin α = 0,96 tarkoittaa, että 96 % painosta tulee gyroskoopin integraalista (nopea, tarkka lyhyellä aikavälillä) ja 4 % kiihtyvyysanturin kulmasta (vakaa pitkällä aikavälillä, korjaa gyroskoopin ajautumisen). Tämä on laskennallisesti kevyt ja riittävän tarkka useimpiin harrasteprojekteihin.
/*
* MPU-6050 kallistuskulmat komplementaarifiltterillä
* Laskee pitch ja roll -kulmat asteina
*/
#include <Wire.h>
const int MPU_ADDR = 0x68;
float pitch = 0, roll = 0;
unsigned long prevTime = 0;
const float alpha = 0.96; // Komplementaarifiltterin kerroin
void setup() {
Serial.begin(115200);
Wire.begin();
// Herätä MPU-6050
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission(true);
// Aseta DLPF (Digital Low Pass Filter) taajuudeksi ~44 Hz
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x1A); // CONFIG rekisteri
Wire.write(0x03); // DLPF_CFG = 3
Wire.endTransmission(true);
prevTime = millis();
delay(100);
}
void loop() {
// Lue raakadata
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 14, true);
int16_t accX = Wire.read() << 8 | Wire.read();
int16_t accY = Wire.read() << 8 | Wire.read();
int16_t accZ = Wire.read() << 8 | Wire.read();
int16_t temp = Wire.read() << 8 | Wire.read(); // ohitetaan
int16_t gyroX = Wire.read() << 8 | Wire.read();
int16_t gyroY = Wire.read() << 8 | Wire.read();
int16_t gyroZ = Wire.read() << 8 | Wire.read();
// Muunna kiihtyvyys g-voimaksi
float ax = accX / 16384.0;
float ay = accY / 16384.0;
float az = accZ / 16384.0;
// Muunna gyro asteiksi/sekunti
float gx = gyroX / 131.0;
float gy = gyroY / 131.0;
// Laske aika-askel
unsigned long now = millis();
float dt = (now - prevTime) / 1000.0;
prevTime = now;
// Kiihtyvyysanturin kulmat (trigonometria)
float accPitch = atan2(ay, sqrt(ax * ax + az * az)) * 180.0 / PI;
float accRoll = atan2(-ax, sqrt(ay * ay + az * az)) * 180.0 / PI;
// Komplementaarifiltteri
pitch = alpha * (pitch + gx * dt) + (1.0 - alpha) * accPitch;
roll = alpha * (roll + gy * dt) + (1.0 - alpha) * accRoll;
Serial.print("Pitch: "); Serial.print(pitch, 1);
Serial.print("° Roll: "); Serial.print(roll, 1);
Serial.println("°");
delay(10); // ~100 Hz näytteenottotaajuus
}
Huomaa, että koodissa otetaan käyttöön myös DLPF (Digital Low Pass Filter) kirjoittamalla rekisteriin 0x1A. Tämä suodattaa korkeataajuista kohinaa pois jo anturin sisällä, mikä parantaa lukemien laatua merkittävästi.
Koodi 3: Tasapainotusalusta servolla ja PID-säädöllä
Seuraava esimerkki demonstroi, miten MPU-6050 Arduino -ympäristössä voidaan hyödyntää aktiiviseen tasapainotukseen. Käytämme servoa, joka korjaa alustan kallistusta pitch-akselin mukaan. Tämä on yksinkertaistettu versio itsetasapainottavan robotin periaatteesta.
PID-säätimen perusteet
PID-säädin koostuu kolmesta osasta:
- P (Proportional) – korjaa nykyisen virheen suhteessa. Mitä suurempi kallistus, sitä voimakkaampi korjaus.
- I (Integral) – korjaa kertynyttä virhettä ajan myötä. Poistaa pysyvän poikkeaman.
- D (Derivative) – ennakoi tulevaa virhettä muutosnopeuden perusteella. Vaimentaa värähtelyä.
/*
* Yksinkertainen tasapainotusalusta
* MPU-6050 + servo – demonstroi tasapainotuksen periaatteen
* Servo korjaa kallistusta pitch-akselin mukaan
*/
#include <Wire.h>
#include <Servo.h>
const int MPU_ADDR = 0x68;
Servo balanceServo;
float pitch = 0;
unsigned long prevTime = 0;
const float alpha = 0.96;
// PID-kertoimet (vaativat viritystä projektikohtaisesti)
float Kp = 2.0;
float Ki = 0.05;
float Kd = 1.0;
float prevError = 0;
float integral = 0;
float setpoint = 0; // Tavoitekulma (0° = vaakasuora)
void setup() {
Serial.begin(115200);
Wire.begin();
// Herätä MPU-6050
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission(true);
balanceServo.attach(9); // Servo pinniin D9
balanceServo.write(90); // Keskiasento
prevTime = millis();
delay(500);
}
void loop() {
// Lue anturidata
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 14, true);
int16_t accX = Wire.read() << 8 | Wire.read();
int16_t accY = Wire.read() << 8 | Wire.read();
int16_t accZ = Wire.read() << 8 | Wire.read();
int16_t temp = Wire.read() << 8 | Wire.read();
int16_t gyroX = Wire.read() << 8 | Wire.read();
int16_t gyroY = Wire.read() << 8 | Wire.read();
int16_t gyroZ = Wire.read() << 8 | Wire.read();
float ax = accX / 16384.0;
float ay = accY / 16384.0;
float az = accZ / 16384.0;
float gx = gyroX / 131.0;
unsigned long now = millis();
float dt = (now - prevTime) / 1000.0;
prevTime = now;
// Komplementaarifiltteri pitch-kulmalle
float accPitch = atan2(ay, sqrt(ax * ax + az * az)) * 180.0 / PI;
pitch = alpha * (pitch + gx * dt) + (1.0 - alpha) * accPitch;
// PID-säätö
float error = setpoint - pitch;
integral += error * dt;
integral = constrain(integral, -50, 50); // Anti-windup
float derivative = (error - prevError) / dt;
float output = Kp * error + Ki * integral + Kd * derivative;
prevError = error;
// Muunna servokulmaksi (90° = keskiasento)
int servoAngle = constrain(90 + (int)output, 0, 180);
balanceServo.write(servoAngle);
Serial.print("Pitch: "); Serial.print(pitch, 1);
Serial.print("° Servo: "); Serial.println(servoAngle);
delay(10);
}
PID-kertoimet (Kp, Ki, Kd) vaativat aina projektikohtaista viritystä. Hyvä aloitustapa on asettaa ensin vain P-kerroin ja kasvattaa sitä, kunnes järjestelmä alkaa värähdellä. Pienennä sitten hieman ja lisää D-kerroin vaimentamaan värähtelyä. I-kerroin lisätään viimeisenä poistamaan mahdollinen pysyvä poikkeama.
Vianetsintä ja vinkit
MPU-6050 on luotettava I2C-anturi, mutta muutama asia kannattaa tarkistaa, jos jokin ei toimi:
Yleisimmät ongelmat
- Kaikki lukemat ovat nollia: Unohdit herättää anturin lepotilasta. Varmista, että kirjoitat arvon
0x00rekisteriin0x6Bsetup()-funktiossa. - I2C-laitetta ei löydy: Tarkista johdotus ja käytä Arduino I2C Scanner -esimerkkisketsaa. Varmista myös AD0-pinnin tila (GND = osoite 0x68).
- Kohinaiset lukemat: Ota käyttöön DLPF kirjoittamalla rekisteriin
0x1A(esim. arvo 0x03 = ~44 Hz suodatus). Varmista myös, että johdot ovat kunnolla kiinni. - Gyroskooppi ajautuu: Tämä on normaalia! Käytä komplementaarifiltteriä tai Kalman-filtteriä kompensoimaan ajautumista.
- Arvot vaikuttavat vääriltä: Tarkista, että jakoluku vastaa asetettua mittausaluetta. Oletusalueella ±2g jakoluku on 16384, ja ±250 °/s jakoluku on 131.
Kalibrointi parantaa tarkkuutta
Jokainen MPU-6050-moduuli on hieman erilainen. Kalibroimalla saat tarkempia tuloksia:
- Aseta anturi tasaiselle, vakaalle pinnalle.
- Lue noin 200 näytettä ja laske keskiarvo jokaiselle akselille.
- Kiihtyvyysanturin X ja Y pitäisi olla ~0, Z pitäisi olla ~16384 (1g). Gyroskoopin kaikkien akselien pitäisi olla ~0.
- Vähennä lasketut offset-arvot tulevista lukemista koodissa.
MPU-6050 Arduino -jatkoprojektit ja ideat
Kun MPU-6050 Arduino -perusteet ovat hallussa, voit laajentaa projektia moneen suuntaan:
- Itsetasapainottava robotti – klassinen MPU-6050-projekti. Vaatii DC-moottorit, moottoriohjaimen (esim. L298N) ja huolellisesti viritetyn PID-säätimen.
- Dronen lennonvakautus – MPU-6050 on monien DIY-lennokkien ytimessä. Tehokkaampiin projekteihin voit harkita ESP32 DevKitC -ohjainta, joka tarjoaa Wi-Fi-yhteyden telemetriadatalle.
- Eleohjaus – tunnista käden liikkeitä ja ohjaa niillä LED-valoja, servoja tai muita laitteita.
- Kallistusmittari – rakenna digitaalinen vesivaaka tai inklinometri.
- Kameran gimbaali – stabiloi kamera kahdella tai kolmella servolla kiihtyvyysanturin datan perusteella.
- Tärinämonitorointi – seuraa koneiden tai rakenteiden tärinää kiihtyvyysdatan avulla.
Yhteenveto
MPU-6050 on erinomainen I2C-anturi harrasteprojekteihin ja oppimiseen. Tässä oppaassa kävimme läpi kolme esimerkkiä: raakadatan lukemisen rekisteritasolla, kallistuskulmien laskemisen komplementaarifiltterillä ja PID-pohjaisen tasapainotuksen servolla. Nämä esimerkit antavat vankan pohjan MPU-6050 Arduino -projekteihin ja sensorifuusion ymmärtämiseen.
Sen edullinen hinta, helppo kytkentä ja laaja yhteisötuki tekevät MPU-6050:stä täydellisen valinnan ensimmäiseksi IMU-anturiksi. Hanki kaikki tarvittavat komponentit Protocachesta ja aloita kokeileminen!
👉 Tilaa MPU-6050-moduuli Protocachesta ja rakenna oma anturiprojektisi jo tänään!






















