Arduino-тестер длинных линий интерфейса SPI
- Войдите на сайт для отправки комментариев
Чт, 30/01/2020 - 13:19
Доброго времени суток!
В статье предлагается устройство для проверки прохождения данных в длинных линиях интерфейса SPI. В статье приводятся структурная и принципиальная электрическая схемы устройства, текст программы. Подробно рассматривается постановка задачи. Даны необходимые объяснения.
Устройство позволяет:
1. Опробовать кабель для линии передачи данных.
2. Опробовать схемное решение кабельных драйверов.
3. Оценить влияние фактических помех на передачу данных.
4. Подобрать параметры вызова функций стандартной библиотеки SPI.
Устройство обладает следующими особенностями:
1. В качестве Master-устройства используется МК Arduino UNO (допускается другой МК того же семейства).
2. Устройством считывания информации и ввода данных служит Ардуино-шилд с дисплеем LCD 1602 и 5-и кнопочной аналоговой клавиатурой.
3. В качестве Slave-устройства в базовой версии используется ИМС 74HC165.
4. Программирование Slave-устройства не требуется.
5. Для реализации программной части обмена данными используется стандартная библиотека SPI с возможностью оперативного параметрирования вызова функций.
6. Устройство может использоваться автономно (без компьютера).
7. Устройство не требует наладки.
Ниже идут следующие разделы:
• О чем
• Для кого
• Для чего
• ТЗ. Без него нельзя
• Общий подход
• Особенности программы
• Структура устройства
• Минимальная схемная реализация
• Результаты экспериментов
Печатный вариант статьи в формате pdf можно скачать по ссылке: https://yadi.sk/i/n5xK7MvoE_PUpg
О чём
Время от времени возникает необходимость обеспечить связь микроконтроллера Ардуино с удаленными датчиками, исполнительными устройствами, другими контроллерами Ардуино. Такие задачи возникают при проектировании «умного дома», игровых комплексов, теплиц и других проектов с распределённой структурой. Если проект объёмен, и делает его профессионал в области АСУ ТП или IT, то решение, скорее всего, он будет искать ближе к проверенным и хорошо им освоенным промышленным вариантам с использованием интерфейсов RS-485, CAN, Ethernet, I2C.
А что делать, если у калитки кодовый замок с клавиатурой из 16 клавиш, Ардуина в теплом доме (что совершенно оправдано), а между домом и калиткой метров эдак 15 по дорожке и 25 — 30 — по кабелю? Устраивать из этого «кусочек АСУ ТП» как то «не оно», да, честно говоря, и некому.
Помочь тут может интерфейс SPI (Serial Peripheral Interface). Штука простая и при правильном применении весьма эффективная. Требует минимальных познаний в программировании и схемотехнике. Кто четко понимает, что такое «сдвиговый регистр», так вот это «оно и есть», только слегка приукрашенное.
Если «сдвиговый регистр» всплыл из памяти неуверенно, или его там раньше и вовсе не было, это не беда. Тогда сначала рекомендую прочесть:
«Множим выходы с помощью сдвигового регистра 74HC595» (для входов всё будет аналогично, только микросхема другая — 74HC165)
http://arduino.ru/Tutorial/registr_74HC595
Весьма полезно будет почитать в Википедии: «Serial Peripheral Interface»
https://ru.wikipedia.org/wiki/Serial_Peripheral_Interface
«Последовательный интерфейс SPI (3-wire)»
http://www.gaw.ru/html.cgi/txt/interface/spi/index.htm
Там всё коротко, по делу, без зауми. И по жизни при работе с Ардуино может не один раз пригодиться. Рекомендую освоить.
И обязательно нужно будет в итоге прочесть несколько страничек описания библиотеки SPI на сайте Arduino.ru, поскольку мы будем ориентироваться в дальнейшем на её использование.
http://arduino.ru/Reference/Library/SPI
Для кого
Статья написана для тех, кто уже попробовал, кому понравилось, и кто хочет продолжать. В статье много букв. Это не модно. И это специально. Из статьи можно почерпнуть фрагменты кода или схем. Всё работает. Но главное - другое. Я показываю, как могу, как и почему я ставил задачу и как её решал. Можно согласиться или нет с моей постановкой задачи или с её решением, а, может быть, и с тем, и с другим. Главное, чтобы мой пример помог читателям правильно ставить собственные задачи и подбирать для них эффективные пути решения.
Для чего
Интерфейс SPI прост, быстр и эффективен на… сверхкоротких и коротких дистанциях. Т.е. когда обменивающиеся по нему информацией устройства расположены на одной плате, на платах в «бутерброде» из Ардуино-шилдов, на одном столе.
Если речь идет о расстояниях от метров до десятков метров, то всё может оказаться не только ни радужно, а совсем даже плачевно. «Длинная линия» - это такое состояние проводов, когда их уже нельзя рассматривать, как на схеме, идеальным проводником с нулевым сопротивлением. Начинают самым неприятным образом сказываться их индуктивность, емкость, омическое (активное) сопротивление да и ещё и во взаимовлиянии отдельных жил. Последовательные интерфейсы — суть импульсные цепи, и импульсы эти могут в длинных линиях искажаться до неузнаваемости. На картинках потом сами увидите. Да, и на длинную линию можно еще и помех нацеплять, если она будет проходить рядом с силовым оборудованием, особенно, если в нем есть тиристорные регуляторы с фазо-импульсным управлением.
Можно ли эту неприятность как то преодолеть? Да, можно. При разумной постановке задачи и оправданном выборе:
1. Кабеля.
2. Кабельных драйверов (усилителей) и кабельных приемников.
3. Схемы питания.
4. Параметров интерфейса (частоты тактовых импульсов и сдвига фаз).
Описываемое устройство как раз и предназначено для облегчения указанного выбора в конкретных, вплоть до полевых, условий.
Используя конкретный кабель, проложенный и подключенный конкретным образом, Master-устройство посылает байт на Slave-устройство и принимает его же в ответ. Делает оно это много тысяч раз и подсчитывает, сколько байт вернулись без изменений, а сколько оказались сбойными. Человек это видит и принимает решение, устраивает его результат или нет. По-хорошему, сбойных байт не должно быть совсем. Но могут и допускаться. От задачи зависит.
Если человека результат не устроил, то он может:
• Заменить кабель.
• Изменить схему его включения («поиграть» с «землёй», например).
• Изменить его трассу (чтобы обойти источники помех).
• Изменить электронную схему, работающую непосредственно с кабелем.
• Развязать между собой, а лучше и с кабелем, питание Master- и Slave-устройств.
• Изменить частоту и/или фазу тактовых импульсов.
После проведенных изменений вновь запускается цикл измерений. По его результатам оценивают, принесли ли сделанные изменения пользу. «Материальные» замены испытатель материально и делает, а изменять параметры интерфейса он может по меню, используя дисплей устройства. На нем же он видит и результаты измерений.
ТЗ. Без него нельзя
Итак. Нам нужно устройство, которое позволит нам в конкретной, возможно полевой (дачно-приусадебной) обстановке проверять, насколько достоверно передаётся информация с использованием интерфейса SPI.
Я посчитал, что такое устройство должно отвечать следующим требованиям:
1. В качестве Master-устройства использовать Arduino UNO.
2. В качестве устройства ввода-вывода ЧМИ использовать Ардуино-шилд LCD 1602 c 5-и кнопочной аналоговой клавиатурой.
3. Slave-устройство не должно требовать программирования.
4. Устройство не должно требовать настройки или калибровки.
5. Устройство должно допускать применение без использование компьютера.
6. Устройство должно допускать батарейное питание.
7. Программная реализация интерфейса SPI должна использовать стандартную библиотеку SPI.
8. Программирование задачи и загрузка программы в МК должны вестись средствами Arduino IDE без использования ассемблерных вставок.
Сделаем некоторые пояснения к пунктам Технического Задания (ТЗ).
Пункты 1, 2, 5 весьма тесно связаны. Задуманное устройство будет использоваться редко, но при использовании циклы измерений и ввод параметров будут весьма частыми. Изменять параметры интерфейса непосредственно в программе и потом каждый раз загружать её в МК через компьютер банально неудобно, особенно, если делать это приходится на выезде. Параметров у интерфейса не сильно много, но они имеют численные значения, да и результаты измерений имеют вид целых чисел. Их хорошо бы видеть. Нужен алфавитно-цифровой дисплей для считывания результатов и для ввода параметров. К нему, соответственно, нужна клавиатура, пусть самая небольшая.
Ардуино-шилд, содержащий двух строчный алфавитно-цифровой дисплей, совмещенный с 5-и кнопочной аналоговой клавиатурой сейчас весьма распространен и не дорог. Его программная поддержка известна и хорошо работает. Этот модуль рассчитан на прямую стыковку с платой Arduino UNO или её клонами и аналогами, выполненными в том же конструктиве. Прямая стыковка обеспечивает максимальную простоту монтажа и достаточную для макета конструктивную устойчивость. Если аккуратно, можно обойтись и без корпуса. Нам, по большому счету, даже и не прибор нужен, а прилично собранный макет. Замеры сделать и разобрать. Дает нам этот шилд такую возможность? Да. И он оставляет нетронутыми важные для нашего проекта пины на МК. Кроме линии SS (Slave Select) на пине D10. В шилде этот пин используется для управления подсветкой экрана в ШИМ-режиме. У нас одно специфичное Slave-устройство, сигнал SS не используется. Библиотеки SPI и LiquidCrystal из-за этого пина тоже не конфликтовали. Всё сошлось.
Для воспроизведения SPI -интерфейса нам нужно Slave-устройство. Оно должно быть самым простым. Чтобы не морочиться, исключить написание, отладку, заливку двух программ вместо одной. Тем более, что библиотека SPI поддерживает только режим «Мастер». Мы не проверим всех режимов SPI? Да и пусть. Мы не интерфейс проверяем, а кабель, электронные драйверы, уровень помех.
Батарейное питание. Вы пришли, например, на площадку квеста, где Вам кинули кабели. Какие надо или, что не редко, какие были. А Вы хотите проверить, оно хоть как то будет работать? А стройка продолжается. Батарейное питание будет весьма кстати.
Зачем нам библиотека SPI? Одна из самых важных причин, почему мы выбрали интерфейс SPI – простая программная реализация. Я бы даже сказал — самая простая из возможных для конкретного случая. Могли бы мы написать драйвер SPI сами? Для самодельных устройств - категорически да! Но… Мы с вами — любители. Успели освоить некоторую часть С++ из среды Arduino IDE. И мы вполне можем сами написать драйвер, даже разными способами. Только скорость его работы будет во много раз ниже, чем при использовании библиотеки SPI. Ассемблера МК мы с вами не знаем, структуру МК подробно — тоже нет. Лучше туда пока не лезть. Так что попользоваться на данном этапе готовой, входящей в «джентельменский набор» Arduino IDE библиотекой — прекрасный выход.
Общий подход
Наша задача состоит в обеспечении одно- или двунаправленной передачи данных по интерфесу SPI на расстояние от нескольких до нескольких десятков метров. Из некоторых исходных предположений выбираем кабель и схемное решение электронной части, к которой подключается непосредственно кабель. В идеальном случае прокладываем кабель так, как должен проходить при эксплуатации системы. Если это невозможно, то раскладываем кабель «примерно» с обязательным учетом его необходимой длины. К одной стороне кабеля через кабельные усилители подключается Master-устройство на базе МК Ардуино, к другой стороне кабеля также через кабельные усилители подключается Slave-устройство, выполненное на базе микросхемы сдвигового регистра, в данном случае — 74HC165. Структурная схема максимальной версии устройства представлена на рис. 1.
Рис. 1. Arduino-тестер длинных линий интерфейса SPI. Максимальная версия.
Схема структурная.
Через экранное меню на Master-устройстве задаются параметры SPI интерфейса:
1. Количество пересылаемых и принимаемых байт в одном цикле измерения (от 100 до 30000).
2. Значение делителя опорной частоты процессора для задания частоты тактовых импульсов Clock Divider (2, 4, 8, 16, 32, 64, 128).
3. Режим фазы синхронизации Date Mode (0, 1, 2, 3).
После запуска цикла измерения программа формирует значение тестового байта и из Master-устройства за 8 тактов пересылает его в Slave-устройство. Сразу после этого Master-устройство также за 8 тактов считывает переданный байт с выхода сдвигового регистра Slave-устройства. Если переданный байт совпал с принятым, то на единицу увеличивается счетчик «годных» байт. Если переданный и принятый байт не совпали, то на единицу увеличивается счетчик сбойных байт. Процедура передачи и приёма байта автоматически повторяется то количество раз, которое было указано при задании параметров.
После окончания цикла измерения на экран выводятся количество переданных байт, количество правильно принятых байт и количество сбойных байт.
Изменяя параметры Clock Divider добиваются, чтобы при минимальном возможном значении параметра, что соответствует максимальной скорости передачи данных, сбойные байты отсутствовали. Отмечу, что для Arduino UNO Rev.3 все указанные значения параметра Clock Divider – рабочие.
Если добиться желаемого только подбором Clock Divider не удалось, значит необходимо менять аппаратную часть устройства и/или кабель и повторять измерения. Весь процесс продолжают до получения необходимого результата.
Значение Date Mode зависит от схемы кабельной части устройства. Имеет смысл подобрать его для выбранной схемы, заменив кабель короткими проводниками. При сохранении схемы значение Date Mode можно не менять.
Особенности программы
Интерфейс данной версии программы англоязычен. Это решение вынужденное, и тому есть несколько причин:
• использование наиболее распространенного и наиболее дешевого дисплея без кириллических символов (Делать ему «кривоколенную» русификацию я посчитал в данном случае излишним);
• параметры библиотеки SPI определены в англоязычном варианте. Делать их перевод — только запутывать пользователя;
• меню очень простое и короткое.
Подробный разбор исходного текста и работы программы выходит за рамки настоящей статьи. Текст программы приведен в приложении и максимально подробно откомментирован. Поэтому отмечу несколько общих моментов.
Основная программа
Основная программа, крутящаяся в цикле LOOP представляет собой всего несколько строк. Это вызовы необходимых подпрограмм.
void loop()
{
KeyInput (); // Читаем кнопки
KeyProcessor (); // Формируем признаки нажатия, отпускания и долгого нажатия кнопок
ScreenMenu (); // Выводим экранные меню
ParamInput (); // Вводим значение параметров
MeasurementCycle (); // Цикл измерения
}
Программа разбита на четкие функциональные задачи. Каждая задача решается своей отдельной подпрограммой.
Обмен данными между подпрограммами осуществляется через глобальные переменные, объявленные в начале текста программы.
Много глобальных переменных не всегда хорошо, но в данном случае их не «вагон», запас памяти для данной задачи в МК большой. В начале программирования общая структура программы ещё недостаточна ясна. Глобальные переменные позволяют в этом случае писать и отлаживать отдельные фрагменты кода, не заботясь об области действия переменных. Когда будет получен полностью функциональный код, его можно будет начать «прилизывать» и убрать «местные», локальные переменные внутрь использующих их функций. Тут нужно быть весьма внимательным. Может оказаться, что после такого переноса нужные переменные станут в каких-то случаях недоступны, а при тестировании вы эту ситуацию пропустите, «ведь раньше всё работало». Если нет прямых показаний на такие действия в виде нехватки памяти или улучшения читаемости программы, то оставьте, как есть. Я поступил именно так. Также рекомендую всегда проводить явное присваивание начальных значений всем объявленным переменным.
Разделение подпрограмм по задачам достаточно очевиден и чёток.
KeyInput ()
Драйвер клавиатуры. Он однозначно связан с аппаратной частью. Его задача — опросить клавиатуру, определить, какая клавиша нажата, заполнить массив признаков нажатия клавиш и… всё. Возьмёте другую «клаву» (шилд) или в этой кнопки перепаяете — замените подпрограмму драйвер. Всё остальное можно не трогать.
В конкретном случае есть некоторые ньюансы. В используемом экранном модуле клавиатура собрана по схеме рис. 2.
Рис. 2. Клавиатура экранного модуля Arduino. Схема электрическая принципиальная.
Особенность схемы в том, что определяется нажатие только одной кнопки. Каждая верхняя по схеме кнопка «глушит» нижние. Для нашей задачи этого достаточно. Пять кнопок позволят нам двигаться по меню, вводить значения параметров и осуществлять выбор режима работы. Для ввода в Ардуино значения напряжения, соответствующего нажатой кнопке, используется жестко заданный пин аналогового ввода А0.
Основа текста драйвера была заимствована мною лет пять назад на просторах Интернета: LCD KeyPad Shield For Arduino SKU: DFR0009 https://www.dfrobot.com/wiki/index.php?title=LCD_KeyPad_Shield_For_Ardui...
Отличие в том, что в моем варианте драйвер выдает не единственное значение, а заполняет единицей элемент массива, соответствующий нажатой кнопке. Это нужно для совместимости с написанной и отлаженной ранее подпрограммой обработки нажатия клавиш, ориентированной на дискретную клавиатуру с возможностью одновременного нажатия произвольного сочетания клавиш.
На практике оказалось, что нажатие кнопки RIGHT частенько определялось как срабатывание кнопки UP. Я пробовал бороться с этим троекратным считыванием с аналогового входа и вычислением среднего. Мало помогло. Ситуация не исправилась полностью, но заметно улучшилась при более тщательном подборе порога определения клавиши RIGHT. На этом и остановился.
Для пробы взял экранный модуль другого производителя. Там подглючивала другая кнопка и по-другому. Модульность общей программы позволяет побороться с этими неприятностями программным способом на уровне драйвера, не затрагивая других частей общей программы. Так и придётся сделать, если уровень неприятностей будет мешать работать с устройством. Но это отдельная история.
KeyProcessor ()
Драйвер клавиатуры выдаёт наружу только текущее состояние кнопок. Нам же нужно определить факт нажатия, долгого нажатия и отпускания кнопки. Факт нажатия (передний фронт) кнопки нужен для движения по меню и однократного изменения значения вводимого параметра. Долгое нажатие нужно для перехода в режим автоувеличения или автоуменьшения значения параметра, а отпускание — бонусом. Бывает полезно.
KeyProcessor (), сравнивая текущее и предыдущее состояния кнопки, как раз и выдаёт нам по каждой кнопке признаки: кнопку нажали, кнопку нажали долго (более заданного времени, здесь — 0,5 с), кнопку отпустили. Обработчик был рассчитан на работу с дискретной клавиатурой, где клавиши можно было нажимать независимо и в любых сочетаниях. Здесь такой код избыточен, но он хорошо показал себя в предыдущих решениях, поэтому и был оставлен без изменений.
ScreenMenu ()
Эта подпрограмма выводит кранное меню. Точнее, текстовые заготовки содержимого экранов для ввода параметров, запуска измерения и результатов измерения. Тексты заранее заготовлены для 1-й и 2-й строк отдельно в виде двух раздельных строковых массивов.
Нажатие на кнопки UP и DOWN вызывает смену экранов в одном или другом направлении. Смена экранов идёт по кругу. Ввиду малости количества экранов долгое нажатие на кнопки UP и DOWN не отрабатывается.
ParamInput ()
Подпрограмма непосредственно позволяет вводить численные значения параметров процесса измерения. В поле ввода индицируется текущее значение вводимого параметра. Это значение можно увеличивать или уменьшать на единицу коротким нажатием кнопок RIGHT или LEFT соответственно. При нажатии на эти кнопки более 0,5 с начинается процесс автоувеличения или автоуменьшения вводимого параметра. Он продолжается до момента отпускания кнопки или до достижения параметром предельно допустимых значений. Поскольку диапазон значений количества измерений в цикле многократно превышает диапазоны изменения других параметров, а механизм ввода значений у них один и тот же, то для сокращения времени ввода значения количества измерений при его автоувеличения или автоуменьшения принимается шаг изменения, равный 50. Значения шага задается в программе явным образом и может быть легко изменено для каждого из параметров.
Значения параметра Clock Divider меняются не непрерывно, а в соответствии с множеством его возможных значений согласно описания библиотеки SPI: 2, 4, 8, 16, 32, 64, 128.
MeasurementCycle ()
Подпрограмма MeasurementCycle () реализует цикл измерений согласно заданных ранее параметров. Первоначально значения библиотечных параметров переводятся из условной численной формы в вид, определённый в библиотеке SPI, и инициализируются.
Параметр SPI.setBitOrder() всегда имеет значение MSBFIRST, поскольку наше Slave-устройство заранее известно и неизменно для всех измерений. И это просто сдвиговый регистр. По-другому тут никак.
После инициализации параметров библиотека запускается. Проводится указанное количество передачи и приема байт, подсчитывается количество правильно принятых и ошибочно принятых байт. Всё это выводится на экран.
Внутри цикла измерений вызывается подпрограмма BytePreparation (). Она задаёт значение тому байту, который будет передаваться в данный момент. У меня это единственное присвоение байту значения, состоящего из чередующихся нулей и единиц. И стоило из-за одного оператора огород городить? Если будет нужда или желание устроить более серьезные испытания, применив «бегущий ноль», «бегущую единицу» и ещё более хитроумные алгоритмы формирования данных для передачи, то это можно будет сделать внутри подпрограммы BytePreparation () никак ни затронув остальные части программы.
Во время цикла измерений опрос клавиатуры не производится, чтобы не тратить на это время. Поэтому, если появилось желание прервать процесс измерений, то нужно нажать кнопку RESET и перезагрузить МК.
Если цикл измерений завершился штатным образом, клавиатура вновь оживает, экраны меню можно пролистывать, вводить новые параметры. При этом результаты прошедшего измерения не пропадают и их можно увидеть, долистав до соответствующего экрана.
Полученные измерения бесследно исчезнут только в случае выключения/перезагрузки МК или запуска нового цикла измерений, который происходит после нажатия кнопки SELECT на экране запуска измерений.
Структура устройства
На рис. 1 приведена структурная схема устройства в максимальной версии. Эта максимальная версия весьма желательна как раз для тех случаев, когда линия передачи данных «длинная». Т.е. малопонятный кабель значительной (до десятков метров) длины, у которого явным образом сказываются индуктивность, емкость и омическое сопротивление, мешающие прохождению наших импульсных сигналов.
Что в этом варианте относится к максимуму, а что к необходимому минимуму? Минимум — это Master-устройство и Slave-устройство. Максимум получится, если добавить довесок из кабельных усилителей и кабельных приемников с обеих сторон линии связи. Для чего они нужны?
Первая задача — гальванически изолировать кабель и от Master-устройства, и от Slave-устройства. Вокруг нас огромное количество источников электромагнитных излучений. Буквально все электрические, электромеханические и электронные устройства. Все они излучают помехи. Прикоснитесь пальцем ко входу усилителя низкой частоты. В колонках будет стоять рёв. И это самый безобидный случай. Чем больше мощность устройства, тем больше от него помех. Особенно, если оно импульсное. Длинный кабель — прекрасная антенна. Как только подсоединить такую антенну к высокоомному сигнальному входу МК, о сигнале можно забыть. Даже если далеко от МК вывести только общий провод и то можно нахватать помех. Помеховая обстановка вещь очень специфическая. Борьба с помехами обычно ведется непосредственно по месту методом «Профессора Тыкова». Описываемое в статье устройство один из приборов, помогающих оценить влияние помех и найти эффективный способ борьбы с ними. Гальваническая изоляция передатчика и приемника от кабеля линии передачи данных это как мытьё рук перед едой. 100% гарантий не даёт, а профилактически очень хорошо действует. Правда, в отличие от мытья рук, требует существенно больших усилий по реализации.
Вторая задача — обеспечить необходимую мощность сигнала в кабеле. Чем выше мощность сигнала, тем сложнее помехе его перешибить. Плюс мощность нужна, чтобы быстро перезаряжать паразитные для нас емкости кабеля и продавливать током паразитные же для нас кабельные индуктивности. У обычных цифровых микросхем мощности на это не хватает. Поэтому приходится использовать дополнительные усилители. Конкретных схем таких усилителей огромное множество от самых простых любительских до вполне навороченных профессиональных. Какая из них подойдет в конкретном случае можно определить только практикой.
Всегда ли нужны такие «страсти»? Нет. Вполне может оказаться, что на относительно малых расстояниях, отсутствии мощных источников помех и невысоких требованиях к скорости передачи данных можно обойтись минимальными средствами. Рассмотрим конкретный пример.
Минимальная схемная реализация
Для первых практических опытов будем использовать схему устройства в минимальном варианте, представленном на рис. 3
Рис. 3. Arduino-тестер длинных линий интерфейса SPI. Схема электрическая принципиальная. Минимальный вариант.
Здесь нет никаких кабельных усилителей и приемников. Выводы Master-устройства (МК) и Slave-устройства (74HC165) соединены напрямую. Только сигнальные входы подтянуты к плюсу питания через резисторы сопротивлением 1 кОм. Резисторы помогут избежать неприятностей, когда мы будем подключать и отключать кабели.
Чтобы лучше понимать физику процесса, подключим вход осциллографа к тактовому входу сдвигового регистра 74HC165 Slave-устройства. Тактовые импульсы самые короткие, и неприятностей, в первую очередь, следует ожидать именно с ними.
Slave-устройство небольшое, простое. Для удобства соберем его на макетной плате без пайки.
По имеющимся возможностям подберем для экспериментов разные кабели. Первый вариант -это просто короткие провода с наконечниками. Их часто называют DUPON DIY. Второй и третий варианты это обычные Ethernet витые пары 5-й категории разной длины. В данном эксперименте из витых пар используются только по одному проводу. Второй провод витой пары остаётся неподключенным. Для эксперимента выбрали худший вариант, как двойная телефонная «лапша».
Результаты экспериментов
Результаты экспериментов для нескольких сочетаний тип кабеля/длина кабеля/значение Clock Divider приведены на рис. 4, рис. 5, рис.6.
Рис. 4. Осциллограммы напряжения на входе CLK (пин 2) сдвигового регистра Slave-устройства. Провода DUPON DIY 0,2 м.
Рис. 5. Осциллограммы напряжения на входе CLK (пин 2) сдвигового регистра Slave-устройства. Провода - витая пара категории 5, 1,0 м.
Рис. 6. Осциллограммы напряжения на входе CLK (пин 2) сдвигового регистра Slave-устройства. Провода - витая пара категории 5, 12 м.
В данных экспериментах никаких, даже простых способов улучшения ситуации не проводилось. Это делалось сознательно. Важно было понять, на что можно надеяться, просто подключив «пин к пину». В известном смысле, такой подход лежит в русле общей идеи Ардуино.
Также хотелось оценить эффективность разработанного устройства. Помогает ли оно на практике решить поставленные задачи по выбору параметров устойчивой работы интерфейса SPI? На мой взгляд, полученные результаты достаточно красноречивы. «Сработала, машинка то...»
Максимальный вариант устройства требует уже существенно больших усилий в реализации. Применить с приемлемым результатом детали, просто взятые наугад из коробки, может не получиться. Прежде всего, это касается оптронов. Например, горячо любимые в Ардуино-проектах за распространенность и дешевизну оптроны PC817 даже по паспортному быстродействию «очень не очень». Максимальное время нарастания и спада импульса может доходить до 18 мкс. В моих опытах время спада оказалось и того хуже. Даже, если предположить типовые значения времен нарастания и спада по 4 мкс и 3 мкс соответственно и совсем ничего не оставить на «полку» тактового импульса, то мы не укладываемся даже в самую низкую частоту тактовых импульсов, которые можно получить в библиотеке SPI.
Что, максимальный вариант оказался только «в принципе»? Нет. Его тоже вполне можно реализовать. Самый простой способ — понизить частоту тактовых импульсов до того уровня, когда «тормознутость» оптронов широкого применения перестанет сказываться. Здесь библиотекой SPI пользоваться уже нельзя. Драйвер придется писать самим. Утешает то, что драйвер несложный, и что писать его можно с применением привычных конструкций языка «С++ от Ардуино»: digitalWrite() и digitalRead(), поскольку о быстродействии речи не идет. Ещё и задержки придется ставить.
Второй способ реализации максимальной версии устройства, без категорической потери быстродействия — применить быстродействующие оптроны и проверенное схемотехническое решение. Этот путь явно сложнее и воспроизводимость его в любительских условиях может оказаться не легче, чем использование, например, связки RS-485/Modbus RTU.
А есть ли еще варианты кроме максимального и минимального? Да, есть. Начнем с того, что при использовании витой пары второй провод в паре лучше подключить к общему проводу устройства, часто ошибочно называемого «землей». Причем результат может оказаться разным при подключении к общему проводу Master-устройства, Slave-устройства или обоих одновременно. Если уровень импульсных помех по трассе кабеля ожидается терпимым, то можно попробовать обойтись без оптронов, подгрузив сигнальные линии с двух сторон кабеля резисторами, поставив транзисторные ключи в качестве кабельных усилителей, а входы Master- и Slave-устройств отделить от кабельной линии триггерами Шмитта в интегральном исполнении.
И снова пробовать по месту. Универсальных решений нет. Ардуино-тестер в помощь!
В статье предлагается устройство для проверки прохождения данных в длинных линиях интерфейса SPI.
3. В качестве Slave-устройства в базовой версии используется ИМС 74HC165.
Нет, протокол похожий, но, насколько я помню, 74HC165 не способен отпускать шину, а потому его использование параллельно с другими устройствами вызывает проблемы. И эти проблемы имеют непосредственное отношение к функционированию "длинных линий" (кстати, не уверен в корректности используемой терминологии). Мне кажется, для объективности следовало бы использовать:
- не менее двух устройств. Использование шины, предназначенное для подключение множества устройств, для единственного устройства вряд ли может быть показательным.
- устройства, которые реализуют SPI достаточно строго. По меньшей мере, используют оба сигнала MOSI и MISO, а также могут параллельно работать на одной шине.
Могу порекомендовать в качестве устройств для примера SD карту и SPI дисплей.
Подписываюсь
А Вы уверены, что 74HC165 - это SPI?
Это частный случай простейшей аппаратной эмуляции Slave-устройства, служащей одной единственной цели - проверить прохождение сигнала в конкретном кабеле с конкретными кабельными драйверами, если таковые есть. Библиотека SPI (наш рабочий эталон) работает с 74HC165 штатным образом. Для решения указанной задачи такое использование корректно.
Здесь никаких других устройств нет. Чтобы проверить кабельную сеть, 74HC165 последовательно ставится на место каждого устройства и осуществляется проверка.
Я написал, что имею ввиду: "«Длинная линия» - это такое состояние проводов, когда их уже нельзя рассматривать, как на схеме, идеальным проводником с нулевым сопротивлением."
У меня линия связи - это кабель, который для "настоящего" SPI с его настоящими частотами и длинами не используют. Т.е. это случай относящийся к "начинающему самодельщику", которому надо вынести регистры-расширители портов МК на десяток другой метров от МК.
- не менее двух устройств. Использование шины, предназначенное для подключение множества устройств, для единственного устройства вряд ли может быть показательным.
- устройства, которые реализуют SPI достаточно строго. По меньшей мере, используют оба сигнала MOSI и MISO, а также могут параллельно работать на одной шине.
Могу порекомендовать в качестве устройств для примера SD карту и SPI дисплей.
"Настоящие" SPI-устройства, использующие "настоящий" SPI-протокол, в частности, рекомендованные Вами SD-карта и SPI-дисплей, располагаются на шильде, буквально воткнутым в плату Ардуино. Тут проблемы если и возникают, то совсем другие. Я рассматриваю случай: "А что делать, если у калитки кодовый замок с клавиатурой из 16 клавиш, Ардуина в теплом доме (что совершенно оправдано), а между домом и калиткой метров эдак 15 по дорожке и 25 — 30 — по кабелю? Устраивать из этого «кусочек АСУ ТП» как то «не оно», да, честно говоря, и некому."
Это частный случай... Библиотека SPI (наш рабочий эталон) работает с 74HC165 штатным образом. Для решения указанной задачи такое использование корректно.
...
Я рассматриваю случай: "А что делать, если у калитки кодовый замок с клавиатурой из 16 клавиш, Ардуина в теплом доме (что совершенно оправдано), а между домом и калиткой метров эдак 15 по дорожке и 25 — 30 — по кабелю? Устраивать из этого «кусочек АСУ ТП» как то «не оно», да, честно говоря, и некому."
1. В самом названии темы указано, что речь идет о тестировании длинных линий связи, а не устройств интерфейса SPI.
2. Во 2-м посту темы п. 3 я прямо указываю, что в качестве Slave-устройства использую 74HC165. А дальше подробно обосновываю этот выбор.
3. Библиотека SPI работает с 74HC165 без каких либо условностей, т.е. в данном случае воспринимает его как полноценное SPI-устройство.
4. Единственная "претензия", которую можно предъявить 74HC165 - неотпускание линии MISO по сигналу SS, что не дает строить из 74HC165 сеть устройств SPI по топологии "звезда" (в терминологии Википедии).
4.1. Для проверки линии связи нет необходимости формировать сеть, достаточно одного устройства. При единственном устройстве сигнал выбора устройства SS не нужен, отпускание линии MISO не нужно.
4.2. По топологии "кольцо" SPI-сеть на 74HC165 построить можно. Отпускать линию MISO там также нет необходимости. Причем это будет совершенно реальная сеть, т.к. по единственному сигналу SS во всех регистрах можно будет защелкивать в регистрах внешнюю информацию, а после выталкивать ее по последовательному каналу в мастер-устройство.
4.3. Библиотека SPI формирует один единственный сигнал SS. Даже если бы он в данном случае не был занят шилдом с дисплеем, то в случае сети сигналы выбора устройств пришлось бы формировать самостоятельно.
Предположу, что у Вас есть какие-то нерешенные технические вопросы по одновременному подключению к Ардуино нескольких "классических" SPI-устройств: дисплеев, карт памяти, ... Увидев в названии темы слово "SPI", но не найдя ответов на Ваши вопросы, расстроились. :))
Предполагать, конечно, Вы можете все, что угодно, но в данном случае Ваши предположения ошибочны сразу по нескольким пунктам:
- нерешенных технических вопросов, связанных с SPI, у меня в данный момент нет. Хотя, были, когда я подключал 165 регистры одновременно с другими SPI устройствами. Естественно, они уже давно разрешены, но способом, который может повлиять на функционирование "длинной линии", а именно - включением в линию MISO дополнительного резистора. Т.е., на мой взгляд, у сочетания 74HC165+"длинная линия" есть особенности, которые не позволяют использовать 74HC165 в качестве типового устройства для "длинной линии".
- естественно, каких-либо ответов в Вашей теме я искать не пытался. Более того, не стал искать в ней и другие ляпы. И-нете достаточно много [скажем так:] не слишком достоверной информации, поэтому, дабы не тратить свое время, я, исхожу из принципа "чтобы понять, что яйцо тухлое, не обязательно есть его целиком". Извините.
- нерешенных технических вопросов, связанных с SPI, у меня в данный момент нет. Хотя, были, когда я подключал 165 регистры одновременно с другими SPI устройствами. Естественно, они уже давно разрешены, но способом, который может повлиять на функционирование "длинной линии", а именно - включением в линию MISO дополнительного резистора. Т.е., на мой взгляд, у сочетания 74HC165+"длинная линия" есть особенности, которые не позволяют использовать 74HC165 в качестве типового устройства для "длинной линии".
Сказали бы сразу: "Я придумал проверенный на практике способ, как с помощью одного резистора превратить "неправильный" 74HC165 в "правильный", на котором можно строить SPI-сеть с топологией "звезда"." Прекрасно. Можно было бы предметно обсудить "+" и "-" этого решения и его применимость. Прямого отношения к данной теме это не имеет просто в силу постановки задачи, но, вполне возможно, что кому-то из читателей было бы полезно. "Звезда" часто оказывается удобнее "кольца", доступного "из коробки".
Эта тема не для профессионалов, а для начинающих, желающих продолжить, о чем сразу сказано в пункте "Для кого".
Выявление ляпов и их предметный осознанный разбор помогает другим людям их избежать в будущем. Опять же, осознав в ходе разбора причинно-следственную связь. Но... На "нет" и суда нет.
Взрослый человек сам решает, что ему делать или не делать, на что тратить свое время, а на что - нет. Это - Ваш выбор.