arduino_i2c_slave.py
# Ce travail est publié sous licence MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Tous droits réservés.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# I2C avec l'Arduino comme périphérique maître et l'OpenMV Cam comme esclave.
#
# Veuillez câbler votre OpenMV Cam à votre Arduino comme ceci :
#
# 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)
# Utilisez « struct » pour construire les paquets de données à envoyer.
# « < » place les données de la struct en ordre little endian.
# « %ds » place une chaîne dans le flux de données. Par ex. « 13s » pour « Hello World!\n » (13 caractères).
# Voir https://docs.python.org/3/library/struct.html
# LISEZ-MOI !!!
#
# Veuillez comprendre que lorsque votre OpenMV Cam n'est pas le maître I2C, elle peut manquer de répondre à
# l'envoi de données en tant qu'esclave I2C, que vous appeliez « i2c.send() » dans un callback d'interruption ou dans la
# boucle principale ci-dessous. Lorsque cela se produit, l'Arduino recevra un NAK et devra réessayer de lire depuis
# l'OpenMV Cam. Notez que ni les pilotes I2C de l'Arduino ni ceux de l'OpenMV Cam ne sont doués pour se
# débloquer après une erreur I2C quelconque. Sur l'OpenMV Cam et l'Arduino, vous pouvez récupérer en
# désinitialisant puis en réinitialisant les périphériques I2C.
# Le bus I2C matériel de votre OpenMV Cam est toujours le bus I2C 2.
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
bus.deinit() # Réinitialisation complète du périphérique I2C...
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
print("Waiting for Arduino...")
# Notez que pour que la synchronisation fonctionne correctement, l'OpenMV Cam doit exécuter ce script avant que
# l'Arduino ne commence à interroger l'OpenMV Cam pour obtenir des données. Sinon, le cadrage des octets I2C est perturbé,
# etc. Maintenez donc l'Arduino en réinitialisation jusqu'à ce que l'OpenMV Cam affiche « Waiting for Arduino... ».
while True:
try:
bus.send(
struct.pack("<h", len(data)), timeout=10000
) # Envoyez d'abord la longueur (16 bits).
try:
bus.send(data, timeout=10000) # Envoyez ensuite les données.
print("Sent Data!") # Atteint uniquement en l'absence d'erreur.
except OSError as err:
pass # Peu importe les erreurs - donc pass.
# Notez qu'il existe 3 erreurs possibles. Une erreur de timeout, une erreur d'usage général, ou
# une erreur d'occupation (busy). Les codes d'erreur sont respectivement 116, 5, 16 pour « err.arg[0] ».
except OSError as err:
pass # Peu importe les erreurs - donc pass.
# Notez qu'il existe 3 erreurs possibles. Une erreur de timeout, une erreur d'usage général, ou
# une erreur d'occupation (busy). Les codes d'erreur sont respectivement 116, 5, 16 pour « err.arg[0] ».
###################################################################################################
# Code Arduino
###################################################################################################
#
# #include <Wire.h>
# #define BAUD_RATE 19200
# #define CHAR_BUF 128
#
# void setup() {
# Serial.begin(BAUD_RATE);
# Wire.begin();
# delay(1000); // Laisse à l'OpenMV Cam le temps de démarrer.
# }
#
# void loop() {
# int32_t temp = 0;
# char buff[CHAR_BUF] = {0};
#
# Wire.requestFrom(0x12, 2);
# if(Wire.available() == 2) { // longueur reçue ?
#
# temp = Wire.read() | (Wire.read() << 8);
# delay(1); // Laisse un peu de temps de préparation...
#
# Wire.requestFrom(0x12, temp);
# if(Wire.available() == temp) { // message complet reçu ?
#
# temp = 0;
# while(Wire.available()) buff[temp++] = Wire.read();
#
# } else {
# while(Wire.available()) Wire.read(); // Rejette les octets erronés.
# }
# } else {
# while(Wire.available()) Wire.read(); // Rejette les octets erronés.
# }
#
# Serial.print(buff);
# delay(1); // Ne pas boucler trop rapidement.
# }