TH /TannoHubYOSHINOBU TANNO日本語 ↗
EMBEDDED SYSTEMS / VISION SENSING

Small Camera Bring-Up on RP2040:
From Sensor Identification to QQVGA and PIO+DMA

I bought a compact camera module from an overseas seller as a GC0309-based unit and started by trying to bring it up on an RP2040. Register reads later showed that the actual sensor did not match that assumption. This note records the path from identification and timing checks to QQVGA capture and PIO+DMA acquisition.

← All technical notes

Hardware test log: Sep.–Oct. 2026 · Edited:

Breadboard validation setup connecting a Raspberry Pi Pico 2 and a compact camera module
Board-level validation setup. A Raspberry Pi Pico 2 and the compact camera module were connected with jumper wires while SCCB communication, timing signals, and image-data capture were checked step by step.
Full validation setup connecting a Raspberry Pi Pico 2 and the compact camera module
Full validation setup. The Pico 2 and camera module are connected through breadboards and jumper wires; a Japanese 5-yen coin is included for scale.

I verified the system in layers: MCLK, SCCB communication, VSYNC/HSYNC/PCLK, the data bus, and finally image transport. This made it easier to isolate the failing stage even before a valid image was available.

From a GC0309 assumption to OV7670-class identification

The CM-013 unit was sold as a GC0309-based module, so that was the initial assumption. Once register reads were working over SCCB/I2C, however, the device ID values did not match it.

The device acknowledged at 7-bit address 0x21. Using a STOP→START read sequence, I successfully read multiple registers. On the tested unit, 0x0A=0x76, 0x0B=0x73, 0x1C=0x7F, and 0x1D=0xA2. Based on these values, I treated the evaluated unit as an OV7670-class sensor rather than a GC0309.

The practical lesson is simple: do not lock sensor-specific initialization to the seller's module label alone. Reading identification registers early makes it easier to separate transport problems from sensor-specific configuration problems.

RP2040 wiring

The RP2040-side signal assignment used in this evaluation was:

SignalRP2040
SDAGP0
SCLGP1
D2–D9GP2–GP9
PCLKGP10
VSYNCGP11
HSYNCGP12
MCLKExternal 24 MHz

The prototype was first validated with the breadboard wiring shown above. I verified MCLK and SCCB first, then moved on to VSYNC, HSYNC, PCLK, and the parallel data bus so that image-capture failures could be isolated by layer.

Measured timing in QQVGA mode

After configuring the sensor as an OV7670-class device, I set sensor-side QQVGA output at 160×120 in YUV422 format. The measured timing showed 120 HSYNC periods per frame, 320 PCLK periods per line, and a sensor frame rate of approximately 30.012 fps.

At 160 pixels per line, YUV422 carries an average of two bytes per pixel, so 320 PCLK periods per line is consistent with the selected mode. The important distinction is that the sensor itself running near 30 fps does not mean the complete path to the PC will achieve the same rate.

Y-only capture with PIO+DMA

For capture, I used RP2040 PIO and DMA and evaluated a path that keeps only the luminance Y component from the YUV422 stream. With sensor-side QQVGA, a 160×120 grayscale frame is 19,200 bytes.

I also prepared a PC-side viewer that displays the received grayscale image together with FPS, CRC error count, and frame-drop count. This makes it possible to inspect the image content and transport stability at the same time.

PC-side viewer displaying a 160 by 120 OV7670 grayscale stream with FPS, CRC, and drop status
PC-side viewer for the 160×120 grayscale stream. In this screenshot the application reports 15.0 fps, CRC 0, and Drop 0.

During a stable run that included PC-side display and recording, the effective rate was 15.01 fps. Over 380 consecutive frames, the result was Good frames=380, CRC errors=0, header errors=0, payload errors=0, and frame ID drops=0.

Resolution and effective frame-rate comparison

I compared three acquisition approaches in the same development path.

Acquisition methodOutputEffective rate
320×240 captureQVGA5.24 fps
Downsampling on the Pico160×12012.21 fps
Sensor-side QQVGA160×12015.01 fps

Under these conditions, asking the sensor to output QQVGA directly was more efficient than receiving QVGA first and discarding data on the RP2040. For low-bandwidth and low-resource systems, reducing the data volume at the sensor can be more effective than capturing excess data and filtering it later.

The remaining gap between the approximately 30 fps sensor timing and the approximately 15 fps end-to-end rate also shows that the bottleneck is not only the image sensor. The next measurement step is to separate acquisition time, transport time, and PC-side processing time.

Toward low-bandwidth vision sensing

Everything above this section is implemented or measured. The following items are research candidates rather than demonstrated results.

Before selecting an application, I plan to measure effective frame rate, acquisition time, transport time, loss rate, and long-duration stability so that the useful operating envelope is based on measured data rather than the nominal camera specification.

Related work

Contact me about collaborative research or technical validation.