diff --git a/usr/examples/02-Board-Control/arduino_i2c_slave.py b/usr/examples/02-Board-Control/arduino_i2c_slave.py new file mode 100644 index 000000000..41aa5e09d --- /dev/null +++ b/usr/examples/02-Board-Control/arduino_i2c_slave.py @@ -0,0 +1,91 @@ +# I2C with the Arduino as the master device and the OpenMV Cam as the slave. +# +# Please wire up your OpenMV Cam to your Arduino like this: +# +# OpenMV Cam Master I2C Data (P5) - Arduino Uno Data (A4) +# OpenMV Cam Master I2C Clock (P4) - Arduino Uno Clock (A5) +# OpenMV Cam Ground - Arduino Ground + +import pyb, ustruct + +text = "Hello World!\n" +data = ustruct.pack("<%ds" % len(text), text) +# Use "ustruct" to build data packets to send. +# "<" puts the data in the struct in little endian order. +# "%ds" puts a string in the data stream. E.g. "13s" for "Hello World!\n" (13 chars). +# See https://docs.python.org/3/library/struct.html + +# READ ME!!! +# +# Please understand that when your OpenMV Cam is not the I2C master it may miss responding to +# sending data as a I2C slave no matter if you call "i2c.send()" in an interupt callback or in the +# main loop below. When this happens the Arduino will get a NAK and have to try reading from the +# OpenMV Cam again. Note that both the Arduino and OpenMV Cam I2C drivers are not good at getting +# unstuck after encountering any I2C errors. On the OpenMV Cam and Arduino you can recover by +# de-initing and then re-initing the I2C peripherals. + +# The hardware I2C bus for your OpenMV Cam is always I2C bus 2. +bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12) +bus.deinit() # Fully reset I2C device... +bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12) +print("Waiting for Arduino...") + +# Note that for sync up to work correctly the OpenMV Cam must be running this script before the +# Arduino starts to poll the OpenMV Cam for data. Otherwise the I2C byte framing gets messed up, +# and etc. So, keep the Arduino in reset until the OpenMV Cam is "Waiting for Arduino...". + +while(True): + try: + bus.send(ustruct.pack(" +# #define BAUD_RATE 19200 +# #define CHAR_BUF 128 +# +# void setup() { +# Serial.begin(BAUD_RATE); +# Wire.begin(); +# delay(1000); // Give the OpenMV Cam time to bootup. +# } +# +# void loop() { +# int32_t temp = 0; +# char buff[CHAR_BUF] = {0}; +# +# Wire.requestFrom(0x12, 2); +# if(Wire.available() == 2) { // got length? +# +# temp = Wire.read() | (Wire.read() << 8); +# delay(1); // Give some setup time... +# +# Wire.requestFrom(0x12, temp); +# if(Wire.available() == temp) { // got full message? +# +# temp = 0; +# while(Wire.available()) buff[temp++] = Wire.read(); +# +# } else { +# while(Wire.available()) Wire.read(); // Toss garbage bytes. +# } +# } else { +# while(Wire.available()) Wire.read(); // Toss garbage bytes. +# } +# +# Serial.print(buff); +# delay(1); // Don't loop to quickly. +# } diff --git a/usr/examples/02-Board-Control/arduino_spi_slave.py b/usr/examples/02-Board-Control/arduino_spi_slave.py new file mode 100644 index 000000000..b3f0849cb --- /dev/null +++ b/usr/examples/02-Board-Control/arduino_spi_slave.py @@ -0,0 +1,101 @@ +# SPI with the Arduino as the master device and the OpenMV Cam as the slave. +# +# Please wire up your OpenMV Cam to your Arduino like this: +# +# OpenMV Cam Master Out Slave In (P0) - Arduino Uno MOSI (11) +# OpenMV Cam Master In Slave Out (P1) - Arduino Uno MISO (12) +# OpenMV Cam Serial Clock (P2) - Arduino Uno SCK (13) +# OpenMV Cam Slave Select (P3) - Arduino Uno SS (10) +# OpenMV Cam Ground - Arduino Ground + +import pyb, ustruct + +text = "Hello World!\n" +data = ustruct.pack(" clock is idle low. +# phase = 0 -> sample data on rising clock edge, output data on falling clock edge. +spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0) +pin = pyb.Pin("P3", pyb.Pin.IN, pull=pyb.Pin.PULL_UP) +print("Waiting for Arduino...") + +# Note that for sync up to work correctly the OpenMV Cam must be running this script before the +# Arduino starts to poll the OpenMV Cam for data. Otherwise the SPI byte framing gets messed up, +# and etc. So, keep the Arduino in reset until the OpenMV Cam is "Waiting for Arduino...". + +while(True): + while(pin.value()): pass + try: + spi.send(data, timeout=1000) + # If we failed to sync up the first time we'll sync up the next time. + print("Sent Data!") # Only reached on no error. + except OSError as err: + pass # Don't care about errors - so pass. + # Note that there are 3 possible errors. A timeout error, a general purpose error, or + # a busy error. The error codes are 116, 5, 16 respectively for "err.arg[0]". + while(not pin.value()): pass + +################################################################################################### +# Arduino Code +################################################################################################### +# +# #include +# #define SS_PIN 10 +# #define BAUD_RATE 19200 +# #define CHAR_BUF 128 +# +# void setup() { +# pinMode(SS_PIN, OUTPUT); +# Serial.begin(BAUD_RATE); +# SPI.begin(); +# SPI.setBitOrder(MSBFIRST); +# SPI.setClockDivider(SPI_CLOCK_DIV16); +# SPI.setDataMode(SPI_MODE0); +# delay(1000); // Give the OpenMV Cam time to bootup. +# } +# +# void loop() { +# int32_t temp = 0; +# char buff[CHAR_BUF] = {0}; +# digitalWrite(SS_PIN, LOW); +# delay(1); // Give the OpenMV Cam some time to setup to send data. +# +# if(SPI.transfer(1) == 85) { // saw sync char? +# SPI.transfer(&temp, 4); // get length +# int zero_legnth = 4 + ((temp + 1) % 4); +# if (temp) { +# SPI.transfer(&buff, min(temp, CHAR_BUF)); +# temp -= min(temp, CHAR_BUF); +# } +# while (temp--) SPI.transfer(0); // eat any remaining bytes +# while (zero_legnth--) SPI.transfer(0); // eat zeros. +# } +# +# digitalWrite(SS_PIN, HIGH); +# Serial.print(buff); +# delay(1); // Don't loop to quickly. +# }