Not receiving UART data when disconnected from IDE

I’m using an open MV H7 to send data to an Arduino via UART. This works fine when I run my script in the IDE.

When the H7 is removed from USB, no data is coming over UART (I confirmed this by looking at the serial bus on the arduino with mySerial.available()).

The H7 is warm to the touch so it might be doing something and not writing the data. My script is loaded to the H7 as main.py.

Am I missing something?

Here is my H7 code:

from pyb import UART

# UART 3, and baudrate.
uart = pyb.UART(3, 19200, timeout_char = 1000)
# OpenMV Cam Ground Pin   ----> Arduino Ground
# OpenMV Cam UART3_TX(P4) ----> Arduino UART_RX(0)
# OpenMV Cam UART3_RX(P5) ----> Arduino UART_TX(1)
# OpenMV Cam 5Vin to buck 
while(True):
        #print("No objects, sending x = ",1)
        uart.write("%d\n" % (1))
        while(True):
        #wait until arduino acknoledges, which writes a char to the H7 once the first packet of info is recieved.
            if(uart.readchar()!= -1):
            #write Y
                #print("No objects, sending y =", 1)
                uart.write("%d\n" % (1))
                break

From the arduino

//UART (IMAGE) constructors (strange because this is for a nano33)
UART mySerial (digitalPinToPinName(0), digitalPinToPinName(1), NC, NC);
int max_len = 7; //Max length is 64 bytes

void setup(){ 
  mySerial.begin(19200); //For UART to H7
}
void loop {
  measureImage();
}

void measureImage() {
  char xbuffer [63 + 1]; //A place to store all the chars 64
  char ybuffer [63 + 1]; //A place to store all the chars 64
  //Serial.print("Reading xbuffer from camera\n");
  Serial.println("getline X");
  getline(xbuffer, max_len); //Reads serial data, stores in buffer
  Serial.println("getline complete");
  //Serial.print("Determining x int");
  X = getValue(xbuffer, true); //Gets the value in the buffer
  Serial.println("writing ack");
  mySerial.write('t');
  //Serial.print("Reading ybuffer from camera\n");
  Serial.println("getline Y");
  getline(ybuffer, max_len); //Reads serial data, stores in buffer
  //Serial.print("Determining y int");
  Y = getValue(ybuffer, false); //Gets the value in the buffer
} 

void getline(char *buffer, int max_len)
{
  uint8_t idx = 0;
  char c;
  do
  {
    if (idx >= max_len) return;
    while (mySerial.available() == 0){
    //Code gets stuck here when not connected to IDE
    }
    c = mySerial.read();
    buffer[idx++] = c;
  }
  while (c != '\n' && c != '\r');
  if (idx >= max_len) return;
  buffer[idx] = 0;
}
from pyb import UART

# UART 3, and baudrate.
uart = pyb.UART(3, 19200, timeout_char = 1000)
# OpenMV Cam Ground Pin   ----> Arduino Ground
# OpenMV Cam UART3_TX(P4) ----> Arduino UART_RX(0)
# OpenMV Cam UART3_RX(P5) ----> Arduino UART_TX(1)
# OpenMV Cam 5Vin to buck 
while(True):
        #print("No objects, sending x = ",1)
        uart.write("%d\n" % (1))
        while(True):
        #wait until arduino acknoledges, which writes a char to the H7 once the first packet of info is recieved.
            if(uart.readchar()!= -1):
            #write Y
                #print("No objects, sending y =", 1)
                uart.write("%d\n" % (1))
                break

Does not run in the IDE. Please post the code that runs in the IDE. When I try to run the above I get pyb not defined on line “uart = pyb.UART(3, 19200, timeout_char = 1000)” as you never imported pyb. You used from which is not an import.

Might want to add a blinking LED in that loop to make sure it’s actually running.

Here’s the full code. It uses cars.cascade. I’ve posted it here GitHub - mjaffee1997/OpenMVFiles

#Import libraries
import sensor, image, time, tf, math, pyb

from pyb import UART

# UART 3, and baudrate.
uart = pyb.UART(3, 19200, timeout_char = 1000)
uart.init(19200,bits=8,parity=None, stop=1, timeout_char=1000)
# OpenMV Cam Ground Pin   ----> Arduino Ground
# OpenMV Cam UART3_TX(P4) ----> Arduino Uno UART_RX(0)
# OpenMV Cam UART3_RX(P5) ----> Arduino Uno UART_TX(1)

#Set camera sensor parameters
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE) # grayscale is faster
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_exposure(True)

#Begin clock
clock = time.clock()

CAR_IMAGE_THRESHOLD = 3
CAR_IMAGE_SCALE = 0.25
BIKE_IMAGE_THRESHOLD = 2.0
BIKE_IMAGE_SCALE = 0.5
BUS_IMAGE_THRESHOLD = 2.0
BUS_IMAGE_SCALE = 0.5
MIN_AREA = 300
MAX_VARIANCE = 200

#Load cascade files for object identification in the image
#pedestrian_cascade = image.HaarCascade('pedestrian.cascade')
car_cascade = image.HaarCascade('cars.cascade')
#bike_cascade = image.HaarCascade('two_wheeler.cascade')
#bus_cascade = image.HaarCascade('Bus_front.cascade')

#Computes the mean of a set of data. Data is a list.
def means(data):
    calc = sum(data)/len(data)
    return calc

#Returns the standard deviation of the Cascade feature assessment. x and y are lists
def stddev(x,y):
    sigmax = 0.0
    sigmay = 0.0
    N = len(x)
    for i in range(N): #For every element that has been calculated so far
        sigmax = sigmax+(x[i]*1.0-means(x))**2
        sigmay = sigmay+(y[i]*1.0-means(y))**2
    sigma = (math.sqrt((1/(N))*sigmax),math.sqrt((1/(N))*sigmay))
    return sigma

#Calculates the confidence interval for the data.
def confidenceInterval(Xbar,N,s):
    component = 1.960*(s/math.sqrt(N))
    ci = (int(Xbar+component),int(Xbar-component))
    return ci

#Determines where the object is located in the image frame. Not used.
def determineDirection(widths):
    bins = 320/3
    sides = []
    for x in range(len(widths)):
        if widths[x] <= bins:
            sides.append("right")
        elif widths[x] <= bins:
            sides.append("center")
        else:
            sides.append("left")
    return sides

#Does some fancy statistics stuff to refine cascade detection. Returns an obj(x,y,w,h).
def featureSolve(cascade):
    x = []  #Reset for every loop
    y = []  #Reset for every loop
    A = []  #Reset for every loop
    #Produces a weighted rectangle for all cascade detections. Filters results.
    for n in cascade: #For each car in the picture
        x.append(n[0]) #Add the x cooridnate to our list
        y.append(n[1])  #Add the y coordinate to our list
        A.append(n[2]*n[3]) #Add the area of each shape to our list
        i = 0
        N = len(x)
        while True:
            if i == len(x):
                #print("removed %d features" % (N-len(x)))
                break
            elif A[i] < MIN_AREA:#Min area check for far away objects
                A.remove(A[i])
                x.remove(x[i])
                y.remove(y[i])
                i = 0 #reset
            elif abs(x[i]-means(x)) > MAX_VARIANCE or abs(x[i]-means(x)) > MAX_VARIANCE: #Spatial check
                A.remove(A[i])
                x.remove(x[i])
                y.remove(y[i])
                i = 0 #reset
            else:
                i = i+1
    if len(x) > 0:
        sigma = stddev(x,y)
        #Calculate the centroid of the data set
        centroid = (0,0,0)
        for i in range(len(x)):
            #Properties is a tuple (A,xA, yA)
            properties = (A[i],x[i]*A[i],y[i]*A[i])
            #Compute the cumulative centroid (EA, ExA, EyA)
            centroid = tuple(map(sum, zip(centroid, properties)))
        X = centroid[1]/centroid[0] #X_bar = ExA/EA
        Y = centroid[2]/centroid[0] #Y_bar = EyA/EA
        #Calculates the confidence interval (Xbar,N,s). Returns (#+,#-).
        xci = confidenceInterval(X,len(x),sigma[0])
        yci = confidenceInterval(Y,len(y),sigma[1])
        obj = (xci[0],yci[0],int(X)-xci[1],int(Y)-yci[1])
        return obj #Return object tuple
    else:
        #print("no objects within parameters")
        return (0,0,0,0)

#Shows the vehicles on the image
def plotVehicles(obj):
    #Plot all the objects
    #draw the rectangle
    img.draw_rectangle(obj,thickness = 3, color = (255,0,0))
    # Draw the label above the face
    img.draw_string(obj[0]+3, obj[1]-1, "Car", color = 70, mono_space=False)
    return

#Main loop
while(True):
    clock.tick()
    time.sleep(1000) #Refresh rate
    img = sensor.snapshot().lens_corr(1.9) #Take a picture

    #Set cascade features here
    car = img.find_features(car_cascade, threshold = CAR_IMAGE_THRESHOLD, scale = CAR_IMAGE_SCALE)
    #bike = img.find_features(bike_cascade, threshold = BIKE_IMAGE_THRESHOLD, scale = BIKE_IMAGE_SCALE)
    #bus = img.find_features(bus_cascade, threshold = BUS_IMAGE_THRESHOLD, scale = BUS_IMAGE_SCALE)


    if sum(map(sum,car)) > 0:
        carobj = featureSolve(car) #If features are present, generate an (X,Y,W,H) tuple
        #print(carobj)
        if sum(carobj) > 0:
            plotVehicles(carobj)
            #Write the centroid of the object to the Arduino
            #Write x
            print("sending x =", carobj[0])
            uart.write("%d\n" % (carobj[0]))
            while (True):
                #wait until arduino acknoledges
                print("waiting to acknoledge")
                if(uart.readchar()!= -1):
                    #write Y
                    print("sending y =", carobj[1])
                    uart.write("%d\n" % (carobj[1]))
                    break
                #else:
                    print("Not Acknoledged")
    else: #No vehicles are detected
        print("No objects, sending x = ",1)
        uart.write("%d\n" % (1))
        while(True):
        #wait until arduino acknoledges
            if(uart.readchar()!= -1):
            #write Y
                print("No objects, sending y =", 1)
                uart.write("%d\n" % (1))
                break
            #else:
                print("Not Acknoledged")
    #uart.write("%d%d\n" % (carobj[0],carobj[1]))
    #if sum(map(sum,bike)) > 0:
    #    bikeobj = featureSolve(bike)
    #    plotVehicles(bikeobj)
    #if sum(map(sum,bus))  > 0:
    #    busobj = featureSolve(bus)
    #    plotVehicles(busobj)
    #print(clock.fps(), "fps")

I added the LED code and I understand what happened, all the code is correct.

It was a powering issue. If the arduino is not powered before the H7, then the H7 will wait for an acknowledgment that will never come.

The arduino is slow to power up, so maybe I can add a delay on the H7’s startup? Not sure if this can be done outside the main loop.

Another way would be to have the two “shake hands” over UART but that’s more involved.

Hi, I was just looking for the example code that fails to compile. Can you post the most simple working code possible that has an error which you cannot understand?

Just use pyb.delay() before the main loop.

Great, thanks!

Why not switch to the RPC library ? It may be easier to use.