ربات تعادلی
شتابسنج مرجع بلندمدت گرانش و ژیروسکوپ پاسخ سریع چرخش را فراهم میکند. کنترلکننده باید نرخ نمونهبرداری ثابت، فیلتر و کالیبراسیون بایاس داشته باشد.
آموزش پروژهمحور حسگر حرکت ششمحوره
در این راهنما MPU6050 را بهعنوان یک IMU ششمحوره واقعی میشناسیم، تفاوت تراشه خام و برد آماده را روشن میکنیم و آدرس I2C، محدودههای اندازهگیری، سیمکشی، کد عملی، تحلیل خروجی و عیبیابی را قدمبهقدم پیش میبریم. همه مقادیر فنی با اسناد رسمی TDK/InvenSense و API کتابخانه Adafruit تطبیق داده شدهاند.
0x68 یا 0x69MPU6050 یک واحد اندازهگیری اینرسی یا IMU با شش درجه آزادی است: شتاب خطی و اثر گرانش را روی محورهای X، Y و Z میسنجد و سرعت زاویهای را روی همان سه محور گزارش میکند. هر شش کانال ADC شانزدهبیتی دارند. این قطعه مغناطیسسنج ندارد؛ بنابراین از داده خام آن بهتنهایی نمیتوان جهت مطلق نسبت به شمال را بهدست آورد.
کنترل تعادل ربات، تشخیص شیب، ثبت حرکت، کنترلر حرکتی، پایش لرزش و تخمین Roll و Pitch از کاربردهای مناسباند. برای زاویه پایدار باید داده ژیروسکوپ و شتابسنج با الگوریتمی مانند Complementary یا Kalman ترکیب شوند. انتگرالگیری ساده از ژیروسکوپ بهدلیل بایاس و نویز در طول زمان Drift میکند.
شتابسنج مرجع بلندمدت گرانش و ژیروسکوپ پاسخ سریع چرخش را فراهم میکند. کنترلکننده باید نرخ نمونهبرداری ثابت، فیلتر و کالیبراسیون بایاس داشته باشد.
وقتی حرکت خطی کم است میتوان جهت بردار گرانش را برای Roll و Pitch استفاده کرد. در شتاب شدید، این فرض موقتاً معتبر نیست.
محدوده اندازهگیری و پهنای باند باید متناسب با دامنه و فرکانس پدیده انتخاب شوند؛ انتخاب فیلتر خیلی کند میتواند بخش مهم حرکت را حذف کند.
MPU6050 بهتنهایی شمال مغناطیسی را نمیسنجد. Heading مطلق به مغناطیسسنج، کالیبراسیون و Sensor Fusion مناسب نیاز دارد.
ابتدا تفاوت MPU-6000 و MPU-6050 را ببینید: MPU-6000 رابط I2C و SPI دارد، اما MPU-6050 فقط I2C را پشتیبانی میکند و پایه VLOGIC جداگانه دارد. عددهای زیر مربوط به تراشه خام MPU6050 هستند، نه الزاماً ورودی تغذیه یک ماژول آماده.
| پارامتر رسمی | مقدار | نتیجه عملی |
|---|---|---|
| تغذیه VDD تراشه | 2.375 تا 3.46V | تراشه خام را مستقیم به 5V وصل نکنید. |
| مرجع منطق VLOGIC | 1.71V تا VDD | سطح I2C باید با میزبان و مدار برد سازگار باشد. |
| دمای کاری | -40 تا +85°C | کالیبراسیون بایاس در یک دما برای همه دماها کافی نیست. |
| رابط اصلی | I2C Fast Mode تا 400kHz | برای بردبورد و سیم کوتاه از 100kHz شروع کنید. |
| رزولوشن خروجی | ADC شانزدهبیتی برای هر محور | رزولوشن کد با دقت واقعی یا نویز صفر برابر نیست. |
| بافر FIFO | 1024 byte | برای خواندن Burst و کاهش بار میزبان مفید است. |
| جریان شش محور + DMP | تیپیک 3.9mA | عدد دیتاشیت برای تراشه و شرایط تعریفشده است. |
کلمه «۱۶ بیت» به معنی دقت زاویه ۱/۶۵۵۳۶ دور نیست. نویز، بایاس اولیه، تغییر بایاس با دما، خطای Scale Factor، نصب مکانیکی و ارتعاش روی نتیجه اثر دارند. دیتاشیت برای Zero-Rate Output ژیروسکوپ تلرانس اولیه و تغییر با دما تعریف میکند؛ به همین دلیل اندازهگیری بایاس در شروع پروژه ضروری است.
| حسگر | Full Scale | حساسیت کد خام دیتاشیت |
|---|---|---|
| شتابسنج | ±2g، ±4g، ±8g، ±16g | بهترتیب 16384، 8192، 4096 و 2048 LSB/g |
| ژیروسکوپ | ±250، ±500، ±1000، ±2000 °/s | بهترتیب 131، 65.5، 32.8 و 16.4 LSB/(°/s) |
محدوده کوچکتر حساسیت عددی بیشتری میدهد اما در حرکت بزرگ Saturate میشود. برای نمونه آموزشی، ±4g و ±500°/s تعادلی مناسباند؛ این انتخاب نسخه ثابت برای همه پروژهها نیست. اگر ربات شما ضربه شدید یا چرخش سریع دارد، قبل از افزایش محدوده، Peak واقعی را ثبت کنید.
کتابخانه Adafruit انتخابهای پهنای باند 260، 184، 94، 44، 21، 10 و 5 هرتز را ارائه میکند. فیلتر 21Hz در کد نمونه نویز روی میز را کم میکند، اما برای ثبت حرکت سریع ممکن است کند باشد. پهنای باند، نرخ نمونهبرداری و تأخیر کنترل را با هم طراحی کنید.
حد VDD برابر 2.375 تا 3.46 ولت متعلق به خود تراشه است. برد Adafruit نشاندادهشده در تصویر طبق راهنمای رسمی، رگولاتور و مبدل سطح دارد، Vin آن با 3 تا 5 ولت کار میکند و روی SDA و SCL مقاومت Pull-up دهکیلو اهمی دارد. این مشخصات را نباید به هر برد آبی GY-521 یا ماژول بینام تعمیم داد.
روی برخی GY-521ها رگولاتور تغذیه دیده میشود، اما وضعیت Level Shifting و مقدار Pull-up ممکن است متفاوت باشد. پیش از اعمال 5V، شماتیک همان نسخه و ولتاژ واقعی SDA/SCL را بررسی کنید. اتصال امن و ساده برای ESP32 این است که برد مستند را با 3.3V تغذیه کنید و منطق I2C را 3.3V نگه دارید.
| پایه برد آماده | کاربرد | نکته |
|---|---|---|
| VIN / VCC | تغذیه برد | حد مجاز را از مستند همان ماژول بخوانید؛ برای برد Adafruit برابر 3 تا 5V است. |
| GND | زمین مشترک | زمین ESP32 و حسگر مشترک باشد. |
| SDA | داده I2C | خط Open-drain با Pull-up مناسب به سطح منطق. |
| SCL | کلاک I2C | از سیم کوتاه شروع کنید. |
| AD0 | انتخاب بیت کمارزش آدرس | پایین: 0x68، بالا: 0x69. |
| INT | خروجی وقفه | برای Data Ready، Motion و رویدادهای تنظیمشده قابل استفاده است. |
Register Map رسمی، رجیستر SMPLRT_DIV را در 0x19، CONFIG را در 0x1A، GYRO_CONFIG را در 0x1B و ACCEL_CONFIG را در 0x1C تعریف میکند. داده پیوسته شتاب، دمای تراشه و ژیروسکوپ از 0x3B تا 0x48 قرار دارند. PWR_MGMT_1 در 0x6B و WHO_AM_I در 0x75 است.
| برد MPU6050 مستند | Generic ESP32 | Arduino Uno |
|---|---|---|
| VIN | 3V3 | 5V فقط برای برد Adafruit مستند؛ در غیر این صورت مشخصات ماژول |
| GND | GND | GND |
| SDA | GPIO21 | A4 / SDA |
| SCL | GPIO22 | A5 / SCL |
| AD0 | GND برای 0x68 | GND برای 0x68 |
| INT | در این نمونه وصل نیست | در این نمونه وصل نیست |
GPIO21 و GPIO22 فقط پیشفرض Generic ESP32 هستند. در ESP32-S3، C3 و بردهای سفارشی، پینهای واقعی برد خود را جایگزین کنید. مستند رسمی Arduino-ESP32 توصیه میکند برای تغییر پایهها Wire.setPins را پیش از begin یا فرم مناسب Wire.begin(SDA,SCL) بهکار ببرید.
i2c-scanner.ino را اجرا کنید؛ با AD0 پایین باید 0x68 دیده شود.#include <Wire.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#if defined(ESP32)
constexpr int SDA_PIN = 21;
constexpr int SCL_PIN = 22;
#endif
constexpr uint8_t MPU6050_ADDRESS = 0x68;
constexpr uint16_t CALIBRATION_SAMPLES = 500;
Adafruit_MPU6050 mpu;
float biasX = 0, biasY = 0, biasZ = 0;
void calibrateGyro() {
sensors_event_t a, g, t;
for (uint16_t i = 0; i < CALIBRATION_SAMPLES; ++i) {
mpu.getEvent(&a, &g, &t);
biasX += g.gyro.x;
biasY += g.gyro.y;
biasZ += g.gyro.z;
delay(5);
}
biasX /= CALIBRATION_SAMPLES;
biasY /= CALIBRATION_SAMPLES;
biasZ /= CALIBRATION_SAMPLES;
}
void setup() {
Serial.begin(115200);
#if defined(ESP32)
Wire.begin(SDA_PIN, SCL_PIN);
#else
Wire.begin();
#endif
Wire.setClock(100000);
if (!mpu.begin(MPU6050_ADDRESS, &Wire)) {
Serial.println(F("MPU6050 not found"));
while (true) delay(10);
}
mpu.setAccelerometerRange(MPU6050_RANGE_4_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
calibrateGyro();
}
void loop() {
sensors_event_t a, g, t;
mpu.getEvent(&a, &g, &t);
Serial.print(F("aX=")); Serial.print(a.acceleration.x, 3);
Serial.print(F(" aY=")); Serial.print(a.acceleration.y, 3);
Serial.print(F(" aZ=")); Serial.print(a.acceleration.z, 3);
Serial.print(F(" | wX=")); Serial.print(g.gyro.x - biasX, 4);
Serial.print(F(" wY=")); Serial.print(g.gyro.y - biasY, 4);
Serial.print(F(" wZ=")); Serial.println(g.gyro.z - biasZ, 4);
delay(100);
}
#if defined(ESP32) پایههای Generic ESP32 را صریح میکند؛ Uno از پایههای سختافزاری Wire استفاده میکند.Wire.setClock(100000) برای شروع بردبوردی محافظهکارانه است و از سقف 400kHz دیتاشیت پایینتر میماند.mpu.begin(0x68, &Wire) شناسه WHO_AM_I را از طریق کتابخانه بررسی و تنظیمات اولیه را انجام میدهد.رجیسترهای دما بین داده شتاب و ژیروسکوپ قرار دارند و دیتاشیت رابطه Temperature = TEMP_OUT / 340 + 36.53 را برای تبدیل کد خام به درجه سلسیوس میدهد. این دما مربوط به داخل تراشه است و جای سنسور دقیق دمای محیط را نمیگیرد.
کاربرد مفید آن، ثبت دمای خود IMU کنار بایاس ژیروسکوپ است. برای محصول دقیق، میتوان بایاس را در چند دمای کنترلشده اندازه گرفت و مدل جبرانی ساخت؛ یک Offset در دمای اتاق برای کل بازه -40 تا +85 درجه تضمین نمیشود.
| نشانه | علت محتمل | بررسی پیشنهادی |
|---|---|---|
| 0x68 دیده نمیشود | SDA/SCL جابهجا، زمین مشترک نیست، تغذیه یا Pull-up نامناسب | ولتاژ را اندازه بگیرید و اسکنر را با سیم کوتاه و 100kHz اجرا کنید. |
| فقط 0x69 دیده میشود | AD0 در سطح High است | آدرس کد را به 0x69 تغییر دهید یا AD0 را طبق طراحی پایین بیاورید. |
| ژیروسکوپ در سکون صفر نیست | Zero-rate bias طبیعی یا حرکت هنگام کالیبراسیون | برد را ثابت نگه دارید، میانگین را تکرار و دما را ثبت کنید. |
| زاویه بهآرامی منحرف میشود | انتگرال بایاس ژیروسکوپ | بایاس و نرخ نمونهبرداری را اصلاح و Sensor Fusion اضافه کنید. |
| شتاب Z نزدیک صفر نیست | اثر گرانش | روی سطح افقی، محور همجهت با گرانش باید قدرمطلق نزدیک یک g نشان دهد. |
| اعداد هنگام موتور پرنویزند | ارتعاش مکانیکی، زمین/تغذیه یا پهنای باند نامناسب | نصب مکانیکی، Decoupling، مسیر زمین و فیلتر را جداگانه آزمایش کنید. |
| خروجی روی حد میچسبد | Full Scale کوچک و Saturation | محدوده بزرگتر انتخاب و Peak حرکت واقعی را ثبت کنید. |
| چند ماژول با هم پاسخ میدهند | هر دو آدرس یکسان دارند | برای حداکثر دو قطعه، AD0 یکی را پایین و دیگری را بالا قرار دهید. |
delay(100) فقط برای نمایش آموزشی است.راهاندازی مطمئن MPU6050 فقط وصلکردن چهار سیم نیست. باید تفاوت تراشه و ماژول، آدرس AD0، محدوده اندازهگیری، پهنای باند، واحد خروجی، بایاس ژیروسکوپ و نصب مکانیکی را همزمان در نظر بگیرید. کد این مقاله یک خط مبنای قابلتکرار برای خواندن شش محور است؛ مرحله بعد برای تخمین زاویه، طراحی Sensor Fusion و کالیبراسیون متناسب با محصول واقعی است.
هر دو درستاند. وقتی پایه AD0 پایین باشد آدرس هفتبیتی 0x68 و وقتی AD0 بالا باشد 0x69 است. اسکنر I2C بهترین راه تشخیص وضعیت واقعی برد است.
تراشه خام فقط VDD برابر 2.375 تا 3.46 ولت را میپذیرد. فقط ماژولی را با 5 ولت تغذیه کنید که سازنده همان برد وجود رگولاتور و سازگاری منطق را مستند کرده باشد؛ برد Adafruit این قابلیت را دارد.
ژیروسکوپ بایاس Zero-rate و نویز دارد و بایاس با دما تغییر میکند. حسگر را ثابت نگه دارید، چندصد نمونه میانگین بگیرید و برای محصول دقیق، جبران دمایی انجام دهید.
بهتنهایی نه. MPU6050 مغناطیسسنج ندارد؛ Yaw حاصل از انتگرال ژیروسکوپ در طول زمان Drift میکند. جهت مطلق به مرجع خارجی و Sensor Fusion نیاز دارد.
خیر. خروجی دما وضعیت داخل تراشه را نشان میدهد و بیشتر برای پایش و جبران رفتار IMU مفید است؛ آن را جای سنسور دقیق دمای هوا استفاده نکنید.
اعداد تراشه خام از PS-MPU-6000A-00 Rev.3.4 و رجیسترها از RM-MPU-6000A-00 Rev.4.2 گرفته شدهاند. مشخصات 3 تا 5 ولت و Pull-up دهکیلو اهمی فقط به برد مستند Adafruit تعمیم داده شدهاند. وضعیت Obsolete از صفحه فعلی TDK Product Center کنترل شده است.