arduino_spi_slave.py

# Questo lavoro è concesso in licenza MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Tutti i diritti riservati.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# SPI con l'Arduino come dispositivo master e la OpenMV Cam come slave.
#
# Collega la tua OpenMV Cam al tuo Arduino come segue:
#
# 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
import struct
import time

text = "Hello World!\n"
data = struct.pack("<bi%ds" % len(text), 85, len(text), text)  # 85 è un carattere di sincronizzazione.
# Usa "struct" per costruire i pacchetti di dati da inviare.
# "<" inserisce i dati nella struct in ordine little endian.
# "b" inserisce un char con segno nel flusso di dati.
# "i" inserisce un intero con segno nel flusso di dati.
# "%ds" inserisce una stringa nel flusso di dati. Ad es. "13s" per "Hello World!\n" (13 caratteri).
# Vedi https://docs.python.org/3/library/struct.html

# LEGGIMI!!!
#
# Tieni presente che quando la tua OpenMV Cam non è il master SPI, potrebbe non rispondere all'invio
# di dati come slave SPI, indipendentemente dal fatto che tu chiami "spi.send()" in un callback di interrupt o nel
# ciclo principale sottostante. Per questo motivo devi assolutamente progettare il tuo protocollo di comunicazione in modo
# che se il dispositivo slave (la OpenMV Cam) non chiama "spi.send()" in tempo, i dati spazzatura
# letti dalla periferica SPI dal master (l'Arduino) vengano scartati. Per ottenere questo usiamo un
# carattere di sincronizzazione pari a 85 (binario 01010101) che l'Arduino cercherà come primo byte letto.
# Se non lo trova, interrompe la transazione SPI e riproverà. In secondo luogo, per
# ripulire lo stato della periferica SPI inviamo sempre un multiplo di quattro byte e altri quattro byte zero
# aggiuntivi per assicurarci che la periferica SPI non conservi dati obsoleti che potrebbero essere 85. Nota
# che la OpenMV Cam mancherà casualmente la finestra di "spi.send()" perché deve gestire
# gli interrupt. Gli interrupt si verificheranno molto più spesso quando è collegata al tuo PC.

# Il bus SPI hardware della tua OpenMV Cam è sempre il bus SPI 2.
# polarity = 0 -> il clock è basso a riposo.
# phase = 0 -> campiona i dati sul fronte di salita del clock, restituisce i dati sul fronte di discesa del clock.
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)


# Callback NSS.
def nss_callback(line):
    global spi, data
    try:
        spi.send(data, timeout=1000)
    except OSError as err:
        pass  # Non ci interessano gli errori, quindi pass.
        # Nota che ci sono 3 possibili errori. Un errore di timeout, un errore generico oppure
        # un errore di occupato. I codici di errore sono rispettivamente 116, 5, 16 per "err.arg[0]".


# Configura NSS/CS in modalità IRQ per inviare dati quando richiesto dal master.
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while True:
    time.sleep_ms(1000)

###################################################################################################
# Codice 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); // Dai tempo alla OpenMV Cam di avviarsi.
# }
#
# void loop() {
#   int32_t len = 0;
#   char buff[CHAR_BUF] = {0};
#   digitalWrite(SS_PIN, LOW);
# delay(1); // Dai un po' di tempo alla OpenMV Cam per prepararsi a inviare i dati.
#
# if(SPI.transfer(1) == 85) { // visto il carattere di sincronizzazione?
# SPI.transfer(&len, 4); // ottieni la lunghezza
#     if (len) {
#       SPI.transfer(&buff, min(len, CHAR_BUF));
#       len -= min(len, CHAR_BUF);
#     }
# while (len--) SPI.transfer(0); // consuma i byte rimanenti
#   }
#
#   digitalWrite(SS_PIN, HIGH);
#   Serial.print(buff);
# delay(1); // Non ciclare troppo velocemente.
# }

results matching ""

    No results matching ""