OpenMV Cam RT1062

OpenMV Cam RT1062 เป็นบอร์ดการมองเห็นของเครื่องที่ใช้พลังงานต่ำ สร้างบน NXP i.MX RT1062 (Cortex‑M7 @ 600 MHz) บอร์ดนี้รวม USB‑C เครือข่ายความเร็วสูง, Wi‑Fi/Bluetooth และ Ethernet 10/100 เข้ากับเซนเซอร์ OV5640 5MP บนแผงขยายแบบถอดได้ กล้องใช้ไฟเพียง ~30 µA จากแบตเตอรี่ LiPo ในโหมดสลีปลึก ซึ่งเหมาะสำหรับโปรเจกต์ที่ใช้พลังงานจากแบตเตอรี่

OpenMV Cam RT1062

สำหรับ datasheet เต็ม รูปภาพ และขนาด ดูที่ หน้าผลิตภัณฑ์ OpenMV Cam RT1062

ไฮไลต์

  • NXP i.MX RT1062 Cortex‑M7 ที่ 600 MHz

  • SDRAM ภายนอก 32 MB (16‑bit @ 160 MHz, 320 MB/s) พร้อม SRAM ภายใน 1 MB และ แฟลช QSPI 16 MB (133 MHz 4‑bit SDR, 66 MB/s อ่าน); EEPROM 4 KB บน R6+

  • เซนเซอร์ rolling‑shutter 5MP OV5640

  • IMU ในตัว (แอคเซเลอโรมิเตอร์ 3 แกน 12‑bit, ±2/4/8 g)

  • USB‑C ความเร็วสูง (480 Mb/s, จำกัดกระแส 1.5 A), Ethernet 10/100 Mb/s (รองรับ PoE ผ่านชีลด์), Wi‑Fi a/b/g/n + Bluetooth 5.1 (เสาอากาศชิปหรือตัวเลือก U.FL)

  • ช่อง microSD — SD สูงสุด 2 GB, SDHC สูงสุด 32 GB, SDXC สูงสุด 2 TB

  • เครื่องชาร์จ LiPo (500 mA บน R6+, 100 mA บน R4/R5), RTC พร้อมแผ่น pad สำรองแบตเตอรี่ โหมดสลีปลึกใช้ไฟ ~30 µA จากแบตเตอรี่

  • พิน I/O 14 ตัว ทั้งหมดเอาต์พุต 3.3 V / ทนสัญญาณ 3.3 V, 4 mA ต่อพิน รองรับอินเทอร์รัปต์

  • LED RGB สำหรับผู้ใช้ ปุ่ม SW สำหรับผู้ใช้ ปุ่มเปิด/ปิดฮาร์ดแวร์ (สเตตแมชชีนสลีปลึก / ตื่น) และ LED สถานะแยกต่างหากสำหรับการชาร์จ / USB / ไฟ VIN

Warning

พิน I/O ของ RT1062 ไม่ทนสัญญาณ 5 V ห้ามต่ออุปกรณ์โดยตรงกับ MCU 5 V เช่น Arduino Mega จ่ายไฟให้บอร์ดผ่าน VIN เท่านั้น

พินเอาต์

OpenMV Cam RT1062 OV5640 Pinout

ตารางอ้างอิงพิน

ชื่อพิน

หน้าที่

P0

SPI1 MOSI / PWM2 B3

P1

SPI1 MISO / CAN0 TX

P2

SPI1 SCLK / PWM2 B3

P3

SPI1 SS / CAN0 RX

P4

I2C1 SCL / UART1 TX / PWM1 X2

P5

I2C1 SDA / UART1 RX / PWM1 X3

P6

ADC

P7

PWM2 A0

P8

PWM2 B0

P9

PWM1 A3

P10

PWM1 B3 / frame sync I/O

P11

wakeup (active low, ต่อกับ GND เพื่อปลุกระบบ)

P12

RESET — ดึงลง GND เพื่อรีเซ็ตบอร์ด (ไม่ใช่ GPIO)

P13

digital I/O

P14

digital I/O

ON/OFF

แผ่น pad บนส่วนหัวที่ทำซ้ำปุ่มเปิด/ปิดฮาร์ดแวร์ (active low)

SW

ปุ่มสำหรับผู้ใช้ (active low)

ST

ต่ำเมื่อใช้ไฟ VIN, สูงเมื่อใช้ไฟ USB

CHG

active‑low; ต่ำขณะแบตเตอรี่ LiPo ที่ต่ออยู่กำลังชาร์จ

PG

active‑low; ต่ำเมื่อมีไฟ VIN หรือ USB

LED_RED

ช่องสีแดงของ RGB LED (active low)

LED_GREEN

ช่องสีเขียวของ RGB LED (active low)

LED_BLUE

ช่องสีน้ำเงินของ RGB LED (active low)

Note

สาย P10 frame‑sync เป็นบัสร่วม ต่อเชื่อมกับ MCU พิน trigger/exposure ของเซนเซอร์กล้อง และส่วนหัวสำหรับผู้ใช้พร้อมกัน ทิศทางขึ้นอยู่กับแอปพลิเคชัน — MCU เซนเซอร์ หรือสัญญาณภายนอกสามารถขับสายนี้ได้ขึ้นอยู่กับการตั้งค่าเซนเซอร์ ตรวจสอบให้แน่ใจว่ามีเพียงตัวขับเดียวที่ใช้งานอยู่ในแต่ละครั้ง

Note

ON/OFF และ P11 อ้างอิงกับราง RAW ที่เปิดอยู่เสมอ (ไม่ใช่ราง 3.3 V แบบสวิตช์) ดังนั้นจึงยังคงทำงานได้ขณะที่บอร์ดส่วนที่เหลืออยู่ในโหมดสลีปลึก / ประหยัดพลังงาน อินพุตทั้งสองเป็น active low

พินเหล่านี้ผ่านตัวแปลงระดับสัญญาณเพื่อให้ทำงานบนราง RAW ได้ หากคุณต้องการ GPIO ตรง 3.3 V บน ON/OFF หรือ P11 (เช่น เพื่อขับจาก MCU 3.3 V โดยไม่ผ่านตัวแปลง) บอร์ดมีแผ่น pad สำหรับ pull-up และ resistor 0‑ohm ที่ให้คุณข้ามตัวแปลงได้ นี่คือการดัดแปลงฮาร์ดแวร์ขั้นสูง — ผู้ใช้ส่วนใหญ่ไม่จำเป็นต้องแตะต้อง

Note

P13 และ P14 เป็น GPIO ธรรมดาโดยค่าเริ่มต้น โดยไม่มีหน้าที่พิเศษ แผ่น pad สามารถกำหนดเส้นทางใหม่ไปยังสัญญาณอื่นได้โดยการ reflow สะพาน solder resistor 0‑ohm บนด้านหลังบอร์ด:

  • P13 ↔ CHG status / JTAG TRSTB

  • P14 ↔ ST status / JTAG TDI

ผู้ใช้ส่วนใหญ่ไม่จำเป็นต้องแตะต้อง jumper เหล่านี้ — ปล่อยไว้ที่ค่าเริ่มต้น GPIO เว้นแต่คุณต้องการการอ่านกลับสถานะพลังงานหรือ JTAG โดยเฉพาะ

พินไฟ

  • 3.3V — ราง 3.3 V ที่ควบคุมแล้ว เอาต์พุตเท่านั้น บน RT1062 — ห้ามป้อนไฟจากภายนอกเข้าพินนี้ รองรับกระแสสูงสุด 1 A สำหรับชีลด์

  • VIN — อินพุต 5 V จ่ายไฟให้บอร์ดและเครื่องชาร์จ LiPo ในตัว

  • RAW — อินพุต/เอาต์พุต เปิดอยู่เสมอ (3.6 V – 5 V) นำสัญญาณจากแหล่งที่ใช้งานอยู่ (VIN, USB หรือแบตเตอรี่ที่ต่ออยู่) และยังใช้เป็นอินพุตได้ด้วย คุณต้องต่อ RAW ผ่านไดโอดอนุกรม เมื่อป้อนไฟเข้า — มิฉะนั้นกระแสจะไหลย้อนกลับเข้า VIN/USB และทำให้แหล่งจ่ายหรือการป้องกันในตัวเสียหาย

  • GND — กราวด์ร่วม

Note

ชิปจัดการพลังงานในตัวเลือกโดยอัตโนมัติว่าจะใช้ USB หรือ VIN ที่มีแรงดันสูงกว่า เพื่อจ่ายไฟให้บอร์ดและเครื่องชาร์จแบตเตอรี่ หากต่อ LiPo ไว้จะชาร์จจากแรงดันส่วนต่างที่เหลือ และคอนโทรลเลอร์จะสลับมาใช้แบตเตอรี่เพื่อให้บอร์ดทำงานต่อเนื่องหาก VIN/USB ตกหรือถอดออก

Note

ด้านหลังบอร์ดมีแผ่น pad สำหรับแบตเตอรี่สำรอง RTC 3.3 V ภายนอก การต่อ coin cell กับแผ่น pad เหล่านี้จะทำให้ RTC ทำงานต่อได้ขณะที่บอร์ดส่วนที่เหลือไม่มีไฟ

Tip

ใช้ เครื่องคำนวณอายุแบตเตอรี่ เพื่อประเมินว่า RT1062 จะทำงานได้นานเท่าไรจากแบตเตอรี่สำหรับรอบการทำงาน active / deep-sleep ที่กำหนด

พิน Ethernet

RT1062 แสดงคู่ MDI ของ PHY Ethernet 10/100 Mb/s บนแผ่น pad เฉพาะที่อยู่ถัดจากส่วนหัว GPIO พิน MDI ไม่ปลอดภัยที่จะต่อตรงกับ RJ45 — จำเป็นต้องมีแมกนีติก Ethernet (หม้อแปลงแยกสัญญาณ ไม่ว่าจะฝังอยู่ใน magjack หรือบนชีลด์) ระหว่าง PHY กับสาย OpenMV PoE shield มีแมกนีติกดังกล่าว หากคุณทำ jack เอง ให้ใช้ RJ45 แบบบูรณาการแมกนีติกหรือหม้อแปลงภายนอก

  • ETH_LED — LED แสดงลิงก์/กิจกรรม Active low เมื่อลิงก์ขึ้น; กระพริบเมื่อมีการรับส่งข้อมูล

  • ETH_TXP / ETH_TXN — คู่ส่ง

  • ETH_RXP / ETH_RXN — คู่รับ

Note

ส่วนหัวยังแสดงแผ่น pad สี่แผ่นที่พิมพ์ไว้ว่า Reserved ซึ่งเข้ากันได้กับฟุตพรินต์ของคู่ Ethernet gigabit บน OpenMV N6 (DC P/N และ DD P/N) เพื่อให้ชีลด์ Ethernet / PoE เดียวกันเสียบกับบอร์ดใดก็ได้ PHY ของ RT1062 รองรับเพียง 10/100 Mb/s ดังนั้นแผ่น pad ทั้งสี่นั้น ไม่มีการเชื่อมต่อไฟฟ้า — ปล่อยไว้ไม่ต่อสาย

พินสำหรับการกู้คืนและดีบัก

  • RESET — ดึงลง GND เพื่อรีเซ็ตบอร์ด การปล่อยให้ MCU เริ่มทำงานตามปกติ

  • SBL — ดึงขึ้น 3.3 V ขณะเปิดเครื่องบอร์ดเพื่อเข้าสู่โหมด ROM bootloader (Serial Boot Loader) OpenMV IDE ใช้โหมดนี้ในการเขียน bootloader ใหม่ในตัว

มีส่วนหัว ARM 10‑pin SWD/JTAG เฉพาะที่ติดตั้งมาพร้อม รองรับอแดปเตอร์ ST‑LINK และ SEGGER J‑Link

Note

RT1062 แสดงเฉพาะการดีบัก SWD ผ่านคอนเนกเตอร์นี้โดยค่าเริ่มต้น JTAG เต็มรูปแบบไม่พร้อมใช้งานแบบ out of the box

อุปกรณ์ต่อพ่วงในตัว

LED

RT1062 มี RGB LED สองชุด:

  • User RGB LED — ควบคุมได้ด้วยซอฟต์แวร์ แสดงเป็น LED_RED, LED_GREEN และ LED_BLUE

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • Power LED — ขับโดยฮาร์ดแวร์จัดการพลังงานในตัวโดยตรง ไม่มีการควบคุมด้วยซอฟต์แวร์ ใช้ดูสถานะการจ่ายไฟได้อย่างรวดเร็ว

    ขณะทำงาน:

    ช่อง

    ความหมาย

    น้ำเงิน

    VIN กำลังจ่ายไฟให้บอร์ด (ดับเมื่อใช้ USB)

    เขียว

    มีไฟ USB หรือ VIN

    แดง

    กำลังชาร์จแบตเตอรี่ LiPo ที่ต่ออยู่

    ในโหมดสลีปลึก ทุกช่องดับ ยกเว้นสีแดง ซึ่งยังคงติดขณะที่ LiPo กำลังชาร์จ

ปุ่ม

RT1062 มีสองปุ่ม:

  • SW — ปุ่มสำหรับผู้ใช้เอนกประสงค์ อ่านได้จากโค้ดในรูปอินพุต GPIO active‑low ปกติ:

    from machine import Pin
    
    sw = Pin("SW", Pin.IN)
    print(sw.value())
    
  • ปุ่มเปิด/ปิด — ขับโดยสเตตแมชชีนคอนโทรลเลอร์พลังงานเฉพาะบนบอร์ด RT1062 ทั้งหมดในฮาร์ดแวร์ ไม่แสดงให้โค้ดผู้ใช้ คอนโทรลเลอร์ตัดสินใจว่าจะทำอะไรตามระยะเวลาที่กดค้าง:

    • กดค้างประมาณ 5 วินาที ขณะบอร์ดทำงาน → สเตตแมชชีนเปลี่ยนไปสู่โหมดสลีปลึก

    • กดค้างประมาณ 1 วินาที ขณะบอร์ดอยู่ในโหมดสลีปลึก → สเตตแมชชีนเปิดระบบกลับขึ้น

    การดึงแผ่น pad ส่วนหัว ON/OFF ให้ต่ำมีผลเหมือนกับการกดปุ่มเปิด/ปิดในตัว — มีประโยชน์สำหรับการต่อสวิตช์ภายนอกหรือขับสายจาก microcontroller อื่น

พินสถานะพลังงาน

อินพุตสถานะ active‑low สามตัวจากชิปจัดการพลังงานในตัว:

  • PG — ต่ำเมื่อมีไฟ VIN หรือ USB เชื่อมต่อตลอดเวลา

  • ST — ต่ำเมื่อบอร์ดทำงานบน VIN, สูงเมื่อทำงานบนไฟ USB ไม่เชื่อมต่อโดยค่าเริ่มต้น

  • CHG — ต่ำขณะแบตเตอรี่ LiPo ที่ต่ออยู่กำลังชาร์จ ไม่เชื่อมต่อโดยค่าเริ่มต้น

from machine import Pin

power_ok = not Pin("PG", Pin.IN).value()

เซนเซอร์กล้อง

OV5640 ถูกขับผ่านโมดูล csi --- เซ็นเซอร์กล้อง

import csi

cam = csi.CSI()
cam.reset()
cam.pixformat(csi.RGB565)
cam.framesize(csi.QVGA)
cam.snapshot(time=2000)       # let auto‑exposure settle

while True:
    img = cam.snapshot()

OV5640 มีตัวบีบอัด JPEG ในตัว ตั้ง csi.CSI.pixformat เป็น csi.JPEG แล้วเซนเซอร์จะส่งเฟรมที่บีบอัดแล้วโดยตรงไปยังกล้องผ่านบัสกล้อง ซึ่งทำให้การถ่ายภาพความละเอียดสูงทำได้จริง: csi.HD (1280×720), csi.FHD (1920×1080) และ 5MP เต็ม csi.WQXGA2 (2592×1944) ทั้งหมดสตรีมเป็น JPEG ปรับการบีบอัดด้วย csi.CSI.quality (0-100 สูงกว่า = เฟรมใหญ่กว่า รายละเอียดมากกว่า):

cam.pixformat(csi.JPEG)
cam.framesize(csi.WQXGA2)
cam.quality(90)

เซนเซอร์อยู่บน โมดูลแบบถอดได้ — เปลี่ยนเป็นโมดูลกล้อง OpenMV อื่น ๆ (global shutter, ความร้อน, ความละเอียดสูงกว่า ฯลฯ) โดยไม่ต้องเปลี่ยนส่วนที่เหลือของบอร์ด

Machine learning

ml --- Machine Learning รันโมเดล TFLite แบบ quantised บน Cortex‑M7 ด้วย kernel CMSIS‑NN — เร็วพอสำหรับตัวตรวจจับขนาดกะทัดรัดที่ไม่กี่เฟรมต่อวินาที โมเดลบนไฟล์ระบบ /rom แบบอ่านอย่างเดียวโหลดโดยตรงจากแฟลชโดยไม่คัดลอกไปยัง RAM ต่อไปนี้คือตัวตรวจจับใบหน้า BlazeFace 128×128 ที่ซ้อนทับใบหน้าที่ตรวจพบและ landmark หกจุดบนทุกเฟรม:

import csi
import time
import ml
from ml.postprocessing.mediapipe import BlazeFace

# Initialize the sensor.
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi0.window((400, 400))

# Load built-in face detection model
model = ml.Model("/rom/blazeface_front_128.tflite", postprocess=BlazeFace(threshold=0.4))
print(model)

clock = time.clock()
while True:
    clock.tick()
    img = csi0.snapshot()

    # faces is a list of ((x, y, w, h), score, keypoints) tuples
    for r, score, keypoints in model.predict([img]):
        ml.utils.draw_predictions(img, [r], ("face",), ((0, 0, 255),), format=None)

        # keypoints is a ndarray of shape (6, 2)
        # 0 - right eye (x, y)
        # 1 - left eye (x, y)
        # 2 - nose (x, y)
        # 3 - mouth (x, y)
        # 4 - right ear (x, y)
        # 5 - left ear (x, y)
        ml.utils.draw_keypoints(img, keypoints, color=(255, 0, 0))

    print(clock.fps(), "fps")

IMU

เฟิร์มแวร์ RT1062 ไม่ได้ ต่อแอคเซเลอโรมิเตอร์ในตัวกับโมดูล imu --- imu sensor แทนที่ให้คุยกับมันโดยตรงผ่านบัส I²C ภายใน — ชิปอยู่ที่แอดเดรส 0x15 และบรรจุช่องความเร่ง 12‑bit ที่มีเครื่องหมายสามช่องบวกไบต์อุณหภูมิ 8‑bit เริ่มที่รีจิสเตอร์ 0x03

import machine
import time

ADDR     = 0x15
DATA_REG = 0x03
LSB_PER_G = 1024.0    # ±2 g range

def s12(hi, lo):
    v = ((hi << 8) | lo) >> 4
    return v - 0x1000 if v & 0x800 else v

bus = machine.I2C(2)
print("Devices on I²C2:", bus.scan())

while True:
    d = bus.readfrom_mem(ADDR, DATA_REG, 7)
    x = s12(d[0], d[1]) / LSB_PER_G
    y = s12(d[2], d[3]) / LSB_PER_G
    z = s12(d[4], d[5]) / LSB_PER_G
    temp_c = d[6] * 0.586 + 25.0
    print("x=%+.2fg  y=%+.2fg  z=%+.2fg  T=%.1f°C" % (x, y, z, temp_c))
    time.sleep_ms(100)

EEPROM

บอร์ด R6 และรุ่นใหม่กว่า มี I²C EEPROM ขนาด 4 KB บนบัสภายในเดียวกับแอคเซเลอโรมิเตอร์ (รุ่นก่อนหน้าไม่มี — การเรียกโค้ดเหล่านี้บน R4/R5 จะหมดเวลารอ I²C ack ที่ขาดหายไป) ใช้ machine.I2C API มาตรฐาน readfrom_mem / writeto_mem พร้อมแอดเดรสหน่วยความจำ 16‑bit:

import machine
import time

EEPROM_ADDR = 0x50            # default address
PAGE_SIZE   = 32              # bytes per page (both read and write)
EEPROM_SIZE = 4096

bus = machine.I2C(2)

# Dump the entire 4 KB one page at a time
data = bytearray()
for offset in range(0, EEPROM_SIZE, PAGE_SIZE):
    data += bus.readfrom_mem(EEPROM_ADDR, offset, PAGE_SIZE, addrsize=16)
print(len(data), "bytes")

# Write a small payload back at offset 0 (fits in one page)
bus.writeto_mem(EEPROM_ADDR, 0, b"hello, world", addrsize=16)
time.sleep_ms(10)             # ~5 ms write cycle after each page

# Read it back
print(bus.readfrom_mem(EEPROM_ADDR, 0, 12, addrsize=16))

ทั้ง การอ่านและการเขียน ต้องอยู่ภายในหน้า 32 ไบต์ แบ่งการถ่ายโอนขนาดใหญ่ออกเป็นหนึ่งการเรียกต่อหน้า และเพิ่มความล่าช้าในรอบการเขียน ~5 ms ระหว่างการเขียนต่อเนื่อง

Wi‑Fi

โมดูลในตัว CYW43‑family แสดงผ่าน network --- การกำหนดค่าเครือข่าย เป็นอินเทอร์เฟสสถานี หลังเชื่อมต่อแล้ว ipconfig("addr4") คืนคู่ (ip, netmask)

import network, time

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("ssid", "password")
while not wlan.isconnected():
    time.sleep(1)
print("Wi‑Fi IP:", wlan.ipconfig("addr4")[0])

Bluetooth

โมดูลไร้สายเดียวกันยังแสดง Bluetooth 5.1 ด้วย ใช้ aioble --- Async BLE สำหรับ BLE ที่เป็นมิตรกับ asyncio — ตัวอย่างเช่น โฆษณาเป็น peripheral และรอให้ central เชื่อมต่อ:

import asyncio
import aioble

async def run():
    while True:
        conn = await aioble.advertise(250_000, name="OpenMV-RT1062")
        print("Connected:", conn.device)
        await conn.disconnected()

asyncio.run(run())

Ethernet

เมื่อต่อ RJ45 (พร้อม magnetics) กับแผ่น pad MDI PHY 10/100 จะปรากฏเป็นอินเทอร์เฟส LAN DHCP ทำงานอัตโนมัติเมื่อลิงก์ขึ้น:

import network, time

lan = network.LAN()
lan.active(True)
while not lan.isconnected():
    time.sleep(1)
print("Ethernet IP:", lan.ipconfig("addr4")[0])

การ์ด microSD

เมื่อใส่การ์ด จะถูก mount อัตโนมัติที่ /sdcard และใช้งานได้ผ่านไฟล์ระบบปกติ:

import os

for entry in os.listdir("/sdcard"):
    print(entry)

ข้อมูลอ้างอิงบัส

GPIO

ใช้ machine.Pin เพื่ออ่านหรือขับพินที่พิมพ์ไว้ทุกตัว เอาต์พุตเป็น CMOS 3.3 V และสามารถซิงก์/ซอร์สกระแสได้สูงสุด 4 mA ต่อพิน

from machine import Pin

out = Pin("P0", Pin.OUT)
out.on()
out.off()
out.value(1)

inp = Pin("P1", Pin.IN, Pin.PULL_UP)
print(inp.value())

พินอินพุตใด ๆ ก็ตามสามารถยิงอินเทอร์รัปต์บนการเปลี่ยนแปลงขอบสัญญาณได้:

def handler(pin):
    print("triggered:", pin)

Pin("P1", Pin.IN, Pin.PULL_UP).irq(
    handler, Pin.IRQ_FALLING | Pin.IRQ_RISING,
)

UART

บัส

TX

RX

UART1

P4

P5

from machine import UART

uart = UART(1, baudrate=115200)
uart.write("hello")
uart.read(5)

I²C

บัส

SCL

SDA

I2C1

P4

P5

from machine import I2C

i2c = I2C(1, freq=400_000)
i2c.scan()
i2c.writeto(0x76, b"hi")

ฮาร์ดแวร์เดียวกันยังใช้ในโหมด target (slave) ผ่าน machine.I2CTarget เพื่อแสดงพื้นที่หน่วยความจำให้ I²C controller ตัวอื่น:

from machine import I2CTarget

buf = bytearray(32)
target = I2CTarget(1, addr=0x42, mem=buf)

SPI

บัส

MOSI

MISO

SCK

CS

SPI1

P0

P1

P2

P3

from machine import SPI
from machine import Pin

spi = SPI(1, baudrate=10_000_000)
cs = Pin("P3", Pin.OUT, value=1)   # CS is not driven by the SPI peripheral

cs.value(0)
spi.write(b"hello")
cs.value(1)

CAN

บัส

TX

RX

CAN1

P1

P3

Note

CAN ยังไม่รองรับบนบอร์ดนี้ใน firmware v5.0.0

from machine import CAN

can = CAN(1, 500_000)
can.set_filters(None)
can.send(0x123, b"\xDE\xAD\xBE\xEF")
print(can.recv())

ADC

พิน ADC สำหรับผู้ใช้มีเพียง P6 ซึ่งเต็มสเกลที่ ~3.3 V:

from machine import ADC
import time

adc = ADC("P6")
while True:
    voltage = adc.read_u16() * 3.3 / 65535
    print(voltage)
    time.sleep_ms(100)

PWM

พิน

ช่อง FlexPWM

P0

PWM2 B3

P2

PWM2 B3

P4

PWM1 X2

P5

PWM1 X3

P7

PWM2 A0

P8

PWM2 B0

P9

PWM1 A3

P10

PWM1 B3

ขับทุกตัวผ่าน machine.PWM

from machine import Pin, PWM

pwm = PWM(Pin("P9"), freq=1_000, duty_u16=32768)

บัสแบบ Software bit‑bang

machine.SoftI2C และ machine.SoftSPI ทำงานบน GPIO ใด ๆ หากคุณต้องการบัสเพิ่มเติม

เซนเซอร์ความร้อน (นอกบอร์ด)

เฟิร์มแวร์มีไดรเวอร์ fir --- ไดรเวอร์เซนเซอร์ความร้อน (fir == far infrared) สำหรับเซนเซอร์ถ่ายภาพความร้อนที่ต่อจากภายนอก:

  • MLX90621 — อาร์เรย์ IR 16 × 4

  • MLX90640 — อาร์เรย์ IR 32 × 24

  • MLX90641 — อาร์เรย์ IR 16 × 12

  • AMG8833 — อาร์เรย์ IR 8 × 8

ต่อโมดูลกับบัส I²C ของบอร์ดและอ่านเฟรมด้วย fir.init() + fir.snapshot()

import time
import image
import fir

fir.init()                          # auto‑detects the sensor
clock = time.clock()

while True:
    clock.tick()
    try:
        img = fir.snapshot(x_scale=5, y_scale=5,
                           color_palette=image.PALETTE_IRONBOW,
                           hint=image.BICUBIC,
                           copy_to_fb=True)
    except OSError:
        continue
    print(clock.fps())

ไดรเวอร์ fir คุยกับเซนเซอร์ผ่าน I²C 4 เท่านั้น — ต่อโมดูลกับ P4 (SCL) และ P5 (SDA)

การกำหนดเวลา

time

โมดูล time ครอบคลุมการหน่วงเวลาแบบ blocking, ticks แบบโมโนโทนิก และการวัดเวลาที่ผ่านไป:

import time

time.sleep(1)              # seconds
time.sleep_ms(500)
time.sleep_us(10)

start = time.ticks_ms()
# ...do work...
elapsed = time.ticks_diff(time.ticks_ms(), start)

Virtual timer

machine.Timer กำหนดเวลา callback แบบรอบหรือแบบครั้งเดียวโดยไม่ใช้ slot hardware timer ส่ง -1 เป็น id เพื่อใช้ virtual (software) timer:

from machine import Timer

one_shot = Timer(-1)
one_shot.init(period=5_000, mode=Timer.ONE_SHOT,
              callback=lambda t: print("once"))

periodic = Timer(-1)
periodic.init(period=2_000, mode=Timer.PERIODIC,
              callback=lambda t: print("tick"))

ค่า Period อยู่ในหน่วยมิลลิวินาที เรียก deinit() เพื่อหยุดและปลดปล่อย slot

Real‑time clock

machine.RTC เก็บเวลานาฬิกาแขวนผ่านการรีเซ็ตและ (ด้วยแบตเตอรี่สำรอง 3.3 V เสริมที่ต่อกับแผ่น pad ด้านหลัง ดู พินไฟ) ผ่านการตัดไฟทั้งหมด:

from machine import RTC

rtc = RTC()
rtc.datetime((2026, 4, 30, 4, 12, 0, 0, 0))   # Y, M, D, weekday, h, m, s, subsec
print(rtc.datetime())

RTC ยังทำงานตลอดโหมดสลีปลึก คุณจึงใช้เป็นแหล่ง wakeup สำหรับ machine.deepsleep() ได้

Watchdog

machine.WDT รีเซ็ตบอร์ดหากแอปพลิเคชันค้าง เมื่อเริ่มแล้วหยุดหรือตั้งค่าใหม่ไม่ได้ — feed มันเป็นระยะในลูปหลักของคุณ:

from machine import WDT

wdt = WDT(timeout=5_000)   # 5 second window
while True:
    # ...do work...
    wdt.feed()

ข้อมูลการบูตและ runtime

หน้าต่าง USB bootloader

ทุกครั้งที่เปิดเครื่อง กล้องจะรัน bootloader สั้น (สองสามวินาที) ที่ให้ OpenMV IDE อัปเดตเฟิร์มแวร์โดยไม่ต้องให้ผู้ใช้เข้าสู่โหมด DFU หลังจากหน้าต่างหมดเวลา bootloader จะส่งต่อให้ boot.py แล้ว main.py

สคริปต์ที่กำลังรันสามารถเข้า bootloader อีกครั้งตามต้องการโดยเรียก machine.bootloader()

import machine

machine.bootloader()

ไฟล์ระบบและลำดับการบูต

เฟิร์มแวร์ RT1062 mount ไฟล์ระบบสูงสุดสามระบบเมื่อบูต:

  • แฟลชภายใน — mount ที่ /flash เสมอ เก็บ main.py และ README.txt โดยค่าเริ่มต้น สร้างขึ้นในการบูตครั้งแรก

  • การ์ด microSD — หากใส่การ์ดแล้วจะ mount ที่ /sdcard

  • ROMFS — ไฟล์ระบบแบบ memory-mapped อ่านอย่างเดียวที่ /rom ใช้จัดส่งสินทรัพย์ข้อมูลขนาดใหญ่ (เช่น โมเดล AI) ที่ได้ประโยชน์จากการเข้าถึงแบบ zero‑copy Mount อัตโนมัติโดย MicroPython เมื่อเริ่มต้น ก่อนที่ Python ของผู้ใช้ใด ๆ จะรัน

หลังจาก mount แล้ว working directory จะตั้งเป็น /sdcard เมื่อมีการ์ดอยู่ มิฉะนั้นเป็น /flash จากนั้น interpreter จะรันสคริปต์จากไดเรกทอรีนั้น:

  • boot.py ถูกรันในทุก soft reset (บูตเย็น, Ctrl‑D จาก REPL หรือเมื่อสคริปต์ที่รันอยู่คืนค่า)

  • main.py ถูกรัน เฉพาะเมื่อบูตเย็นเท่านั้น ทันทีหลัง boot.py soft reset ถัดไปจะรัน boot.py อีกครั้งแต่กลับไปยัง REPL โดยตรง — หากต้องการรัน main.py อีกครั้งต้องรีเซ็ตบอร์ดโดยสมบูรณ์

การวาง boot.py หรือ main.py ลงในการ์ด SD จะแทนที่สำเนาใน flash โดยไม่แตะต้องมัน — ไฟล์ทั้งสองถูกค้นหาในไดเรกทอรีบูต (/sdcard เมื่อ mount การ์ดแล้ว มิฉะนั้น /flash)

main.py เริ่มต้นที่จัดส่งมาบนบอร์ดที่แฟลชใหม่เพียงแค่กะพริบช่อง น้ำเงิน ของ User RGB LED เป็นสัญญาณการเต้นของหัวใจ (สองพัลส์สั้น, ช่องว่างสั้น) เพื่อให้รู้ว่าเฟิร์มแวร์บูตสำเร็จโดยไม่มีโฮสต์ต่ออยู่

sys.path ได้รับการขยายให้รวมไฟล์ระบบทั้งสามและ subdirectory lib/ ของแต่ละระบบ ดังนั้นโมดูลที่นำเข้าได้สามารถอยู่ใน /flash/lib, /sdcard/lib หรือ /rom/lib

หากต้องการให้ระบบละเว้นการ์ด SD ที่ใส่อยู่ (เช่น เพื่อรัน main.py ใน flash แม้มีการ์ดอยู่) ให้สร้างไฟล์ว่างชื่อ SKIPSD ที่ root ของ /flash

เมื่อเชื่อมต่อผ่าน USB ไฟล์ระบบบูต (/sdcard หากมีการ์ด มิฉะนั้น /flash) จะแสดงเป็นไดรฟ์ USB mass‑storage บนโฮสต์ด้วย ให้คุณแก้ไข boot.py, main.py และไฟล์อื่น ๆ โดยตรง Eject ไดรฟ์ก่อนรีเซ็ตกล้อง เพื่อให้โฮสต์ flush การเขียนที่แคชไว้

Note

เนื่องจาก OS ถือว่าไดรฟ์เป็นอุปกรณ์บล็อกแบบ passive ไฟล์ที่สร้างหรือแก้ไขโดยโค้ดที่รันบน OpenMV Cam จะไม่ปรากฏจนกว่าโฮสต์จะ remount ไดรฟ์ หาก OS และ OpenMV Cam เขียนไฟล์ระบบเดียวกันในเวลาเดียวกัน OS จะชนะและเขียนทับการเปลี่ยนแปลงที่กล้องทำ ใช้การ์ด SD สำหรับข้อมูลที่สคริปต์เขียนกลับ และ remount ก่อนอ่านไฟล์เหล่านั้นจากโฮสต์

Note

ช่อง แดง ของ User RGB LED อาจสว่างขึ้นชั่วครู่ขณะที่โฮสต์กำลังอ่านจากหรือเขียนไปยังไดรฟ์ USB mass‑storage — นี่คือตัวบ่งชี้กิจกรรมที่ขับโดยเฟิร์มแวร์ ไม่ใช่ข้อผิดพลาด

ขนาดพื้นที่เก็บข้อมูล

RT1062 จัดส่งมาพร้อมกับ:

  • /flash — ไฟล์ระบบ FAT ขนาด 4 MB อ่าน/เขียน

  • /rom — ROMFS แบบ memory-mapped อ่านอย่างเดียวขนาด 8 MB ใช้จัดส่งสคริปต์และโมเดล ML ที่ได้ประโยชน์จากการเข้าถึง mmap แบบ zero-copy

  • /sdcard — ขนาดเต็มของการ์ด microSD ที่ใส่ไว้ (เมื่อมีอยู่) อ่าน/เขียน

ตัวบ่งชี้ hard fault

หาก User RGB LED วนรอบผ่านทุกสี อย่างรวดเร็ว — เร็วพอที่มักดูเหมือน LED ขาวที่กระพริบ มากกว่าสีที่แตกต่างกัน — เฟิร์มแวร์เกิด hard fault ที่ไม่สามารถกู้คืนได้ Reflash เฟิร์มแวร์เพื่อกู้คืน หากการ reflash ไม่ช่วย บอร์ดอาจเสียหายทางกายภาพ

ไลบรารีซอฟต์แวร์

ดู ดัชนีไลบรารี สำหรับรายการโมดูลทั้งหมด รวมถึงโมดูลที่เป็นเอกลักษณ์ของ build RT1062