arduino_spi_slave.py

# Эта работа лицензирована по лицензии MIT.
# Copyright (c) 2013-2023 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# SPI, где Arduino выступает ведущим устройством, а камера OpenMV Cam — ведомым.
#
# Подключите камеру OpenMV Cam к Arduino следующим образом:
#
# 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 — это символ синхронизации.
# Используйте "struct" для сборки передаваемых пакетов данных.
# "<" помещает данные в struct в порядке little endian.
# "b" помещает знаковый символ (char) в поток данных.
# "i" помещает знаковое целое число в поток данных.
# "%ds" помещает строку в поток данных. Например, "13s" для "Hello World!\n" (13 символов).
# См. https://docs.python.org/3/library/struct.html

# ПРОЧТИТЕ ЭТО!!!
#
# Учтите, что когда ваша камера OpenMV Cam не является ведущим устройством SPI, она может пропускать
# отправку данных как ведомое устройство SPI, независимо от того, вызываете ли вы "spi.send()" в обработчике прерывания или в
# основном цикле ниже. Из-за этого вам обязательно нужно спроектировать протокол связи так,
# чтобы если ведомое устройство (камера OpenMV Cam) не вызвало "spi.send()" вовремя, мусорные данные,
# прочитанные с периферии SPI ведущим устройством (Arduino), отбрасывались. Для этого мы используем
# символ синхронизации 85 (двоичное 01010101), который Arduino будет искать в качестве первого прочитанного байта.
# Если он его не видит, то прерывает транзакцию SPI и повторяет попытку. Во-вторых, чтобы
# очистить состояние периферии SPI, мы всегда отправляем количество байт, кратное четырём, и дополнительные четыре нулевых
# байта, чтобы гарантировать, что периферия SPI не хранит устаревшие данные, которые могли бы оказаться равны 85. Обратите внимание,
# что камера OpenMV Cam иногда случайно пропускает окно "spi.send()", поскольку ей нужно обрабатывать
# прерывания. Прерывания случаются намного чаще при подключении к компьютеру.

# Аппаратная шина SPI на вашей камере OpenMV Cam — всегда шина SPI 2.
# polarity = 0 -> тактовый сигнал в состоянии простоя низкий.
# phase = 0 -> выборка данных по нарастающему фронту, вывод данных по спадающему фронту тактового сигнала.
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)


# Обратный вызов NSS.
def nss_callback(line):
    global spi, data
    try:
        spi.send(data, timeout=1000)
    except OSError as err:
        pass  # Ошибки не важны — поэтому pass.
        # Обратите внимание, что возможны 3 вида ошибок: ошибка тайм-аута, общая ошибка или
        # ошибка занятости. Коды ошибок для "err.arg[0]" — 116, 5 и 16 соответственно.


# Настроить NSS/CS в режиме прерываний для отправки данных по запросу ведущего устройства.
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while True:
    time.sleep_ms(1000)

###################################################################################################
# Код 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); // Даём камере OpenMV Cam время на загрузку.
# }
#
# void loop() {
#   int32_t len = 0;
#   char buff[CHAR_BUF] = {0};
#   digitalWrite(SS_PIN, LOW);
# delay(1); // Даём камере OpenMV Cam немного времени, чтобы подготовиться к отправке данных.
#
# if(SPI.transfer(1) == 85) { // увидели символ синхронизации?
# SPI.transfer(&len, 4); // получить длину
#     if (len) {
#       SPI.transfer(&buff, min(len, CHAR_BUF));
#       len -= min(len, CHAR_BUF);
#     }
# while (len--) SPI.transfer(0); // съедаем оставшиеся байты
#   }
#
#   digitalWrite(SS_PIN, HIGH);
#   Serial.print(buff);
# delay(1); // Не выполняем цикл слишком быстро.
# }

results matching ""

    No results matching ""