arduino_i2c_slave.py
# Esta obra está licenciada bajo la licencia MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Todos los derechos reservados.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# I2C con el Arduino como dispositivo maestro y la OpenMV Cam como esclavo.
#
# Conecte su OpenMV Cam a su Arduino de la siguiente manera:
#
# OpenMV Cam Datos I2C Maestro (P5) - Arduino Uno Datos (A4)
# OpenMV Cam Reloj I2C Maestro (P4) - Arduino Uno Reloj (A5)
# OpenMV Cam Tierra - Arduino Tierra
import pyb
import struct
text = "Hello World!\n"
data = struct.pack("<%ds" % len(text), text)
# Utilice "struct" para construir los paquetes de datos a enviar.
# "<" coloca los datos del struct en orden little endian.
# "%ds" coloca una cadena en el flujo de datos. Ej. "13s" para "Hello World!\n" (13 caracteres).
# Consulte https://docs.python.org/3/library/struct.html
# ¡LÉAME!!!
#
# Tenga en cuenta que cuando su OpenMV Cam no es el maestro I2C, puede fallar al responder al
# enviar datos como esclavo I2C, sin importar si llama a "i2c.send()" en una devolución de llamada de interrupción o en el
# bucle principal a continuación. Cuando esto ocurre, el Arduino recibirá un NAK y tendrá que intentar leer de la
# OpenMV Cam de nuevo. Tenga en cuenta que ni los controladores I2C del Arduino ni los de la OpenMV Cam son buenos para
# recuperarse después de encontrar errores I2C. En la OpenMV Cam y el Arduino puede recuperarse
# desinicializando y luego reinicializando los periféricos I2C.
# El bus I2C de hardware de su OpenMV Cam es siempre el bus I2C 2.
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
bus.deinit() # Reiniciar completamente el dispositivo I2C...
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
print("Waiting for Arduino...")
# Tenga en cuenta que para que la sincronización funcione correctamente, la OpenMV Cam debe estar ejecutando este script antes de que el
# Arduino comience a sondear la OpenMV Cam en busca de datos. De lo contrario, el encuadre de bytes I2C se desordena,
# etc. Por lo tanto, mantenga el Arduino en reset hasta que la OpenMV Cam esté "Waiting for Arduino...".
while True:
try:
bus.send(
struct.pack("<h", len(data)), timeout=10000
) # Enviar primero la longitud (16 bits).
try:
bus.send(data, timeout=10000) # Enviar los datos en segundo lugar.
print("Sent Data!") # Solo se alcanza cuando no hay error.
except OSError as err:
pass # No importan los errores, así que se ignora (pass).
# Tenga en cuenta que hay 3 posibles errores: un error de tiempo de espera, un error de propósito general, o
# un error de ocupado. Los códigos de error son 116, 5, 16 respectivamente para "err.arg[0]".
except OSError as err:
pass # No importan los errores, así que se ignora (pass).
# Tenga en cuenta que hay 3 posibles errores: un error de tiempo de espera, un error de propósito general, o
# un error de ocupado. Los códigos de error son 116, 5, 16 respectivamente para "err.arg[0]".
###################################################################################################
# Código Arduino
###################################################################################################
#
# #include <Wire.h>
# #define BAUD_RATE 19200
# #define CHAR_BUF 128
#
# void setup() {
# Serial.begin(BAUD_RATE);
# Wire.begin();
# delay(1000); // Dar tiempo a la OpenMV Cam para arrancar.
# }
#
# void loop() {
# int32_t temp = 0;
# char buff[CHAR_BUF] = {0};
#
# Wire.requestFrom(0x12, 2);
# if(Wire.available() == 2) { // ¿se obtuvo la longitud?
#
# temp = Wire.read() | (Wire.read() << 8);
# delay(1); // Dar algo de tiempo de configuración...
#
# Wire.requestFrom(0x12, temp);
# if(Wire.available() == temp) { // ¿se obtuvo el mensaje completo?
#
# temp = 0;
# while(Wire.available()) buff[temp++] = Wire.read();
#
# } else {
# while(Wire.available()) Wire.read(); // Descartar bytes basura.
# }
# } else {
# while(Wire.available()) Wire.read(); // Descartar bytes basura.
# }
#
# Serial.print(buff);
# delay(1); // No repetir el bucle demasiado rápido.
# }