Máy hiện sóng mini tự chế bằng Arduino
Máy hiện sóng (oscilloscope) thật giá vài triệu đến vài chục triệu đồng, nhưng phần lớn công việc debug mạch analog cơ bản — xem dạng sóng PWM, kiểm tra tín hiệu cảm biến có nhiễu hay không, đo tần số tín hiệu chậm — hoàn toàn có thể làm bằng một chiếc Arduino và một chương trình vẽ đồ thị trên máy tính. Đây không phải máy hiện sóng chuyên nghiệp (tốc độ lấy mẫu của Arduino chỉ vài chục kHz), nhưng là công cụ học tập và debug rất hữu ích, gần như miễn phí nếu bạn đã có sẵn Arduino.
Nguyên lý hoạt động
- Arduino liên tục đọc điện áp analog qua ADC 10-bit (giá trị 0-1023, tương ứng 0-5V) ở tốc độ lấy mẫu cao nhất có thể.
- Mỗi giá trị đọc được gửi ngay qua cổng Serial (USB) về máy tính, đóng gói ở dạng nhị phân để tối đa tốc độ truyền.
- Một script Python trên máy tính đọc dữ liệu từ cổng Serial liên tục, giải mã và vẽ đồ thị điện áp theo thời gian bằng thư viện
matplotlib, cập nhật theo thời gian thực giống màn hình oscilloscope thật. - Vì tốc độ Serial giới hạn (~115200 baud), tần số lấy mẫu thực tế đạt được khoảng 5,000-10,000 mẫu/giây — đủ để quan sát tín hiệu tần số thấp (PWM vài trăm Hz - vài kHz, tín hiệu cảm biến, âm thanh tần số thấp) nhưng không thể bắt được tín hiệu MHz như oscilloscope chuyên dụng.
Linh kiện
- Arduino Uno hoặc Nano (bo mạch càng nhanh xử lý ADC như những dòng dựa trên SAMD/ARM sẽ lấy mẫu nhanh hơn)
- Cáp USB kết nối Arduino với máy tính
- Máy tính có cài Python 3, thư viện
pyserialvàmatplotlib - Dây test hoặc que đo để nối tín hiệu cần quan sát vào chân A0
- (Khuyến nghị) Mạch phân áp hoặc diode zener bảo vệ nếu tín hiệu đo có thể vượt quá 5V, tránh làm hỏng chân ADC
Code mẫu
Firmware Arduino, lấy mẫu liên tục và gửi qua Serial ở dạng nhị phân (nhanh hơn gửi text):
const int SIGNAL_PIN = A0;
void setup() {
Serial.begin(115200);
// Tang toc ADC bang cach giam prescaler (mac dinh 128 -> 16, doc nhanh hon nhung kem chinh xac hon mot chut)
ADCSRA = (ADCSRA & 0xF8) | 0x04;
}
void loop() {
int value = analogRead(SIGNAL_PIN); // 0-1023
byte low = value & 0xFF;
byte high = (value >> 8) & 0xFF;
Serial.write(high);
Serial.write(low);
}
Script Python đọc dữ liệu và vẽ đồ thị theo thời gian thực:
import serial
import matplotlib.pyplot as plt
from collections import deque
PORT = "COM3" # doi thanh cong cua ban, vi du /dev/ttyUSB0 tren Linux
BAUD = 115200
WINDOW = 500 # so mau hien thi tren do thi
ser = serial.Serial(PORT, BAUD, timeout=1)
data = deque([0] * WINDOW, maxlen=WINDOW)
plt.ion()
fig, ax = plt.subplots()
line, = ax.plot(data)
ax.set_ylim(0, 1023)
ax.set_ylabel("Gia tri ADC (0-1023)")
ax.set_xlabel("Mau")
while True:
raw = ser.read(2)
if len(raw) < 2:
continue
value = (raw[0] << 8) | raw[1]
data.append(value)
line.set_ydata(data)
fig.canvas.draw()
fig.canvas.flush_events()
Những lỗi thường gặp
- Đo tín hiệu vượt quá 0-5V (hoặc 0-3.3V với board 3.3V) làm hỏng chân ADC — luôn dùng mạch phân áp hoặc bộ suy hao để đưa tín hiệu về đúng dải điện áp Arduino chấp nhận trước khi đo.
- Gửi dữ liệu dạng text (
Serial.println) thay vì nhị phân làm giảm tốc độ lấy mẫu đáng kể vì mỗi số cần nhiều byte ASCII — luôn dùngSerial.write()với dữ liệu nhị phân khi cần tốc độ cao. - Không có GND chung giữa điểm đo và Arduino khiến phép đo bị lệch hoặc nhiễu hoàn toàn — luôn nối GND trước khi nối dây tín hiệu.
- Kỳ vọng bắt được tín hiệu tần số cao (MHz) — ADC của Arduino chỉ lấy mẫu vài chục kHz tối đa, không phù hợp để xem tín hiệu số tốc độ cao như I2C hay SPI.
Mở rộng
Thêm chức năng trigger (chỉ bắt đầu vẽ khi tín hiệu vượt một ngưỡng, giống oscilloscope thật) để quan sát tín hiệu lặp lại ổn định hơn, dùng ESP32 với ADC nhanh hơn và gửi dữ liệu qua WiFi thay vì Serial để tự do di chuyển, hoặc kết hợp với dự án dashboard giám sát cảm biến bằng Grafana để lưu trữ và xem lại dạng sóng theo thời gian.
Bình luận