Save image on PC from Raspberry Pico and OV5642

Hi,
I am trying to save a still on my PC from the Arducam 5MP Plus OV5642 connected to a Raspberry Pico. The camera works fine and when I use HostApp.exe I can capture with no problems. Now I am trying to save a still on my computer using Python. So far I can communicate, and send the trigger signal to capture, then I can see the buffer coming back in hex, but I am having troubles formatting it properly. This is the code I have so far, and bellow the current error. Thanks for any help!

import serial
from binascii import unhexlify

s = serial.Serial('COM9', 115200)

# Set resolution
command = "06"
command = unhexlify(command)
s.write(command)

# Grab still
command = "10"
command = unhexlify(command)
s.write(command)

currByte = b""
buffer = []

while True:
    if s.isOpen():
        line = s.readline().strip()
        print(line)
        currByte = unhexlify(b'0' + line)

s.close()

Traceback (most recent call last):
  File "E:/envs/camcontrol/camcontrol.py", line 23, in <module>
    currByte = unhexlify(b'0' + line)
binascii.Error: Odd-length string
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00\x00\x00\x00\x00\x00\xff\xdb\x00C\x00\x04\x03\x03\x04\x03\x03\x04\x04\x03\x04\x05\x04\x04\x05\x06'

Process finished with exit code 1

So, it seems no one is listening but I will keep updating this thread in case anyone finds it useful. Kind of Robinson Crusoe but without the nice beach.

I learned that I am receiving a JPEG (hence the JFIF above) and that FF and D8 is the header. Also that I need to find the end/trailer which comes as FF and D9. Now the problem is that of the many times I tried to find those FF and D9, only once I found them. It seems I am not sending the right command to retrieve, or maybe I have to do something else after sending the capture command b’\x10’. I will keep digging and spotting the horizon here and there in case some ship passes by.

while True:
    if s.isOpen():
        line = s.readline().strip()
        out_hex = ['{:02X}'.format(b) for b in line]
        h_temp = ""
        print(line)
        for h in out_hex:
            if h_temp == "FF" and h == "D9":
                print(line)
                break

Hello, again my dear readers. I made more progress, now I can save the data from Arducam/Pico to a jpg and it works. Sometimes. Most of the times if set to low resolution. Only some times if I set the resolution higher. As proof I send you one of the jpgs that I proudly saved:

This is the code that I used for this first partial success, I am reading in chunks of 128 bytes:

import serial
import binascii

s = serial.Serial('COM9', 921600)

# Set resolution
command = b'\x05'
s.write(command)

# Grab still
command = b'\x10'
s.write(command)


data = ""
stop = 0
while True:
    if s.isOpen():
        lines = s.read(128)
        out_hex = ['{:02X}'.format(b) for b in lines]
        # print(out_hex)
        h_temp = ""
        for h in out_hex:
            if h_temp == "FF" and h == "D9":
                data += h
                stop = 1
                print("Found footer")
                break
            else:
                data += h
                h_temp = h
    if stop == 1:
        break

data_b = binascii.a2b_hex(data)
with open(r"buffer.jpg", "wb") as f:
    f.write(data_b)

I think I might be skipping some step to clear the buffer, or maybe I just have to make the process wait at some point so it has time to receive all the data and that is why it fails many times.

Long ago I found that patience is a virtue. Arducam feels the same. Just add a stop between the call to the resolution setting and the grab and it finally works perfectly!

import serial
import binascii
import time

s = serial.Serial('COM9', 921600)

# Set resolution
command = b'\x05'
s.write(command)

time.sleep(1)

# Grab still
command = b'\x10'
s.write(command)


data = ""
stop = 0
while True:
    if s.isOpen():
        lines = s.read(128)
        out_hex = ['{:02X}'.format(b) for b in lines]
        # print(out_hex)
        h_temp = ""
        for h in out_hex:
            if h_temp == "FF" and h == "D9":
                data += h
                stop = 1
                print("Found footer")
                break
            else:
                data += h
                h_temp = h
    if stop == 1:
        break

data_b = binascii.a2b_hex(data)
with open(r"buffer.jpg", "wb") as f:
    f.write(data_b)

Hi i just want to thank you, cause your code help me to much to control the camera with out the .exe of arducam, i am bulding my proyect to get my degree of engineering

I am happy it worked out for you too! I ended up sync linking 12 cams to shot at the same time to later reconstruct in 3d. What is your project about? Un abrazo!