Данная статья носит больше практический характер - у нас есть несколько плат Arduino и нам необходимо организовать между ними связь. Для чего это может быть нужно? Иногда может не хватить ног. Понятно что в данном случае можно использовать сдвиговые регистры, мультиплексоры и другие решения, но в данном случае мы получаем дополнительные ноги в комплекте с дополнительным мозгами, а главный плюс - у нас появляются дополнительные интерфейсы. Вторая причина такого объединения - недостаток вычислительной мощности в плане реализации многозадачности. Например у нас есть сложный проект в котором необходимо производить много вычислений - и использовать механизм прерываний не представляется возможным.
Для сборки тестового примера (код которого потом вы сможете легко подправить под свои задачи) потребуются:
2 платы Ардуино NANO (UNO)
4 светодиода
4 резистора 220 Om
4 потенциометра 10 ком
Макетная плата и макетные перемычки.
Схема подключения:
Левая плата сконфигурирована программно в режиме мастера - правая в режиме ведомого устройства. Потенциометры R1 и R2 - управляют яркостью зеленых светодиодов HL3 и HL4. Потенциометры R3 и R4- управляют яркостью красных светодиодов HL1 и HL2. Сам тестовый стенд можно питать от USB компьютера или повербанка.
У нас как бы получилась одна большая двухпроцессорная Arduino. C 2-мя интерфейсами UART, с двумя шинами I2C и множеством аналоговых и цифровых пинов. К одной из плат можно подключить какой-нибудь датчик и полностью возложить на неё обработку информации, а со второй платы мы можем пользоваться уже обработанными данными (забирая их по SPI), отдавать команды исполнительным механизмам или транслировать их по радиоканалу.
Для того чтобы разобраться как работает данный код - необходимо в общих чертах представлять как работает интерфейс SPI
Шина SPI состоит из четырех линий:
MOSI (Master Out Slave In) – передача данных от ведущего к ведомому.
MISO (Master In Slave Out) – передача данных от ведомого к ведущему.
SS (Slave Select) – выбор ведомого устройства.
SCK (Serial ClocK) – передача тактового сигнала от ведущего к ведомому.
Одно из устройств на шине называется ведущим (master), а все остальные - ведомыми (slave). Master инициализирует передачу со slave, выставляя низкий уровень на его линии SS, после чего производится одновременная двухсторонняя передача данных по линиям MOSI и MISO с тактированием по линии SCK.
Конфигурация плат, какая из них будет ведущим устройством:
а какая ведомым:
выполняется программно - при этом нужно понимать что штатных средств (набора библиотек, включающий в себя некоторые функции (вроде pinMode) для превращения платы Arduino в ведомое устройство нет.
Для настройки ведущего и ведомого использует регистр управления SPI - SPCR - (Control Register).
Bit 7 - SPIE: SPI Interrupt Enable - Разрешение прерывания SPI
Установка бита SPIE в состояние 1 приводит к установке бита SPIF регистра SPSR и, при разрешении глобального прерывания, к выполнению прерывания SPI.
Bit 6 - SPE: SPI Enable - Разрешение SPI
Установка бита SPE в состояние 1 разрешает подключение SS, MOSI, MISO и SCK к выводам PB4, PB5, PB6 и PB7.
Bit 5 - DORD: Data Order - Порядок данных
При установленном в состояние 1 бите DORD передача слова данных происходит LSB вперед. При очищенном бите DORD первым передается MSB слова данных.
Bit 4 - MSTR: Master/Slave Select - Выбор режима ведущий/ведомый
При установленном в состояние 1 бите MSTR SPI работает в ведущем режиме и при очищенном бите в ведомом режиме.
Bit 3 - CPOL: Clock Polarity - Полярность тактового сигнала
SCK в режиме ожидания находится на высоком уровне при установленном в состояние 1 бите CPOL и на низком уровне при сброшенном бите CPOL. См. рис. 40 и 41.
Bit 2 - CPHA : Clock Phase - Фаза тактового сигнала
Работа этого бита отражена на рис. 40 и 41.
Bits 1,0 - SPR1, SPR0: SPI Clock Rate Select 1 and 0 - Выбор частоты тактового сигнала, биты 1 и 0
В данном случае мы работаем с платой Arduino именно как с микроконтроллером на языке C/C++.
Еще одно важное замечание касается настройки выводов SPI:
Если мы настраиваем плату Arduino как ведущее устройство (Master) - то выводы MOSI, SCK, SS как выходы необходимо настроить самостоятельно - причем в качестве выхода SS может использоваться любой цифровой пин. (SS у мастера может быть и несколько).
Если мы настраиваем плату Arduino как ведомое устройство (Slave) - то нам необходимо настроить на выход только вывод MISO.
Все остальные выходы микроконтроллер настроит самостоятельно в зависимости от роли которую мы ему назначим.
Упрощенный механизм работы интерфейса SPI показан на этом рисунке:
Из этой картинки понятно что ведущее устройство может быть только одно, а вот ведущих сколько угодно:
Если мы подадим логический 0 на линию SS2 то обмен байтами произойдет между Arduino Master и Arduino Slave 2. то есть на каждое дополнительное подключаемое устройство потребуется один дополнительный цифровой PIN.
Осталось разобраться как подгружать байты в ведомое устройство - ведь обмен происходит сразу, как только мы подгрузим байт в регистр мастера.
Для этого можно применить небольшую хитрость:
- мастер отправляет байт, но мы не читаем и не обрабатываем его;
- в ведомом устройстве поступление этого "мусорного" байта отслеживаем по прерыванию и тут же происходит загрузка байта с нулевым индексом;
- далее ведем обмен массивами между ведущим и ведомым устройствами один в один - поэлементно.
В коде это будет выглядеть следующим образом:
На мастере:
На ведомом устройстве (SLAVE) :
Разумеется, что для Вам для практического применения разбираться во всех этих тонкостях совсем не обязательно. Вы можете просто увеличить размеры массивов под необходимый Вам объем информации - и продолжать программировать используя привычные функций среды Arduino IDE.
Используя данную технологию можно объединять любые платы Arduino и получать самодельные платформы под любые нестандартные задачи.
К примеру объединим 2 платы Ардуино на базе микроконтроллера ATmega328PB. Фишка данной платформы в том, что в нем есть два аппаратных SPI и второй сидит на аналоговых пинах.
Получившийся гибрид будет обладать следующими характеристиками:
- Порты с поддержкой PWM 18
- Аппаратные интерфейсы UART 4
- 2 свободных интерфейса SPI
- 2 шины I2C (что может быть актуально при необходимости подключить два датчика у которых нет возможности аппаратной смены адреса)
- 36 цифровых пинов 8 из которых могут работать как аналоговые
Данную плату пока я видел только у компании Амперка.
Пример скетча можно скачать по этой ссылке.
Как выглядит сама плата и её характеристики можно посмотреть здесь
Примеры кода скачивайте по этой ссылке
Работу тестового примера и узнать дополнительную информацию можно посмотрев видео:
Если информация была Вам полезной и Вы узнали что-то новое ставим лайк, чтобы статью смогли увидеть и другие люди. Собери свою многопроцессорную Дуню! Удачи!