'''
Bắt đầu với MicroPython trên ESP32: Điều khiển LED và Nút nhấn với Wokwi
Tài liệu này sẽ hướng dẫn bạn cách bắt đầu với MicroPython trên trình giả lập ESP32 của Wokwi. Chúng ta sẽ không cần phần cứng vật lý, giúp việc học và thử nghiệm trở nên vô cùng tiện lợi. Chúng ta sẽ tìm hiểu cách thiết lập một dự án, điều khiển một đèn LED, đọc trạng thái từ một nút nhấn và in thông tin ra màn hình giao tiếp (Serial Monitor).
MicroPython là gì?
MicroPython là phiên bản triển khai lại của Python 3, được tối ưu hóa cho vi điều khiển và các hệ thống nhúng. Nếu bạn đã biết lập trình Python, bạn gần như đã sẵn sàng để làm việc với MicroPython. Sự khác biệt chính là MicroPython được thiết kế để hoạt động trong môi trường có tài nguyên hạn chế, vì vậy nó chỉ bao gồm một phần nhỏ của thư viện chuẩn Python nhưng được bổ sung các mô-đun để tương tác trực tiếp với phần cứng như các chân GPIO.
Tại sao lại dùng Wokwi?
Wokwi là một trình giả lập trực tuyến mạnh mẽ cho các dự án điện tử.[1] Thay vì phải mua bo mạch ESP32, dây cắm, và cài đặt driver phức tạp, bạn có thể:
Bắt đầu ngay lập tức: Chỉ cần một trình duyệt web.
Không cần phần cứng: Giảm chi phí và rào cản ban đầu.
Mô phỏng chính xác: Wokwi mô phỏng hoạt động của ESP32 và các linh kiện đi kèm một cách trực quan.
Dễ dàng chia sẻ: Bạn có thể chia sẻ toàn bộ dự án của mình chỉ với một đường link.
Mục tiêu
Trong bài hướng dẫn này, chúng ta sẽ xây dựng một mạch đơn giản trên Wokwi gồm:
Một bo mạch ESP32.
Một đèn LED.
Một nút nhấn.
Chương trình MicroPython của chúng ta sẽ thực hiện chức năng: Khi nút nhấn được nhấn, đèn LED sẽ sáng. Khi nút nhấn được thả ra, đèn LED sẽ tắt. Trạng thái của nút nhấn sẽ được in ra màn hình Serial Monitor.
Bắt đầu với Wokwi
Bước 1: Tạo một dự án MicroPython trên ESP32 mới
Truy cập vào trang Wokwi.
Tạo một dự án mới bằng cách chọn MicroPython on ESP32.[2]
Bạn sẽ thấy một giao diện gồm 3 phần chính:
Cửa sổ soạn thảo mã (bên trái): Nơi bạn viết mã trong tệp main.py.
Cửa sổ sơ đồ mạch (bên phải): Nơi bạn thêm và kết nối các linh kiện.
Màn hình Serial Monitor (phía dưới): Nơi hiển thị kết quả từ lệnh print() và thông tin từ REPL.
Bước 2: Thêm các linh kiện vào sơ đồ
Trong cửa sổ sơ đồ mạch, bạn sẽ thấy bo mạch ESP32 đã có sẵn.
Nhấn vào nút dấu cộng màu xanh (+) để thêm linh kiện mới.
Chọn "LED" và "Pushbutton".[3] Wokwi cũng sẽ tự động thêm một điện trở cho LED.
Kết nối các linh kiện như sau:
LED:
Nối chân dương (anode, chân dài hơn) của LED vào chân GPIO 15 của ESP32.
Nối chân âm (cathode, chân ngắn hơn) của LED qua điện trở rồi nối xuống đất (GND).
Nút nhấn (Pushbutton):
Nối một chân của nút nhấn vào chân GPIO 4 của ESP32.
Nối chân còn lại của nút nhấn xuống đất (GND).
Sơ đồ mạch của bạn sẽ trông tương tự như thế này:
Lập trình với MicroPython
Bây giờ, hãy chuyển sang cửa sổ soạn thảo mã và viết chương trình cho tệp main.py.
'''
# --- KHAI BÁO THƯ VIỆN ---
# Nhập lớp 'Pin' từ thư viện 'machine' để điều khiển các chân GPIO (General Purpose Input/Output).
from machine import Pin
# Nhập hàm 'sleep' từ thư viện 'time' để tạo độ trễ cho chương trình.
from time import sleep
# --- KHAI BÁO CÁC HẰNG SỐ VÀ BIẾN TOÀN CỤC ---
# Định nghĩa chân GPIO sẽ kết nối với nút nhấn.
buttonPin = 25
# Định nghĩa chân GPIO sẽ kết nối với đèn LED.
LEDPin = 26
# Biến lưu trữ trạng thái hiện tại của nút nhấn (0 là nhấn, 1 là thả).
# Khởi tạo giá trị ban đầu là 0, sẽ được cập nhật ngay trong vòng lặp.
button_state = 0
# Biến lưu trữ trạng thái của đèn LED (0 là tắt, 1 là bật).
# Khởi tạo giá trị ban đầu là tắt.
led_state = 0
# --- CẤU HÌNH PHẦN CỨNG (GPIO) ---
# Tạo một đối tượng Pin cho đèn LED, cấu hình chân 'LEDPin' (26) làm đầu ra (OUTPUT).
led = Pin(LEDPin, Pin.OUT)
# Tạo một đối tượng Pin cho nút nhấn, cấu hình chân 'buttonPin' (25) làm đầu vào (INPUT).
# Pin.PULL_UP: Kích hoạt điện trở kéo lên nội bộ của ESP32.
# Điều này có nghĩa là:
# - Khi nút không được nhấn, chân sẽ ở mức logic CAO (giá trị là 1).
# - Khi nút được nhấn (nối chân xuống đất), chân sẽ ở mức logic THẤP (giá trị là 0).
push_button = Pin(buttonPin, Pin.IN, Pin.PULL_UP)
# --- VÒNG LẶP CHÍNH CỦA CHƯƠNG TRÌNH ---
# Vòng lặp này sẽ chạy vô hạn sau khi các thiết lập ban đầu hoàn tất.
while True:
# Lưu lại trạng thái của nút nhấn từ vòng lặp TRƯỚC ĐÓ.
# Đây là bước quan trọng để so sánh sự thay đổi.
last_State = button_state
# Đọc và cập nhật trạng thái MỚI của nút nhấn.
button_state = push_button.value()
# Đây là logic "Phát hiện cạnh xuống" (Falling Edge Detection)
# Kiểm tra xem nút nhấn có VỪA ĐƯỢC NHẤN hay không.
# Điều kiện này chỉ đúng tại thời điểm chuyển giao:
# - button_state == 0: Nút đang được nhấn.
# - last_State == 1: Ở vòng lặp ngay trước đó, nút đang được thả.
if button_state == 0 and last_State == 1:
# Đảo ngược trạng thái của đèn LED.
# Nếu led_state đang là 0 (tắt), nó sẽ thành 1 (bật).
# Nếu led_state đang là 1 (bật), nó sẽ thành 0 (tắt).
led_state = not(led_state)
# Cập nhật trạng thái mới này ra đèn LED thật.
led.value(led_state)
# Dừng chương trình một chút (0.1 giây).
# Việc này giúp chống dội phím (debouncing) và giảm tải cho CPU.
sleep(0.1)