Synchronizing data transfers between OpenMV and RoboRIO over SPI

My team and I have been messing around with an OpenMV for vision this year and want to get it working over SPI because we are low on USB slots. The issue is that the OpenMV updates very slowly compared to the RoboRIO, so when we try to read data, we get halves of data, or no data at all. Is there a solution to this in java? Currently we are sending data from the OpenMV every time it loops, and reading on the RoboRIO every time the periodic function in the subsystem is called.

byte[] bytes = new byte[4];
SPI openMV = new SPI(SPI.Port.kOnboardCS0);
openMV.setClockRate(640000);
openMV.setChipSelectActiveLow();
openMV.setMode(SPI.Mode.kMode2);
...
@Override
periodic() {
  openMV.read(true, bytes, 4);
  //print bytes as hex
}

OpenMV:

# AprilTags Example
#
# This example shows the power of the OpenMV Cam to detect April Tags
# on the OpenMV Cam M7. The M4 versions cannot detect April Tags.

import sensor, image, time, math, struct
from pyb import SPI
import pyb
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # we run out of memory if the resolution is much bigger...
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)  # must turn this off to prevent image washout...
sensor.set_auto_whitebal(False)  # must turn this off to prevent image washout...
clock = time.clock()
ledb = pyb.LED(3)
ledg = pyb.LED(2)
ledr = pyb.LED(1)
ledb.on()
shouldSend = bytearray(b'\x01');
seeSomething = False

# Note! Unlike find_qrcodes the find_apriltags method does not need lens correction on the image to work.

# The apriltag code supports up to 6 tag families which can be processed at the same time.
# Returned tag objects will have their tag family and id within the tag family.

tag_families = image.TAG16H5


# What's the difference between tag families? Well, for example, the TAG16H5 family is effectively
# a 4x4 square tag. So, this means it can be seen at a longer distance than a TAG36H11 tag which
# is a 6x6 square tag. However, the lower H value (H5 versus H11) means that the false positve
# rate for the 4x4 tag is much, much, much, higher than the 6x6 tag. So, unless you have a
# reason to use the other tags families just use TAG36H11 which is the default family.

#initialize SPI
spi = SPI(2)
spi.init(mode=SPI.SLAVE, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
recvBuf = bytearray(4);


tagsize = 6

def getDistances(tag):
    return (tag.x_translation(),tag.y_translation(),abs(tag.z_translation()))

ledb.off()
while(True):
    clock.tick()
    seeSomething = False
    img = sensor.snapshot()
    for tag in img.find_apriltags(families=tag_families): # defaults to TAG36H11 without "families".
        img.draw_rectangle(tag.rect(), color = (255, 0, 0))
        img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0))
        seeSomething = True
        try:
            spi.recv(shouldSend, timeout=200)
            if shouldSend != b'\x01':
                spi.send(bytearray(b'\x40\x3f\x00\xfc'))
                print("sent")
        except:
            2+2
        shouldSend = b'\x01'
    if seeSomething == True:
        ledr.off()
        ledg.on()
    else:
        ledg.off()
        ledr.on()

The OpenMV doesn’t seem to be receiving the initialization and it only sends data the first time it views an AprilTag. Removing the check for initialization just results in garbled data every time.

Do you mean nothing is received here? I don’t see anywhere where you are sending data in the roboRIO code. spi.recv(shouldSend, timeout=200)

One way to handle this is to add a delimiter at the front of the data sent (some data that won’t occur in the rest of the data being sent). Then you can wait until the delimiter is received, and then add the data to a buffer until the next delimiter is received and then process the buffered data all at once.

The Rio can send an initialization byte “O”. That is what true is for when it reads. Also I think they changed to where the OpenMV needs to us a Pin callback function. Any links or other help would be much appreciated as I don’t quite have access to the robot right now.