Problem running usb_vcp.py code.

Hello.

I have been trying to establish a connection between my openMV M7 camera and a raspberry pi 3 B+ model.
I used the following code, found in the openMV github repo.
https://github.com/openmv/openmv/blob/master/scripts/examples/02-Board-Control/usb_vcp.py

I currently encounter this error:

That looks like no data was received and then you Ctrl+c the script.

Hey! Thanks for the reply.
You’re spot on with your analysis.

I saved the script as main.py on the camera.
Thereafter I ran the commented script on my raspberry pi. Are there any probable reasons for this to occur?

Yes, a couple of things can happen. 1st, what serial port name does your OpenMV Cam appear as? The script we gave as an example expects a certain serial port name.

Other than that… Can you verify the main.py script on the camera is the example script and was saved to the camera as main.py? Please check after a power cycle of the camera.

Hello. Thanks for your replies.

The problem suddenly went away, I am not exactly sure how it did.
So I have progressed on with my work.

Currently, I am trying to coordinate a robot arm with your camera.
I have integrated the usb_vcp code with the Single Color RGB565 Blob Tracking Example to send out the following parameters: blob.cx(), blob.cy().
I use the same receive code used on usb_vcp, modified for integer transmission.

Even though, the coordinates do get passed on, I have encountered a number of problems:

  1. a lot of garbage values are transmitted. (to overcome this, I filtered them using the frame size dimensions)
  2. the receiving side stops receiving data after a while.


    Is there a way to completely eliminate garbage transmission. My knowledge on the serial communication protocols being used here is rather limited.

This is the code running on the camara.


This is the code I have on the receiving end

Filtered output with correct details

Raw output with garbage

Can you post the code in non screen shot form?

Code running on camera

# Single Color RGB565 Blob Tracking Example
#
# This example shows off single color RGB565 tracking using the OpenMV Cam.


import sensor, image, time, math, pyb, ustruct
from pyb import USB_VCP



#def blobDetails(blobInput, xMin, xMax, yMin, yMax):

led = pyb.LED(1) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4.
threshold_index = 0 # 0 for red, 1 for green, 2 for blue

# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green/blue things. You may wish to tune them...
thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds
              (30, 100, -64, -8, -32, 32), # generic_green_thresholds
              (0, 30, 0, 64, -128, 0)] # generic_blue_thresholds

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()


# Creat usb virtual communication port.
usb = USB_VCP()

# Switch on red led to indicate program is running
led.on()


# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are
# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the
# camera resolution. "merge=True" merges all overlapping blobs in the image.



while(True):


    img = sensor.snapshot()
    for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):


        print(clock.tick())
        # These values depend on the blob not being circular - otherwise they will be shaky.
        if blob.elongation() > 0.5:
            img.draw_edges(blob.min_corners(), color=(255,0,0))
            img.draw_line(blob.major_axis_line(), color=(0,255,0))
            img.draw_line(blob.minor_axis_line(), color=(0,0,255))
        # These values are stable all the time.
        img.draw_rectangle(blob.rect())
        img.draw_cross(blob.cx(), blob.cy())
        # Note - the blob rotation is unique to 0-180 only.
        img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
        print("blob rectangle ", blob.rect())
        print("blob center.", blob.cx(), blob.cy())
        
        cmd = usb.recv(4, timeout=5000)
        if (cmd == b'snap'):
            usb.send(ustruct.pack("<II", blob.cx(), blob.cy()))

Code running on receiving side(raspberry pi 3 b+)

#!/usr/bin/env python2.7
import sys, serial, struct
port = '/dev/ttyACM0'

sp = serial.Serial(port, baudrate=115200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,
             xonxoff=False, rtscts=False, stopbits=serial.STOPBITS_ONE, timeout=None, dsrdtr=True)
sp.setDTR(True) # dsrdtr is ignored on Windows.
while(True):
    sp.write("snap")
    sp.flush()
    sentData = struct.unpack('<II', sp.read(8))
    
    # Raw output.
    '''print("X coordinate: {0}, Y coordinate: {1}".format(sentData[0], sentData[1]))'''

    # Filter garbage.
    if ((sentData[0] > -1) and (sentData[0] < 320)):
        if ((sentData[1] > -1) and (sentData[1] < 240)):
            print("X coordinate: {0}, Y coordinate: {1}".format(sentData[0], sentData[1]))
    
sp.close()

Hi, just remove all the print() statements and the code will work as expected, you can’t print while using USB VCP, all that output goes through USB as well.

For clarification, we only have one USB link to the PC. Print and the vcp send method do effectively the same thing and both use the same pipe.

If you’d like to make your code more flexible If recommend just using the print method only and USB vcp read method.

Then, in the desktop code just parse lines of text and ignore lines that don’t start with like a certain character combo.

I am not in the lab right now, it is the weekend. I have no way to test the code out anymore.

The knowledge youy guys have is incredible.

Does this method of communication enable full duplex communication?

Yes, it’s full duplex. The fifo buffer on the OpenMV Cam can receive about 512 bytes before running out of space.