I’ve hooked up an OpenMV Cam to an Arduino Pro Mini (3.3V 8MHz) using I2C. The OpenMV is defined as a SLAVE:
# Edge Detection Example:
#
# This example demonstrates using the morph function on an image to do edge
# detection and then thresholding and filtering that image afterwards.
import sensor, image, time
from pyb import Pin, I2C
kernel_size = 1 # kernel width = (size*2)+1, kernel height = (size*2)+1
kernel = [-1, -1, -1,\
-1, +8, -1,\
-1, -1, -1]
# This is a high pass filter kernel. see here for more kernels:
# http://www.fmwconcepts.com/imagemagick/digital_image_filtering.pdf
thresholds = [(150, 255)] # grayscale thresholds
TestData = 123
bus = I2C(2, I2C.SLAVE, addr=0x12) # P4=SCL, P5=SDA, set the slave address to whatever...
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.RGB565
sensor.set_framesize(sensor.QVGA) # or sensor.QVGA (or others)
sensor.skip_frames(10) # Let new settings take affect.
clock = time.clock() # Tracks FPS.
# On the OV7725 sensor, edge detection can be enhanced
# significantly by setting the sharpness/edge registers.
# Note: This will be implemented as a function later.
if (sensor.get_id() == sensor.OV7725):
sensor.__write_reg(0xAC, 0xDF)
sensor.__write_reg(0x8F, 0xFF)
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the image.
img.morph(kernel_size, kernel)
img.binary(thresholds)
# Erode pixels with less than 2 neighbors using a 3x3 image kernel
img.erode(1, threshold = 2)
# Send a test byte
try:
bus.send(TestData, timeout=1000)
except OSError as err:
if err.args[0] == 116:
print("Check I2C Circuit")
elif err.args[0] == 5:
print("ACK missing on Data")
elif err.args[0] == 16:
print("Reset the board")
else:
print(err)
print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while
# connected to your computer. The FPS should increase once disconnected.
The Arduino has an 23LC512 SRAM chip on SPI (32K bytes):
#define SlaveAddress 0x12
#include <SPI.h>
#include <Wire.h>
//---------------------------------------------------
byte GetByte(unsigned int Offset, unsigned int Index)
//---------------------------------------------------
{
unsigned int address;
byte data;
address = Index + Offset;
digitalWrite(10, LOW);
SPI.transfer(3); // SRAM Read instruction
SPI.transfer((byte) (address >> 8));
SPI.transfer((byte) (address & 0xFF));
data = SPI.transfer(0);
digitalWrite(10, HIGH);
return data;
}
//---------------------------------------------------------------
void PutByte(unsigned int Offset, unsigned int Index, byte value)
//---------------------------------------------------------------
{
unsigned int address;
address = Index + Offset;
digitalWrite(10, LOW);
SPI.transfer(2); // Write instruction
SPI.transfer((byte) (address >> 8));
SPI.transfer((byte) (address & 0xFF));
SPI.transfer(value);
digitalWrite(10, HIGH);
}
//----------
void setup()
//----------
{
byte Mode;
Serial.begin(115200); // start serial for output
Serial.print(F("ARDUINO "));
pinMode(10, OUTPUT);
digitalWrite(10, HIGH); //Set SPI chip select pins HIGH.
pinMode(11, OUTPUT);
pinMode(12, INPUT);
pinMode(13, OUTPUT);
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0)); // Begin SPI
// In SPI_MODE0 (default the clock is normally low (CPOL = 0), and data
// is sampled on the transition from low to high (leading edge) (CPHA = 0)
delay(10);
// Read the SRAM Mode
digitalWrite(10, LOW);
SPI.transfer(5); // read mode instruction
Mode = SPI.transfer(0);
digitalWrite(10, HIGH);
//Default Mode = 64 or Sequential
Serial.print(F("SRAM Mode = "));
Serial.println(Mode);
Wire.begin(); // join i2c bus as master
}
//---------
void loop()
//---------
{
/*
Arduino 1 will write to data1 and read from data1
Arduino 2 will write to data2 and read from data2
*/
// Define SRAM Allocation:
// Name Offset SRAM Bytes
//-----------------------------------
unsigned int Map = 0;
unsigned int i,j,k,l;
unsigned int ReadError, WriteError;
unsigned long ExecTime;
byte x = 10;
ReadError = 0;
WriteError = 0;
ExecTime = micros();
for (i = 1; i <= 100; i++)
{
for (j = 0; j < 100; j++) PutByte(Map,j,i); // test write
for (j = 0; j < 100; j++) // test read
{
k = GetByte(Map,j);
if (k != i)
{
Serial.print(k);
Serial.print(" ");
Serial.println(i);
l = GetByte(Map,j);
if (k == l) WriteError++;
else ReadError++;
}
}
}
ExecTime = micros() - ExecTime;
Serial.print("ExecTime = ");
Serial.print(ExecTime);
Serial.print(" ReadError = ");
Serial.print(ReadError);
Serial.print(" WriteError = ");
Serial.println(WriteError);
//Wire.beginTransmission(SlaveAddress); // transmit to Slave
//Wire.write(ePointer >> 8); // MSB
//Wire.write(ePointer & 0xFF); // LSB
//Wire.write(x); // write byte to EEPROM
//Wire.endTransmission(); // stop transmitting
Wire.requestFrom(SlaveAddress, 1); // request 1 bytes from slave
i = Wire.available();
if (i == 0)
{
Serial.println("Check I2C circuit");
}
else
{
while(Wire.available()) // slave may send less than requested
{
x = Wire.read(); // receive a byte
Serial.println(x); // print byte
}
}
}
10K pull ups on both clock and data lines on the I2C bus. It works sometimes, but other times I get a “Reset the board” error from the OpenMV. I’m guessing there’s a synchronization problem . Both OpenMV Cam and the Arduino are doing their own thing, I think I may need a synchronization pulse so both chips can always talk on I2C. Any ideas appreciated.
Moe