Данная статья создана с ознакомительной целью и служит рекомендацией по работе с Raspberry Pi 4 Model B («Ягода»), WEMOS WiFi & Bluetooth ESP32 («ESP32») при настройки Serial Peripheral Interface (SPI).
Хочу выразить огромную благодарность соавтору данной статьи @Artuiu за плодотворную работу и помощь
P.S. Это наша первая серьёзная статья на данную тему, поэтому ждём от Вас комментарии, предложения и критику!

Материал, который мы использовали для изучения
-
https://microtechnics.ru/raspberry-pi-obmen-dannymi-po-interfejsu-spi/
-
https://www.seeedstudio.com/blog/2019/09/25/uart-vs-i2c-vs-spi-communication-protocols-and-uses/
-
https://blog.stabel.family/raspberry-pi-4-multiple-spis-and-the-device-tree/
Компоненты для работы
-
Микроконтроллер WEMOS WiFi & Bluetooth ESP32 — 5 шт.
-
Микрокомпьютер Raspberry Pi 4 Model B — 1 шт.
-
Монтажные провода типа «мама-мама» — 13 шт.
-
Монтажные провода типа «мама-папа» — 21 шт.
-
Кабель Ethernet — 1 шт.
-
Кабель USB type c — 1 шт.
-
Кабель USB micro USB — 1 шт.
-
Карта памяти microSD 64 Гб — 1 шт.
-
Аккумулятор 18650 Li-ion — 5 шт.
Теория
SPI (Serial Peripheral Interface) — это синхронный последовательный интерфейс обмена данными между микроконтроллерами, микропроцессорами и периферийными устройствами. Он позволяет передавать данные между устройствами по нескольким проводам, включая провод для синхронизации и по одному проводу на каждое направление передачи данных (один для отправки данных и один для приема).
Пины SPI: На Raspberry Pi используется несколько GPIO (General Purpose Input/Output) пинов для реализации интерфейса SPI. Основные пины, используемые для SPI, это:
SCLK (Serial Clock): Пин для синхронизации передачи данных между устройствами.
MISO (Master In Slave Out): Пин для передачи данных от периферийного устройства к микроконтроллеру (Raspberry Pi).
MOSI (Master Out Slave In): Пин для передачи данных от микрокомпьютера к микроконтроллеру.
CS (Chip Select): Пин для выбора конкретного микроконтроллера, с которым микрокомпютер будет взаимодействовать.
Raspberry Pi имеет три основных интерфейса SPI — SPI0, SPI1 и SPI2.
SPI0: Этот интерфейс доступен на GPIO пинах 9 (MISO), 10 (MOSI), 11 (SCLK) и 8 (CS0). Он также может использоваться для доступа к специфическим периферийным устройствам, таким как экраны или сенсорные панели.
SPI1: Этот интерфейс доступен на GPIO пинах 19 (MISO), 20 (MOSI), 21 (SCLK) и 18 (CS1). Он может быть использован для подключения к другим периферийным устройствам, требующим SPI интерфейса.
Подготовка к работе
1. Установка ПО «Raspberry Pi OS» на microSD через «Raspberry Pi Imager».
Скачать установщик с официального сайта: https://www.raspberrypi.com/software/. После чего открыть «Raspberry Pi Imager». Выбрать Operating System > Raspberry Pi OS (32-bit).
Вставьте microSD карту в ПК. Перейдите во вкладку Storage и выбрать microSD карту (у нас это Kingston 64 Gb). Сюда будет устанавливаться Ваше ПО. Форматировать заранее не нужно, установщик сделает это за Вас.
После чего нажать WRITE и ждать установку. После установки необходимо вставить microSD в лот на самой «Ягоде».
2. Установка Arduino IDE для работы с «ESP32». Заходим на официальный сайт https://www.arduino.cc/en/software, скачиваем Arduino IDE и устанавливаем.
Теперь настроим Arduino IDE. Для начала перейдём в Файл > Настройки и нажимаем на кнопку

После копируем ссылку на json файл https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Вставляем в открытое окошко и нажимаем ОК
Далее заходим в Инструменты > Управлять библиотеками.
У Вас откроется меню менеджер библиотек. Ищем библиотеку esp32 от Espressif версии 1.0.6 (версии выше не работают в некоторых случаях) и устанавливаем.
После установки, Вам нужно выбрать плату, поэтому заходим в Инструменты > Плата > ESP32 Arduino > WeMos WiFi & Bluetooth Battery.
Также Вам нужно скачать библиотеку ESP32SPISlave.h
Установить можно здесь: https://github.com/hideakitai/ESP32SPISlave?ysclid=ll6fdafeu2422870462
Скачиваем библиотеку и распаковываем её там, где будет основной код.

3. Подготовка к удобной работе «Ягоды». Управление «Ягодой» будет осуществляться с помощью ноутбука, поэтому будем использовать систему удалённого доступа Virtual Network Computing (VNC).
Присоединяем ноутбук к “Ягоде” через порт для кабеля Ethernet. В программе «Putty» прописываем raspberrypi.local в HostName и указываем подключение по протоколу SSH (порт при подключении стандартный 22).
При первом входе требуется ввести логин/пароль: pi/raspberry. Сразу обновите ПО с помощью команды
sudo apt-get update && sudo apt-get upgrade -y
Дальше идём в менеджер пакетов с помощью команды
sudo raspi-config
Перейдите в Interface Options и включите VNC, также сразу активируем SPI
В появившемся окне выбрать «YES». Для завершения настройки необходимо перейти в System Options > Boot/Auto Login > Desktop Autologin

Наконец, нажмите «Enter», чтобы применить изменения. Потом нажмите «Tab» и «Enter». Это перезагрузит ваш Raspberry Pi, и сеанс SSH завершится.
Теперь закройте «Putty» и другие окна. Установим VNC Viewer на ноутбук, ссылка с официального сайта: https://www.realvnc.com/en/connect/download/viewer/.
Вводим raspberrypi.local
Вводим имя пользователя/пароль: pi/raspberry.
И если все сделано правильно, то у вас появится рабочий стол «Ягоды»
4. Активация дополнительных SPI интерфейсов. Стандартно «Ягода» имеет три интерфейса: SPI0-2. Для активации дополнительных интерфейсов нужно добавить строчки в файле config.txt (находится в папке boot)
Вводим cтрочку с текстом
spi5 — новый интерфейс
2cs — количество устройств, которые будут работать на этом интерфейсе
dtoverlay=spi5-1cs
Более подробно это можно прочитать тут: https://blog.stabel.family/raspberry-pi-4-multiple-spis-and-the-device-tree/
Практическая часть
Для установки соединения по технологии SPI понадобится: 1 «Ягода», 5 «ESP32», 1 ноутбук, 13 кабелей типа «мама-мама» и 31 кабель типа «папа-мама».
Чтобы установить соединение пяти «ESP32» с «Ягодой», нужно задействовать 5 пинов на каждой «ESP32»: MISO, MOSI, SCLK, SS, Ground(GND)
И 19 пинов на «Ягоде»
SPI0: MISO — 21 (GPIO 9), MOSI — 19 (GPIO 10), SCLK — 23 (GPIO 11), SS0 — 24 (GPIO 8),
SS1 — 26 (GPIO 7);
SPI1: MISO — 35 (GPIO 19), MOSI — 38 (GPIO 20), SCLK — 40 (GPIO 21), SS1 — 11 (GPIO 17),
SS2 — 36 (GPIO 16);
SPI5: MISO — 33 (GPIO 13), MOSI — 8 (GPIO 14), SCLK — 10 (GPIO 15), SS0 — 32 (GPIO 12)
+1 GND для каждой из «ESP32»
Самое главное, надо помнить, что все пины надо подключать в сопоставлении с названием, то есть MISO к MISO, MOSI к MOSI и т.д.
Для наглядности распиновки прикладываю ниже принципиальную схему
Также вот макетная плата подключения пяти «ESP32»
Теперь вам необходимо подключить каждую «ESP32» через кабель USB micro USB по отдельности к ноутбуку и через Arduino IDE загрузить код, который используется для приёма данных с «Ягоды», выводит в монитор порта, и далее отправляет данные на «Ягоду».
Код для Arduino:
#include "ESP32SPISlave.h" ESP32SPISlave slave; // Создаём два буфера на приём и передачу данных static constexpr uint32_t BUFFER_SIZE {51}; uint8_t spi_slave_tx_buf[BUFFER_SIZE]; uint8_t spi_slave_rx_buf[BUFFER_SIZE]; void setup() { Serial.begin(115200); delay(2000); // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12 // VSPI = CS: 5, CLK: 18, MOSI: 23, MISO: 19 // Функция устанавливает режим работы шины SPI, задавая //уровень сигнала синхронизации и фазу синхронизации. slave.setDataMode(SPI_MODE0); slave.begin(VSPI); // Заполняем буфер нулями memset(spi_slave_tx_buf, 0, BUFFER_SIZE); memset(spi_slave_rx_buf, 0, BUFFER_SIZE); } // В дальнейшем будет считывать задержку int wd = 0; void loop() { // если в очереди нет транзакции, добавляем транзакцию if (slave.remained() == 0) { slave.queue(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE); } // если транзакция завершена из master, // available() возвращает размер результатов транзакции, // и буфер автоматически обновляется while (slave.available()) { Serial.println(micros() - wd); wd = micros(); String receivedData; // считываем полученный данные в переменную receivedData for (size_t i = 0; i < slave.size(); ++i) { receivedData += (char)spi_slave_rx_buf[i]; } Serial.println("Received: " + receivedData); String sentData = "0101010010101011010XCVASDFratatatata"; // Отправляем данные на raspberry size_t len = sentData.length(); memcpy(spi_slave_tx_buf, sentData.c_str(), len); slave.pop(); } }
Компилируем код и так повторяем с каждым из пяти «ESP32»
Дальше заходим в «Ягоду» и будем использовать «Thonny» для написания скрипта на Python. Скрипт отвечает за отправку данных с «Ягоды» и приём данных с пяти «ESP32».
Заранее нужно будет скачать библиотеку spidev (заходим в терминал «Ягоды» и прописываем pip install spidev)
import spidev # Импорт библиотеки spidev для работы с SPI. spi0 = spidev.SpiDev() # Создание объекта spi0 для управления SPI устройством на шине 0. spi0.open(0, 0) # Открытие подключения к SPI устройству с номером шины 0 и устройством 0. spi0.max_speed_hz = 100000 # Установка максимальной скорости передачи данных и количества бит на слово. spi0.bits_per_word = 8 spi1 = spidev.SpiDev() # Создание объекта spi1 для управления другим SPI устройством на шине 1. spi1.open(1, 0) # Открытие подключения к SPI устройству с номером шины 1 и устройством 0. spi1.max_speed_hz = 100000 spi1.bits_per_word = 8 spi5 = spidev.SpiDev() spi5.open(5, 0) spi5.max_speed_hz = 100000 spi5.bits_per_word = 8 rx_data_len = 10 while True: # Организация цикла отправки и чтения данных для spi0. for dev in range(1): data_str = "B" * 10 data = data_str.encode() spi0.open(0, dev) spi0.writebytes(data) rx_data = spi0.readbytes(rx_data_len) received_data = bytes(rx_data) print(f"B0 D{dev} R_Data: {received_data}\n") spi0.close() for dev in range(1): # Организация цикла отправки и чтения данных для spi1. data_str = "A" * 10 data = data_str.encode() spi1.open(1, dev) spi1.writebytes(data) rx_data = spi1.readbytes(rx_data_len) received_data = bytes(rx_data) print(f"B1 D{dev} R_Data: {received_data}\n") spi1.close() for dev in range(1): # Организация цикла отправки и чтения данных для spi5. data_str = "C" * 10 data = data_str.encode() spi5.open(5, dev) spi5.writebytes(data) rx_data = spi5.readbytes(rx_data_len) received_data = bytes(rx_data) print(f"B5 D{dev} R_Data: {received_data}\n") spi5.close()
Дальше необходимо запустить скрипт на «Ягоде» и нажать физическую кнопку «Enable» на каждой «ESP32».
Все соединение SPI установлено. Не забудьте вставить аккумуляторы в «ESP32»
Ждём ваши комментарии и критику!
ссылка на оригинал статьи https://habr.com/ru/articles/754496/
Добавить комментарий