boot.py và main.py trong MicroPython: chương trình tự chạy khi cấp nguồn, chế độ an toàn, ghi lỗi

boot.py và main.py trong MicroPython: thứ tự chạy khi khởi động, nên đặt gì vào mỗi file, chế độ an toàn bằng nút BOOT, bắt lỗi và ghi lỗi ra file, watchdog, chép file bằng Thonny, mpremote.

Trong MicroPython, chương trình chỉ tự chạy khi cấp nguồn nếu được lưu trên bo với đúng tên main.py; còn boot.py chạy trước nó để cấu hình. Bài này giải thích thứ tự MicroPython chạy các file khi khởi động, nên đặt gì vào boot.py và main.py, cách thoát khi main.py làm bo bị treo, chế độ an toàn bằng nút BOOT, bắt lỗi và ghi lỗi ra file, watchdog, chép file bằng Thonny và mpremote, kèm boot.py, main.py mẫu cho ESP32.

1. MicroPython chạy những file nào khi khởi động

Năm bước: cấp nguồn hoặc bấm EN, firmware chạy _boot.py gắn hệ thống file, chạy boot.py cấu hình và Wi-Fi, chạy main.py chương trình chính, về REPL khi main.py kết thúc
Thứ tự chạy khi khởi động.
  1. Firmware chạy _boot.py nằm sẵn trong firmware: gắn hệ thống file trên flash (lần đầu thì tạo mới).
  2. Chạy boot.py nếu có trên bo.
  3. Chạy main.py nếu có trên bo.
  4. Khi main.py kết thúc (hết lệnh, hoặc lỗi, hoặc bấm Ctrl+C), bo về dấu nhắc REPL >>>.

Bấm Ctrl+D trong REPL là khởi động mềm: chạy lại boot.py và main.py nhưng không khởi động lại phần cứng. Chạy file trong Thonny bằng nút Run không cần lưu thành main.py; chỉ khi muốn bo tự chạy lúc cắm điện (không cắm máy tính) mới cần lưu thành main.py trên bo.

2. Nên đặt gì vào boot.py, gì vào main.py

Bảng: boot.py chứa Wi-Fi có giới hạn thời gian, tần số CPU, chế độ an toàn; main.py chứa chương trình chính có bắt lỗi và watchdog; module riêng chứa hàm dùng chung; file dữ liệu chứa cấu hình, nhật ký
Cách chia file hay dùng.

boot.py phải ngắn và không bao giờ chờ vô hạn: một vòng while not wlan.isconnected() không giới hạn thời gian sẽ treo bo mãi khi router tắt. main.py chứa chương trình chính và nên bắt mọi lỗi để tự phục hồi. Hàm, driver cảm biến dài đặt thành module riêng (ví dụ cam_bien.py) rồi import trong main.py: dễ thử từng phần trong REPL.

3. boot.py mẫu: chế độ an toàn và Wi-Fi có giới hạn thời gian

# PYWORLD.VN - boot.py cho ESP32 chạy MicroPython: chạy trước main.py mỗi lần khởi động, chỉ làm việc ngắn và an toàn
# PYWORLD.VN - Trong 2 giây đầu, bấm nút BOOT (GPIO0) để vào chế độ an toàn: main.py dừng ngay, REPL trống để sửa file
# PYWORLD.VN - Kết nối Wi-Fi có giới hạn thời gian; thay TEN_WIFI, MAT_KHAU_WIFI

import time
import machine
import network

TEN_WIFI = "TEN_WIFI"
MAT_KHAU_WIFI = "MAT_KHAU_WIFI"
CHO_WIFI_GIAY = 10
CHO_NUT_MS = 2000
FILE_AN_TOAN = "an_toan.co"

# Không giữ nút BOOT lúc bấm EN: ESP32 sẽ vào chế độ nạp firmware. Bấm sau khi đã khởi động.
nut_boot = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
print("boot.py: bam nut BOOT trong 2 giay de vao che do an toan")
an_toan = False
bat_dau = time.ticks_ms()
while time.ticks_diff(time.ticks_ms(), bat_dau) < CHO_NUT_MS:
    if nut_boot.value() == 0:
        an_toan = True
        break
    time.sleep_ms(50)

if an_toan:
    open(FILE_AN_TOAN, "w").close()           # main.py thấy file này thì dừng
    print("boot.py: che do an toan")
else:
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        wlan.connect(TEN_WIFI, MAT_KHAU_WIFI)
        bat_dau = time.ticks_ms()
        while not wlan.isconnected() and time.ticks_diff(time.ticks_ms(), bat_dau) < CHO_WIFI_GIAY * 1000:
            time.sleep_ms(200)
    if wlan.isconnected():
        print("boot.py: Wi-Fi", wlan.ifconfig()[0])
    else:
        print("boot.py: chua ket noi duoc Wi-Fi, main.py van chay")
Trục thời gian: sau khi bấm EN, boot.py chờ nút BOOT trong 2 giây; không bấm thì kết nối Wi-Fi rồi chạy main.py, có bấm thì tạo file an_toan.co và main.py bỏ qua, về REPL; cảnh báo không giữ BOOT lúc bấm EN
Chế độ an toàn: bấm BOOT trong 2 giây đầu.

Nút BOOT trên bo ESP32 nối với GPIO0. Lưu ý quan trọng: không giữ BOOT trong lúc bấm EN, vì khi đó ESP32 vào chế độ chờ nạp firmware chứ không chạy MicroPython. Cách đúng: bấm EN, thả ra, rồi bấm BOOT trong 2 giây đầu. boot.py tạo một file đánh dấu, main.py thấy file đó thì không chạy chương trình chính.

4. main.py mẫu: bắt lỗi, ghi lỗi ra file, watchdog

# PYWORLD.VN - main.py cho ESP32 chạy MicroPython: chương trình chính tự chạy sau boot.py, có watchdog và ghi lỗi ra file
# PYWORLD.VN - Nháy LED GPIO2, in thời gian chạy mỗi 5 giây; lỗi bất ngờ được ghi vào loi.txt rồi khởi động lại sau 10 giây
# PYWORLD.VN - Dừng bằng Ctrl+C thì watchdog vẫn chạy và sẽ khởi động lại chip sau 30 giây: muốn sửa file lâu, dùng chế độ an toàn

import os
import sys
import time
import machine


def la_che_do_an_toan():
    try:
        os.stat("an_toan.co")               # boot.py tạo file này khi người dùng bấm BOOT
    except OSError:
        return False
    os.remove("an_toan.co")
    return True


def ghi_loi(loi):
    with open("loi.txt", "a") as f:
        f.write("ticks {}: ".format(time.ticks_ms()))
        sys.print_exception(loi, f)


def vong_lap(led, cho):
    lan_in = time.ticks_ms()
    while True:
        led.value(not led.value())
        if time.ticks_diff(time.ticks_ms(), lan_in) >= 5000:
            lan_in = time.ticks_ms()
            print("main.py dang chay, {} giay".format(time.ticks_ms() // 1000))
        cho.feed()
        time.sleep_ms(500)


# Không dùng raise SystemExit ở đây: MicroPython coi đó là lệnh khởi động mềm lại, chế độ an toàn sẽ mất
if la_che_do_an_toan():
    print("main.py: che do an toan, khong chay chuong trinh, ve REPL")
else:
    led = machine.Pin(2, machine.Pin.OUT)
    cho = machine.WDT(timeout=30000)        # quá 30 giây không gọi feed() thì chip tự khởi động lại
    try:
        vong_lap(led, cho)
    except KeyboardInterrupt:
        print("Dung boi Ctrl+C; watchdog se khoi dong lai chip sau 30 giay")
    except Exception as loi:
        ghi_loi(loi)
        print("Loi, da ghi vao loi.txt; khoi dong lai sau 10 giay")
        time.sleep(10)
        machine.reset()
  • Bắt lỗi: lỗi bất ngờ (cảm biến rút dây, mất mạng) được ghi vào loi.txt kèm dòng gây lỗi bằng sys.print_exception, rồi bo khởi động lại sau 10 giây thay vì đứng ở REPL.
  • Watchdog (machine.WDT): nếu chương trình bị kẹt quá 30 giây không gọi feed(), chip tự khởi động lại. Watchdog đã bật thì không tắt được: dừng chương trình bằng Ctrl+C thì sau 30 giây bo vẫn tự khởi động lại. Muốn sửa file lâu, vào chế độ an toàn để watchdog không bị bật.
  • Không dùng raise SystemExit để dừng main.py: trên ESP32, MicroPython coi đó là lệnh khởi động mềm lại, chạy lại boot.py và main.py.

5. Chép file lên bo

Bảng lệnh: Thonny Save as MicroPython device; mpremote cp chép file; mpremote ls liệt kê; mpremote rm xóa main.py; mpremote cat xem loi.txt; mpremote reset khởi động lại
Thonny và mpremote.

Trong Thonny: mở file, File → Save as → MicroPython device, đặt tên boot.py hoặc main.py. Dùng dòng lệnh: cài pip install mpremote rồi chạy mpremote cp boot.py :boot.py, mpremote cp main.py :main.py, mpremote reset. Bo bị main.py làm treo: chạy mpremote rm :main.py (mpremote tự ngắt chương trình đang chạy trước khi xóa), hoặc vào chế độ an toàn.

6. Kết quả mong đợi

Hai khung REPL: khởi động bình thường in boot.py Wi-Fi 192.168.1.45, main.py đang chạy 7 giây, 12 giây, dừng bởi Ctrl C; chế độ an toàn in boot.py che do an toan, main.py không chạy chương trình, về dấu nhắc
REPL khi khởi động bình thường và ở chế độ an toàn.

7. Lỗi hay gặp

Hiện tượngNguyên nhân thường gặpCách xử lý
Cắm điện ngoài thì chương trình không chạyfile chưa lưu trên bo, sai tên (Main.py, main.py.py)lưu đúng tên main.py lên MicroPython device
Thonny không kết nối, REPL không hiệnmain.py vòng lặp dày đặc, in liên tụcbấm Stop nhiều lần, hoặc chế độ an toàn, hoặc mpremote rm
Bo khởi động lại sau khi bấm Ctrl+Cwatchdog đã bật vẫn chạydùng chế độ an toàn khi cần sửa lâu
Treo ở boot.py khi router tắtchờ Wi-Fi không giới hạngiới hạn thời gian như boot.py mẫu
Giữ BOOT rồi bấm EN thì không thấy REPLESP32 vào chế độ chờ nạp firmwarebấm EN trước, thả, rồi mới bấm BOOT

8. Xem thêm

MicroPython là gì và cách nạp firmware MicroPython cho ESP32 có ở các bài cùng cụm chủ đề.


Tin tức liên quan

Pin 18650 dòng xả cao: Samsung 25R, 30Q, LG HG2, Murata VTC6, C-rate và chọn cell cho khối pin
Pin 18650 dòng xả cao: Samsung 25R, 30Q, LG HG2, Murata VTC6, C-rate và chọn cell cho khối pin

Pin 18650 dòng xả cao là gì: dòng xả liên tục, C-rate, đánh đổi với dung lượng, điện trở trong và sụt áp, bảng cell Samsung, LG, Murata theo datasheet, chọn số cell song song; có script.

Phần mềm cho máy CNC: thiết kế, CAM, chọn mũi phay, tốc độ cắt và gửi G-code
Phần mềm cho máy CNC: thiết kế, CAM, chọn mũi phay, tốc độ cắt và gửi G-code

Ba loại phần mềm cho máy CNC phay: CAD, CAM và phần mềm gửi G-code; các kiểu đường dao, công thức tốc độ cắt theo lượng ăn mỗi răng, phay thuận, phay nghịch, cầu giữ chi tiết.

Máy hiện sóng cầm tay cho người mới: volt/div, time/div, kích hoạt, đầu đo x10, đo tín hiệu ESP32
Máy hiện sóng cầm tay cho người mới: volt/div, time/div, kích hoạt, đầu đo x10, đo tín hiệu ESP32

Đọc màn hình máy hiện sóng, chỉnh volt/div, time/div, kích hoạt; dùng và bù đầu đo x10; đo PWM, sóng cosin từ DAC và dội phím nút nhấn của ESP32; an toàn khi đo.

Robot dò line với ESP32: dự án STEM cuối khóa cho học sinh
Robot dò line với ESP32: dự án STEM cuối khóa cho học sinh

Làm robot dò line với ESP32, thanh 5 cảm biến TCRT5000 và L298N: bản 1 ba quy tắc nếu thì, bản 2 lái theo tỉ lệ độ lệch (điều khiển P), cách làm sân thi đấu cuối khóa.

Mô phỏng ESP32 trên Wokwi: thử mạch và chương trình ngay trên trình duyệt, có cả Wi-Fi
Mô phỏng ESP32 trên Wokwi: thử mạch và chương trình ngay trên trình duyệt, có cả Wi-Fi

Wokwi mô phỏng ESP32 làm được gì và chưa làm được gì, ba tệp sketch.ino, diagram.json, libraries.txt, dựng mạch LED, nút, biến trở, Wi-Fi ảo và cách chuyển sang mạch thật.

Thực hành hiệu chuẩn tĩnh gia tốc kế MEMS bằng trọng trường: sáu vị trí, độ lệch, độ nhạy chéo
Thực hành hiệu chuẩn tĩnh gia tốc kế MEMS bằng trọng trường: sáu vị trí, độ lệch, độ nhạy chéo

Hiệu chuẩn tĩnh gia tốc kế MPU-6050 bằng trọng trường với ESP32: sáu vị trí ±1 g, tính độ lệch không, độ nhạy, độ nhạy chéo dạng ma trận, lưu hệ số và kiểm tra độ lớn gia tốc ở tư thế bất kỳ.

Điều khiển hồng ngoại hoạt động thế nào: sóng mang 38 kHz, giao thức NEC và ESP32
Điều khiển hồng ngoại hoạt động thế nào: sóng mang 38 kHz, giao thức NEC và ESP32

Giải thích điều khiển hồng ngoại: sóng mang 38 kHz, mắt thu và giao thức NEC với khung 32 bit, mã lặp. Hướng dẫn tự giải mã phím điều khiển và tự phát lệnh bằng ESP32, không dùng thư viện ngoài.

Edge Impulse với ESP32: thu dữ liệu MPU6050, huấn luyện nhận dạng cử chỉ, xuất thư viện Arduino
Edge Impulse với ESP32: thu dữ liệu MPU6050, huấn luyện nhận dạng cử chỉ, xuất thư viện Arduino

Quy trình Edge Impulse với ESP32 và MPU6050: gửi dữ liệu gia tốc qua data forwarder, gắn nhãn, cửa sổ và đặc trưng phổ, đọc ma trận nhầm lẫn, xuất thư viện Arduino và chạy nhận dạng cử chỉ.


Bình luận
Đã thêm vào giỏ hàng