Series
Series 37 Module Cảm Biến
  1. Series 37 Module Cảm Biến: Nguyên lý hoạt động và cách test với Arduino, ESP32
  2. 1Series 37 Module Cảm Biến – DS3231 RTC: TCXO ±2ppm, I2C, Alarm Ngắt SQW & Đồng Hồ Thực Với Backup Pin
  3. 2Series 37 Module Cảm Biến – SD Card Module SPI: FAT32, Ghi Log CSV Cảm Biến & Đọc Config File Không Hardcode
  4. 3Series 37 Module Cảm Biến – LCD 1602 I2C: PCF8574 Expander, LiquidCrystal_I2C, Cuộn Chữ & Ký Tự Tùy Chỉnh
  5. 4Series 37 Module Cảm Biến – 7-Segment 1 Chữ Số: Mã Segment 0x3F-0x7F, Common Anode vs Cathode & Đếm 0-9
  6. 5Series 37 Module Cảm Biến – OLED SSD1306 0.96\” I2C: Frame Buffer, Adafruit GFX & Hiển Thị Dữ Liệu Thực Tế
  7. 6Series 37 Module Cảm Biến – Nguyên Lý LM35 Analog: Đặc Tuyến 10mV/°C, Đọc ADC Chính Xác & Hiệu Chỉnh Nhiệt Độ
  8. 7Series 37 Module Cảm Biến – Nguyên Lý Knock Sensor KY-031: Piezoelectric Thuận, Va Đập → Điện Áp & Nhận Dạng Pattern
  9. 8Series 37 Module Cảm Biến – Nguyên Lý MPU-6050: IMU 6 Trục, MEMS Gia Tốc + Con Quay, Complementary Filter & Góc Nghiêng
  10. 9Series 37 Module Cảm Biến – Nguyên Lý Relay 5V SRD-05VDC: Cơ Điện Từ, Cách Ly Galvanic & Điều Khiển Thiết Bị 220V
  11. 10Series 37 Module Cảm Biến – Nguyên Lý Hall Effect Analog (49E/SS49E): Đo Cường Độ Từ Trường Tuyến Tính & ADC
  12. 11Series 37 Module Cảm Biến – Nguyên Lý Hall Effect KY-003: Hiệu Ứng Hall, IC Số Unipolar & Phát Hiện Nam Châm
  13. 12Series 37 Module Cảm Biến – Nguyên Lý Reed Switch: Tiếp Điểm Từ Trong Kính, Phát Hiện Cửa & Đo Tốc Độ Quay
  14. 13Series 37 Module Cảm Biến – Nguyên Lý Vibration Switch SW-18010P: Lò Xo Dẫn Điện, Phát Hiện Rung & Pattern Gõ
  15. 14Series 37 Module Cảm Biến – Nguyên Lý Tilt Switch SW-520D: Bi Kim Loại Dẫn Điện, Phát Hiện Nghiêng & Báo Động
  16. 15Series 37 Module Cảm Biến – Nguyên Lý Touch Sensor TTP223: Capacitive Self-Capacitance, Chế Độ Toggle & Latch
  17. 16Series 37 Module Cảm Biến – Nguyên Lý Rotary Encoder KY-040: Xung Quadrature, Đếm Hướng Xoay & Điều Khiển Menu
  18. 17Series 37 Module Cảm Biến – Nguyên Lý Joystick KY-023: Biến Trở 2 Trục, Dead Zone & Điều Khiển Robot / Servo
  19. 18Series 37 Module Cảm Biến – Nguyên Lý Sound Sensor: Microphone Electret, LM393 Comparator & Phát Hiện Tiếng Ồn
  20. 19Series 37 Module Cảm Biến – Nguyên Lý Passive Buzzer: PWM Điều Khiển Tần Số, Hàm tone() & Phát Nhạc Arduino ESP32
  21. 20Series 37 Module Cảm Biến – Nguyên Lý Active Buzzer: Oscillator Tích Hợp, Phân Biệt Active/Passive & Code Cảnh Báo
  22. 21Series 37 Module Cảm Biến – Nguyên Lý 7-Color LED Tự Đổi Màu: IC Tích Hợp, Tần Số Dao Động Nội & Ứng Dụng Trang Trí
  23. 22Series 37 Module Cảm Biến – Nguyên Lý RGB LED Module KY-016: Điốt 3 Màu, PWM Mix Màu 16 Triệu Sắc & Hiệu Ứng
  24. 23Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động IR Receiver VS1838B: Demodulate 38kHz, NEC Protocol & Điều Khiển Từ Xa
  25. 24Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động LDR Quang Trở: CdS Photoconductor, Voltage Divider & Điều Khiển Theo Ánh Sáng
  26. 25Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Laser Module KY-008: Diode Laser 650nm, Cộng Hưởng Quang Học & An Toàn Laser
  27. 26Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Flame Sensor: Phổ IR Lửa 760-1100nm, LM393 & Ứng Dụng Chữa Cháy
  28. 27Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Line Tracking Sensor TCRT5000: Dò Đường IR, Khoảng Cách Tối Ưu & Robot Theo Vạch
  29. 28Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động IR Obstacle Sensor: Phản Xạ Hồng Ngoại, LM393 & Tránh Vật Cản Robot
  30. 29Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động PIR HC-SR501: Pyroelectric Infrared, Fresnel Lens & Phát Hiện Chuyển Động
  31. 30Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động HC-SR04: Sóng Siêu Âm 40kHz, Thời Gian Bay & Đo Khoảng Cách Chính Xác
  32. 31Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động MQ-2: Semiconductor SnO₂, Đường Cong Nhạy Khí & Đo Nồng Độ Gas
  33. 32Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Rain Sensor FC-37: Phát Hiện Mưa, LM393 Comparator & Ứng Dụng Thực Tế
  34. 33Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Soil Moisture Sensor: Điện Trở Đất, Hiệu Chỉnh & Tưới Cây Tự Động
  35. 34Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động BMP280: Cảm Biến Áp Suất & Nhiệt Độ Chính Xác Của Bosch
  36. 35Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động DS18B20: Cảm Biến Nhiệt Độ 1-Wire Chống Nước
  37. 36Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động DHT22 (AM2302): Độ Chính Xác Cao, Dải Đo Rộng
  38. 37Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động DHT11: Cảm Biến Nhiệt Độ & Độ Ẩm Phổ Biến Nhất
Cảm biến

Series 37 Module Cảm Biến – Nguyên Lý MPU-6050: IMU 6 Trục, MEMS Gia Tốc + Con Quay, Complementary Filter & Góc Nghiêng

Th7 2026
Series 37 Module Cảm Biến – Nguyên Lý MPU-6050: IMU 6 Trục, MEMS Gia Tốc + Con Quay, Complementary Filter & Góc Nghiêng

MPU-6050 là IMU (Inertial Measurement Unit) phổ biến nhất trong thế giới maker: 1 chip tích hợp 3 trục gia tốc kế + 3 trục con quay hồi chuyển, giao tiếp I2C. Bài này giải thích từng cảm biến hoạt động ra sao, tại sao không thể dùng riêng từng loại để đo góc, và complementary filter là giải pháp thực tế nhất.

Nguyên Lý Hoạt Động

1. MEMS Accelerometer — Đo Gia Tốc Tuyến Tính

MPU-6050 dùng MEMS (Micro-Electro-Mechanical System) capacitive accelerometer:

Nguyên lý MEMS accelerometer 1 trục (nhìn từ mặt cắt):

Substrate (cố định)
    │
    │   [Cấu trúc con lắc di động] ←── khối mass
    │      │      │      │
    │   ┃──┃   ┃──┃   ┃──┃
    │   C1          C2      ← tụ điện (fingers)
    │   ┃──┃   ┃──┃   ┃──┃
    │
    └────────── Substrate cố định

Khi không có gia tốc: C1 = C2 → output = 0
Khi gia tốc sang phải: khối mass lệch → C1 ≠ C2 → ΔC → điện áp

Tác dụng trọng lực: Khi nằm phẳng, trục Z đọc +1g (trọng lực kéo xuống = gia tốc đo ngược chiều).

  • Phẳng trên bàn: ax=0g, ay=0g, az=+1g
  • Nghiêng 90° sang phải: ax=+1g, ay=0g, az≈0g

2. MEMS Gyroscope — Đo Vận Tốc Góc

Gyroscope MEMS dùng hiệu ứng Coriolis:

Hiệu ứng Coriolis trong MEMS:
- Cấu trúc rung (vibrating mass) dao động theo trục X
- Khi quay quanh trục Z: lực Coriolis theo trục Y
- F_Coriolis = 2m(ω × v)
  ω = vận tốc góc (rad/s) — cần đo
  v = vận tốc dao động (biết)
- Đo lực Coriolis → suy ra ω

Output: Vận tốc góc (°/s). Tích phân theo thời gian → góc quay tuyệt đối. Nhưng tích phân sai số → drift tích lũy theo thời gian.

3. Vấn Đề Đo Góc — Tại Sao Cần Kết Hợp

AccelerometerGyroscope
Đo góc từVector trọng lực (arctan)Tích phân vận tốc góc
Chính xác lâu dàiCó (trọng lực không đổi)Không (drift theo thời gian)
Nhiễu ngắn hạnNhiều (rung, va chạm)Ít (ổn định)
Khi di chuyển nhanhSai (gia tốc tuyến tính + trọng lực)Đúng

Giải pháp — Complementary Filter:

angle = α × (angle + gyro_rate × dt) + (1-α) × accel_angle

α = 0.98 (98% tin vào gyro ngắn hạn)
(1-α) = 0.02 (2% hiệu chỉnh drift từ accelerometer)
dt = thời gian giữa 2 lần đọc (giây)

4. I2C Address và DMP

Địa chỉ I2C:

  • AD0 = LOW (nối GND): 0x68
  • AD0 = HIGH (nối VCC): 0x69
  • Có thể dùng 2 MPU-6050 trên cùng bus với 2 địa chỉ khác nhau

DMP (Digital Motion Processor):

  • IC bên trong MPU-6050 có processor nhỏ
  • Tính toán quaternion/góc trực tiếp trên chip
  • Giảm tải MCU, nhưng cần firmware phức tạp (thư viện jeff-rowberg/i2cdevlib)

Thông Số Kỹ Thuật

Thông sốGiá trị
Điện áp hoạt động3.3V (tối đa 3.6V — KHÔNG 5V!)
Dòng tiêu thụ3.9mA (active)
Giao tiếpI2C (400kHz max)
ADC16-bit per channel
Gyro range±250 / ±500 / ±1000 / ±2000 °/s
Accel range±2g / ±4g / ±8g / ±16g
Gyro sensitivity131 LSB/(°/s) tại ±250
Accel sensitivity16384 LSB/g tại ±2g
Nhiệt độ cảm biến-40°C đến 85°C

Sơ Đồ Chân (Pinout)

MPU-6050 Module:

┌──────────────────────────────────────┐
  [MPU-6050 IC]                       
└──────────────────────────────────────┘
  VCC  GND  SCL  SDA  XDA  XCL  AD0  INT
ChânMô tả
VCC3.3V — KHÔNG cấp 5V!
GNDMass
SCLI2C Clock
SDAI2C Data
AD0Địa chỉ: GND=0x68, VCC=0x69
INTInterrupt output (tùy chọn)
XDA, XCLI2C phụ cho external sensor (ít dùng)

Kết Nối Phần Cứng

MPU-6050 với ESP32 DevKit V1

ESP32 DevKit V1           MPU-6050 Module
─────────────────────     ─────────────────
3V3  ─────────────────→  VCC   ← 3.3V — bắt buộc!
GND  ─────────────────→  GND
GPIO21 (SDA) ──────────→  SDA
GPIO22 (SCL) ──────────→  SCL
GND  ─────────────────→  AD0   ← Địa chỉ 0x68

I2C mặc định của ESP32: SDA=GPIO21, SCL=GPIO22.

MPU-6050 với Arduino Uno

Arduino Uno               MPU-6050 Module
─────────────────────     ─────────────────
3.3V ─────────────────→  VCC   ← 3.3V pin trên Uno (max 50mA — đủ)
GND  ─────────────────→  GND
A4 (SDA) ──────────────→  SDA
A5 (SCL) ──────────────→  SCL
GND  ─────────────────→  AD0

⚠️ Quan trọng: Chỉ nối VCC vào 3.3V pin. Arduino Uno có 3.3V regulator nhỏ nhưng đủ cấp cho MPU-6050 (3.9mA). Không nối 5V — sẽ hỏng chip.

I2C level: Arduino Uno chạy I2C ở 5V, MPU-6050 SDA/SCL tolerance đến 5V → an toàn trong trường hợp này.

Cài Đặt Thư Viện

Arduino IDE → Library Manager:

  • Tìm “MPU6050” by Electronic Cats → Install
  • Hoặc “MPU6050_tockn” (đơn giản hơn)
  • Cài thêm “Wire” (thường đã có)

Code Arduino IDE

Code Đọc Raw Data Cơ Bản — Arduino Uno

/*
 * MPU-6050 — Đọc raw accelerometer và gyroscope
 * Board: Arduino Uno
 * Kết nối: VCC→3.3V, GND→GND, SDA→A4, SCL→A5, AD0→GND
 *
 * Library: MPU6050 by Electronic Cats (Library Manager)
 */

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

void setup() {
  Serial.begin(9600);
  Wire.begin();        // Khởi động I2C
  mpu.initialize();    // Khởi động MPU-6050

  // Kiểm tra kết nối
  if (mpu.testConnection()) {
    Serial.println("MPU-6050 kết nối OK (0x68)");
  } else {
    Serial.println("MPU-6050 KHÔNG kết nối được!");
    while (true); // Dừng nếu lỗi
  }

  // Cấu hình range
  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);    // ±2g
  mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_250);    // ±250°/s

  Serial.println("ax(g)\tay(g)\taz(g)\tgx(°/s)\tgy(°/s)\tgz(°/s)");
}

void loop() {
  int16_t ax_raw, ay_raw, az_raw;
  int16_t gx_raw, gy_raw, gz_raw;

  // Đọc raw data (16-bit signed integer)
  mpu.getMotion6(&ax_raw, &ay_raw, &az_raw, &gx_raw, &gy_raw, &gz_raw);

  // Chuyển đổi về đơn vị thực tế
  // Accel: 16384 LSB/g (ở ±2g range)
  float ax = ax_raw / 16384.0;
  float ay = ay_raw / 16384.0;
  float az = az_raw / 16384.0;

  // Gyro: 131 LSB/(°/s) (ở ±250°/s range)
  float gx = gx_raw / 131.0;
  float gy = gy_raw / 131.0;
  float gz = gz_raw / 131.0;

  Serial.print(ax, 3); Serial.print("\t");
  Serial.print(ay, 3); Serial.print("\t");
  Serial.print(az, 3); Serial.print("\t");
  Serial.print(gx, 2); Serial.print("\t");
  Serial.print(gy, 2); Serial.print("\t");
  Serial.println(gz, 2);

  delay(200);
}

Code Tính Góc Nghiêng Từ Accelerometer — Arduino Uno

/*
 * MPU-6050 — Tính pitch và roll từ accelerometer
 * Pitch (xoay quanh trục Y), Roll (xoay quanh trục X)
 * Board: Arduino Uno
 * Kết nối: VCC→3.3V, GND→GND, SDA→A4, SCL→A5
 *
 * Giới hạn: chỉ chính xác khi gần tĩnh (không rung, không chuyển động)
 */

#include <Wire.h>
#include <MPU6050.h>
#include <math.h>  // Cho atan2() và sqrt()

MPU6050 mpu;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();
  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
  Serial.println("Pitch (°)\tRoll (°)");
}

void loop() {
  int16_t ax_raw, ay_raw, az_raw;
  int16_t gx_dummy, gy_dummy, gz_dummy;

  mpu.getMotion6(&ax_raw, &ay_raw, &az_raw, &gx_dummy, &gy_dummy, &gz_dummy);

  float ax = ax_raw / 16384.0; // g
  float ay = ay_raw / 16384.0;
  float az = az_raw / 16384.0;

  // Tính góc nghiêng từ vector trọng lực:
  // Pitch: quay quanh trục Y (nghiêng trước/sau)
  // Roll: quay quanh trục X (nghiêng trái/phải)
  float pitch = atan2(-ax, sqrt(ay * ay + az * az)) * 180.0 / PI;
  float roll  = atan2(ay, az) * 180.0 / PI;

  Serial.print(pitch, 2); Serial.print("°\t\t");
  Serial.print(roll, 2);  Serial.println("°");

  delay(100);
}

Code Complementary Filter — Ổn Định Góc (Arduino Uno)

/*
 * MPU-6050 — Complementary Filter: kết hợp accel + gyro
 * Kết quả: góc ổn định, không bị rung (như accel) và không bị drift (như gyro)
 * Board: Arduino Uno
 * Kết nối: VCC→3.3V, GND→GND, SDA→A4, SCL→A5
 */

#include <Wire.h>
#include <MPU6050.h>
#include <math.h>

MPU6050 mpu;

const float ALPHA = 0.98;    // 98% gyro, 2% accel
float pitch = 0.0;           // Góc pitch tổng hợp (°)
float roll  = 0.0;           // Góc roll tổng hợp (°)
unsigned long lastTime = 0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();
  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
  mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_250);

  // Calibrate bằng cách đọc vài giây tĩnh
  // (Bỏ qua trong ví dụ này — gyro offset cần ~50 mẫu trung bình)

  lastTime = millis();
  Serial.println("Pitch(°)\tRoll(°)");
}

void loop() {
  unsigned long now = millis();
  float dt = (now - lastTime) / 1000.0; // Thời gian giữa 2 lần (giây)
  lastTime = now;

  int16_t ax_r, ay_r, az_r, gx_r, gy_r, gz_r;
  mpu.getMotion6(&ax_r, &ay_r, &az_r, &gx_r, &gy_r, &gz_r);

  // Chuyển đổi
  float ax = ax_r / 16384.0;
  float ay = ay_r / 16384.0;
  float az = az_r / 16384.0;
  float gx = gx_r / 131.0;   // °/s (vận tốc góc trục X)
  float gy = gy_r / 131.0;   // °/s (vận tốc góc trục Y)

  // Góc từ accelerometer (chính xác dài hạn, nhiễu ngắn hạn)
  float accel_pitch = atan2(-ax, sqrt(ay * ay + az * az)) * 180.0 / PI;
  float accel_roll  = atan2(ay, az) * 180.0 / PI;

  // Complementary Filter:
  // pitch += gy * dt  ← gyro cập nhật (chính xác ngắn hạn)
  // Kết hợp với accel_pitch (hiệu chỉnh drift dài hạn)
  pitch = ALPHA * (pitch + gy * dt) + (1.0 - ALPHA) * accel_pitch;
  roll  = ALPHA * (roll  + gx * dt) + (1.0 - ALPHA) * accel_roll;

  Serial.print(pitch, 2); Serial.print("°\t\t");
  Serial.print(roll, 2);  Serial.println("°");

  delay(10); // 100Hz sampling
}

Code ESP32 — MPU-6050 với Wire.h

/*
 * MPU-6050 — ESP32, đọc gyro + accel + nhiệt độ
 * Board: ESP32 DevKit V1
 * Kết nối: VCC→3V3, GND→GND, SDA→GPIO21, SCL→GPIO22
 */

#include <Wire.h>
#include <MPU6050.h>

MPU6050 mpu;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22); // SDA=GPIO21, SCL=GPIO22 (ESP32 default)
  mpu.initialize();

  if (mpu.testConnection()) {
    Serial.println("MPU-6050 OK");
  } else {
    Serial.println("MPU-6050 KHÔNG TÌM THẤY!");
    while (true);
  }

  mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
  mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_250);
  Serial.println("Đọc IMU 6 trục...");
}

void loop() {
  int16_t ax, ay, az, gx, gy, gz;
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  int16_t tempRaw = mpu.getTemperature();

  // Chuyển đổi
  float accelX = ax / 16384.0; float accelY = ay / 16384.0; float accelZ = az / 16384.0;
  float gyroX  = gx / 131.0;   float gyroY  = gy / 131.0;   float gyroZ  = gz / 131.0;
  float tempC  = tempRaw / 340.0 + 36.53; // Theo datasheet MPU-6050

  Serial.printf("Accel: X=%.2fg Y=%.2fg Z=%.2fg\n", accelX, accelY, accelZ);
  Serial.printf("Gyro:  X=%.1f°/s Y=%.1f°/s Z=%.1f°/s\n", gyroX, gyroY, gyroZ);
  Serial.printf("Temp: %.1f°C\n\n", tempC);

  delay(500);
}

Kết Quả Mong Đợi

MPU-6050 kết nối OK (0x68)
ax(g)   ay(g)   az(g)   gx(°/s) gy(°/s) gz(°/s)
0.003   -0.012  1.001   0.31    -0.15   0.08
0.002   -0.011  0.999   0.29    -0.12   0.10

Ứng Dụng Thực Tế

Ứng dụngChi tiết
Robot tự cân bằngPID điều khiển motor dựa trên pitch angle
Gimbal cameraBù rung bằng cách phản chiều góc đo
Phát hiện ngãTích phân gia tốc lớn đột ngột → alert
Điều khiển cử chỉNghiêng tay phải → rẽ phải
Drone flight controller6-DOF cho attitude estimation

Lưu Ý Khi Sử Dụng

1. VCC phải là 3.3V — không có ngoại lệ

MPU-6050 VCC max là 3.6V. 5V sẽ phá hủy chip ngay lập tức và vĩnh viễn.

2. Gyro drift — calibrate offset

Khi đặt yên, gyro không đọc 0 mà có offset nhỏ (~0.1-0.5°/s). Tích phân offset này → drift góc theo thời gian. Calibrate: đọc 100-500 mẫu khi yên → lấy trung bình → đó là offset → trừ ra khi đọc.

// Calibrate gyro offset (giữ module yên trong 2-3 giây)
float gx_offset = 0, gy_offset = 0, gz_offset = 0;
for (int i = 0; i < 200; i++) {
  int16_t ax, ay, az, gx, gy, gz;
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  gx_offset += gx / 131.0;
  gy_offset += gy / 131.0;
  gz_offset += gz / 131.0;
  delay(10);
}
gx_offset /= 200; gy_offset /= 200; gz_offset /= 200;

3. Complementary filter vs Kalman filter

Complementary filter: đơn giản, phù hợp hobby. Kalman filter: tối ưu toán học, phức tạp hơn, dùng trong nghiên cứu. Cho hầu hết ứng dụng maker: complementary filter đủ.

4. dt (delta time) phải chính xác

Gyro tích phân cần dt chính xác. Dùng millis() không đủ tốt vì resolution 1ms. micros() tốt hơn cho sampling > 100Hz.

Bài tiếp theo: