Skip to content

Demo Code

Software Requirements

This example is written for Arduino and requires the IDE, the Thing Plus - RP2350 board definition included in the Arduino Pico boards package as well as the SparkFun iCap OV5640 and SparkFun HSTX ST7789 Arduino libraries. Make sure you've gone through the boards package installation instructions in the Arduino Setup section of this guide and then follow the instructions below to install the required libraries.

Required Libraries

The example requires the SparkFun ImageCapture and RP2 HSTX ST7789 Arduino Libraries. You can install them through the Library Manager in the Arduino IDE by searching for "SparkFun ImageCapture" and "SparkFun RP2 HSTX ST7789" and install the latest version. Alternatively, you can download a ZIP of each library to manually install them by clicking the buttons below:

SparkFun ImageCapture Arduino Library (ZIP)

SparkFun RP2 HSTX ST7789 Arduino Library (ZIP)

With the libraries installed, let's move on to uploading the code.

Vision Demo Example Code

The example code for this demo can be found in the Thing Plus - RP2350 GitHub Repository in the "Examples/Vision_Demo" folder. You can find it from the link above or download a ZIP of the entire repository by clicking the button below:

Thing Plus - RP2350 GitHub Repo (ZIP)

Open up the example in Arduino or open a blank sketch and copy the code below:

Vision Demo
#include "SparkFun_iCap_OV5640.h"
#include "SparkFun_RP2_HSTX_ST7789_Arduino_Library.h"

// Configuration for the display
RP2_HSTX_ST7789_Config displayConfig = {
    .pinDin  =   18, // Must support HSTX (GPIO 12-19 on RP2350)
    .pinSck  =   19, // Must support HSTX (GPIO 12-19 on RP2350)
    .pinCs   =   16, // Must support HSTX (GPIO 12-19 on RP2350)
    .pinDc   =   17, // Must support HSTX (GPIO 12-19 on RP2350)
    .pinRst  =   -1, // Any GPIO pin, or -1 if not connected
    .pinBl   =   -1, // Any GPIO pin, or -1 if not connected
    .width   =  320, // Display width
    .height  =  240, // Display height
    .rawMode = true, // Whether to use raw mode
};

// Set up arch and pins structures for Pico RP2040.
iCap_arch arch =
{
    .pio = pio0, // Can be pio0, pio1, or pio2 on the RP2350
    .bswap = false // Whether to swap the camera data bytes
};

// Pins for the OV5640 camera
OV5640_pins pins =
{
    .enable = -1, // Any GPIO pin, or -1 if not connected
    .reset  = -1, // Any GPIO pin, or -1 if not connected
    .xclk   = 11, // Any GPIO pin
    .pclk   = 26, // Any GPIO pin
    .vsync  = 27, // Any GPIO pin
    .hsync  = 28, // Any GPIO pin
    .data   = {0, 1, 2, 3, 4, 5, 6, 7}, // Any GPIO pins, must be sequential!
    .sda    = 20, // Any I2C pin pair
    .scl    = 21  // Any I2C pin pair
};

// Create an instance of the camera
SparkFun_iCap_OV5640 cam(pins, &arch, Wire1);

// Create an instance of the display
RP2_HSTX_ST7789 display;

// Threshold pin
int thresholdPin = 22;

void setup() {
    Serial.begin(115200);
    Serial.println("Hello! Camera Test.");

    // Begin camera with QVGA resolution (320x240) and RGB565 color (16-bit)
    iCap_status status = cam.begin(OV5640_SIZE_QVGA, ICAP_COLOR_RGB565);
    while(status != ICAP_STATUS_OK)
    {
        Serial.println("Camera not found, please check wiring!");
        delay(1000);
    }

    // Initialize the display
    display.begin(displayConfig);

    // Set the threshold pin as an input with pull-up
    pinMode(thresholdPin, INPUT_PULLUP);
}

void loop()
{
    // Record the current time
    uint32_t t0 = micros();

    // Get the camera buffer
    uint16_t* buffer = cam.getBuffer();

    // Check whether thresholding is requested
    bool threshold = digitalRead(thresholdPin) != 0;

    // Send the command to start a new frame
    display.startNewFrameRaw();

    // Loop through all pixels in the frame buffer
    for (int y = 0; y < displayConfig.width; ++y)
    {
        for (int x = 0; x < displayConfig.height; ++x)
        {
            // Get the pixel value from the camera buffer
            int rgb = buffer[x * displayConfig.width + y];

            // Check whether thresholding is requested
            if(threshold)
            {
                // Extract the red, green, and blue components (RGB565)
                int r = (rgb >> 11) & 0x1f;
                int g = (rgb >> 5) & 0x3f;
                int b = rgb & 0x1f;

                // Calculate the sum of the components. Only use 5 bits of green
                // to match red and blue
                int sum = r + (g>>1) + b;

                // With 5 bits per channel, the maximum sum is 96, so we'll use
                // half of that as the threshold
                if(sum >= 48)
                {
                    // We're above the threshold, so set the pixel to white
                    rgb = 0xffff;
                }
                else
                {
                    // We're below the threshold, so set the pixel to black
                    rgb = 0x0000;
                }
            }

            // Send this pixel to the display
            display.putPixelRaw(rgb);
        }
    }

    // Record the current time
    uint32_t t1 = micros();

    // Print FPS of the display
    float fps = 1e6 / (t1 - t0);
    Serial.printf("Display FPS: %.2f\n", fps);
}

Select the board (SparkFun Thing Plus - RP2350) and port and click the "Upload" button. Once the code finishes uploading, you should see the screen turn on and start displaying a live feed from the camera.

Photo showing the display running and seeing a curious owl.

If the screen remains black, press the Reset button on the Thing Plus and it should start up after that. If you do not see anything, open the Serial Monitor in Arduino with the baud set to 115200, reset the board again and check to see if the camera connection error message prints. If it does, double check the wiring to make sure everything is connected properly.