Cảm biến gia tốc: cấu tạo MEMS răng lược, áp điện, cách chế tạo và đo góc nghiêng bằng ESP32
Cảm biến gia tốc hoạt động thế nào: mô hình khối lượng – lò xo, MEMS răng lược điện dung vi sai, chế tạo vi cơ bề mặt, áp điện, servo, đo góc nghiêng và đọc MPU-6050 bằng ESP32.
Cảm biến gia tốc có mặt trong hầu hết thiết bị quanh ta: điện thoại tự xoay màn hình, vòng đeo tay đếm bước, túi khí ô tô bung khi va chạm, drone giữ thăng bằng, máy giám sát rung động của động cơ và vòng bi. Bên trong một cảm biến gia tốc MEMS nhỏ hơn hạt gạo là một khối silic treo trên những lò xo mảnh hơn sợi tóc. Bài viết giải thích mô hình khối lượng – lò xo chung cho mọi cảm biến gia tốc, cấu tạo cảm biến MEMS kiểu răng lược, quy trình chế tạo bằng vi cơ bề mặt, cảm biến áp điện và các loại khác, cách đo góc nghiêng từ trọng trường, rồi hướng dẫn đọc MPU-6050 bằng ESP32 qua thanh ghi.
1. Nguyên lý chung: khối lượng treo trên lò xo

- Gia tốc đo bằng m/s² hoặc g (1 g = 9,80665 m/s², bằng gia tốc trọng trường tiêu chuẩn).
- Một khối thử m gắn vào vỏ cảm biến qua lò xo độ cứng k. Khi vỏ tăng tốc, khối thử "tụt lại" một đoạn x = m · a / k (định luật Newton và định luật Hooke). Đo x là biết a.
- Khi cảm biến nằm yên trên bàn, khối thử vẫn bị trọng lực kéo xuống: cảm biến đọc 1 g theo phương thẳng đứng. Đây là cơ sở để đo góc nghiêng.
- Hệ có tần số riêng f₀ = (1/2π)·√(k/m). Rung ở gần f₀ thì khối thử dao động mạnh bất thường (cộng hưởng); cảm biến chỉ đo đúng ở tần số thấp hơn nhiều so với f₀. Giảm chấn vừa phải (khoảng 0,7) cho đường đáp ứng phẳng nhất.
Các loại cảm biến gia tốc khác nhau chủ yếu ở cách đo độ dịch x (hoặc lực tác dụng lên khối thử): đo điện dung (MEMS), đo điện tích của tinh thể áp điện, đo điện trở áp trở, hoặc giữ khối thử đứng yên bằng lực điện từ rồi đo dòng điện cần thiết (servo).
2. Cảm biến gia tốc MEMS kiểu răng lược


- Khối thử: một tấm silic dày vài micromet, rộng vài trăm micromet, có hàng chục "răng" hai bên.
- Lò xo gấp: các dầm silic mảnh uốn khúc nối khối thử với các điểm neo cố định trên đế, cho khối thử dịch theo một phương.
- Răng cố định: xen kẽ với răng của khối thử, mỗi cặp là một tụ điện nhỏ. Mỗi răng của khối thử nằm giữa hai răng cố định nên tạo hai tụ C1 và C2.
- Điện dung vi sai: khi khối thử lệch, một khe hẹp lại (C tăng) và khe kia rộng ra (C giảm). Mạch đo lấy hiệu C1 − C2, nhỏ cỡ phần nghìn pF, rồi khuếch đại và chuyển đổi số. Cách đo vi sai triệt bớt ảnh hưởng nhiệt độ và nhiễu chung.
- Ba trục X, Y, Z dùng ba cấu trúc riêng (trục Z thường là tấm bập bênh lệch tâm đo khoảng cách tới đế).
3. Chế tạo bằng vi cơ bề mặt

- Lớp hy sinh: trên đế silic, phủ một lớp oxit silic. Lớp này chỉ để "đỡ" kết cấu trong lúc chế tạo và sẽ bị loại bỏ.
- Lớp kết cấu: phủ silic đa tinh thể (hoặc dùng tấm silic trên lớp cách điện) dày vài đến vài chục micromet.
- Tạo hình: quang khắc rồi khắc sâu bằng plasma để tạo khối thử, răng lược, lò xo và điểm neo.
- Giải phóng: hơi axit HF đi qua các lỗ nhỏ trên khối thử, ăn mòn lớp oxit bên dưới. Khối thử và lò xo chỉ còn bám vào đế ở các điểm neo, tự do chuyển động. Đây là bước quyết định: nếu khối thử dính xuống đế do sức căng bề mặt thì chip hỏng.
- Đóng nắp: hàn một tấm nắp silic lên trên ở cấp tấm wafer, bên trong là khí ở áp suất chọn trước để tạo giảm chấn.
- Ghép ASIC và hiệu chuẩn: cắt rời, đặt cạnh (hoặc chồng lên) chip mạch đo, đóng vỏ nhựa; đo và ghi hệ số bù điểm không, độ nhạy từng trục bằng bàn quay, bàn rung.
4. Cảm biến gia tốc áp điện và các loại khác


- Áp điện: khối thử đè lên một phần tử gốm áp điện (hoặc thạch anh), được ép trước bằng bu lông. Khi rung, lực quán tính của khối thử thay đổi và gốm sinh ra điện tích tỉ lệ với gia tốc. Rất cứng nên tần số riêng cao, đo rung tới hàng chục kHz với nhiễu rất thấp. Loại IEPE có sẵn mạch khuếch đại bên trong, nuôi bằng nguồn dòng không đổi qua chính dây tín hiệu. Không đo được gia tốc tĩnh (không đo được góc nghiêng). Bài cảm biến gia tốc áp điện RION PV-90B giải thích loại ngõ ra điện tích.
- Áp trở: các điện trở trên dầm silic treo khối thử; đo được cả gia tốc tĩnh và va đập rất lớn, dùng trong thử va chạm ô tô.
- Servo (cân bằng lực): khối thử được giữ ở giữa bằng lực điện từ; dòng điện cần dùng tỉ lệ với gia tốc. Rất chính xác, dùng trong đo nghiêng chính xác, địa chấn, dẫn đường quán tính.
5. Đo góc nghiêng bằng gia tốc trọng trường

Khi cảm biến đứng yên, gia tốc đo được chỉ là trọng trường 1 g, chia ra ba trục theo hướng của cảm biến. Nghiêng 30° quanh trục X thì trục Y đọc sin 30° = 0,5 g và trục Z đọc cos 30° ≈ 0,866 g. Từ đó: roll = atan2(ay, az), pitch = atan2(−ax, √(ay² + az²)). Cách này chỉ đúng khi cảm biến không bị rung lắc hay tăng tốc; lúc đó độ lớn √(ax² + ay² + az²) khác 1 g và góc tính ra bị sai. Thiết bị thật (drone, gimbal) kết hợp thêm con quay hồi chuyển bằng bộ lọc bù hoặc bộ lọc Kalman.
6. Thực hành: đọc MPU-6050 bằng ESP32

Linh kiện
- ESP32 DevKit V1 30 chân.
- Một module MPU-6050 (GY-521).
- Dây cắm.
Sơ đồ nối

| GY-521 | ESP32 |
|---|---|
| VCC, GND | 3V3, GND |
| SDA, SCL | GPIO21, GPIO22 |
| AD0 | Để hở hoặc GND (địa chỉ 0x68) |
Chương trình
Chương trình chỉ dùng thư viện Wire: đánh thức chip (mặc định ở chế độ ngủ), chọn thang ±2 g, rồi mỗi 200 ms đọc 8 byte từ thanh ghi 0x3B (gia tốc X, Y, Z và nhiệt độ).
/*
PYWORLD.VN - Cảm biến gia tốc MEMS MPU-6050 với ESP32: đọc thanh ghi bằng Wire, tính góc nghiêng và phát hiện rung lắc
MPU-6050 (module GY-521): VCC = 3V3, GND = GND, SDA = GPIO21, SCL = GPIO22, AD0 để hở hoặc nối GND (địa chỉ 0x68)
Thang đo ±2 g: 16384 đơn vị mỗi g; góc nghiêng tính từ hướng của gia tốc trọng trường
*/
#include <Wire.h>
#include <math.h>
#define CHAN_SDA 21
#define CHAN_SCL 22
const uint8_t DIA_CHI_MPU = 0x68;
const uint8_t TG_PWR_MGMT_1 = 0x6B; // Ghi 0 để đánh thức chip (mặc định đang ngủ)
const uint8_t TG_ACCEL_CONFIG = 0x1C; // Bit 4:3 chọn thang đo: 0 = ±2 g
const uint8_t TG_ACCEL_XOUT_H = 0x3B; // 6 byte gia tốc X, Y, Z, rồi 2 byte nhiệt độ
const float DON_VI_MOI_G = 16384.0;
const float NGUONG_RUNG_G = 0.35; // |a| lệch khỏi 1 g quá mức này: đang rung lắc hoặc va chạm
bool ghiThanhGhi(uint8_t thanhGhi, uint8_t giaTri) {
Wire.beginTransmission(DIA_CHI_MPU);
Wire.write(thanhGhi);
Wire.write(giaTri);
return Wire.endTransmission() == 0;
}
bool docGiaToc(float *ax, float *ay, float *az, float *nhietDo) {
Wire.beginTransmission(DIA_CHI_MPU);
Wire.write(TG_ACCEL_XOUT_H);
if (Wire.endTransmission(false) != 0 || Wire.requestFrom(DIA_CHI_MPU, (uint8_t)8) != 8) {
return false;
}
int16_t raw[4];
for (int i = 0; i < 4; i++) {
uint8_t cao = Wire.read(); // Byte cao trước
uint8_t thap = Wire.read();
raw[i] = (int16_t)((cao << 8) | thap);
}
*ax = raw[0] / DON_VI_MOI_G;
*ay = raw[1] / DON_VI_MOI_G;
*az = raw[2] / DON_VI_MOI_G;
*nhietDo = raw[3] / 340.0f + 36.53f; // Công thức nhiệt độ trong tài liệu thanh ghi
return true;
}
void setup() {
Serial.begin(115200);
Wire.begin(CHAN_SDA, CHAN_SCL, 400000);
if (!ghiThanhGhi(TG_PWR_MGMT_1, 0x00) || !ghiThanhGhi(TG_ACCEL_CONFIG, 0x00)) {
Serial.println("\nKhong thay MPU-6050 o dia chi 0x68: kiem tra day SDA, SCL va nguon");
} else {
Serial.println("\nMPU-6050: thang do +/-2 g, goc nghieng va phat hien rung");
}
}
void loop() {
float ax, ay, az, t;
if (!docGiaToc(&ax, &ay, &az, &t)) {
Serial.println("Khong doc duoc MPU-6050");
delay(1000);
return;
}
float doLon = sqrtf(ax * ax + ay * ay + az * az);
// Khi đứng yên, cảm biến chỉ chịu trọng trường: góc nghiêng suy ra từ tỉ lệ ba thành phần
float gocRoll = atan2f(ay, az) * 180.0f / PI;
float gocPitch = atan2f(-ax, sqrtf(ay * ay + az * az)) * 180.0f / PI;
const char *trangThai = fabsf(doLon - 1.0f) > NGUONG_RUNG_G ? "RUNG LAC" : "on dinh";
Serial.printf("ax %+.3f | ay %+.3f | az %+.3f g | |a| %.3f g | roll %+6.1f | pitch %+6.1f | %s\n",
ax, ay, az, doLon, gocRoll, gocPitch, trangThai);
delay(200);
}
Giải thích
- Mỗi giá trị là số nguyên có dấu 16 bit, byte cao trước. Ở thang ±2 g, 16384 đơn vị là 1 g.
- Ghi 0 vào thanh ghi 0x6B (PWR_MGMT_1) để tắt chế độ ngủ; ghi 0 vào 0x1C (ACCEL_CONFIG) để chọn ±2 g. Thang ±4, ±8, ±16 g ứng với giá trị 0x08, 0x10, 0x18 và độ nhạy 8192, 4096, 2048 đơn vị/g.
- Độ lớn gia tốc lệch khỏi 1 g quá 0,35 g thì báo "RUNG LAC".
Kết quả mong đợi

Khi đặt nằm ngang, số đọc thường lệch khỏi 0 g và 1 g vài phần trăm do sai số điểm không của từng chip. Muốn chính xác hơn, đặt cảm biến ở sáu hướng (mỗi trục hướng lên và xuống), ghi giá trị lớn nhất, nhỏ nhất của từng trục rồi tính điểm không và hệ số cho từng trục.
7. Xử lý lỗi thường gặp
| Hiện tượng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
| "Khong thay MPU-6050" | Sai địa chỉ (AD0 nối VCC là 0x69), sai chân | Chạy chương trình quét I2C |
| Mọi giá trị đều bằng 0 | Chip vẫn đang ngủ | Kiểm tra lệnh ghi 0x6B thành công khi khởi động |
| Góc nghiêng dao động khi máy chạy | Rung từ động cơ lẫn vào | Lấy trung bình, bật bộ lọc thông thấp trong chip (thanh ghi 0x1A), gắn đệm cao su |
| Góc lệch vài độ khi nằm ngang | Sai số điểm không; module gắn không phẳng | Hiệu chuẩn sáu hướng, trừ góc lệch lắp đặt |
| Số đọc kẹt ở ±2 g khi va đập | Vượt thang đo | Chọn thang ±8 g hoặc ±16 g |
8. Xem thêm
- Cảm biến gia tốc áp điện RION PV-90B (ngõ ra điện tích).
- I2C là gì: cách đọc ghi thanh ghi trên ESP32.
- Quét địa chỉ I2C và nối nhiều thiết bị.
- Các bài khác trong loạt: cảm biến áp suất (cũng là MEMS), cảm biến từ trường, cảm biến biến dạng.
Xem thêm