3.1. Vi điều khiển¶
OpenMV Cam chạy trên một vi điều khiển (MCU): một chip đơn tích hợp CPU, bộ nhớ làm việc (RAM), bộ nhớ lưu trữ chương trình (flash) và một tập hợp các ngoại vi -- các khối phần cứng dùng để tương tác với thế giới bên ngoài.
Các ngoại vi mới là phần thú vị. Mỗi ngoại vi là một mảnh silicon được thiết kế chuyên cho một công việc: điều khiển chân (pin) lên cao hay xuống thấp, đo điện áp tương tự, truyền byte qua bus nối tiếp. CPU cấu hình và đọc mỗi ngoại vi thông qua các thanh ghi -- các địa chỉ bộ nhớ cố định mà phần cứng theo dõi và cập nhật.
MicroPython bọc các thanh ghi đó trong các lớp bên trong mô-đun machine. machine.Pin(...) trả về một đối tượng điều khiển chân đầu vào/đầu ra đa năng (GPIO) -- một dây mà chip có thể giữ ở mức cao (khoảng 3,3 V) hoặc thấp (khoảng 0 V), hoặc đọc là một trong hai trạng thái đó khi có nguồn bên ngoài điều khiển. machine.ADC(...) cung cấp bộ chuyển đổi tương tự-số, đo điện áp trên một chân (pin) và báo cáo dưới dạng số. machine.UART(...) chạy bộ thu phát không đồng bộ vạn năng (UART) -- một ngoại vi gửi và nhận byte từng bit một qua một cặp dây, TX (truyền) và RX (nhận). Các lớp khác bao gồm phần còn lại của các ngoại vi. Tập lệnh đọc và ghi các đối tượng Python; MicroPython dịch mỗi lần truy cập thành các thao tác đọc và ghi thanh ghi tương ứng, và những thao tác đó di chuyển các bit trên dây vật lý.
Một MCU đóng gói CPU, bộ nhớ và ngoại vi vào một chip đơn. Mỗi ngoại vi được hiển thị cho Python bởi một lớp trong mô-đun machine.¶
3.1.1. Vòng lặp chính¶
Hầu hết mọi chương trình vi điều khiển đều có cùng một cấu trúc: thiết lập một lần ở đầu tập lệnh (import mô-đun, cấu hình chân (pin), mở bus), sau đó là một vòng lặp while True: vô tận ở cuối. Bên trong vòng lặp, chương trình đọc đầu vào, đưa ra quyết định và cập nhật đầu ra lặp đi lặp lại. Vòng lặp chính là chương trình; khi tập lệnh thoát, thiết bị ngừng hoạt động.
# setup, runs once
from machine import Pin
led = Pin("P0", Pin.OUT)
# main loop, runs forever
while True:
led.value(1)
# ... do work ...
led.value(0)
# ... do other work ...
Cấu trúc này -- thiết lập một lần, sau đó lặp mãi mãi -- là mẫu vòng lặp chính. Mọi thứ tiếp theo đều nói về những gì nằm bên trong nó.
3.1.2. Điều khiển thời gian thực¶
Một chương trình máy tính để bàn chạy cùng với nhiều chương trình khác. Hệ điều hành lên lịch công việc của nó trên một hoặc nhiều luồng -- các luồng thực thi độc lập mà nó chuyển đổi giữa chúng từng mili giây. Khi một luồng chờ I/O (đĩa, mạng, người dùng di chuyển chuột), HĐH giao CPU cho luồng khác. Chương trình chủ yếu hướng sự kiện: trình quản lý cửa sổ gọi vào code của bạn khi có đầu vào, thư viện HTTP tiếp tục code của bạn khi byte đến trên socket. Có thứ gì đó lớn hơn đang gọi bạn.
Chương trình vi điều khiển thì ngược lại. Theo mặc định, không có hệ điều hành, không có bộ lập lịch và không có luồng nào khác. Vòng lặp chính vừa nêu là vòng lặp duy nhất. Các ngoại vi kích hoạt ngắt hoặc hiển thị cờ trạng thái; vòng lặp thăm dò chúng hoặc xử lý ngắt trực tiếp. Nếu vòng lặp dừng lại trong time.sleep_ms(1000), thiết bị không làm gì trong giây đó; không có luồng nào khác để lấp đầy khoảng trống.
Có hai hệ quả và áp dụng ở khắp nơi:
Thời gian là thực. Đọc một chân (pin) hai lần trong một vòng lặp chặt mất vài micro giây; ngủ mười mili giây có nghĩa là mười mili giây không có gì khác xảy ra. Mẫu định thời không chặn là câu trả lời.
Phần cứng là thực. Đặt
machine.Pin.valuethành1đặt khoảng 3,3 V lên một dây vật lý; đặt thành0đặt khoảng 0 V ở đó. Các phần khác của mạch nhìn thấy điện áp đó ngay lập tức -- bao gồm bất kỳ thành phần nào mà chân (pin) có thể làm hỏng nếu điều khiển sai.