Fastest serial communication

Hi,

in theory, what is the fastest way of serial communication between OpenMV M7 and a Linux computer? I am about to transfer images to the PC. I have tried the serial port through the pins (UART1 with a USB-serial converter, CP2104) and also through the USB cable with USB_VCP.

I was not able to achieve a faster communication than ca. 512 kbit/sec even though as I understood I should be able to reach max.2Mb/s with the CP2104 and over 12Mb/s with the USB wire.

Of course I have tried with different baudrates. I am pasting my codes below which might help for many people playing with serial communication.

Here is my code on cam:

# Cam serial communication speed test - By: @pvadam - Thu Aug 2 2018

import sensor, image, time
from pyb import LED, UART, USB_VCP

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)

led_blue = LED(3)
led_green = LED(2)
usb = USB_VCP()

clock = time.clock()

uart = UART(1)
uart.init(1152000, bits=8, parity=None, stop=1, timeout=1000, flow=0, timeout_char=0, read_buf_len=64)

USE_USB_CONVERTER = True

def send(data):
    if USE_USB_CONVERTER:
        uart.write(data)
    else:
        usb.send(data)

i = 0
start_signal = '____start____'
end_signal = '____end____'
while(True):
    clock.tick()
    i += 1
    led_blue.on()
    img = sensor.snapshot()         # Take a picture and return the image.
    img_compressed = img.compress(quality=60)
    send(b'{0}save_image{1}'.format(start_signal, end_signal))
    send(start_signal)
    send(img_compressed)
    send(end_signal)
    led_blue.off()

The code on the receiver part:

import serial
import io
import sys
import time

device = sys.argv[1]

if device == None:
    device = '/dev/ttyUSB0'

ser = serial.Serial(device)  # open serial port
ser.baudrate = 1152000
ser.bytesize = serial.EIGHTBITS
ser.parity = serial.PARITY_NONE
ser.stopbits = serial.STOPBITS_ONE
ser.timeout = 1  # timeout in seconds
ser.xonxoff = False
ser.inter_byte_timeout = None
print(ser.name)         # check which port was really used

ser.flushInput()
ser.flushOutput()

separator_start = '____start____'
separator_end = '____end____'
def read_data(ser, buf=b''):
    # Read enough data for a message
    while separator_start not in buf:
        buf += ser.read(ser.inWaiting())

    # Remove the garbage before the message start position
    start_pos = buf.find(separator_start)
    buf = buf[start_pos:]
    
    cnt = 0
    # Wait for the whole message
    while not (separator_start in buf and separator_end in buf):
        buf += ser.read(ser.inWaiting())
        cnt += 1

    # Locate message separators
    end_pos = buf.find(separator_end)
    start_pos = buf.find(separator_start)

    # Save the beginning of the next message if any
    new_msg = buf[end_pos + len(separator_end):]
    
    # Extract the message
    msg = buf[start_pos+len(separator_start):end_pos]
    
    return [msg, new_msg]

i = 0
line = []
msgs = [b'', b'']
running = True
try:
    while True:
        msgs = read_data(ser, msgs[1])
        msg = msgs[0]
        if msg == 'save_image':
            print('save command')
        else:
            i += 1
            ct = time.localtime()
            ct_str = '{0}{1}{2}_{3}{4}{5}'.format(ct.tm_year, ct.tm_mon, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec)
            f = open("images/img_{1}_{0}_{2}.jpg".format(i, ser.name.replace('/', '_'), ct_str), 'wb')  # open in binary
            f.write(msg)
            f.close()
            print(ct_str)
            print('image saved', len(msg))
        
except:
    ser.close()  # close port
    raise

Thank you,
Peter

Hi, the print() sends data over the USB serial port to any application that opens the serial port. Note that you can’t use the USB VCP or receive any data with print when OpenMV IDE is using the camera.

Anyway:

print(img.compress(), end=‘’)

Generally is fast. Note that when used with OpenMV IDE you need to change compress to compress_for_ide(). Finally, when the serial port is open by the IDE the OpenMV Cam will not block on writes… However, when not opened by the IDE the camera will. Debug mode for USB happens when opening the serial port with a baud rate of 12000000. Note that when opening the serial port on a PC the baud rate doesn’t actually matter except as being a flag to enter into the debug mode protocol OpenMV IDE uses.

Note, Ibrahim got WiFi programming working. We will release a new way to communicate to the camera soon. Effectively the USB debug experience over WiFi.

Hi,

thank you for the quick reply. I am still confused a bit since I do not know how the image transfer could be faster. I never attach the IDE when testing the transfer speed to the PC. I always use different baud rates than 921600 and 12000000.

The other TTL serial port can also be used with the cam and OpenMV IDE at the same time… But, then you have to use another USB to serial adapter which will be limited to 3mbs… Not as fast as the 12mbs full speed USB.

In the linked post you have mentioned the full speed is 12 Mbps, so my 0.5 Mbps could be improved a lot I guess, but I got stuck with this. And if I use the TTL pins with the USB to serial adapter, I can almost reach the 1152000 baud rate, though the error rate is a bit higher. So actually I have a better performance through the TTL pins with the adapter than the USB port.

I have removed the image snapshot capturing and image compression out of the loop (sending the same image always) to have a cleaner view, so I indeed simply testing the data transfer part. I have also changed the send command to

print(img.compress(), end='')

, but I guess that

usb.send(img.compress())

does the same.

Could you please advise if it could be significantly faster?

Thanks,
Peter

Mmm, your scripts look fine. Question, can you profile things and see what the camera is spending it’s time on? Also, what model are you using? Is this the M4 or M7?

It’s an M7. What profiling do you mean? I might have some progression now, still verifying…

Um, profiling means to find what part was being slow.

:slight_smile:) You’re cute. I meant if I should use a logic analyzer or the code only. I guess you meant the code only, but that is so simple that there is hardly anything to profile. Anyways, I will return to the issue very soon and try to fix.

Okay.