Reading stream of data sent from OpenMV to Raspberry Pi through USB

General discussion about topics related to OpenMV.
Eats
Posts: 3
Joined: Mon Apr 01, 2019 7:52 pm

Reading stream of data sent from OpenMV to Raspberry Pi through USB

Postby Eats » Mon Apr 01, 2019 8:27 pm

Hi all,

I have been trying to send a stream of data from the OpenMV which I am using for image processing and then output numbers to my Pi in order to guide a robot I am building for a project.

I am able to receive the data and read it when using the screen function on the Pi, however I seem to only be receiving unusable values when I try to read it with my python script.
I am unsure if this is a problem with how the data is being sent from the camera or if it is a problem with how the Pi is reading it.

I am using an OpenMV M7 and a Raspberry Pi 3 B+ running Ubuntu Mate.
The OpenMV code is some linear regression code from the OpenMV blog that I have made some minor changes to.

Code for the OpenMV camera:

Code: Select all

BINARY_VIEW = True
GRAYSCALE_THRESHOLD = (0, 230) #230
MAG_THRESHOLD = 4
THETA_GAIN = 40.0
RHO_GAIN = -1.0
P_GAIN = 0.7
I_GAIN = 0.0
I_MIN = -0.0
I_MAX = 0.0
D_GAIN = 0.1


import sensor, image, time, math, pyb

usb = pyb.USB_VCP()

sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QQVGA)
#sensor.set_vflip(True)
#sensor.set_hmirror(True)
sensor.skip_frames(time = 2000)
clock = time.clock()

def line_to_theta_and_rho(line):
    if line.rho() < 0:
        if line.theta() < 90:
            return (math.sin(math.radians(line.theta())),
                math.cos(math.radians(line.theta() + 180)) * -line.rho())
        else:
            return (math.sin(math.radians(line.theta() - 180)),
                math.cos(math.radians(line.theta() + 180)) * -line.rho())
    else:
        if line.theta() < 90:
            if line.theta() < 45:
                return (math.sin(math.radians(180 - line.theta())),
                    math.cos(math.radians(line.theta())) * line.rho())
            else:
                return (math.sin(math.radians(line.theta() - 180)),
                    math.cos(math.radians(line.theta())) * line.rho())
        else:
            return (math.sin(math.radians(180 - line.theta())),
                math.cos(math.radians(line.theta())) * line.rho())

def line_to_theta_and_rho_error(line, img):
    t, r = line_to_theta_and_rho(line)
    return (t, r - (img.width() // 2))

old_result = 0
old_time = pyb.millis()
i_output = 0
output = 90
operation = ""

while True:
    out_tot = 0
    out_avg = 0
    for x in range(3):
        clock.tick()
        img = sensor.snapshot().histeq()
        if BINARY_VIEW:
            img.binary([GRAYSCALE_THRESHOLD])
            img.erode(1)

        line = img.get_regression([(0, 0)], robust=True)
        print_string = ""

        if line and (line.magnitude() >= MAG_THRESHOLD):
            img.draw_line(line.line(), color=127)

            t, r = line_to_theta_and_rho_error(line, img)
            new_result = (t * THETA_GAIN) + (r * RHO_GAIN)
            delta_result = new_result - old_result
            old_result = new_result

            new_time = pyb.millis()
            delta_time = new_time - old_time
            old_time = new_time

            p_output = new_result
            i_output = max(min(i_output + new_result, I_MAX), I_MIN)
            d_output = (delta_result * 1000) / delta_time
            pid_output = (P_GAIN * p_output) + (I_GAIN * i_output) + (D_GAIN * d_output)

            output = 90 + max(min(int(pid_output), 90), -90)
            print_string = "Line Ok - turn %d - line t: %d, r: %d" % (output, line.theta(), line.rho())
        else:
            print_string = "Line Lost - turn %d" % output
        out_tot += output

    out_avg = out_tot // 3
    
    usb.send(str(out_avg), timeout=100)

Code for the Raspberry Pi:

Code: Select all

#!/usr/bin/python
import serial
ser = serial.Serial()
ser.port = "/dev/ttyACM0"
ser.baudrate = 115200
ser.timeout = 100
ser.open()
while True:
	if ser.isOpen():
		value = ser.read()
		print(value)
User avatar
kwagyeman
Posts: 3048
Joined: Sun May 24, 2015 2:10 pm

Re: Reading stream of data sent from OpenMV to Raspberry Pi through USB

Postby kwagyeman » Tue Apr 02, 2019 11:09 am

Hi, you're the second person who's mentioned the VCP port might be unstable. What errors are you getting exactly?

You didn't quite mention what the problem is in detail.
Nyamekye,
User avatar
iabdalkader
Posts: 840
Joined: Sun May 24, 2015 3:53 pm

Re: Reading stream of data sent from OpenMV to Raspberry Pi through USB

Postby iabdalkader » Tue Apr 02, 2019 1:02 pm

I tested your code, seems to be working. Try opening the port like this:

Code: Select all

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.
print(sp.read())
Eats
Posts: 3
Joined: Mon Apr 01, 2019 7:52 pm

Re: Reading stream of data sent from OpenMV to Raspberry Pi through USB

Postby Eats » Tue Apr 02, 2019 4:43 pm

I tried iabdalkader's code and I am getting the same problem as before.

The problem I am having is what I am reading with the python code. I am trying to send the output value through USB which is a value such as 90 or 104, and when I use screen /dev/ttyACM0 115200 I am able to see the numbers being sent. However when I try to read it using python code I am receiving values like b'7' and b'1'. And these values do not seem to be consistent. When I am looking at the bit stream with screen, I can see the same value repeating like 90909090909090 if I am not moving the camera indicating that nothing is changing as expected. However when reading with the python code, the values are changing constantly and seem to have no pattern.
User avatar
iabdalkader
Posts: 840
Joined: Sun May 24, 2015 3:53 pm

Re: Reading stream of data sent from OpenMV to Raspberry Pi through USB

Postby iabdalkader » Wed Apr 03, 2019 2:25 pm

This is not a problem with the port it's how you send the data, you send a str and when you recv you read 1 byte at a time, I get the same values. If you want to send a 4 bytes int and read that try:

Code: Select all

usb.send(ustruct.pack("<L", 90))
Then read 4 bytes and unpack:

Code: Select all

struct.unpack('<L', sp.read(4))[0]
Eats
Posts: 3
Joined: Mon Apr 01, 2019 7:52 pm

Re: Reading stream of data sent from OpenMV to Raspberry Pi through USB

Postby Eats » Wed Apr 03, 2019 5:33 pm

That was my problem.
Thank you for your help.

Return to “General Topics”

Who is online

Users browsing this forum: No registered users and 2 guests