Solved: OpenMV communications with Arduino

Here’s a method for setting up simple Serial communications between an OpenMV camera and an Arduino

Since we had challenges getting communications working between these two, we thought others might benefit from our research and experimentation.


###### Example code to create non-blocking serial communications between OpenMV Camera and Arduino
#
# Uses timer callbacks on OpenMV to send data periodically to Arduino and 
# non-blocking reads to check for data incoming from Arduino
#
# We've used an Arduino Mega and connected a common ground between the two devices and 
# Connected the Serial1 TX/RX pins 18/19 on Arduino Mega to the RX/TX 4/5 on H7 (starting at 0 from left side top)

# Since an Arduino Mega has multiple Serial connections - we've used Serial1 for the connection to the OpenMV
# Check here for a reference on your Arduino https://www.arduino.cc/reference/en/language/functions/communication/serial/
# If it only has a single Serial, use that and replace instances of Serial1 with Serial in the Arduino code here and change to your appropriate Arduino pins


#
# OpenMV Code

MyData = 100  # data to send to Arduino

# Function to check if any serial data receive from Arduino
def available():  
    return uart.any()

# Function to read serial data from host
def read_byte():  
    return uart.readchar()

# Function to process each byte received from Arduino	
def parse_byte(byte):  
    print("Serial Input: ", byte)

    if byte == 65: # Letter 'A'
		# do something
		
    elif byte == 66: # Letter 'B'
        # do something
    else:
        print("Error - Unknown serial received %3d %c" % (byte, byte))


def UpdateHost(timer):            # callback for periodically passing data to Arduino
    global MyData

    uart.writechar(255) 	# start of transmission marker 
    uart.writechar(1)    

    uart.writechar(MyData//253)                            # Write high byte.  Since we're using 255 and 254 as markers - filters these out too
    uart.writechar(MyData - 253*(MyData//253))			   # Write low byte 

    uart.writechar(254)    # end of transmission marker 

	

# Setup
	
uart = UART(3, 115200, timeout_char=1000)	# Setup communications with Arduino - be sure speeds match

UpdateHost = Timer(4, freq=1)               # create a timer object using timer 4 - trigger at 1Hz
UpdateHost.callback(UpdateHost)    # set the callback to our tick function

while(True):
    clock.tick()
		
	# Do your regular OpenMV image processing / etc

    
    for looping in range(available()): # Check for Serial input and process data from Arduino
        parse_byte(read_byte())





// Arduino Code
///////////////////////////////////////////////////// Serial /////////////////////////////////////////////////////

// Serial reference documents to talk with OpenMV camera
// Concepts from https://forum.arduino.cc/index.php?topic=396450
//  https://www.arduino.cc/reference/en/language/functions/communication/serial/
//  https://forum.arduino.cc/index.php?topic=396450
//  https://docs.openmv.io/_images/pinout.png
//

const byte Serial_numBytes = 60; // receive buffer size
byte Serial_InBytes[Serial_numBytes]; // receive buffer
byte Serial_numReceived = 0;
boolean Serial_newData = false;  // flag to receive in progress


void Serial_recvBytes() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    byte startMarker = 0xFF;
    byte endMarker = 0xFE;
    byte rb;

    while (Serial1.available() > 0 && Serial_newData == false) {
        rb = Serial1.read();

        if (recvInProgress == true) {
            if (rb != endMarker) {
                Serial_InBytes[ndx] = rb;
                ndx++;
                if (ndx >= Serial_numBytes) {
                    ndx = Serial_numBytes - 1;
                }
            }
            else {
                Serial_InBytes[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                Serial_numReceived = ndx;  // save the number for use when printing
                ndx = 0;
                Serial_newData = true;
            }
        }

        else if (rb == startMarker) {
            recvInProgress = true;
        }
    }
}

void Serial_showNewData() {
    if (Serial_newData == true) {
        for (byte n = 0; n < Serial_numReceived; n++) {
			sprintf(output,"%03d ",Serial_InBytes[n]);
            Serial.println(output);
        }
        Serial_newData = false;
    }
}



void setup() /// initialization code
{
    Serial.begin(115200); // local serial console for debugging
    Serial1.begin(115200);  // link to OpenMV
}


// Sample command to send data to the OpenMV
void OpenMV_Comamnd(char cmd)  
{  
	Serial1.print(cmd);  // send command to camera
} 


void loop() 
{
	// Regular Arduino code
	
	Serial_recvBytes();  // Check for new data from OpenMV - non-blocking
	
	Serial_showNewData();  // Parse the data when a full set is received
	
}

Thanks for posting!

Send a PR to our examples folder to have this included with the IDE if you’d like

Thanks! Will do once we refine the sample a little more - some additional testing on our part, documentation and comments would help others.

We could really use more Arduino examples, thanks. I’ll keep an eye out for your PR.

Just found this. I will build my Arduino Mega to two OpenMV cameras using some of this code. Thanks.

How to you define “output” in the Arduino sketch?

Hey Chris19,

Did you make any changes to your example code since posting it here last May?

Scott