arduino_i2c_slave.py
# Эта работа лицензирована по лицензии MIT.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# I2C, где Arduino выступает ведущим устройством, а камера OpenMV Cam — ведомым.
#
# Подключите камеру OpenMV Cam к Arduino следующим образом:
#
# 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
import struct
text = "Hello World!\n"
data = struct.pack("<%ds" % len(text), text)
# Используйте "struct" для сборки передаваемых пакетов данных.
# "<" помещает данные в struct в порядке little endian.
# "%ds" помещает строку в поток данных. Например, "13s" для "Hello World!\n" (13 символов).
# См. https://docs.python.org/3/library/struct.html
# ПРОЧТИТЕ ЭТО!!!
#
# Учтите, что когда ваша камера OpenMV Cam не является ведущим устройством I2C, она может пропускать
# отправку данных как ведомое устройство I2C, независимо от того, вызываете ли вы "i2c.send()" в обработчике прерывания или в
# основном цикле ниже. Когда это происходит, Arduino получит NAK и должен будет попытаться снова прочитать данные с
# камеры OpenMV Cam. Обратите внимание, что драйверы I2C и на Arduino, и на OpenMV Cam плохо умеют
# восстанавливаться после ошибок I2C. На OpenMV Cam и Arduino можно восстановиться,
# деинициализировав, а затем повторно инициализировав периферию I2C.
# Аппаратная шина I2C для вашей камеры OpenMV Cam — всегда шина I2C 2.
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
bus.deinit() # Полностью сбросить устройство I2C...
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
print("Waiting for Arduino...")
# Обратите внимание, что для правильной синхронизации камера OpenMV Cam должна выполнять этот скрипт до того, как
# Arduino начнёт опрашивать камеру OpenMV Cam на предмет данных. В противном случае разбиение байтов I2C собьётся
# и т. п. Поэтому держите Arduino в состоянии сброса, пока камера OpenMV Cam не покажет "Waiting for Arduino...".
while True:
try:
bus.send(
struct.pack("<h", len(data)), timeout=10000
) # Сначала отправить длину (16 бит).
try:
bus.send(data, timeout=10000) # Затем отправить данные.
print("Sent Data!") # Достигается только при отсутствии ошибок.
except OSError as err:
pass # Ошибки не важны — поэтому pass.
# Обратите внимание, что возможны 3 вида ошибок: ошибка тайм-аута, общая ошибка или
# ошибка занятости. Коды ошибок для "err.arg[0]" — 116, 5 и 16 соответственно.
except OSError as err:
pass # Ошибки не важны — поэтому pass.
# Обратите внимание, что возможны 3 вида ошибок: ошибка тайм-аута, общая ошибка или
# ошибка занятости. Коды ошибок для "err.arg[0]" — 116, 5 и 16 соответственно.
###################################################################################################
# Код Arduino
###################################################################################################
#
# #include <Wire.h>
# #define BAUD_RATE 19200
# #define CHAR_BUF 128
#
# void setup() {
# Serial.begin(BAUD_RATE);
# Wire.begin();
# delay(1000); // Даём камере OpenMV Cam время на загрузку.
# }
#
# void loop() {
# int32_t temp = 0;
# char buff[CHAR_BUF] = {0};
#
# Wire.requestFrom(0x12, 2);
# if(Wire.available() == 2) { // получили длину?
#
# temp = Wire.read() | (Wire.read() << 8);
# delay(1); // Даём немного времени на настройку...
#
# Wire.requestFrom(0x12, temp);
# if(Wire.available() == temp) { // получили полное сообщение?
#
# temp = 0;
# while(Wire.available()) buff[temp++] = Wire.read();
#
# } else {
# while(Wire.available()) Wire.read(); // Отбрасываем мусорные байты.
# }
# } else {
# while(Wire.available()) Wire.read(); // Отбрасываем мусорные байты.
# }
#
# Serial.print(buff);
# delay(1); // Не выполняем цикл слишком быстро.
# }