arduino_spi_slave.py

# Este trabalho está licenciado sob a licença MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Todos os direitos reservados.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# SPI com o Arduino como dispositivo mestre e a OpenMV Cam como escravo.
#
# Conecte sua OpenMV Cam ao seu Arduino da seguinte forma:
#
# 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 é um caractere de sincronização.
# Use "struct" para montar os pacotes de dados a serem enviados.
# "<" coloca os dados na struct em ordem little endian.
# "b" coloca um char com sinal no fluxo de dados.
# "i" coloca um inteiro com sinal no fluxo de dados.
# "%ds" coloca uma string no fluxo de dados. Ex.: "13s" para "Hello World!\n" (13 caracteres).
# Veja https://docs.python.org/3/library/struct.html

# LEIA-ME!!!
#
# Entenda que, quando sua OpenMV Cam não é o mestre SPI, ela pode deixar de responder ao
# envio de dados como escravo SPI, mesmo que você chame "spi.send()" em um callback de interrupção ou no
# laço principal abaixo. Por isso, você deve obrigatoriamente projetar seu protocolo de comunicação de forma
# que, se o dispositivo escravo (a OpenMV Cam) não chamar "spi.send()" a tempo, os dados inválidos
# lidos do periférico SPI pelo mestre (o Arduino) sejam descartados. Para isso, usamos um
# caractere de sincronização 85 (binário 01010101), que o Arduino procurará como o primeiro byte lido.
# Se não o encontrar, ele aborta a transação SPI e tentará novamente. Em segundo lugar, para
# limpar o estado do periférico SPI, sempre enviamos um múltiplo de quatro bytes e mais quatro bytes zero
# extras, para garantir que o periférico SPI não retenha dados obsoletos que possam ser 85. Note
# que a OpenMV Cam perderá a janela de "spi.send()" aleatoriamente, pois precisa atender
# interrupções. As interrupções ocorrerão com muito mais frequência enquanto estiver conectada ao seu PC.

# O barramento SPI de hardware da sua OpenMV Cam é sempre o barramento SPI 2.
# polarity = 0 -> o clock fica em nível baixo quando ocioso.
# phase = 0 -> amostra os dados na borda de subida do clock, gera saída na borda de descida.
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)


# Callback do NSS.
def nss_callback(line):
    global spi, data
    try:
        spi.send(data, timeout=1000)
    except OSError as err:
        pass  # Não se importa com erros - portanto, pass.
        # Note que há 3 possíveis erros. Um erro de timeout, um erro de propósito geral, ou
        # um erro de ocupado. Os códigos de erro são 116, 5, 16, respectivamente, para "err.arg[0]".


# Configura o NSS/CS no modo IRQ para enviar dados quando solicitado pelo mestre.
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while True:
    time.sleep_ms(1000)

###################################################################################################
# Código do 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); // Dá tempo para a OpenMV Cam inicializar.
# }
#
# void loop() {
#   int32_t len = 0;
#   char buff[CHAR_BUF] = {0};
#   digitalWrite(SS_PIN, LOW);
# delay(1); // Dá algum tempo para a OpenMV Cam se preparar para enviar dados.
#
# if(SPI.transfer(1) == 85) { // viu o caractere de sincronização?
# SPI.transfer(&len, 4); // obtém o comprimento
#     if (len) {
#       SPI.transfer(&buff, min(len, CHAR_BUF));
#       len -= min(len, CHAR_BUF);
#     }
# while (len--) SPI.transfer(0); // descarta quaisquer bytes restantes
#   }
#
#   digitalWrite(SS_PIN, HIGH);
#   Serial.print(buff);
# delay(1); // Não repete o laço rápido demais.
# }

results matching ""

    No results matching ""