arduino_spi_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
#
# SPI 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 Salida Maestro/Entrada Esclavo (P0) - Arduino Uno MOSI (11)
# OpenMV Cam Entrada Maestro/Salida Esclavo (P1) - Arduino Uno MISO (12)
# OpenMV Cam Reloj Serial              (P2) - Arduino Uno SCK  (13)
# OpenMV Cam Selección de Esclavo      (P3) - Arduino Uno SS   (10)
# OpenMV Cam Tierra                         - Arduino Tierra

import pyb
import struct
import time

text = "Hello World!\n"
data = struct.pack("<bi%ds" % len(text), 85, len(text), text)  # 85 es un carácter de sincronización.
# Utilice "struct" para construir los paquetes de datos a enviar.
# "<" coloca los datos del struct en orden little endian.
# "b" coloca un char con signo en el flujo de datos.
# "i" coloca un entero con signo en el flujo de datos.
# "%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 SPI, puede fallar al responder al
# enviar datos como esclavo SPI, sin importar si llama a "spi.send()" en una devolución de llamada de interrupción o en el
# bucle principal a continuación. Por ello, debe diseñar absolutamente su protocolo de comunicaciones de tal manera
# que si el dispositivo esclavo (la OpenMV Cam) no llama a "spi.send()" a tiempo, los datos basura
# leídos del periférico SPI por el maestro (el Arduino) se descarten. Para lograr esto, utilizamos un
# carácter de sincronización de 85 (binario 01010101) que el Arduino buscará como el primer byte leído.
# Si no lo encuentra, aborta la transacción SPI y lo intentará de nuevo. En segundo lugar, para
# limpiar el estado del periférico SPI, siempre enviamos un múltiplo de cuatro bytes y cuatro bytes cero adicionales
# para asegurarnos de que el periférico SPI no retenga datos obsoletos que podrían ser 85. Tenga en cuenta
# que la OpenMV Cam perderá aleatoriamente la ventana de "spi.send()" porque tiene que atender
# interrupciones. Las interrupciones ocurrirán con mucha más frecuencia mientras esté conectada a su PC.

# El bus SPI por hardware de su OpenMV Cam siempre es el bus SPI 2.
# polarity = 0 -> el reloj está inactivo en bajo.
# phase = 0 -> muestrea los datos en el flanco de subida del reloj y saca los datos en el flanco de bajada.
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)


# Devolución de llamada NSS.
def nss_callback(line):
    global spi, data
    try:
        spi.send(data, timeout=1000)
    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]".


# Configure NSS/CS en modo IRQ para enviar datos cuando lo solicite el maestro.
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while True:
    time.sleep_ms(1000)

###################################################################################################
# Código Arduino
###################################################################################################
#
# #include <SPI.h>
# #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); // Dar tiempo a la OpenMV Cam para arrancar.
# }
#
# void loop() {
#   int32_t len = 0;
#   char buff[CHAR_BUF] = {0};
#   digitalWrite(SS_PIN, LOW);
# delay(1); // Dar algo de tiempo a la OpenMV Cam para prepararse a enviar datos.
#
# if(SPI.transfer(1) == 85) { // ¿se vio el carácter de sincronización?
# SPI.transfer(&len, 4); // obtener la longitud
#     if (len) {
#       SPI.transfer(&buff, min(len, CHAR_BUF));
#       len -= min(len, CHAR_BUF);
#     }
# while (len--) SPI.transfer(0); // descartar los bytes restantes
#   }
#
#   digitalWrite(SS_PIN, HIGH);
#   Serial.print(buff);
# delay(1); // No repetir el bucle demasiado rápido.
# }

results matching ""

    No results matching ""