3.1. ไมโครคอนโทรลเลอร์

OpenMV Cam ทำงานบน ไมโครคอนโทรลเลอร์ (MCU): ชิปตัวเดียวที่รวม CPU, หน่วยความจำใช้งาน (RAM), พื้นที่จัดเก็บโปรแกรม (แฟลช) และชุด อุปกรณ์ต่อพ่วง -- บล็อกฮาร์ดแวร์สำหรับโต้ตอบกับโลกภายนอก

อุปกรณ์ต่อพ่วงคือส่วนที่น่าสนใจ แต่ละตัวเป็นชิ้นส่วนซิลิคอนที่ทำหน้าที่เฉพาะอย่างหนึ่ง: ขับพินให้สูงหรือต่ำ, วัดแรงดันไฟฟ้าแบบอนาล็อก, ส่งไบต์ผ่านบัสอนุกรม CPU กำหนดค่าและอ่านข้อมูลจากอุปกรณ์ต่อพ่วงแต่ละตัวผ่าน รีจิสเตอร์ -- ที่อยู่หน่วยความจำคงที่ที่ฮาร์ดแวร์คอยตรวจสอบและอัปเดต

MicroPython ห่อหุ้มรีจิสเตอร์เหล่านั้นเป็นคลาสใน machine machine.Pin(...) คืนออบเจ็กต์ที่ควบคุม general-purpose input/output (GPIO) พิน -- สายที่ชิปสามารถดึงให้ สูง (ประมาณ 3.3 V) หรือ ต่ำ (ประมาณ 0 V) หรืออ่านเป็นหนึ่งในสองสถานะนั้นเมื่อมีสิ่งภายนอกขับมัน machine.ADC(...) เปิดใช้งานตัวแปลงอนาล็อกเป็นดิจิทัล ซึ่งวัดแรงดันบนพินและรายงานเป็นตัวเลข machine.UART(...) เรียกใช้งาน universal asynchronous receiver/transmitter (UART) -- อุปกรณ์ต่อพ่วงที่ส่งและรับไบต์ทีละบิตผ่านคู่สาย TX (ส่ง) และ RX (รับ) คลาสอื่นๆ ครอบคลุมอุปกรณ์ต่อพ่วงที่เหลือ สคริปต์อ่านและเขียนออบเจ็กต์ Python และ MicroPython แปลงการเข้าถึงแต่ละครั้งเป็นการอ่านและเขียนรีจิสเตอร์ที่สอดคล้องกัน ซึ่งเคลื่อนย้ายบิตบนสายไฟฟ้าจริง

A single chip outline containing labelled blocks -- CPU, RAM, flash, and a row of peripheral blocks (GPIO, ADC, Timer/PWM, UART/SPI/I2C, CAN) connected by an internal bus, with arrows from each peripheral exiting the chip toward physical pin labels.

MCU บรรจุ CPU, หน่วยความจำ และอุปกรณ์ต่อพ่วงไว้ในชิปเดียว อุปกรณ์ต่อพ่วงแต่ละตัวเปิดเผยต่อ Python ผ่านคลาสใน machine

3.1.1. ลูปหลัก

โปรแกรมไมโครคอนโทรลเลอร์เกือบทุกตัวมีรูปแบบเดียวกัน: การตั้งค่าครั้งเดียวที่ต้นสคริปต์ (นำเข้าโมดูล, กำหนดค่าพิน, เปิดบัส) จากนั้นตามด้วยลูป while True: แบบอนันต์ที่ท้าย ภายในลูป โปรแกรมอ่านอินพุต ตัดสินใจ และอัปเดตเอาต์พุตซ้ำแล้วซ้ำเล่า ลูป คือ โปรแกรม เมื่อสคริปต์ออก อุปกรณ์จะหยุดทำงาน

# 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 ...

รูปแบบนี้ -- ตั้งค่าครั้งเดียว จากนั้นวนซ้ำตลอด -- คือรูปแบบ main loop ทุกสิ่งที่ตามมาเกี่ยวข้องกับสิ่งที่อยู่ภายในมัน

3.1.2. การควบคุมแบบเรียลไทม์

โปรแกรมเดสก์ท็อปทำงานร่วมกับโปรแกรมอื่นๆ มากมาย ระบบปฏิบัติการจัดตารางงานข้าม เธรด หนึ่งหรือหลายตัว -- กระแสการทำงานอิสระที่สลับระหว่างกันทุกมิลลิวินาที เมื่อเธรดหนึ่งรอ I/O (ดิสก์, เครือข่าย, ผู้ใช้เลื่อนเมาส์) ระบบปฏิบัติการจะส่ง CPU ให้กับเธรดอื่น โปรแกรมส่วนใหญ่ขับเคลื่อนด้วยเหตุการณ์: window manager เรียกโค้ดของคุณเมื่ออินพุตมาถึง ไลบรารี HTTP กลับมาที่โค้ดของคุณเมื่อไบต์มาถึงบนซ็อกเก็ต สิ่งที่ใหญ่กว่าเป็นผู้เรียกคุณ

โปรแกรมไมโครคอนโทรลเลอร์เป็นตรงกันข้าม โดยค่าเริ่มต้นไม่มีระบบปฏิบัติการ ไม่มีตัวกำหนดตาราง และไม่มีเธรดอื่น ลูปหลักที่แสดงไว้คือ ลูปเดียว อุปกรณ์ต่อพ่วงส่งอินเทอร์รัปต์หรือเปิดเผยแฟล็กสถานะ ลูปจะ poll หรือจัดการอินเทอร์รัปต์โดยตรง หากลูปหยุดใน time.sleep_ms(1000) อุปกรณ์จะไม่ทำอะไรในช่วงวินาทีนั้น ไม่มีเธรดอื่นมาเติมช่องว่าง

ผลลัพธ์สองประการที่เกิดขึ้นและใช้ได้ทุกที่:

  • เวลาเป็นจริง การอ่านพินสองครั้งในลูปที่แน่นต้องใช้ไมโครวินาที การหลับเป็นสิบมิลลิวินาทีหมายความว่าสิบมิลลิวินาทีที่ไม่มีอะไรเกิดขึ้น รูปแบบ การจับเวลาแบบไม่บล็อก คือการตอบสนอง

  • ฮาร์ดแวร์เป็นจริง การตั้งค่า machine.Pin.value เป็น 1 จะใส่แรงดันประมาณ 3.3 V บนสายไฟจริง การตั้งเป็น 0 จะใส่ประมาณ 0 V ชิ้นส่วนอื่นของวงจรเห็นแรงดันนั้นทันที -- รวมถึงส่วนประกอบที่พินอาจทำให้เสียหายหากขับผิด