OpenMV Cam M4

OpenMV Cam M4는 180 MHz의 STMicroelectronics STM32F427을 기반으로 만들어진 소형 Cortex‑M4 머신 비전 보드로, 256 KB의 내장 SRAM과 1 MB의 내장 플래시를 갖추고 있습니다. 기본 제공되는 OV7725 센서는 320×240 그레이스케일 또는 RGB565 프레임을 캡처하며, 9핀 사용자 헤더는 UART, I²C, SPI, CAN, ADC/DAC, PWM 주변장치를 노출합니다.

참고

OV7725은 양산 M4 보드의 표준 센서였습니다. 매우 초기 변형 M4는 대신 OmniVision OV2640을 탑재하고 출하되었습니다 — 동일한 QVGA 프리뷰 파이프라인을 가지지만, OV2640은 최대 UXGA(1600×1200) JPEG 프레임도 캡처할 수 있습니다. 두 센서 모두 동일한 csi — 카메라 센서 API를 통해 구동됩니다.

OpenMV Cam M4

전체 데이터시트, 사진, 치수는 OpenMV Cam M4 제품 페이지 를 참조하세요.

주요 특징

  • STMicroelectronics STM32F427 Cortex‑M4, 180 MHz.

  • 256 KB 내장 SRAM — 외장 SDRAM 없음.

  • 1 MB 내장 플래시 (외장 QSPI 플래시 없음).

  • OV7725 센서 (또는 매우 초기 변형 M4의 경우 OV2640) — 320×240 8비트 그레이스케일 또는 RGB565; OV2640은 추가로 최대 UXGA(1600×1200) JPEG를 캡처할 수 있습니다.

  • 풀 스피드 USB (12 Mb/s) — 호스트에는 VCP + USB 대용량 저장 장치로 나타납니다.

  • microSD 소켓 — SD는 최대 2 GB, SDHC는 최대 32 GB, SDXC는 최대 2 TB.

  • 9개의 I/O 핀, 3.3 V 출력에 5 V 허용, 핀당 25 mA(헤더 전체 합계 120 mA), 인터럽트 지원. P6은 ADC 또는 DAC 모드로 사용될 때 5 V를 허용하지 않습니다.

  • 저조도 비전에서의 능동 조명을 위한 사용자 RGB LED 및 두 개의 고출력 850 nm IR LED.

참고

M4에는 온보드 전원 관리 칩이 없습니다: 배터리 커넥터, 배터리 충전기, 배터리 전압 ADC, 충전/전원 상태 LED, 하드웨어 전원 버튼이 없습니다. USB 또는 VIN으로 보드에 전원을 공급하세요.

핀아웃

OpenMV Cam M4 OV7725 핀아웃

핀 레퍼런스

핀 이름

기능

P0

SPI2 MOSI

P1

SPI2 MISO

P2

SPI2 SCK / CAN2 TX

P3

SPI2 NSS (CS) / CAN2 RX

P4

I2C2 SCL / UART3 TX / TIM2 CH3

P5

I2C2 SDA / UART3 RX / TIM2 CH4

P6

ADC / DAC / TIM2 CH1

P7

TIM4 CH1

P8

TIM4 CH2

RESET

GND로 당기면 보드가 리셋됩니다

BOOT0

전원 인가 시 3.3 V로 당기면 DFU / ROM 부트로더로 진입

SWCLK

ARM SWD 클록 (디버거 접근)

SWDIO

ARM SWD 데이터 (디버거 접근)

LED_RED

RGB LED 적색 채널 (액티브 로우)

LED_GREEN

RGB LED 녹색 채널 (액티브 로우)

LED_BLUE

RGB LED 청색 채널 (액티브 로우)

LED_IR

고출력 IR LED (두 채널이 함께 구동됨)

전원 핀

  • 3.3V — 안정화된 3.3 V 레일. 실드용으로 최대 250 mA 사용 가능(microSD 카드 사용 중이면 더 적음). 최신 카메라와 달리 이 핀은 양방향입니다 — 아래 경고를 참조하세요.

  • VIN — 3.6 – 5 V 입력. 온보드 레귤레이터를 통해 보드에 전원을 공급합니다.

  • GND — 공통 접지.

참고

USB와 VIN이 모두 연결되어 있으면 더 높은 전압을 가진 쪽이 보드에 전원을 공급합니다 — 온보드 다이오드가 단순히 더 강한 레일을 선택합니다.

경고

온보드 레귤레이터를 거치고 싶지 않다면 3.3 V를 3.3V 핀에 직접 공급하여 M4에 전원을 공급할 수 있습니다. 그 경우 VIN이나 USB 전원을 동시에 인가하지 마세요 — 다른 전원이 활성화된 상태에서 레귤레이터를 역구동하면 카메라가 영구적으로 손상되고 파괴될 수 있습니다.

주어진 활성/딥슬립 듀티 사이클에서 M4가 배터리로 얼마나 오래 작동할지 모델링하려면 배터리 수명 추정기 를 사용하세요.

복구 및 디버그 핀

  • RESET — GND로 당기면 보드가 리셋됩니다. 이를 해제하면 MCU가 정상적으로 시작됩니다.

  • BOOT0 — 보드에 전원을 공급하는 동안 3.3 V로 당기면 STM32 ROM 부트로더(DFU 모드)로 진입합니다. OpenMV IDE는 이 모드를 사용하여 온보드 부트로더를 다시 플래시합니다.

SWCLK와 SWDIO는 (전용 SWD 커넥터가 아닌) 일반 헤더 핀으로 노출되어 있습니다. 보드를 디버그하려면 RESET, SWCLK, SWDIO, GND, 3.3 V를 ST‑LINK 또는 SEGGER J‑Link 어댑터에 연결하세요.

온보드 주변장치

LED

M4에는 단일 사용자 RGB LED와 한 쌍의 고출력 850 nm IR LED가 있습니다:

  • 사용자 RGB LED — 소프트웨어로 제어 가능하며, LED_RED, LED_GREEN, LED_BLUE 로 노출됩니다:

    from machine import LED
    
    LED("LED_RED").on()
    LED("LED_GREEN").on()
    LED("LED_BLUE").on()
    
  • IR LED — 두 LED는 LED_IR 핀을 통해 함께 구동됩니다. LED_IR 은 하드웨어에서 액티브 하이로 배선되어 있는 반면 펌웨어는 다른 모든 온보드 LED를 액티브 로우로 취급하므로, on() / off() (의미가 반전됨) 대신 low() / high() 를 사용하세요:

    from machine import LED
    
    ir = LED("LED_IR")
    ir.low()    # turn IR illumination ON
    ir.high()   # turn IR illumination OFF
    

카메라 센서

기본 제공 센서(표준 보드의 OV7725, 매우 초기 변형의 OV2640)는 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()

M4의 센서는 보드에 납땜되어 있습니다 — 교체 가능한 모듈에 있지 않습니다.

참고

OV7725 보드에서는 센서의 FSIN(프레임 동기) 핀이 MCU에 연결되어 있지만 이에 대한 펌웨어 지원은 아직 추가되지 않았습니다.

OV2640 보드에서는 센서의 STROBE, FREX(프레임 노출), EXPST(노출 리셋) 핀이 MCU에 연결되어 있지만 이에 대한 펌웨어 지원은 아직 추가되지 않았습니다.

서보 헤더

보드 뒷면에는 P7P8용 표준 3핀 서보 헤더(신호 / VIN / GND)를 노출하는 두 개의 서보 커넥터 납땜 패드가 있습니다. 신호 핀은 곧바로 TIM4 채널 1과 2(pyb.Servo 가 사용하는 것과 동일한 채널)에 매핑되며, 각 헤더의 V+ 핀은 직접 VIN에 배선되어 있어 서보는 3.3 V 레귤레이터가 아닌 입력 레일에서 전류를 끌어옵니다.

패드에 직각 3핀 헤더 한 쌍을 납땜하고 두 개의 취미용 서보를 연결하여 팬‑틸트 마운트를 구동하세요:

from pyb import Servo

pan  = Servo(1)              # P7 — TIM4 CH1
tilt = Servo(2)              # P8 — TIM4 CH2
pan.angle(0)
tilt.angle(0)

microSD 카드

카드가 삽입되면 자동으로 /sdcard 에 마운트되며 일반 파일 시스템을 통해 사용할 수 있습니다:

import os

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

버스 레퍼런스

GPIO

실크스크린된 핀 중 아무거나 읽거나 구동하려면 machine.Pin 을 사용하세요. 출력은 3.3 V CMOS이고, 입력 측에서 5 V를 허용하며, 핀당 최대 25 mA를 싱크/소스할 수 있습니다(헤더 전체 합계 120 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

UART3

P4

P5

from machine import UART

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

I²C

버스

SCL

SDA

I2C2

P4

P5

from machine import I2C

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

동일한 하드웨어를 machine.I2CTarget 를 통해 타깃(슬레이브) 모드로 사용하여 다른 I²C 컨트롤러에 메모리 영역을 노출할 수도 있습니다:

from machine import I2CTarget

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

SPI

버스

MOSI

MISO

SCK

CS

SPI2

P0

P1

P2

P3

from machine import SPI
from machine import Pin

spi = SPI(2, 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

CAN2

P2

P3

from machine import CAN

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

ADC 및 DAC

P6은 유일한 사용자 아날로그 핀입니다. 12비트 ADC 입력 또는 DAC 출력 중 하나로 사용할 수 있습니다.

  • ADC — 핀에서 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)
    
  • DACpyb.DAC 를 통해 사용합니다. 8비트 값이 0–3.3 V를 커버합니다:

    from pyb import DAC
    
    dac = DAC("P6")
    voltage = 1.65
    dac.write(int(voltage / 3.3 * 255))
    

ADC 또는 DAC 모드에서 P6은 3.3 V만 허용 — 5 V를 공급하지 마세요.

PWM

타이머 / 채널

P4

TIM2 CH3

P5

TIM2 CH4

P6

TIM2 CH1

P7

TIM4 CH1

P8

TIM4 CH2

참고

TIM1은 카메라 센서의 픽셀 클록을 생성하기 위해 펌웨어에 의해 예약되어 있으므로, P0/P1/P2에 물리적으로 있는 TIM1 채널은 카메라를 손상시키지 않고는 사용자 PWM에 사용할 수 없습니다.

TIM4는 pyb.Servo공유됩니다 — 서보를 인스턴스화하면 타이머 전체가 50 Hz 동작으로 재구성되므로, 동일한 스크립트에서 P7/P8의 machine.PWMpyb.Servo 와 혼용하지 마세요.

그중 아무거나 machine.PWM 을 통해 구동하세요:

from machine import Pin, PWM

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

소프트웨어 비트뱅 버스

추가 버스가 필요한 경우 machine.SoftI2Cmachine.SoftSPI 는 모든 GPIO에서 동작합니다.

열화상 센서 (오프보드)

펌웨어에는 외부 배선된 열화상 이미저를 위한 fir — 열 센서 드라이버 (fir == far infrared, 원적외선) 드라이버가 포함되어 있습니다:

  • MLX90621 — 16 × 4 IR 어레이

  • MLX90640 — 32 × 24 IR 어레이

  • MLX90641 — 16 × 12 IR 어레이

  • AMG8833 — 8 × 8 IR 어레이

모듈을 보드의 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 2를 통해서만 센서와 통신합니다 — 모듈을 P4 (SCL)와 P5 (SDA)에 배선하세요.

타이밍

time

time 모듈은 블로킹 지연, 모노토닉 틱, 경과 시간 측정을 다룹니다:

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)

가상 타이머

machine.Timer 는 하드웨어 타이머 슬롯을 소비하지 않고 주기적 또는 일회성 콜백을 스케줄링합니다. 가상(소프트웨어) 타이머를 사용하려면 id로 -1 을 전달하세요:

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"))

주기 값은 밀리초 단위입니다. 슬롯을 멈추고 해제하려면 deinit() 을 호출하세요.

실시간 클록

machine.RTC 는 리셋 전반에 걸쳐 벽시계 시간을 유지합니다:

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())

워치독

machine.WDT 는 애플리케이션이 멈추면 보드를 리셋합니다. 일단 시작되면 멈추거나 재구성할 수 없습니다 — 메인 루프 안에서 주기적으로 피드(feed)하세요:

from machine import WDT

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

부팅 및 런타임 정보

USB 부트로더 윈도우

전원이 켜질 때마다 카메라는 짧은 부트로더(몇 초)를 실행하여, 사용자가 DFU 모드로 진입하지 않고도 OpenMV IDE가 펌웨어를 업데이트할 수 있게 합니다. 윈도우가 만료되면 부트로더는 boot.py 에 이어 main.py 로 제어를 넘깁니다.

실행 중인 스크립트는 machine.bootloader() 를 호출하여 필요할 때 부트로더로 다시 진입할 수 있습니다:

import machine

machine.bootloader()

파일 시스템 및 부팅 순서

M4 펌웨어는 부팅 시 최대 세 개의 파일 시스템을 마운트합니다:

  • 내장 플래시 — 항상 /flash 에 마운트됩니다. 기본적으로 main.pyREADME.txt 를 담고 있으며, 최초 부팅 시에 생성됩니다.

  • microSD 카드 — 카드가 삽입되어 있으면 /sdcard 에 마운트됩니다.

  • ROMFS/rom 에 있는 읽기 전용, 메모리 매핑 파일 시스템으로, 제로 카피 접근의 이점을 누리는 대용량 데이터 자산(예: AI 모델)을 제공하는 데 사용됩니다. 사용자 Python이 실행되기 전, 시작 시 MicroPython에 의해 자동으로 마운트됩니다.

마운트 후, 카드가 있으면 작업 디렉터리가 /sdcard 로 설정되고, 그렇지 않으면 /flash 로 설정됩니다. 그런 다음 인터프리터는 해당 디렉터리에서 스크립트를 실행합니다:

  • boot.py모든 소프트 리셋(콜드 부트, REPL에서의 Ctrl‑D, 또는 실행 중인 스크립트가 반환될 때마다)에서 실행됩니다.

  • main.pyboot.py 직후, 콜드 부트 시에만 실행됩니다. 이후의 소프트 리셋은 boot.py 를 다시 실행하지만 곧바로 REPL로 떨어집니다 — main.py 를 다시 실행하려면 보드를 완전히 리셋해야 합니다.

boot.py 또는 main.py 를 SD 카드에 넣으면 플래시의 사본을 건드리지 않고 그것을 재정의합니다 — 두 파일 모두 부팅 디렉터리(카드가 마운트되어 있으면 /sdcard, 그렇지 않으면 /flash)에서 조회됩니다.

새로 플래시된 보드에 기본 제공되는 main.py 는 단지 사용자 RGB LED의 청색 채널을 하트비트로 깜박일 뿐이므로(짧은 펄스 두 번, 짧은 간격), 호스트를 연결하지 않고도 펌웨어가 정상적으로 부팅되었는지 알 수 있습니다.

sys.path 는 세 파일 시스템 모두와 그들의 lib/ 하위 디렉터리를 포함하도록 확장되므로, 임포트 가능한 모듈은 /flash/lib, /sdcard/lib, /rom/lib 에 둘 수 있습니다.

시스템이 삽입된 SD 카드를 무시하도록 강제하려면(예: 카드가 있어도 플래시의 main.py 를 실행하려면) /flash 의 루트에 SKIPSD 라는 이름의 빈 파일을 생성하세요.

USB로 연결되면 부팅 파일 시스템(카드가 있으면 /sdcard, 그렇지 않으면 /flash)도 호스트에서 USB 대용량 저장 드라이브로 열거되어 boot.py, main.py 및 기타 파일을 직접 편집할 수 있습니다. 호스트가 캐시된 쓰기를 플러시하도록 카메라를 리셋하기 전에 드라이브를 꺼내세요(eject).

참고

OS가 드라이브를 수동 블록 장치로 취급하기 때문에, OpenMV Cam에서 실행되는 코드가 생성하거나 수정한 파일은 호스트가 드라이브를 다시 마운트할 때까지 나타나지 않습니다. OS와 OpenMV Cam이 동시에 같은 파일 시스템에 쓰면 OS가 이기고 카메라가 만든 변경 사항을 덮어씁니다. 스크립트가 기록하는 데이터에는 SD 카드를 사용하고, 호스트에서 해당 파일을 읽기 전에 다시 마운트하세요.

참고

호스트가 USB 대용량 저장 드라이브에서 읽거나 쓰는 동안 사용자 RGB LED의 적색 채널이 잠시 켜질 수 있습니다 — 이는 펌웨어가 구동하는 활동 표시기이지 결함이 아닙니다.

저장 용량

M4는 다음을 탑재하고 출하됩니다:

  • /flash32 KB FAT 파일 시스템, 읽기/쓰기.

  • /rom128 KB 읽기 전용 메모리 매핑 ROMFS.

  • /sdcard — 삽입된 microSD 카드의 전체 용량(있는 경우), 읽기/쓰기.

하드 폴트 표시기

사용자 RGB LED가 모든 색상을 빠르게 순환하고 있다면 — 뚜렷한 색조라기보다 반짝이는 흰색 LED처럼 보일 정도로 빠르게 — 펌웨어가 복구 불가능한 하드 폴트에 빠진 것입니다. 복구하려면 펌웨어를 다시 플래시하세요; 다시 플래시해도 도움이 되지 않으면 보드가 물리적으로 손상되었을 수 있습니다.

소프트웨어 라이브러리

M4 빌드에 고유한 모듈을 포함한 전체 모듈 목록은 라이브러리 색인 을 참조하세요.