Sambungkan SDA dan SCL GY-521 ke pin A4 dan A5 Arduino Uno, kejutkan MPU-6050 daripada mod sleep, kemudian bahagikan bacaan mentah 16-bit dengan faktor skala datasheet — 16384 setiap g dan 131 setiap °/s pada julat lalai — dan gabungkan accelerometer dengan gyro melalui complementary filter untuk sudut tilt yang stabil di OLED.
Apa yang ada pada board GY-521 dan apa fungsi lapan pin dia?
GY-521 ialah PCB biru kecil yang membawa MPU-6050 keluaran InvenSense: gyroscope 3-paksi dan accelerometer 3-paksi dalam satu cip hitam. Gyro meliputi ±250 hingga ±2000°/s, accelerometer ±2 hingga ±16 g, dan regulator pada board menerima 3–5V — datasheet MPU-6050 meletakkan cip itu sendiri pada 2.375–3.46V, dan sebab itulah 5V daripada Uno selamat di sini. Anak panah pada silkscreen menandakan paksi X dan Y.
Dua daripada lapan pad emas ini mengelirukan hampir semua orang. AD0 memilih alamat I2C: board ini menarik pin tersebut ke bawah (low), jadi kalau dibiarkan tanpa sambungan, modul menjawab di 0x68; sambungkan ke 3.3V dan alamat berpindah ke 0x69 untuk modul kedua atas satu bus yang sama. XDA dan XCL pula ialah auxiliary I2C master milik MPU-6050 sendiri untuk merantai sensor tambahan seperti magnetometer di belakang cip — jangan sekali-kali sambungkan Uno anda ke situ.
Pin header sampai sebagai dua jalur longgar, satu lurus dan satu bengkok 90 darjah — solderkan yang mana sesuai dengan binaan anda, ikut panduan solder header pin kami. Jangan sekadar cucuk tanpa solder: sambungan geseran akan terlepas sebaik sahaja anda condongkan board, sedangkan itulah tujuan utama projek ini.
Senarai komponen
Parts list
Pasang kedua-dua modul atas breadboard dan sambungkan wayar Dupont male-to-male ke Uno — jauh lebih kemas daripada wayar longgar pada board yang anda asyik condongkan.
Macam mana nak sambung GY-521 dan OLED ke Uno?
Arduino Uno mendedahkan I2C pada dua pin analog: A4 ialah SDA dan A5 ialah SCL. Kedua-dua modul berkongsi dua wayar itu berserta bekalan kuasa — lapan jumper wayar kesemuanya.
| Pin modul | Pin Uno | Nota |
|---|---|---|
| GY-521 VCC | 5V | Regulator atas board turunkan voltan untuk cip |
| GY-521 GND | GND | — |
| GY-521 SCL | A5 | Talian clock I2C dikongsi |
| GY-521 SDA | A4 | Talian data I2C dikongsi |
| GY-521 AD0 | Tidak disambung | Alamat kekal pada lalai 0x68 |
| GY-521 XDA, XCL | Tidak disambung | Auxiliary I2C master — bukan untuk Uno |
| GY-521 INT | Tidak disambung | Output interrupt, tidak digunakan di sini |
| OLED GND | GND | Pin pertama pada display ini — semak silkscreen |
| OLED VCC | 5V | Pin kedua, bukan pertama |
| OLED SCL | A5 | Wayar clock sama dengan GY-521 |
| OLED SDA | A4 | Wayar data sama dengan GY-521 |
Perhatikan susunan header OLED: dari kiri ke kanan ia berbunyi GND, VCC, SCL, SDA, dan tertukar dua pin pertama ialah cara klasik display jenis ini rosak. Berkongsi satu bus tiada masalah kerana I2C memberi alamat kepada setiap cip: MPU-6050 menjawab di 0x68, OLED ini di 0x3C, dan Uno memanggil setiap satu dengan namanya — corak yang sama seperti monitor suhu DHT11 OLED kami.

Untuk melihat modul ini disambung dan nilai mentah bergerak atas bench sebenar, walkthrough ini menunjukkan bahagian fizikalnya dengan baik:
Kenapa MPU6050 pulangkan nombor besar macam 16384?
MPU-6050 tidak menghantar darjah atau g — ia menghantar integer 16-bit bertanda dari −32768 hingga +32767, dan membaca nombor ini seolah-olah unit sebenar ialah kesilapan nombor satu pemula. Terletak rata atas meja, accelerometer paksi Z membaca lebih kurang 16384: bukan rosak, cuma 1 g dalam kiraan mentah. Bahagikan dengan sensitivity scale factor untuk julat yang anda pilih, daripada datasheet: 16384 ÷ 16384 = 1.00 g, dan bacaan gyro 262 menjadi 262 ÷ 131 = 2°/s. Kedua-dua pembahagi ini bukan nombor rawak: +2 g memiliki separuh positif skala 16-bit — 32768 kiraan — jadi satu g ialah 32768 ÷ 2 = 16384, dan 32768 ÷ 250 pula asal-usul angka 131 milik gyro.
| Tetapan julat | Bahagikan nilai mentah dengan | Unit hasil |
|---|---|---|
| Accel ±2 g (lalai) | 16384 | g |
| Accel ±4 g | 8192 | g |
| Accel ±8 g | 4096 | g |
| Accel ±16 g | 2048 | g |
| Gyro ±250°/s (lalai) | 131 | °/s |
| Gyro ±500°/s | 65.5 | °/s |
| Gyro ±1000°/s | 32.8 | °/s |
| Gyro ±2000°/s | 16.4 | °/s |
Tukar gantinya ialah julat lawan resolusi: 16 bit yang sama diregangkan meliputi ±16 g menjadikan setiap kiraan bernilai lapan kali ganda pecutan. Tutorial ini mengekalkan tetapan lalai semasa power-up — paling sesuai untuk tilt — dan kalau kelak anda luaskan julat, pembahaginya turut berubah.
Kenapa perlu kedua-dua accelerometer dan gyroscope?
Accelerometer MPU-6050 memberi anda tilt hampir percuma: condongkan board dan 1 g graviti yang tetap itu terbahagi antara paksi Y dan Z, jadi atan2(ay, az) memulihkan sudut roll daripada pembahagian itu — kukuh stabil berminit-minit lamanya. Masalahnya: ia mengukur setiap pecutan, bukan graviti sahaja. Goncang board dan pergerakan itu menambah tarikan sendiri, vektor gabungan tidak lagi menunjuk tepat ke bawah, dan sudut yang dikira melompat liar — tepat pada masa keadaan mula menarik.
Gyroscope pula berperangai sebaliknya: darabkan kelajuan putarannya dengan selang masa dan jumlahkan — proses integrate — dapatlah sudut yang licin dan pantas, langsung tidak pedulikan goncangan. Tetapi setiap modul ada bias rehat yang kecil, dan mengintegrasi ralat tetap itu membesarkannya tanpa had — bias baki 0.5°/s sekalipun terbaca sebagai 30° tilt hantu selepas satu minit, walaupun board langsung tidak bergerak.
Penyelesaian praktikalnya ialah complementary filter, satu baris yang mengambil kelebihan kedua-duanya: angle = 0.96 * (angle + rate * dt) + 0.04 * accelAngle. Setiap loop, filter ini menyimpan 96% sudut yang baru dikemas kini gyro dan mencampurkan 4% jawapan accelerometer. 4% itu terlalu kecil untuk spike accelerometer semasa goncangan menjejaskan output, tetapi ia berulang berpuluh kali sesaat, jadi apa-apa drift gyro yang bertakung disalirkan keluar dalam beberapa saat sahaja. Naikkan 0.96 ke arah 0.98 dan anda percayakan gyro lebih lama; turunkannya dan jitter accelerometer mula kelihatan. Tiada firmware DMP, tiada matematik Kalman, dan ia berjalan lancar atas Uno.

Bias itulah sebab sketch ini membuat kalibrasi semasa startup: ia memurata 500 bacaan gyro dengan board dipegang pegun dan menolak offset itu daripada setiap bacaan selepasnya.
Macam mana rupa sketch Arduino yang lengkap?
Adafruit display stack sahaja yang perlu dipasang: dalam Library Manager Arduino IDE, install Adafruit SSD1306 dan terima prompt untuk dependency Adafruit GFX dan Adafruit BusIO. Bahagian MPU-6050 langsung tidak guna library — Wire yang terbina dalam membaca register secara terus, jadi setiap pembahagian yang anda baru pelajari kelihatan jelas dalam kod.
Dua fakta register memandu bahagian setup: cip ini hidup dalam mod sleep, jadi kita kosongkan bit SLEEP dalam PWR_MGMT_1 (0x6B) dahulu, dan kesemua empat belas byte data duduk berturutan bermula dari register 0x3B, jadi satu burst read mengambil semuanya sekali gus.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define MPU_ADDR 0x68 // GY-521 dengan AD0 dibiarkan tanpa sambungan
#define OLED_ADDR 0x3C // alamat modul 0.96" ini
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Sensitivity scale factor daripada datasheet MPU-6050
// (julat lalai: +/-2 g dan +/-250 deg/s)
const float ACCEL_LSB_PER_G = 16384.0;
const float GYRO_LSB_PER_DPS = 131.0;
const float ALPHA = 0.96; // pekali complementary filter
int16_t ax, ay, az, gx, gy, gz;
float gyroBiasX = 0; // offset rehat gyro, diukur semasa startup
float angle = 0; // sudut tilt gabungan dalam darjah
unsigned long lastMicros;
int16_t read16() { // satu nilai 16-bit big-endian daripada MPU
int16_t v = Wire.read() << 8;
v |= Wire.read();
return v;
}
void readMPU() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B); // ACCEL_XOUT_H: permulaan blok data
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 14, true); // accel(6) + suhu(2) + gyro(6)
ax = read16(); ay = read16(); az = read16();
read16(); // langkau suhu
gx = read16(); gy = read16(); gz = read16();
}
void setup() {
Wire.begin();
// MPU-6050 hidup dalam keadaan tidur: kosongkan bit SLEEP dalam PWR_MGMT_1
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission(true);
delay(100);
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(F("Calibrating..."));
display.println(F("Keep the board still"));
display.display();
// Purata 500 bacaan gyro pegun untuk cari bias
long sum = 0;
for (int i = 0; i < 500; i++) {
readMPU();
sum += gx;
delay(2);
}
gyroBiasX = sum / 500.0;
lastMicros = micros();
}
void loop() {
readMPU();
unsigned long now = micros();
float dt = (now - lastMicros) / 1000000.0; // saat sejak loop sebelumnya
lastMicros = now;
// Kiraan mentah ke unit sebenar (bahagi dengan scale factor)
float ayG = ay / ACCEL_LSB_PER_G; // g
float azG = az / ACCEL_LSB_PER_G; // g
float rateX = (gx - gyroBiasX) / GYRO_LSB_PER_DPS; // deg/s, bias dibuang
// Tilt accelerometer: stabil jangka panjang, noisy bila digerakkan
float accelAngle = atan2(ayG, azG) * 180.0 / PI;
// Complementary filter: gyro bawa perubahan pantas,
// accelerometer perlahan-lahan betulkan drift
angle = ALPHA * (angle + rateX * dt) + (1.0 - ALPHA) * accelAngle;
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print(F("MPU6050 tilt"));
display.setTextSize(3);
display.setCursor(0, 28);
display.print(angle, 1);
display.setTextSize(1);
display.print(F(" deg"));
display.display();
}
Upload, biarkan board rata sepanjang mesej kalibrasi, kemudian gulingkannya sekitar paksi X — ikut anak panah pada silkscreen. Sudutnya patut mengikut tangan anda serta-merta, kembali ke sifar atas meja, dan kekal di situ.

Macam mana kalau bacaan nampak pelik atau tiada apa-apa keluar?
GY-521 gagal dengan cara yang boleh dicam, dan setiap simptom menunjuk ke satu tempat tertentu.
| Simptom | Punca berkemungkinan | Penyelesaian |
|---|---|---|
| Tiada apa-apa dijumpai pada bus I2C | Pendawaian atau header belum disolder | Jalankan sketch I2C scanner; semak SDA pada A4, SCL pada A5, dan pastikan jalur header betul-betul disolder, bukan sekadar dicucuk |
| Semua bacaan sifar | Cip masih tidur | Sahkan penulisan PWR_MGMT_1 ke 0x6B benar-benar berjalan dan alamatnya 0x68 |
| Satu paksi tersekat pada 32767 atau −32768 | Nilai mentok pada skala penuh | Clipping sekejap daripada ketukan kuat itu normal; kalau kekal mentok pada satu paksi, berkemungkinan sensor rosak |
| Sudut drift perlahan-lahan walaupun pegun | Bias gyro tidak dibuang | Pastikan board betul-betul pegun semasa kalibrasi startup; reset untuk kalibrasi semula |
| Sudut melompat bila board diketuk | Accelerometer bertindak balas pada hentakan | Dijangka dalam dos kecil; naikkan ALPHA ke arah 0.98 untuk lebih percayakan gyro |
| OLED kekal gelap | Pin bekalan terbalik atau alamat salah | Semak susunan header GND-dahulu; cuba 0x3D kalau scanner jumpa display di situ |
Kesilapan biasa yang kami nampak daripada pelanggan sebenar
Corak yang paling kerap kami jumpa ialah menyambung Uno ke XDA dan XCL kerana namanya nampak macam adik-beradik SDA dan SCL. Pad itu bus auxiliary milik sensor itu sendiri — sambungan Uno hanya pernah ke SDA dan SCL.
Kedua, langkau kerja solder: jalur header longgar dicucuk sahaja, elok berjalan masa rata atas meja, kemudian terputus sebaik sahaja board dicondongkan dan pin beralih. Solderkan jalur itu dahulu sebelum debug benda lain.
Ketiga, menilai modul daripada output mentahnya — nampak 16384 terus membuat kesimpulan sensor rosak, atau membahagi dengan faktor daripada tetapan julat yang lain. Dan tabiat wayar-merah-dahulu pada header GND-dahulu OLED kekal satu-satunya kesilapan yang hardware ini tidak maafkan.
FAQ
Perlukah saya guna DMP untuk dapat sudut yang baik?
Tidak. Digital Motion Processor terbina dalam MPU-6050 mengira orientasi terus atas cip tetapi memerlukan muat naik firmware yang besar dan library yang lebih berat. Untuk tilt, complementary filter di sini sudah memberi hasil yang licin dan stabil dengan aritmetik yang anda benar-benar boleh faham.
Boleh tak MPU6050 mengukur kedudukan atau jarak?
Secara praktikalnya, tidak. Kedudukan bermakna mengintegrasi pecutan dua kali, jadi setiap bias kecil berganda dua kali dan kedudukan yang dikira melencong bermeter-meter dalam beberapa saat — sistem sebenar menambah GPS, wheel encoder atau kamera. Anggap MPU-6050 sebagai sensor orientasi, bukan penjejak.
Kenapa sudut saya drift walaupun board pegun?
Itu bias rehat gyro yang sedang diintegrasi: setiap modul membaca sedikit bukan-sifar semasa rehat, dan menjumlahkan ralat itu membesarkannya tanpa had. Kalibrasi semasa startup dengan board pegun, dan biarkan bahagian accelerometer dalam filter menarik balik bakinya.
Boleh tak saya guna GY-521 dengan ESP32?
Boleh — sambungkan ke GPIO21 (SDA) dan GPIO22 (SCL) ESP32 dengan 3.3V pada VCC dan kod register yang sama berjalan tanpa perubahan. Panduan perbandingan board kami membantu anda menentukan bila kelajuan dan WiFi ESP32 berbaloi.
Perlukah kalibrasi setiap kali hidupkan power?
Ya, dan sketch ini melakukannya dalam kira-kira dua saat semasa startup. Bias gyro berubah dengan suhu dan dari hari ke hari, jadi kalibrasi yang disimpan menjadi basi — purata segar setiap kali boot langsung tidak membebankan.
Kemas kini terakhir Ogos 2026. Tersangkut? Chat dengan kami di WhatsApp.



Arduino Uno Compatible SMD UNO R3 with Type B Cable - ATMEGA328P with CH340G-Microcontroller Project
GY-521 Gyroscope Accelerometer Module MPU6050 MPU-6050 Motion Measurement Drone Robotic Application
0.96‘ OLED Display Module Blue White Screen I2C IIC Serial 128X64 LCD Display Board - 0.96' OLED WHITE
MB102 Breadboard 170 400 830 Holes Breadboard Donut Board Arduino Prototype Multi Color - MINI BREADBOARD 170 HOLES (WHITE)
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-M 30CM