OpenMV RT1062 with Arduino Mega

Hello.
I’m using openMV RT1062 and I want to send data to Arduino Mega 2560 via jumperwire.

[Project] I want to print out the value of a defective product if a certain brightness value is too high in the openMV, and I want to send those values to Arduino Mega to create a code where the servomotor runs when the value of a defective product comes out. I’m a non-major, so I tried my best to solve it by looking at the community, but it didn’t work out, so I’m asking you this question. OpenMV RX(P5) is connected to TX1(Pin 18) and RX1(Pin 19) in Arduino Mega, and GND is connected to each other. Also, by connecting with USB, COM6 is using openMV and COM12 is using Arduino Mega, and I’m running it on my laptop with their own code. I’ve tried it a few times using the rpc library, but the results don’t show up very well.

I’m not sure if I should use

  1. Uart communication or USB.vpc.
  2. Arduino and openMV results come up as follows, how can I solve this?
  3. Is there a need for presence of servos shields, etc.?
  4. Is there anything strange about the code and the circuit diagram?
    (* First of all, I just wanted to make sure that the data transfer was possible, so I designed the code that way.)

(openMV is 4.4.4IDE.)

I’ll attach a picture. It took me a while to figure out this far as I’m a non-major… I’m just asking because I’m trying my best and I really don’t know. The question might be weird using a translator. Thank you.

[openMV 코드]

import time
from machine import UART

#UART1 초기화 (P4=TX, P5=RX)
uart = UART(1, 115200, timeout=1000, timeout_char=1000)

while True:
    uart.write("Hello World!\r\n")  # Arduino로 메시지 전송
    l = uart.readline()            # Arduino로부터 응답 수신
    print(l)                       # 응답 출력
    time.sleep(1)

[Arduino 코드]

#include <Wire.h>

// OpenMV와 통신용 Serial 설정
void setup() {
    Serial.begin(115200);      // 디버깅용 Serial Monitor
    Serial1.begin(115200);     // OpenMV와 통신 (HardwareSerial1)
}

void loop() { 
    String dataToSend = "Hello OpenMV!";
    byte receivedData[32];    // 수신 데이터 버퍼
    int receivedLength = 0;   // 수신 데이터 길이
    
    // OpenMV에 데이터 전송
    Serial1.println(dataToSend);  // println으로 '\n' 추가
    Serial.print("Sent to OpenMV: ");
    Serial.println(dataToSend);

    // OpenMV의 응답 수신
    delay(100);  // 데이터 수신 대기 시간 (필요 시 조정)
    if (Serial1.available()) {
        receivedLength = Serial1.readBytesUntil('\n', receivedData, sizeof(receivedData) - 1); // '\n' 기준 수신
        receivedData[receivedLength] = '\0';  // 문자열 종료 추가
        Serial.print("Received from OpenMV: ");
        Serial.println((char*)receivedData);  // 수신 데이터 출력
    } else {
        Serial.println("No response from OpenMV.");
    }

    delay(1000);  // 1초 대기 후 반복
}

When I try to use the rpc protocol, the window will pop up like this, so I was using the same code as above.

[openMV code]

# This work is licensed under the MIT license.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Remote Control - As The Remote Device
#
# This script configures your OpenMV Cam as a co-processor that can be remotely controlled by
# another microcontroller or computer such as an Arduino, ESP8266/ESP32, RaspberryPi, and
# even another OpenMV Cam.
#
# This script is designed to pair with "popular_features_as_the_controller_device.py".

import image
import math
import rpc
import sensor
import struct

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

# The RPC library above is installed on your OpenMV Cam and provides multiple classes for
# allowing your OpenMV Cam to be controlled over CAN, I2C, SPI, UART, USB VCP, or LAN/WLAN.

################################################################
# Choose the interface you wish to control your OpenMV Cam over.
################################################################

# Uncomment the below line to setup your OpenMV Cam for control over CAN.
#
# * message_id - CAN message to use for data transport on the can bus (11-bit).
# * bit_rate - CAN bit rate.
# * sample_point - Tseg1/Tseg2 ratio. Typically 75%. (50.0, 62.5, 75, 87.5, etc.)
#
# NOTE: Master and slave message ids and can bit rates must match. Connect master can high to slave
#       can high and master can low to slave can lo. The can bus must be terminated with 120 ohms.
#
# interface = rpc.rpc_can_slave(message_id=0x7FF, bit_rate=250000, sample_point=75)

# Uncomment the below line to setup your OpenMV Cam for control over I2C.
#
# * slave_addr - I2C address.
#
# NOTE: Master and slave addresses must match. Connect master scl to slave scl and master sda
#       to slave sda. You must use external pull ups. Finally, both devices must share a ground.
#
# interface = rpc.rpc_i2c_slave(slave_addr=0x12)

# Uncomment the below line to setup your OpenMV Cam for control over SPI.
#
# * cs_pin - Slave Select Pin.
# * clk_polarity - Idle clock level (0 or 1).
# * clk_phase - Sample data on the first (0) or second edge (1) of the clock.
#
# NOTE: Master and slave settings much match. Connect CS, SCLK, MOSI, MISO to CS, SCLK, MOSI, MISO.
#       Finally, both devices must share a common ground.
#
# interface = rpc.rpc_spi_slave(cs_pin="P3", clk_polarity=1, clk_phase=0)

# Uncomment the below line to setup your OpenMV Cam for control over UART.
#
# * baudrate - Serial Baudrate.
#
# NOTE: Master and slave baud rates must match. Connect master tx to slave rx and master rx to
#       slave tx. Finally, both devices must share a common ground.
#
interface = rpc.rpc_uart_slave(baudrate=115200)

# Uncomment the below line to setup your OpenMV Cam for control over a USB VCP.
#
# interface = rpc.rpc_usb_vcp_slave()

# Uncomment the below line to setup your OpenMV Cam for control over the lan.
#
# import network
# network_if = network.LAN()
# network_if.active(True)
# network_if.ifconfig('dhcp')
#
# interface = rpc.rpc_network_slave(network_if)

# Uncomment the below line to setup your OpenMV Cam for control over the wlan.
#
# import network
# network_if = network.WLAN(network.STA_IF)
# network_if.active(True)
# network_if.connect('your-ssid', 'your-password')
#
# interface = rpc.rpc_network_slave(network_if)

################################################################
# Call Backs
################################################################

# Helper methods used by the call backs below.


def draw_detections(img, dects):
    for d in dects:
        c = d.corners()
        l = len(c)
        for i in range(l):
            img.draw_line(c[(i + 0) % l] + c[(i + 1) % l], color=(0, 255, 0))
        img.draw_rectangle(d.rect(), color=(255, 0, 0))


# Remote control works via call back methods that the controller
# device calls via the rpc module on this device. Call backs
# are functions which take a bytes() object as their argument
# and return a bytes() object as their result. The rpc module
# takes care of moving the bytes() objects across the link.
# bytes() may be the micropython int max in size.


# When called returns x, y, w, and h of the largest face within view.
#
# data is unused
def face_detection(data):
    sensor.set_pixformat(sensor.GRAYSCALE)
    sensor.set_framesize(sensor.QVGA)
    faces = (
        sensor.snapshot()
        .gamma_corr(contrast=1.5)
        .find_features(image.HaarCascade("frontalface"))
    )
    if not faces:
        return bytes()  # No detections.
    for f in faces:
        sensor.get_fb().draw_rectangle(f, color=(255, 255, 255))
    out_face = max(faces, key=lambda f: f[2] * f[3])
    return struct.pack("<HHHH", out_face[0], out_face[1], out_face[2], out_face[3])


# When called returns the payload string for the largest qrcode
# within the OpenMV Cam's field-of-view.
#
# data is unused
def qrcode_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.VGA)
    sensor.set_windowing((320, 240))
    codes = sensor.snapshot().find_qrcodes()
    if not codes:
        return bytes()  # No detections.
    draw_detections(sensor.get_fb(), codes)
    return max(codes, key=lambda c: c.w() * c.h()).payload().encode()


# When called returns a json list of json qrcode objects for all qrcodes in view.
#
# data is unused
def all_qrcode_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.VGA)
    sensor.set_windowing((320, 240))
    codes = sensor.snapshot().find_qrcodes()
    if not codes:
        return bytes()  # No detections.
    draw_detections(sensor.get_fb(), codes)
    return str(codes).encode()


# When called returns the x/y centroid, id number, and rotation of the largest
# AprilTag within the OpenMV Cam's field-of-view.
#
# data is unused
def apriltag_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QQVGA)
    tags = sensor.snapshot().find_apriltags()
    if not tags:
        return bytes()  # No detections.
    draw_detections(sensor.get_fb(), tags)
    output_tag = max(tags, key=lambda t: t.w * t.h)
    return struct.pack(
        "<HHHH",
        output_tag.cx,
        output_tag.cy,
        output_tag.id,
        int(math.degrees(output_tag.rotation)),
    )


# When called returns a json list of json apriltag objects for all apriltags in view.
#
# data is unused
def all_apriltag_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QQVGA)
    tags = sensor.snapshot().find_apriltags()
    if not tags:
        return bytes()  # No detections.
    draw_detections(sensor.get_fb(), tags)
    return str(tags).encode()


# When called returns the payload string for the largest datamatrix
# within the OpenMV Cam's field-of-view.
#
# data is unused
def datamatrix_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.VGA)
    sensor.set_windowing((320, 240))
    codes = sensor.snapshot().find_datamatrices()
    if not codes:
        return bytes()  # No detections.
    draw_detections(sensor.get_fb(), codes)
    return max(codes, key=lambda c: c.w() * c.h()).payload().encode()


# When called returns a json list of json datamatrix objects for all datamatrices in view.
#
# data is unused
def all_datamatrix_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.VGA)
    sensor.set_windowing((320, 240))
    codes = sensor.snapshot().find_datamatrices()
    if not codes:
        return bytes()  # No detections.
    draw_detections(sensor.get_fb(), codes)
    return str(codes).encode()


# When called returns the payload string for the largest barcode
# within the OpenMV Cam's field-of-view.
#
# data is unused
def barcode_detection(data):
    sensor.set_pixformat(sensor.GRAYSCALE)
    sensor.set_framesize(sensor.VGA)
    sensor.set_windowing((sensor.width(), sensor.height() // 8))
    codes = sensor.snapshot().find_barcodes()
    if not codes:
        return bytes()  # No detections.
    return max(codes, key=lambda c: c.w() * c.h()).payload().encode()


# When called returns a json list of json barcode objects for all barcodes in view.
#
# data is unused
def all_barcode_detection(data):
    sensor.set_pixformat(sensor.GRAYSCALE)
    sensor.set_framesize(sensor.VGA)
    sensor.set_windowing((sensor.width(), sensor.height() // 8))
    codes = sensor.snapshot().find_barcodes()
    if not codes:
        return bytes()  # No detections.
    return str(codes).encode()


# When called returns the x/y centroid of the largest blob
# within the OpenMV Cam's field-of-view.
#
# data is the 6-byte color tracking threshold tuple of L_MIN, L_MAX, A_MIN, A_MAX, B_MIN, B_MAX.
def color_detection(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    thresholds = struct.unpack("<bbbbbb", data)
    blobs = sensor.snapshot().find_blobs(
        [thresholds], pixels_threshold=500, area_threshold=500, merge=True, margin=20
    )
    if not blobs:
        return bytes()  # No detections.
    for b in blobs:
        sensor.get_fb().draw_rectangle(b.rect(), color=(255, 0, 0))
        sensor.get_fb().draw_cross(b.cx(), b.cy(), color=(0, 255, 0))
    out_blob = max(blobs, key=lambda b: b.density())
    return struct.pack("<HH", out_blob.cx(), out_blob.cy())


# When called returns a jpeg compressed image from the OpenMV
# Cam in one RPC call.
#
# data is unused
def jpeg_snapshot(data):
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    img = sensor.snapshot()
    img.to_jpeg(quality=90)
    return img.bytearray()


# Register call backs.

interface.register_callback(face_detection)
interface.register_callback(qrcode_detection)
interface.register_callback(all_qrcode_detection)
interface.register_callback(apriltag_detection)
interface.register_callback(all_apriltag_detection)
interface.register_callback(datamatrix_detection)
interface.register_callback(all_datamatrix_detection)
interface.register_callback(barcode_detection)
interface.register_callback(all_barcode_detection)
interface.register_callback(color_detection)
interface.register_callback(jpeg_snapshot)

# Once all call backs have been registered we can start
# processing remote events. interface.loop() does not return.

interface.loop()

=> Error Message
ValueError: UART(3) doesn’t exist

Traceback (most recent call last):
** File “< stdin>”, line 69, in
*
** File “rpc.py”, line 644, in init**
ValueError: UART(3) doesn’t exist
OpenMV v4.5.9; MicroPython v1.23.0-r19; OpenMV IMXRT1060-MIMXRT1062DVJ6A
Type “help()” for more information.
>>>

Hi, you have to pass the UART value for the RT1062 as it has different UARTs than the H7/H7 Plus:

rpc — rpc library — MicroPython 1.23 documentation

I can’t see any reason this isn’t working from your code. It’s hard to see if it’s wired correctly. It appears to be so.

The OpenMV Cam code looks right. Same for the Arduino.

Can you provide a better picture of the wiring?

Thank you so much if you can take a look! I’m experimenting for a while, so I’ll take another circuit picture and send it to you as soon as possible. Thank you for your reply.

It is connected as follows. P4 of OPEN MV is connected to pin 19 of Arduino Mega. P5 of OpenMV is connected to pin 18 of Arduino Mega.

When I try to use the rpc library, it says I can’t find UART(3), how do I fix this? OpenMV RT1062 only has UART(1) available, so I think I need to change it, but I’m not sure what to modify.

Hi, the wiring looks right. That should work…

That said, the RT1062 is a 3.3V board and the Arduino is a 5V board. Unlike the STM32-based OpenMV Cams, the pins aren’t 5V tolerant. However, even given this, things still work. There are 100ohm filters ont he I/O pins which protect the MCU from this.

You may wish to upgrade to a 3.3V Arduino in the future.

Just do this in the RC library:

Replace:

interface = rpc.rpc_uart_slave(baudrate=115200)

With:

interface = rpc.rpc_uart_slave(baudrate=115200, uart_port=1)