MicroPython và ESP32 trong Thí nghiệm Vật lý
ESP32 và MicroPython vật lý
Biến ESP32 thành Công cụ Thí nghiệm
ESP32 không chỉ là một vi điều khiển để nhấp nháy đèn LED. Với bộ xử lý lõi kép mạnh mẽ và các ngoại vi tích hợp, nó là một công cụ thu thập dữ liệu di động, chi phí thấp cho các thí nghiệm vật lý. Thay vì các thiết bị phòng thí nghiệm cồng kềnh, bạn có thể sử dụng một bo mạch nhỏ gọn để đo lường mọi thứ, từ chuyển động của con lắc đến sự thay đổi nhiệt độ trong phản ứng hóa học.
Để làm được điều này, chúng ta cần khai thác phần cứng của nó một cách hiệu quả. Trọng tâm của chúng ta không phải là học lại cách viết vòng lặp for, mà là hiểu cách cấu hình các chân của ESP32 để giao tiếp với cảm biến, đọc dữ liệu tương tự một cách chính xác và sử dụng các giao thức tốc độ cao để thu thập dữ liệu cho các phân tích vật lý.
Sơ đồ chân - Giao diện với Thế giới Thực
Mỗi chân trên bo mạch ESP32 đều có một hoặc nhiều chức năng cụ thể. Việc hiểu sơ đồ chân (pinout) là bước đầu tiên để kết nối cảm biến và các thành phần khác. Sơ đồ này khác nhau một chút giữa các phiên bản bo mạch (như DOIT DevKit v1, NodeMCU-32S), vì vậy hãy luôn kiểm tra tài liệu cho bo mạch cụ thể của bạn.
Đối với các ứng dụng đo lường vật lý, chúng ta quan tâm chủ yếu đến các loại chân sau:
| Loại Chân | Chức năng Chính | Ví dụ |
|---|---|---|
| Nguồn (Power) | Cung cấp điện áp ổn định cho cảm biến | 3V3 (3.3V), GND (Nối đất) |
| ADC | Đọc điện áp tương tự từ cảm biến | GPIO32-39 (ADC1), GPIO0, 2, 4, 12-15 (ADC2) |
| I2C | Giao tiếp hai dây với nhiều thiết bị | GPIO21 (SDA), GPIO22 (SCL) |
| SPI | Giao tiếp bốn dây tốc độ cao | GPIO23 (MOSI), GPIO19 (MISO), GPIO18 (SCLK) |
Việc kết nối không đúng chân có thể không chỉ làm mạch không hoạt động mà còn có nguy cơ làm hỏng cả ESP32 và cảm biến. Luôn kiểm tra kỹ điện áp hoạt động của cảm biến. Hầu hết các cảm biến hiện đại hoạt động ở 3.3V, tương thích hoàn hảo với chân 3V3 của ESP32.
Chuyển đổi Tương tự-Số (ADC)
Nhiều hiện tượng vật lý được biểu diễn bằng các đại lượng liên tục, như nhiệt độ, áp suất hoặc vị trí. Cảm biến tương tự (analog) chuyển các đại lượng này thành một tín hiệu điện áp thay đổi tương ứng. Bộ chuyển đổi tương tự-số (ADC) của ESP32 sẽ đo điện áp này và chuyển nó thành một con số mà bộ vi xử lý có thể hiểu được.
ESP32 có , nghĩa là nó có thể phân biệt $2^{12}$ hay 4096 mức điện áp khác nhau. Điều này mang lại độ chính xác cao hơn nhiều so với ADC 10-bit (1024 mức) trên các bo mạch Arduino Uno cũ hơn. Tuy nhiên, độ phân giải cao cũng đi kèm với thách thức: nhiễu tín hiệu.
Nhiễu là kẻ thù của các phép đo chính xác. Nó có thể đến từ nguồn điện không ổn định, nhiễu điện từ từ các thiết bị khác, hoặc ngay cả từ chính các thành phần bên trong ESP32. Để giảm nhiễu, có thể sử dụng tụ điện lọc trên đường cấp nguồn cho cảm biến hoặc áp dụng các kỹ thuật phần mềm như lấy trung bình nhiều lần đọc để làm mịn kết quả.
Giao thức Giao tiếp
Không phải cảm biến nào cũng là tương tự. Nhiều cảm biến hiện đại có bộ vi xử lý riêng và giao tiếp kỹ thuật số để gửi dữ liệu phức tạp hơn, ví dụ như một cảm biến IMU (Inertial Measurement Unit) có thể cung cấp dữ liệu gia tốc và vận tốc góc trên ba trục cùng một lúc. Để nói chuyện với các cảm biến này, ESP32 sử dụng các giao thức giao tiếp tiêu chuẩn.
I2C
noun
Inter-Integrated Circuit, một bus giao tiếp nối tiếp chỉ sử dụng hai dây: một dây dữ liệu (SDA) và một dây đồng hồ (SCL). Nó cho phép một thiết bị chủ (master) giao tiếp với nhiều thiết bị tớ (slave) trên cùng một bus.
I2C rất tiện lợi vì nó tiết kiệm chân và cho phép bạn kết nối hàng chục cảm biến chỉ với hai chân GPIO. Mỗi thiết bị trên bus I2C có một địa chỉ duy nhất, giống như số nhà trên một con đường. ESP32 sẽ gọi địa chỉ này để bắt đầu cuộc trò chuyện. Nhược điểm của nó là tốc độ tương đối chậm, không phù hợp cho các ứng dụng cần lấy mẫu dữ liệu ở tần số hàng nghìn lần mỗi giây.
Khi tốc độ là ưu tiên hàng đầu, chúng ta sử dụng (Serial Peripheral Interface).
Thiết lập MicroPython
Để khai thác sức mạnh này, chúng ta sẽ sử dụng MicroPython. Nó cung cấp một môi trường tương tác giúp việc thử nghiệm và thu thập dữ liệu nhanh chóng hơn nhiều so với chu trình biên dịch-tải lên truyền thống của C/C++. Các thư viện machine.ADC, machine.I2C và machine.SPI cung cấp quyền truy cập trực tiếp vào phần cứng mà chúng ta vừa thảo luận.
# Ví dụ khởi tạo các đối tượng phần cứng trong MicroPython
from machine import Pin, ADC, I2C, SPI
# Thiết lập chân ADC trên GPIO 34
adc = ADC(Pin(34))
adc.atten(ADC.ATTN_11DB) # Đặt dải đo đầy đủ (0-3.3V)
# Thiết lập bus I2C trên các chân mặc định
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000) # 400kHz
# Thiết lập bus SPI
# VSPI: sck=18, mosi=23, miso=19
spi = SPI(2, baudrate=10000000, polarity=0, phase=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
Tối ưu hóa tốc độ thu thập dữ liệu trong MicroPython đòi hỏi sự chú ý đến hiệu quả của mã. Tránh các phép tính phức tạp hoặc phân bổ bộ nhớ bên trong các vòng lặp thu thập dữ liệu. Sử dụng mảng (array) hoặc bytearray đã được cấp phát trước để lưu trữ dữ liệu có thể giảm đáng kể độ trễ và jitter, đảm bảo tần số lấy mẫu nhất quán, điều cực kỳ quan trọng cho các phân tích như Phép biến đổi Fourier nhanh (FFT).
Đâu là độ phân giải của Bộ chuyển đổi tương tự-số (ADC) trên ESP32?
Trong trường hợp nào bạn nên ưu tiên sử dụng giao thức I2C thay vì SPI để kết nối cảm biến?
Hiểu rõ về phần cứng là nền tảng. Từ đây, chúng ta có thể bắt đầu kết nối các cảm biến thực tế và viết mã để thu thập dữ liệu vật lý một cách chính xác và hiệu quả.

