</>CoderDIY
← Quay lại danh sách
Bài viết

Máy hiện sóng mini tự chế bằng Arduino

Tác giả: CoderDIY··Đọc bằng tiếng Anh
📈

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

  1. 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ể.
  2. 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.
  3. 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.
  4. 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.
<rect x="10" y="20" width="140" height="60" rx="10" class="box" />
<text x="80" y="45" text-anchor="middle" class="label">Đọc ADC (A0)</text>
<text x="80" y="62" text-anchor="middle" class="label">liên tục</text>

<rect x="170" y="20" width="140" height="60" rx="10" class="box" />
<text x="240" y="45" text-anchor="middle" class="label">Gửi Serial</text>
<text x="240" y="62" text-anchor="middle" class="label">(nhị phân, 115200 baud)</text>

<rect x="330" y="20" width="140" height="60" rx="10" class="box" />
<text x="400" y="45" text-anchor="middle" class="label">Python đọc</text>
<text x="400" y="62" text-anchor="middle" class="label">pyserial</text>

<rect x="490" y="20" width="140" height="60" rx="10" class="box" />
<text x="560" y="45" text-anchor="middle" class="label">Vẽ đồ thị</text>
<text x="560" y="62" text-anchor="middle" class="label">matplotlib (live)</text>

<line x1="150" y1="50" x2="170" y2="50" class="arrow" />
<line x1="310" y1="50" x2="330" y2="50" class="arrow" />
<line x1="470" y1="50" x2="490" y2="50" class="arrow" />

<text x="320" y="130" text-anchor="middle" class="sublabel">Tốc độ lấy mẫu thực tế: ~5,000-10,000 mẫu/giây, giới hạn bởi băng thông Serial</text>
Dữ liệu điện áp chảy từ ADC của Arduino, qua Serial, tới script Python vẽ đồ thị theo thời gian thực.

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 pyserial và 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
<rect x="30" y="50" width="170" height="120" rx="10" class="box" />
<text x="115" y="115" text-anchor="middle" class="label">Arduino (A0)</text>

<rect x="440" y="50" width="170" height="120" rx="10" class="box" />
<text x="525" y="105" text-anchor="middle" class="label">Điểm đo tín hiệu</text>
<text x="525" y="125" text-anchor="middle" class="label">(0-5V)</text>

<line x1="200" y1="90" x2="440" y2="90" class="wire" />
<text x="320" y="82" text-anchor="middle" class="sublabel">Qua điện trở phân áp nếu &gt;5V</text>
<circle cx="200" cy="90" r="4" class="pin" />
<circle cx="440" cy="90" r="4" class="pin" />

<line x1="200" y1="140" x2="440" y2="140" class="wire" />
<text x="320" y="132" text-anchor="middle" class="sublabel">GND chung</text>
<circle cx="200" cy="140" r="4" class="pin" />
<circle cx="440" cy="140" r="4" class="pin" />
Tín hiệu cần đo nối vào A0, luôn dùng chung GND với Arduino để phép đo có điểm tham chiếu chính xác.

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ùng Serial.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.

Thẻ:#arduino#electronics#diy-tools

Bình luận