Hi there I had bought this kit recently ` https://spotpear.com/shop/Raspberry-Pi-Pico-2-RP2350-Linux-MINI-RP2350A-USB.html ` and I tried the screen it was perfect, and also I should note that in the kit there were a lot of pieces like OV5640 camera and the board itself, but when I returned to the schematics provided for this board I can see in it that it was meant to be connected with OV2640 camera, have a look on the schematics file, and when I tried to connect the camera provided in the kit it always is not recognized I had tested it using a multimeter to see if there is any major short circuit but nothing found, and the two power regulators is fine also, so I tried to push it more harder in the board and even with that didn't work, right now I don't know what to do, if anyone has a ready-made demo for using the camera I would be thankful if provided
The code I tried to test with the camera is this, and note that always the result says no ACK found:
#include
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/pwm.h"
#define CAMERA_SDA 28
#define CAMERA_SCL 29
#define ALT_CAMERA_SDA 26
#define ALT_CAMERA_SCL 27
#define CAMERA_XCLK 11
#define CAMERA_PWDN 24
#define CAMERA_VSYNC 8
#define CAMERA_HSYNC 9
#define CAMERA_PCLK 10
// This board's 24-pin connector does not place CSI_D1..CSI_D3 sequentially.
// The PIO capture code must reorder these three bits before using image data.
static const uint8_t csi_gpio_for_camera_bit[8] = {
0, 3, 2, 1, 4, 5, 6, 7
};
struct camera_reg {
uint16_t address;
uint8_t value;
};
static uint8_t camera_address = 0;
static i2c_inst_t *camera_i2c = i2c0;
static const camera_reg ov5640_qvga_rgb565[] = {
{0x3103, 0x11}, {0x3008, 0x82}, {0xffff, 10}, {0x3008, 0x02},
{0x3017, 0xff}, {0x3018, 0xff}, {0x3034, 0x1a}, {0x3035, 0x21},
{0x3036, 0x69}, {0x3037, 0x13}, {0x3108, 0x01},
{0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x00},
{0x3804, 0x0a}, {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9f},
{0x3808, 0x01}, {0x3809, 0x40}, {0x380a, 0x00}, {0x380b, 0xf0},
{0x380c, 0x07}, {0x380d, 0x68}, {0x380e, 0x03}, {0x380f, 0xd8},
{0x3814, 0x31}, {0x3815, 0x31}, {0x3820, 0x41}, {0x3821, 0x07},
{0x3a02, 0x03}, {0x3a03, 0xd8}, {0x3a08, 0x01}, {0x3a09, 0x27},
{0x3a0a, 0x00}, {0x3a0b, 0xf6}, {0x4300, 0x61}, {0x501f, 0x01},
{0x5000, 0xa7}, {0x5001, 0xa3}, {0x4713, 0x03}, {0x4407, 0x04},
{0x460b, 0x35}, {0x460c, 0x22}, {0x4837, 0x0a}, {0x3008, 0x02},
{0x0100, 0x01}
};
static bool write_register(uint16_t address, uint8_t value) {
uint8_t data[] = {
static_cast(address >> 8),
static_cast(address),
value
};
return i2c_write_blocking(camera_i2c, camera_address, data, 3, false) == 3;
}
static bool read_register(uint16_t address, uint8_t *value) {
uint8_t register_address[] = {
static_cast(address >> 8),
static_cast(address)
};
if (i2c_write_blocking(camera_i2c, camera_address, register_address, 2, true) != 2) {
return false;
}
return i2c_read_blocking(camera_i2c, camera_address, value, 1, false) == 1;
}
static bool scan_address(uint8_t address) {
uint8_t register_address = 0x30;
return i2c_write_blocking(camera_i2c, address, ®ister_address, 1, false) == 1;
}
static bool find_camera() {
const uint8_t addresses[] = {0x3c, 0x3d};
for (uint8_t address : addresses) {
camera_address = address;
if (scan_address(address)) {
printf("I2C address ACK: 0x%02X\n", address);
}
uint8_t id_high;
uint8_t id_low;
if (read_register(0x300a, &id_high) && read_register(0x300b, &id_low)) {
printf("Address 0x%02X IDs: 0x%02X 0x%02X\n", address, id_high, id_low);
if (id_high == 0x56 && id_low == 0x40) {
return true;
}
}
}
camera_address = 0;
return false;
}
static void configure_camera() {
size_t count = sizeof(ov5640_qvga_rgb565) / sizeof(ov5640_qvga_rgb565[0]);
for (size_t index = 0; index < count; index++) {
if (ov5640_qvga_rgb565[index].address == 0xffff) {
sleep_ms(ov5640_qvga_rgb565[index].value);
continue;
}
if (!write_register(ov5640_qvga_rgb565[index].address,
ov5640_qvga_rgb565[index].value)) {
printf("Write failed at register 0x%04X\n", ov5640_qvga_rgb565[index].address);
}
sleep_ms(2);
}
}
static void start_camera_clock() {
gpio_set_function(CAMERA_XCLK, GPIO_FUNC_PWM);
uint slice = pwm_gpio_to_slice_num(CAMERA_XCLK);
pwm_set_clkdiv(slice, 6.25f);
pwm_set_wrap(slice, 0);
pwm_set_chan_level(slice, pwm_gpio_to_channel(CAMERA_XCLK), 1);
pwm_set_enabled(slice, true);
}
int main() {
stdio_init_all();
stdio_usb_init();
while (!stdio_usb_connected()) {
sleep_ms(100);
}
printf("OV5640 camera-only test\n");
printf("Pins: SDA=%d SCL=%d XCLK=%d PWDN=%d VSYNC=%d HSYNC=%d PCLK=%d\n",
CAMERA_SDA, CAMERA_SCL, CAMERA_XCLK, CAMERA_PWDN,
CAMERA_VSYNC, CAMERA_HSYNC, CAMERA_PCLK);
printf("CSI mapping: D0=GPIO%d D1=GPIO%d D2=GPIO%d D3=GPIO%d D4=GPIO%d D5=GPIO%d D6=GPIO%d D7=GPIO%d\n",
csi_gpio_for_camera_bit[0], csi_gpio_for_camera_bit[1],
csi_gpio_for_camera_bit[2], csi_gpio_for_camera_bit[3],
csi_gpio_for_camera_bit[4], csi_gpio_for_camera_bit[5],
csi_gpio_for_camera_bit[6], csi_gpio_for_camera_bit[7]);
start_camera_clock();
gpio_init(CAMERA_PWDN);
gpio_set_dir(CAMERA_PWDN, GPIO_OUT);
gpio_put(CAMERA_PWDN, 0);
sleep_ms(200);
i2c_init(i2c0, 50 * 1000);
gpio_set_function(CAMERA_SDA, GPIO_FUNC_I2C);
gpio_set_function(CAMERA_SCL, GPIO_FUNC_I2C);
gpio_pull_up(CAMERA_SDA);
gpio_pull_up(CAMERA_SCL);
printf("I2C levels: SDA=%d SCL=%d\n", gpio_get(CAMERA_SDA), gpio_get(CAMERA_SCL));
printf("I2C scan: ");
bool any_device = false;
for (uint8_t address = 0x08; address <= 0x77; address++) {
if (scan_address(address)) {
printf("0x%02X ", address);
any_device = true;
}
}
printf("%s\n", any_device ? "" : "no ACKs");
if (!find_camera()) {
printf("I2C0 did not find an OV5640 with PWDN=0. Testing PWDN=1...\n");
gpio_put(CAMERA_PWDN, 1);
sleep_ms(100);
if (find_camera()) {
printf("OV5640 responds with PWDN=1; this board uses active-high PWDN.\n");
} else {
gpio_put(CAMERA_PWDN, 0);
}
}
if (camera_address == 0) {
printf("I2C0 did not find an OV5640. Testing I2C1 on GPIO26/27...\n");
i2c_init(i2c1, 50 * 1000);
gpio_set_function(ALT_CAMERA_SDA, GPIO_FUNC_I2C);
gpio_set_function(ALT_CAMERA_SCL, GPIO_FUNC_I2C);
gpio_pull_up(ALT_CAMERA_SDA);
gpio_pull_up(ALT_CAMERA_SCL);
printf("I2C1 levels: SDA=%d SCL=%d\n", gpio_get(ALT_CAMERA_SDA), gpio_get(ALT_CAMERA_SCL));
camera_i2c = i2c1;
if (!find_camera()) {
printf("OV5640 was not found on I2C0 GPIO28/29 or I2C1 GPIO26/27.\n");
while (true) {
sleep_ms(1000);
}
}
}
printf("OV5640 found at 0x%02X. Configuring QVGA RGB565...\n", camera_address);
configure_camera();
printf("Streaming enabled. Measuring camera signals...\n");
gpio_init(CAMERA_VSYNC);
gpio_set_dir(CAMERA_VSYNC, GPIO_IN);
gpio_init(CAMERA_HSYNC);
gpio_set_dir(CAMERA_HSYNC, GPIO_IN);
gpio_init(CAMERA_PCLK);
gpio_set_dir(CAMERA_PCLK, GPIO_IN);
while (true) {
uint32_t pclk_edges = 0;
uint32_t vsync_edges = 0;
uint32_t hsync_edges = 0;
bool previous_pclk = gpio_get(CAMERA_PCLK);
bool previous_vsync = gpio_get(CAMERA_VSYNC);
bool previous_hsync = gpio_get(CAMERA_HSYNC);
uint32_t start = time_us_32();
while (time_us_32() - start < 1000000) {
bool pclk = gpio_get(CAMERA_PCLK);
bool vsync = gpio_get(CAMERA_VSYNC);
bool hsync = gpio_get(CAMERA_HSYNC);
pclk_edges += pclk && !previous_pclk;
vsync_edges += vsync && !previous_vsync;
hsync_edges += hsync && !previous_hsync;
previous_pclk = pclk;
previous_vsync = vsync;
previous_hsync = hsync;
}
printf("Signals/sec: PCLK=%lu VSYNC=%lu HSYNC=%lu levels=%d/%d/%d\n",
pclk_edges, vsync_edges, hsync_edges,
gpio_get(CAMERA_VSYNC), gpio_get(CAMERA_HSYNC), gpio_get(CAMERA_PCLK));
}
}
The serial monitor:
OV5640 camera-only test
Pins: SDA=28 SCL=29 XCLK=11 PWDN=24 VSYNC=8 HSYNC=9 PCLK=10
CSI mapping: D0=GPIO0 D1=GPIO3 D2=GPIO2 D3=GPIO1 D4=GPIO4 D5=GPIO5 D6=GPIO6 D7=GPIO7
I2C levels: SDA=1 SCL=1
I2C scan: no ACKs
I2C0 did not find an OV5640 with PWDN=0. Testing PWDN=1...
I2C0 did not find an OV5640. Testing I2C1 on GPIO26/27...
I2C1 levels: SDA=0 SCL=0
OV5640 was not found on I2C0 GPIO28/29 or I2C1 GPIO26/27.