Русский
Русский
English
Статистика
Реклама

Передача данных

Power-line communication. Часть 1 Основы передачи данных по линиям электропередач

25.08.2020 02:16:19 | Автор: admin
Не так давно передо мной встала нетривиальная задачка собрать устройство, которое могло бы по линиям электропередач (0,4 кВ), в сетях обычных бытовых потребителей, передавать некоторую информацию, а точнее показания электросчетчиков.



Перед началом работы над созданием этого устройства, я мало понимал в цифровой обработке сигналов и в том, как работают компьютерные сети на физическом уровне. Нужно было быстро погрузиться в вопрос и выстроить план по созданию рабочего прототипа.
В процессе изучения я нашел очень много специализированной литературы по электронике, микроконтроллерам и цифровой обработке сигналов, которая очень помогла мне в этом. Но в самом начале пути для выбора направлений изучения мне бы пригодились обзорные статьи вроде этой.

Дальнейший материал это выжимка из профессионального опыта в том виде, в котором я бы хотел это рассказать самому себе из прошлого. Многие факты сильно упрощены для лучшей читаемости.



Коммуникация


Начнём с абстракций. Представим, что нужно передать порцию информации от одного человека другому. На изображении: красный человечек это передатчик, а синий приёмник.



Для передачи информации будем использовать голос. Информация это какой-то текст в нашей голове. Текст можно разбить на буквы и каждую букву представить в виде звукового сигнала. Таким образом можно кодировать каждую букву каким-то соответствующим звуковым сигналом.



Проводник


Звук, как известно, распространяется в виде волн колебаний частиц воздуха или иной среды. В нашем случае средой для распространения сигнала служит воздух. От красного человечка звуковые волны по воздуху распространяются во все стороны.

Полезный сигнал




К счастью, информацию из нашей головы мы не можем мысленно передать напрямую в голову собеседнику. Поэтому буквы из нашей головы на аппаратном уровне мы преобразуем (кодируем) в звуковые сигналы (наборы звуковых волн). Будем называть это полезным сигналом.
Важно: каждая буква кодируется устойчивым набором звуковых волн. Из этих волн мы можем распознать определенную букву (если мы ее знаем, конечно же). Происходит преобразование из буквы в звук и обратно из звука в букву.

Шум



Шум это такой же сигнал, но он не несёт в себе полезной информации. Шум искажает полезный сигнал и уменьшает дальность уверенного приема. Это может быть толпа людей, громко говорящих о чем-то своем, а может быть даже эхо или другие посторонние звуки, которые смешиваются с полезным сигналом. Шум обычно мешает прохождению полезного сигнала до приемника.

Протокол



В таком виде сигнал доходит до приемника. Приёмник из набора звуковых волн узнаёт (декодирует) буквы и собирает из них слова. Если ему кажется, что это бессмысленный набор звуков, то он их отбрасывает либо пытается восстановить исходный сигнал по сложному алгоритму. Отчасти, из-за этого мы иногда сначала переспрашиваем Что?, а уже потом понимаем, что всё расслышали.

Протокол это, по сути, набор правил и алгоритмов, по которым мы из полезного сигнала сможем вычленить информацию. В данном примере это наш язык, на котором мы общаемся с собеседником. По нему мы узнаем смысл переданных звуков. Всё это происходит неосознанно можно сказать на аппаратном уровне.

Всё описанное выше в очень упрощенном виде показывает, как работает передача данных не только между людьми, но и между электронными устройствами. Только физическим воздействием у них будет, например, электрическое напряжение, а проводником медный кабель. Информация, хранящаяся в устройстве, может быть передана с помощью различных физических сред передачи и протоколов, но суть примерно одна и та же: проводник, физическое воздействие, протокол.


Линии электропередач как канал связи



Далее мы по шагам разберемся, как передавать данные по линиям электропередач, и по ходу дела придумаем свой велосипед протокол. Основные идеи из открытого промышленного стандарта X10.

Чтобы использовать линии электропередач в качестве канала связи, нужно понять, как они устроены, и какие физические процессы в них происходят.
Взглянем на схему доставки электроэнергии от подстанции до жилых домов. Электрические сети трехфазные, и от подстанции идут три фазы (A, B и С), которые электрически изолированы друг от друга.



Для простоты условимся, что каждая фаза это отдельный канал связи. Устройства, подключенные к разным фазам, не слышат друг друга.
Сейчас на рынке есть устройства, которые умеют общаться между фазами, для них вся подстанция это один канал связи. Но пока для понимания это не играет особой роли.
Далее на схемах будем рассматривать только фазу А (в других всё аналогично).



При подключении нескольких приемо-передающих устройств к одной фазе образуется сетевая топология типа общая шина. Сигнал, отправленный одним из устройств, получат все остальные устройства, находящиеся в пределах распространения сигнала.



Проводник


Подробнее изучим среду передачи сигнала. Для этого рассмотрим, в каком виде передается электрическая энергия, и узнаем, как через этот поток мы можем передать свой полезный сигнал.
Электроэнергия передается в виде переменного тока. Проводниками обычно выступают алюминиевый или медный кабели. Напряжение в электрической сети имеет форму синусоиды с периодом 20 миллисекунд (частота 50 Гц).



Так как ток переменный, он периодически меняет направление течения, и в момент смены направления мощность практически не передается (если не учитывать сдвиг из-за сильной емкостной или индуктивной нагрузки). Наступают мгновения затишья. Это называется zero cross (далее ZC) момент, в который напряжение равно нулю.



В этот момент в сети также наблюдается наименьший уровень шума. Это самый благоприятный момент для генерации полезного сигнала.

В электрической сети с частотой 50 Гц (как в России) момент ZC происходит 100 раз в секунду. И если передавать по одному символу за один переход через ноль, то скорость соединения будет равна 100 бод/сек. Скорость передачи в байтах уже зависит от формата кадра, от того, сколько служебных бит, помимо самих данных, будет в кадре (о формате кадров ниже по тексту).

Синхронизация


Еще один немаловажный момент это синхронизация момента передачи и приема между устройствами.
Для нашего нового протокола будем использовать синхронную передачу данных, так как это проще в реализации.
Передатчику нужно знать, в какой конкретный момент надо включить ЦАП для генерации сигнала. Приемнику нужно понимать в какой конкретный момент надо включить АЦП для измерения и оцифровки входящего сигнала. Для этого кто-то должен подавать сигнал процессору.
Этим будет заниматься отдельная часть схемы устройства Zero Cross Detector. Он просто дожидается, когда напряжение на линии будет 0 вольт, и подает об этом сигнал. В сетях с частотой 50 Гц, сигнал будет приходить каждые 10 миллисекунд.



Электрическое напряжение распространяется со скоростью света, и поэтому можем условно принять, что момент ZC во всех точках сети происходит одновременно.

В интернете можно найти примеры схем детектора под названиями Детектора нуля или Zero Cross Detector.


Полезный сигнал


Существуют различные варианты кодирования информации для передачи по ЛЭП. Мы будем использовать узкополосную передачу с частотной модуляцией, т.к. она проще для понимания и надежнее. Минусом является низкая скорость передачи данных, но для нас это пока не играет особой роли.
Полезный сигнал это обычная синусоида фиксированной амплитуды. Изменяется у только частота сигнала. Выберем пару частот и скажем, что сигнал с одной частотой это 0, а сигнал с другой частотой это 1.



Другой вариант: как в стандарте X10, наличие сигнала означает 1, а его отсутствие 0.

Физически этот сигнал можно генерировать с помощью модуля ЦАП, который есть почти в любом современном микроконтроллере. На вход ЦАП принимает программным путем цифры (уровень сигнала), а на выходе выдает соответствующий этой цифре уровень напряжения. Таким нехитрым образом можно по таймеру подавать в модуль ЦАП массив чисел, а на выходе получать синусоиду с нужной нам частотой.


Подробнее о том, как эффективно генерировать синусоидальный сигнал, расскажу в следующей статье.

Шум


В ЛЭП изначально присутствует довольно мощный сигнал это передаваемая электрическая энергия от подстанции до жилых домов. И при нагрузке появляется большое количество шума на широкой полосе частот. Бытовая техника, блок питания компьютера, зарядные устройства они испускают широкий спектр частот в электрическую сеть.

Для понимания, сравним выделенную линию передачи данных с ЛЭП.
Выделенная линия это отдельный провод, по которому общается некоторое количество устройств. Можно сравнить с пустой комнатой, в которой можно комфортно общаться.



А ЛЭП можно сравнить с коридором, в котором проводят работы перфоратором, и по середине едет поезд (очень шумно). В этих условиях передать информацию сложно, но реально.



Протокол


Кодирование очень простое выбираем несколько символов и ставим в соответствие каждому какую-либо частоту сигнала. Для простоты сделаем три символа:

  • Start по этому символу устройство поймёт, что началась передача кадра;
  • 0 это символ бита 0;
  • 1 это символ бита 1.


Передатчик по сигналу из ZC детектора на короткое время генерирует синусоиду нужной частоты. И таким образом передается по одному символу (S, 0 или 1) за один переход напряжения сети через ноль (каждые 10 миллисекунд). Приемники измеряют этот сигнал, узнают его частоту и записывают соответствующий этой частоте символ (S, 0 или 1) в буфер.


Теперь мы умеем сообщать о начале кадра и передавать некоторый набор единиц и нулей. Далее из них будем складывать слова или кадры. Целостные порции информации.

Формат кадра


Нужно ещё придумать формат кадра, который мы будет передавать с помощью этих символов. Есть несколько важных моментов, которые отразятся на формате данных: длина кадра, адресация, проверка целостности.

Длина кадра
Чем больше порция данных, тем меньше накладных расходов на передачу данных, так как помимо самих данных в кадре есть служебная информация вроде контрольной суммы и адреса назначения. Но чем меньше порция данных, тем больше вероятность успешной передачи. Тут важно найти золотую середину. Определяется это обычно опытным путем. Если взять пример из компьютерных сетей, то в Ethernet кадре было выбрано ограничение в 1500 байт данных (несмотря на то, что эта цифра быстро устарела, она используется до сих пор).


При сильном увеличении длины кадра, вероятность передать хоть какие-то данные стремится к нулю.

Адресация
Нужно ещё не забыть, что у нас топология сети общая шина. Информацию, отправляемую в эту шину, будут получать все устройства. И чтобы общение у них хоть как-то заладилось, у них должны быть адреса.
Адрес добавим в самое начало кадра, чтобы принимающая сторона, для которой не предназначены эти данные, не тратила время на прослушивание и ожидание всего кадра, так мы немного освободим процессор от бесполезной работы.

Длина адреса выбирается исходя из максимального количества устройств, которые могут одновременно находится в одной области видимости. Например, 8 бит это максимум 255 устройств (если 0 оставить как широковещательный).

Проверка целостности
При передаче информации по ЛЭП очень большая вероятность потерять часть данных. Поэтому обязательно должна быть проверка целостности. Для этих целей в кадр добавляется концевик. Это некоторая избыточная информация, с помощью которой приёмник сможет убедиться в том, что данные не искажены.

Придумаем окончательный вид кадра. Пусть длина адреса будет 8 бит (255 устройств в канале + 1 широковещательный адрес). Затем идут данные 8 бит (1 байт).
Концевиком у нас будет просто результат сложения адреса и байта. Но есть один нюанс: устройство может стабильно ловить сильный шум на частоте наших символов 0 или 1 и думать, что это полезный сигнал. И есть большая вероятность ложно считывать крайние значения типа 0x00 или 0xFF. Для защиты от этого, при подсчете концевика, просто будем прибавлять число 42.

Примерно так будет выглядеть один кадр данных: отправляем число 110 на устройство с адресом 17, концевик 169 (110 + 17 + 42).


Целый кадр будем собирать по кусочку из приходящих символов 0 и 1 после символа Start.

Опишем алгоритм приема кадра.
Изначально устройство находится в ожидании символа Start. Буфер отключен, в него ничего не пишем.
Когда пришёл символ Start, для удобства очищаем буфер приема и запускаем счетчик бит (по счетчику бит будем определять целый кадр).


Каждый следующий символ (0 или 1) последовательно пишем в буфер приема и инкрементируем счетчик бит.


Когда соберется нужное количество бит (полный кадр), проверяем целостность. Выделяем из кадра Адрес и Данные. Подсчитываем по алгоритму Концевик и сравниваем с тем, что в кадре.



Если значения сошлись, извлекаем из кадра данные и отправляем в вышестоящий протокол.



Если значения не сошлись, продолжаем ждать символ Start. И всё заново.

Примерно таким образом мы можем медленно, но верно передавать байт за байтом от одного устройства другому. Приемник будет складывать эти байты в приемный буфер протокола на уровень выше физического и там уже будет решать, что делать: выполнить входящую команду или вернуть какие-то данные в ответ.

Итог


В этой статье я постарался общим и понятным языком ввести читателя в тему передачи данных по линиям электропередач. Надеюсь, кому-то это информация пригодится, возможно, не только в области PLC.
В следующей части хотелось бы рассказать про алгоритм быстрой генерации синуса, который я применял. И о том, как из массива чисел оцифрованного сигнала узнать его частоту (ДПФ). Немного расскажу про железки для всего этого.

Возможно кто-то в комментариях подкинет ещё идей. Буду рад обратной связи!


Ссылки и материалы по теме:
Про шум в сетях
Ещё про шум в сетях
Один из вариантов Детектора нуля
Wiki: Связь по ЛЭП
Wiki: Трёхфазная система электроснабжения
ГОСТ Р 51317.3.8-99 (МЭК 61000-3-8-97) Совместимость технических средств электромагнитная. Передача сигналов по низковольтным электрическим сетям.
Подробнее..

Power-line communication. Часть 2 Основные блоки устройства

26.01.2021 02:10:54 | Автор: admin

Часть 1 Основы передачи данных по линиям электропередач

В первой части статьи мы кратко ознакомились с основными понятиями при передаче данных по линиям электропередач. Узнали, что такое полезный сигнал, как с его помощью можно кодировать передаваемую информацию. Но ни слова не было о том, как это устройство должно быть выполнено физически, как оно будет генерировать сигнал, и каким образом его вообще подключить к сети 220 В.

В этой и следующей частях статьи опишем, какие основные блоки должны быть в простейшем устройстве передачи данных по PLC. Постепенно, как конструктор, будем добавлять в общую картину блок за блоком и разберемся для чего нужен каждый блок и как он работает.

- Введение
- Мозги устройства микроконтроллер
- Основные требования к микроконтроллеру
- Выбор подходящего микроконтроллера
- Особенности питания устройства

Дисклеймер: статья не является руководством по созданию устройства и не является справочником по электронным компонентам. Это просто результаты моих экспериментов и некоторый накопленный практикой опыт, который, надеюсь, будет полезен тем, кто интересуется темой. Если есть какие-то замечания, интересные ссылки и книги, обязательно оставляй это в комментах.

Введение

Для начала кратко вспомним из части 1, как происходит передача данных. На изображении одна из фаз ЛЭП. Красное устройство передает, синие слушают. Биты данных один за одним передаются в виде синусоидальных сигналов различной частоты (FSK модуляция).

В мозге устройства микроконтроллере зашит протокол, по которому передаются/принимаются данные. Также в прошивке микроконтроллера для каждого передаваемого символа (или бита) задана соответствующая частота сигнала.

Для примера: если передается символ 0, то генерируется полезный сигнал в виде синусоиды 74 кГц. А если передается 1, то генерируется синусоида с частотой, например, 80 кГц. Номиналы частот не особо важны, просто выбираются любые из разрешенных диапазонов. Главное, чтобы приемник смог их различить.

В первой части статьи упоминалось про третий символ S, который означал начало кадра. Он также кодировался своей определенной частотой. Когда устройство получало символ S, входной буфер очищался. Для простоты в этой статье будут упоминаться только 0 и 1.

Передающие и принимающие устройства синхронизируются между собой с помощью отдельного блока устройства zero cross детектора.

Представим передающее устройство, в котором есть подготовленный кадр данных некий массив нулей и единиц, и этот кадр нужно передать по PLC каналу связи (ЛЭП). Передача/прием кадра происходит по одному биту за один синхросигнал из ZC детектора.

Физически это значит, что за один синхросигнал из ZC детектора генерируется один полезный сигнал определенной частоты. В нашем случае это синусоиды 74 кГц или 80 кГц.

Таким образом, бит за битом, передается кадр данных в PLC канал. Совместно с микроконтроллером генерацией сигналов будет заниматься отдельная часть схемы. Назовём её Выходная цепь.

Задача принимающих устройств каждый раз, по сигналу ZC детектора, оцифровывать полезный сигнал из PLC канала и узнавать, какой символ там был закодирован.

Но сначала сырой сигнал нужно грубо очистить от шума, подогнать уровень очищенного сигнала под пригодный для оцифровки и уже затем передать на АЦП микроконтроллера для дальнейшего цифрового анализа. Этой подготовкой полезного сигнала для АЦП будет заниматься Входная цепь.

Чтобы не раздувать эту часть статьи, расскажу только про задачи, решаемые микроконтроллером и некоторые особенности питания устройства.

В следующей части рассмотрим как устройство можно согласовать с сетью 220 В, работу ZC детектора, а также про входную и выходную цепи.

Мозги устройства микроконтроллер

Центральная часть устройства микроконтроллер, который будет контролировать всю схему: обрабатывать входной сигнал, генерировать полезный сигнал, управлять усилителями, хранить данные и т.д.

Микроконтроллер это такой мини-компьютер, который в одном корпусе содержит процессор (ЦПУ), память (ПЗУ и ОЗУ), ввод-вывод и периферийные устройства. По сути, внутри уже все есть для работы: подаем питание и поехали. Дальше все зависит уже от программы прошивки, которую мы в него записали.

Рисунок с сайта digikey.comРисунок с сайта digikey.com

Сейчас выпускают микроконтроллеры с большим количеством различной встроенной периферии. Это очень удобно, так как меньше необходимости во внешних компонентах, что экономит место на печатной плате (и, конечно же, ваши денежки). Внутри может иметь ЦАП и АЦП, часы с календарем. Даже встроенный USB уже не удивляет.

На рынке огромное разнообразие микроконтроллеров с разной вычислительной мощностью и периферией. Обычно они группируются в серии и подходят под разные классы задач. Например, чтобы помигать светодиодом в миниатюрном устройстве, нам не нужен мощный камень, на котором можно запустить Linux, подойдет ATtiny. Но для нашего устройства его уже не хватит, так как нужны ЦАП, АЦП и быстрые вычисления в реальном времени.

Поэтому к выбору камня нужно подойти немного поразмыслив. Подумаем, что же требуется от микроконтроллера в нашем случае.

Основные требования к микроконтроллеру

Производительность

Основной нагрузкой на ЦПУ будет обработка оцифрованного входного сигнала с помощью ДПФ для выяснения того, какой символ был закодирован в сигнале: 0 или 1. Далее этот символ будет отправляться в протокол на уровень выше. Больше всего вычислений будет происходить именно при подсчете гармоник в ДПФ.

Циклично, с интервалом 10 миллисекунд, АЦП будет оцифровывать входящий сигнал и сохранять его в виде массива чисел. Затем этот массив несколько раз прогоняется через ДПФ для выяснения амплитуд гармоник каждой из интересующих нас частот в полезном сигнале.

Результат визуально можно представить в виде эквалайзера, на котором нарисованы полоски определенных частот разной высоты (амплитуды). Для подсчета высоты каждой отдельной полоски нужно сигнал прогонять через ДПФ.

После подсчета некоторого количества гармоник, делаются выводы о том, какой символ закодирован.

В самом простом случае можно просто сравнить амплитуды гармоник 74 и 80 кГц между собой. Если в сигнале преобладает гармоника с частотой 74 кГц, записываем в входной буфер бит 0.

Если в сигнале преобладает гармоника с частотой 80 кГц, записываем в входной буфер 1.

В таком случае, любой шум что-то означает: 0 либо 1, даже если ничего не передавалось. Отделением зерен от плевел будет заниматься отдельная подпрограмма уровнем выше которая будет проверять целостность кадра и прочие прелести.

Задача же этого уровня просто, как конвейер, подавать 0 и 1 наверх, а дальше из них будут складываться правильные целостные кадры данных. Или не будут.

Также можно заморочиться и дополнительно рассчитывать амплитуды смежных гармоник и узнавать уровень шума относительно полезного сигнала. Можно программно фильтровать сигнал и тд. Вариантов много.

Суть в том, что считать, возможно, придется много. Успевать считать нужно гарантированно, так как это реалтайм-конвейер.

Если разложить всю нагрузку на которую ЦПУ тратит время друг за другом, то получим примерно это:

  • оцифровка сигнала

  • подсчет амплитуд гармоник через ДПФ и анализ результата

  • прочая нагрузка (обработка прерываний из интерфейсов USB или CAN, обработчики таймеров, моргания светодиодами, работа с памятью, какие-то вычисления по протоколу и т.д.)

Это должно циклично выполняться каждые 10 миллисекунд снова и снова. ЦПУ никогда не должен быть загружен на 100%, иначе есть риск не успеть посчитать что-то важное. Поэтому всегда нужно оставлять запас по производительности.

Энергоэффективность

Обратная сторона быстрых вычислений большее потребление энергии. Чем быстрее контроллер считает, тем больше он потребляет энергии. Поэтому нам не нужен слишком мощный процессор.

Подобрать нужную производительность ЦПУ можно опытным путём: берём микроконтроллер с запасом вычислительной мощности и памяти, пишем код, запускаем и смотрим за какое время он справляется с конкретными задачами. Выбираем из линейки контроллеров подходящий, оставляя небольшой запас мощности и памяти (для возможных обновлений и улучшений).

Должен быть достаточно быстрый АЦП

Нам нужно оцифровывать входной аналоговый сигнал и желательно, чтобы был встроенный АЦП. Точность тут не так важна, как скорость. Так как измеряемый сигнал имеет частоту до сотни килогерц. Для корректных вычислений гармоник есть условие.

Частота дискретизации должна быть минимум в два раза больше частоты измеряемого сигнала [Теорема Котельникова].

Это значит, что для распознавания сигнала нужно сделать от двух точек измерения на период. А по-хорошему 4-5. Посмотрим на примере.

Представим, что мы измеряем сигнал, в котором есть нужная нам гармоника частотой 80 кГц. У сигнала с частотой 80 кГц период 1/80000 = 12,5 микросекунд. Чтобы оцифровать 5 точек на период нужно успевать делать измерение раз в 2.5 микросекунды для адекватного распознавания сигнала.

С пятью точками измерений на период уже выглядит неплохо. ДПФ с этим отлично справится.

Но для чего брать с запасом? Что если измерять по минимуму, только две точки на период? Вот такой сигнал мы оцифруем при удачном попадании.

А так будет выглядеть оцифрованный сигнал, если попасть в момент, когда сигнал в нуле.

Не похоже на синусоиду.

Если интересно посмотреть, что будет, если проводить измерения частотой меньше двух точек за период, то поищите в гугле картинки Эффект алиасинга.

Должен быть достаточно быстрый ЦАП

Для полезного сигнала нужно сгенерировать синусоиду большой частоты. Чем больше точек на период синусоиды успеет генерировать ЦАП, тем плавнее будет сигнал на выходе (меньше лесенка, которую затем сгладит конденсатор).

Представим на примере синусоиды с частотой 80 кГц, период 12.5 микросекунд. Возьмем для начала 4 точки на период. Генерация каждые 3.125 микросекунды.

Такой сигнал сложновато будет сгладить конденсатором, чтобы сделать его похожим на синус.

Увеличим количество точек вдвое. Генерация каждые 1.56 микросекунды.

Нужна достаточная скорость ЦАП для того, чтобы сигнал был хотя бы похож на синус. В нашем случае, с сигналом частотой до 80 кГц, будет достаточно чтобы ЦАП успевал менять уровень сигнала раз в 1.5 микросекунды. Если успеет быстрее, то еще лучше.

С выхода ЦАП этот угловатый сигнал проходит через пассивный фильтр нижних частот и в сглаженном виде идет на усилитель выходной цепи.

Если нет АЦП

Помню, в самом начале я проводил эксперименты на 8-битных AVR от Atmel серии ATmega8, и у них в распоряжении не было АЦП. Но на них было очень удобно начинать знакомство с миром микроконтроллеров. Низкий порог вхождения и никаких танцев с бубнами при запуске.

Ну так вот, входной сигнал я решил оцифровывать простой ножкой в режиме входа. Если входное напряжение выше 2.5В, то у ножки было логическое состояние 1, если ниже 2.5В, то 0. В равные промежутки времени просто считывалось текущее состояние ножки и эти значения записывались в массив.

И этот оцифрованный сигнал прогонялся через ДПФ и вычислялось наличие нужных гармоник. Ни о какой точности или чувствительности речи и не шло, но это работало.

Если нет ЦАП

Аналогичная ситуация на ATmega8 была с ЦАП. Его там нет, и мне очень не хотелось заморачиваться с внешним ЦАП.

Оказалось, что можно пожертвовать логическими выходами микроконтроллера и подключить к ним резисторную матрицу R-2R. Таким образом из горстки резисторов собрать свой ЦАП с нужной разрядностью.

Картинка с сайта easyelectronics.ruКартинка с сайта easyelectronics.ru

Подавая 0 и 1 на выходы микроконтроллера, можно получать нужный уровень напряжения на выходе OUT. Чем больше выходов будет использовано, тем выше разрядность ЦАП. По схеме R-2R оставил ссылку в конце.

Выбор подходящего микроконтроллера

После экспериментов на ATmega8 мне захотелось улучшить то, что есть. Выбирая из разных вариантов, я положил глаз на STM32. А конкретно на STM32F103 это 32-битные микроконтроллеры на ядре ARM Cortex-M3 (до 72 MHz).

Эксперименты проводил на отладочной плате, которая, наверное, есть в любом магазине электроники. На отладочной плате сразу располагался программатор, с помощью которого прошивается на МК.

Немного пострадав с его запуском, сразу же побежал проверять его по своему чек листу.

Производительность?

Схема тактирования позволяет работать ЦПУ на частоте 72 MHz, что после 8-битных на 20 MHz было с запасом. Хватало для более точных расчетов по алгоритму ДПФ.

Энергоэффективность?

При почти максимальной нагрузке потреблял около 40-50 мА. Дешевый стабилизатор напряжения в схеме питания на 100 мА с этим справлялся. Даже с учетом остальной маложрущей периферии этого было достаточно.

Достаточно быстрый АЦП?

Разобрался, как разогнать до максимальной скорости АЦП при частоте ЦПУ 72 MHz. Так как ранее было сказано, что полезный сигнал будет частотой в районе 80 кГц, то будем считать исходя из этого.

В доках для STM32 нашел, как вычислять минимальное время преобразования: нужно к настраиваемому времени семплирования (минимум 1.5 цикла) прибавить 12.5 машинных циклов. Получается 14 машинных циклов на одну точку измерения.

При определенной настройке схемы тактирования на модуль АЦП приходится 14 MHz. Если перевести в секунды, то 14 циклов при частоте тактирования 14 MHz это одно измерение в 1 микросекунду.

Идеально! Даже если полезный сигнал будет частотой 100 кГц, я смогу измерить 10 точек за один период сигнала. С минимальной точностью, но быстро.

Примерно так будет выглядеть оцифровка синусоиды 80 кГц.

Достаточно быстрый ЦАП?

По той же логике нам нужно сгенерировать синусоиду частотой около 80 кГц. И если мы хотим, чтобы синусоида была похожа на синусоиду, а не на странную угловатую фигуру, нужно генерировать одну точку хотя бы раз в 1.5 микросекунды, как мы выяснили ранее.

Почитав документацию, я понял, что в ЦАП STM32F103 встроенный ОУ имеет ограничение в 1 MSPS. Получилось настроить генерацию каждой точки сигнала раз в 1 микросекунду.

Примерно так при этом будет выглядеть синусоида с частотой 80 кГц на выходе из ЦАП.

Периферия

Что еще мне понравилось в STM32F103 это наличие встроенного USB. Там есть режим эмуляции COM порта. Мне показалось это очень удобным, особенно после внешних преобразователей USB-UART.

Можно подключать устройство к ПК обычным шнурком от телефона и через терминал посылать на устройство какие-нибудь отладочные команды.

Для экспериментов подключал два PLC устройства к двум компам, и они посылали друг другу ASCII символы, вводимые с клавиатуры. Получилось что-то вроде чата через розетку 220 В.

Особенности питания устройства

Сразу отмечу, что я не спец в проектировании блоков питания, для подробностей есть специализированная литература. Но считаю важным отметить некоторые моменты, которые влияют на стабильность системы, и с которыми у меня были проблемы.

Блок питания можно либо собирать самому, либо взять готовый модуль с нужными характеристиками, это неважно. В любом случае, нужно адекватно развести линии питания по печатной плате.

Схема питания устройства зависит от потребителей. В нашем случае основные жрущие потребители это микроконтроллер и выходная цепь, так как в ней усилитель для отправки сигнала в ЛЭП.

Остальные потребители вроде усилителей входного сигнала во входной цепи, EEPROM памяти или какие-то UART конвертеры потребляют немного.

Стабильное питание микроконтроллера

Первое и самое важное на что нужно обратить внимание это стабильность питания микроконтроллера. Он не любит скачки напряжения и может в самый неподходящий момент перезагружаться или просто начать себя странно вести (пропускать блоки кода).

И тут у нас проблемка: как назло, под боком у микроконтроллера находится выходная цепь с усилителем полезного сигнала. Этот блок устройства во время генерации сигнала импульсами потребляет мощность, что может прилично потрясти всю систему питания, обнулив при этом микроконтроллер.

Примерная картина потребления мощностиПримерная картина потребления мощности

При передаче кадра это происходит каждые 10 миллисекунд длиной в 1 миллисекунду.

С этим у меня возникли трудности. Иногда устройство работало нормально, но чаще предсказуемо перезагружалось. Сначала пытался решить проблему блоком питания помощнее, но не помогало. В поисках решений много интересного узнал из форумов по робототехнике. Там похожие проблемы были в основном из-за сервоприводов, которые потребляют приличное количество энергии и, при неправильной разводке платы, могут внезапно перезагружать микроконтроллер.

Для тяжелых случаев есть пара советов, которые помогут уменьшить влияние скачков напряжения.

Совет 1 - Разделить землю на аналоговую и цифровую

Первый важный момент это обеспечение минимального влияния аналоговой части схемы на цифровую.

Для этого нужно разделить дорожки GND в самом начале схемы питания возле минуса блока питания. Ни в коем случае нельзя их пересекать или как-то замыкать в других частях схемы.

Для питания условно цифровых компонентов схемы (микроконтроллер, EEPROM память и т.д.) от самого блока питания должна идти отдельная линия, можно назвать её DGND.

Для питания аналоговой схемы генерации полезного сигнала от блока питания, соответственно, должна идти отдельная линия AGND. Подробнее можно почитать в статьях или литературе по заземлению.

Совет 2 - Не забыть про керамику

Конденсаторы нужно ставить перед каждой ножкой питания микроконтроллера и как можно ближе к ним. Обязательно выполнить минимум обвеса, который указан в Datasheet на микроконтроллер.

Картинка с сайта allexpress.comКартинка с сайта allexpress.com

Также желательно добавить в цепи питания микроконтроллера дополнительную емкость, в виде электролитического или танталового конденсатора, чтобы он мог даже выдерживать кратковременное отключение питания.

С танталовыми осторожнее, они красиво взрываются :).

Еще надо не забыть защитить ножку Reset микроконтроллера, как указано в Datasheet. В противном случае микроконтроллер может внезапно перезагружаться. Если нет светодиодной индикации запуска программы микроконтроллера, то можно этого даже не заметить.

Совет 3 - Экранировать цифровые компоненты

Может получиться так, что недалеко от микроконтроллера расположен высокочастотный трансформатор, который во время передачи сигнала генерирует электромагнитные помехи.

Мне помогло расположение микроконтроллера на другой от ВЧ трансформатора стороне печатной платы и наличие земляного полигона под корпусом микроконтроллера.

Картинка с сайта caxapa.ru "Помехоустойчивые устройства, Алексей Кузнецов"Картинка с сайта caxapa.ru "Помехоустойчивые устройства, Алексей Кузнецов"

Подробнее можно почитать в статье по ссылке в конце.

Заключение

В этой части мы в общих чертах разобрали чем занимается микроконтроллер. Узнали некоторые особенности питания устройства и возможные проблемы.

Статья вышла довольно объемной. Я постарался максимально коротко передать основные моменты. Может сложиться ощущение незаконченности и это нормально. Для углубленного изучения оставлю ссылки внизу.

В следующей части подробнее разберём оставшиеся блоки устройства: входная и выходная цепи, zc детектор и согласование устройства в сетью 220 В. После этого должна сложиться целостная картинка. В заключительной части пробежимся по программной части: обработке оцифрованного сигнала, генерация синуса и т.д.

У кого был/есть какой-либо опыт в PLC обязательно делитесь этим с остальными в комментариях :)

Полезные ссылки

https://nag.ru/articles/article/24485/strasti-po-plc.html - интересная статья по истории PLC
https://www.electronshik.ru/catalog/interfeys-modemy-plc - заводские PLC микросхемы с datasheet (там много схем и характеристик)
https://ru.wikipedia.org/wiki/Частотная_манипуляция - FSK модуляция
http://www.atmega8.ru/ - про ATmega8

STM32
https://www.st.com/en/microcontrollers-microprocessors/stm32f103.html - STM32F103
https://themagicsmoke.ru/courses/stm32/led.html - Помигать светодиодом на stm32
https://blog.avislab.com/stm32-clock_ru - схема тактирования stm32
http://personeltest.ru/aways/habr.com/ru/post/312810/ - подробнее про ЦАП в stm32
https://blog.avislab.com/stm32-adc_ru/ - АЦП в stm32
https://blog.avislab.com/stm32-usb_ru/ - USB в stm32

Аналоговая часть
http://easyelectronics.ru/parallelnyj-cifro-analogovyj-preobrazovatel-po-sxeme-r-2r.html - преобразователь по схеме R-2R
http://caxapa.ru/lib/emc_immunity.html - "Помехоустойчивые устройства", Алексей Кузнецов
https://www.ruselectronic.com/passive-filters - пассивные фильтры

Подробнее..

Power-line communication. Часть 3 Основные блоки устройства

25.05.2021 00:13:35 | Автор: admin

Во второй части статьи мы начали знакомиться с основными блоками устройства для передачи данных по PLC. Это будет заключительная часть статьи, которая касается описания железа.

Осталось разобраться, что такое ZC детектор, на примере одной из его возможных реализаций. Посмотрим, как можно реализовать входную и выходную сигнальные цепи, и как их подключить к сети 220 В.

В статье не рассматриваются какие-либо серьёзные темы в области PLC. Как и в первых двух частях, кратко описываются блоки устройства и их взаимодействие. Темы выстроены так, чтобы у новичка примерно выстроилась общая картина простейшего PLC устройства. Также повествование касается множества сложных тем, которые не раскрываются. Поэтому в конце постарался оставить побольше ссылок.

Zero cross детектор

Как говорилось ранее, передающие и принимающие устройства синхронизируются между собой с помощью отдельного блока zero cross детектора.

Передающее устройство, отправляет подготовленный кадр данных по одному биту за один синхросигнал из ZC детектора. Физически это значит, что за один синхросигнал из ZC детектора генерируется один полезный сигнал определённой частоты, которым кодируется один бит.

В электросетях с частотой 50 Гц, синусоида напряжения пересекает ноль 100 раз в секунду.

Есть несколько вариантов исполнения ZC детектора. Ниже я покажу пример реализации на оптопаре.

Начнём с конца схемы сначала представим, как сигнал с ZC детектора попадает на контроллер.

На картинке схема с подтягивающим pull-up резистором и ключом. При замыкании ключа, на вход МК будет подаваться логический 0, а при размыкании ключа, pull-up резистор будет подтягивать напряжение на входе МК до логической единицы.

На место ключа ставим оптрон. Оптрон (оптопара) это простой элемент, в котором с одной стороны светодиод, а с другой фототранзистор.

При подаче напряжения на светодиод, фототранзистор будет пропускать ток. Оптрон также служит гальванической развязкой между сетью 220 В и цифровой частью схемы.

Остается только подавать на светодиод переменное напряжение из сети 220 В, но перед этим его необходимо выпрямить и уменьшить до приемлемого уровня, который выдержит светодиод оптопары.

Для выпрямления можно использовать smd мостовой выпрямитель.

После выпрямления на фотодиод пойдёт пульсирующее с удвоенной частотой напряжение от 0 до 310 В. Разумеется диод не выдержит такого размаха напряжения, поэтому после мостового выпрямителя поставим сопротивление.

Номинал сопротивления можно вычислить исходя из характеристик фотодиода в оптопаре

В datasheet на оптопару пишут максимальный ток, на который рассчитан фотодиод, исходя из этого нужно выбрать сопротивление с расчётом на 310 В. Чтобы резистор не перегрелся, можно вместо одного последовательно поставить несколько резисторов для эффективного отвода тепла (это особенно полезно если у вас SMD резисторы).

Из datasheet на PLC817Из datasheet на PLC817

На примере PC817 видно, что максимальный ток, который выдержит светодиод - 50 мА. Максимальный коэффициент передачи при 20 мА. И "замыкать ключ" он будет уже и при >1 мА.

SMD резисторы типоразмера 1210 выдерживают рассеивание до 0.5 Вт мощности. Максимальный постоянный ток, который мы может пропускать при 310 вольт равен 0.5/310 = 0.00161 А. С учетом, того что у нас пульсирующее напряжение, округлим до 0.002 А (2 мА). Этого тока достаточно, чтобы "ключ замыкался". Номинал сопротивления при этом равен 310/0.002 = 155000 Ом. Итог: ставим последовательно три SMD резистора, типоразмером 1210, номиналом 51 кОм каждый.

В итоге, схема ZC детектора выглядит примерно так.

Теперь микроконтроллеры PLC устройств, подключенных к одной фазе могут синхронизироваться между собой с помощью сигнала на ножке "ZC input" из такого ZC детектора.

Схема согласования сигнальных цепей с линией 220 В

Схема согласования закрывает собой компоненты входной и выходной цепей. Входная и выходная сигнальные цепи обычно выполнены на микросхемах усилителях, которые питаются небольшим постоянным напряжением (3-12 В). Подключить их напрямую к 220 В не получится.

Из электросети должны проходить только высокочастотные сигналы. Основная гармоника 50 Гц, на которой передаётся электроэнергия, не должна попасть в сигнальные цепи устройства. Также в этой схеме обычно располагается защита от скачков напряжения и перегрузок.

Эта часть схемы принимает различный вид в разных datasheet на готовые PLC микросхемы. Опишем минимально работоспособный вариант.

Для первых опытов

Можно взять ферритовое кольцо типа 17,5x8,2x5 М2000Н, есть в любом магазине электроники. Провод МГТФ наматываем сразу 3 обмотки в 20 витков.

Конденсатор плёночный из серии MKP или любой аналогичный, который выдерживает от 220 В переменки (с запасом).

Для отсечения ненужных низкочастотных гармоник ставится конденсатор, который выдержит 220 В. После него, для гальванической развязки и также фильтрации, высокочастотный трансформатор. Трансформатор можно сделать с отдельными обмотками для входной и выходной цепей (как на изображениях) или использовать одну обмотку на "вход"/"выход".

Для защиты усилителей от импульсных перенапряжений можно поставить защитные диоды (супрессоры) и/или варисторы с предохранителем. Тема защиты устройства от электрических неприятностей довольно обширная, в этой статье не рассматривается. Но забывать про это не стоит.

Варианты схемы согласования можно подглядеть в готовых решениях различных фирм, выпускающих PLC микросхемы. Каждая схема согласования разрабатывается под входные/выходные усилители, используемые в этих решениях.

Входная цепь измерение полезного сигнала

Входная цепь должна выполнить как минимум две задачи:

  • отфильтровать грубый входящий сигнал, срезав все лишнее;

  • после этого усилить сигнал до приемлемого уровня, подходящего для измерения и оцифровки с помощью ЦАП микроконтроллера.

Фильтрация

Существует большое разнообразие вариантов исполнений фильтров. В нашем случае подойдёт простой пассивный полосовой фильтр. При узкополосной передаче можно грубо отсечь ненужные частоты сверху и снизу. Фильтр нужно рассчитываем так, чтобы наши рабочие частоты попадали по центру полосы пропускания и меньше всего срезались.

В самом простом случае можно особо не заморачиваться с фильтром, так как в линиях электропередач запросто могут быть шумы с частотами близкими к полезным. Нам просто нужно примерно совместить полосу пропускания фильтра с полезной полосой частот, срезав все сверху и снизу. Остальное можно решить программным путём.

Важно помнить, что элементы пассивного фильтра изготавливаются с большими погрешностями и характеристики сильно завязаны на температуру. Поэтому при расчетах нужно оставлять небольшой запас с учётом этих погрешностей и влияния температуры.

Усиление

У АЦП есть такая характеристика как разрешение. Оцифровка сигнала происходит с некоторой дискретностью. А после пассивной фильтрации входной сигнал заметно похудеет в амплитуде. И если подать на АЦП очень слабый сигнал, то его форма сильно исказится и потеряется большая часть информации о сигнале.

Амплитуду сигнала нужно поднять до приемлемой для измерений и оцифровки. В этом помогут операционные усилители (ОУ), которых на рынке огромное количество, и про которые написано тонны статей.

Самое сложное это выбрать подходящий ОУ по полосе пропускания и коэффициенту усиления. Выходная мощность ОУ в этом случае не важна, так как нам нужно лишь оцифровать форму сигнала.

Бывает, что одного ОУ не хватает для усиления сигнала до приемлемого уровня. В этом случае можно сразу после первого ОУ поставить второй по аналогичной схеме. В продаже есть микросхемы сразу с двумя ОУ в одном корпусе.

Ссылки на статьи про операционные усилители и их про каскадное подключение оставил в конце статьи.

Выходная цепь генерация полезного сигнала

Задача выходной цепи фильтровать и усиливать сигнал из ЦАП микроконтроллера.

Микроконтроллер по специальному алгоритму генерирует полезный сигнал, нужной длительности и частоты, соответствующей передаваемому символу. На выходе из ЦАП у нас получается просто болванка полезного сигнала, угловатая, примерно похожая на синусоиду, но (самое главное!) нужной нам частоты.

Далее сигнал сглаживается фильтром и отправляется в аналоговую часть схемы (усилитель и схема согласования с 220 В).

Можно подумать, что форма сигнала не особо важна при кодировании, так как преобразование Фурье всё равно может вычленить основную гармонику полезного сигнала, отбросив всё лишнее. Но чем сигнал ближе по форме к синусоиде, тем меньше энергии мы будем тратить в пустоту, просто добавляя высокочастотный шум в сеть. И выходной усилитель будет работать стабильнее. Как уже говорилось на входе важна лишь основная гармоника сигнала. Остальные гармоники это шум.

Так как мощности сигнала на выходе ЦАП микроконтроллера недостаточно для отправки его напрямую в линию электропередач, после ЦАП нам обязательно нужен внешний усилитель.

При выборе усилителя разбегаются глаза. Не буду рассказывать про всё многообразие, но подскажу вариант для ленивых, как я. Можно использовать одну из готовых микросхем для усиления аудио сигналов в аудиоплеерах. Мощность у них обычно не большая около 1W.

Гуглить их можно по фразе audio amplifier btl 1w. Но тут нужно учесть, что они обычно рассчитаны на аудио сигналы до 20 кГц, и производитель не рассчитывал, что их будут использовать в PLC модеме. Есть модели, которые хорошо усиливают частоты до 100-150 кГц, и обычно в datasheet об этом не пишут.

Плюсы:

  • они очень удобны тем что там встроенная стабилизация сигнала;

  • есть режим mute - мизерное потребление в режиме простоя;

  • хватает однополярного питания не надо париться с блоком питания.

Минусы:

  • во включенном состоянии из-за обратной связи съедают входящий сигнал, поэтому усилитель надо выключать, когда устройство в режиме прослушивания (приёма);

  • большой минус это их незащищённость от импульсных помех в электросети. Сгорают мгновенно. Но от этого можно спастись, поставив на выходе усилителя супрессоры, что-то наподобие P4SMAJ5.0A или аналогичный.

Примерно так выглядит усиление с однополярным питанием.

Также нужно не забыть на выходе усилителя ставить конденсатор, чтобы отсечь постоянную составляющую сигнала.

Итого

Во второй и третей частях мы коротко пробежались по основным блокам простейшего PLC устройства, создали общую картину их взаимодействия. Так как затрагиваемых тем очень много и они дольно глубокие, подробнее осветить их в статье не получилось (да и я в них не специалист). Для более серьезного изучения есть специализированная литература. Но новичку иногда сложно понять в какую сторону копать. Поэтому конце оставил много ссылок на различные обзорные статьи по связанным темам.

В следующей части статьи планировал на примерах показать, как можно программно генерировать синус нужной частоты для ЦАП в STM32. И заодно как обработать приходящий на АЦП сигнал и выяснить наличие в нём нужных гармоник (частот) полезного сигнала.


Полезные ссылки

Общее:

Фильтры:

Операционные усилители:

ZC детекторы:

Схемы согласования с 220 В в доках на PLC микросхемы:

Подробнее..

Перевод Как передавать файлы с компьютера на смартфон и обратно при помощи Qrcp и QR-кода

09.05.2021 16:23:04 | Автор: admin

Для того, чтобы передать файлы с ноутбука или ПК на мобильное устройство или в обратном направлении, можно воспользоваться большим количеством разных способов и инструментов. Наиболее простой и распространенный USB кабель. Но что если нужного провода нет, а передать файл жизненно важно? В этом случае можно использовать передачу при помощи QR-кода без всяких проводов. Для этого потребуется Qrcp.

Версии Qrcp есть для Linux, Windows и macOS. Работает все это благодаря привязке веб-сервера к IP-адресу машины со случайным номером порта. Затем система генерирует уникальный QR-код, который предоставляет устройству-получателю всю необходимую для передачи файлов информацию. Веб-сервер прекращает работу сразу после завершения передачи данных.

Как установить Qrcp


Как и говорилось выше, версии Qrcp доступны для Windows, Mac и Linux систем, включая Raspberry Pi. В этой статье рассказывается о связке Linux и Qrcp. Система создает пакеты deb и rpm для 32- и 64-битных машин, включая поддержку архитектуры ARM, если вам потребуется установить Qrcp на Raspberry Pi. Установить все это несложно и с использованием исходного tarball.

Загружаем последнюю версию системы для вашей машины. На момент написания это версия 0.8.4. Извлекаем загруженный файл в новую папку, которая называется qrcp, в папке Downloads.


Открываем командную строку и идем в новосозданную директорию.

$ cd ~/Downloads/qrcp

Перемещаем извлеченные файлы в /usr/local/bin, что дает возможность запускать команду из любого места. Если у вас Windows, то загружаем все в папку Windows, что предоставляет ту же возможность.

$ sudo mv qrcp /usr/local/bin/

Передача файлов на мобильные устройства


Возможностей конфигурации по умолчанию должно хватить для большинства пользователей. Как только вы укажете файл, который хотите передать, qrcp создаст уникальный URL-адрес, с которого этот файл можно загрузить. Кроме того, в процессе передачи генерируется QR-код, позволяющий передать данные об адресе устройству-получателю.

В примере ниже в качестве сканера QR-кода используется Google Lens, но, конечно, можно использовать и любой другой сканер, включая встроенные.

В командной строке указываем директорию, которая содержит передаваемый файл. В примере это PDF на рабочем столе, который планируется передать на смартфон.

$ cd ~/Desktop

Применяем qrcp для передачи файла.

$ qrcp Technical-Specs.pdf


На мобильном устройстве открываем сканер QR-кода и, соответственно, сканируем код.


Нажимаем на появившийся адрес, и файл моментально начинает передаваться.

Передача нескольких файлов


Аналогичным образом Qrcp можно использовать для передачи любого количества файлов. Они будут передаваться одним .zip архивом. Правда, прописывать файлы в командной строке придется вручную.

$ qrcp filename1 filename2 filename3


Передача файлов с мобильного устройства на компьютер

Аналогичным образом файлы можно передавать и с компьютера или ноутбука на смартфон.

Открываем командную строку на ПК и вводим команду

qrcp receive

Она позволяет получить файл.

Используя мобильное устройство, сканируем QR-код и нажимаем на полученный адрес.


Открывшаяся веб-страничка предложит указать файлы, которые нужно передать.

Выбираем файлы, нажав на соответствующую кнопку.


По умолчанию система загрузит файлы в текущую директорию. Но, если такой вариант не подходит, указываем другую папку.

qrcp receive --output=/path/to/directory

Настройка qrcp



Хотя дефолтной конфигурации qrcp должно хватить для большинства пользователей, можно выполнить и тонкую настройку: запустить команду qrcp config, чтобы установить кастомные значения. Система задаст ряд вопросов: уточнит используемый по умолчанию сетевой интерфейс, порт по умолчанию, каталог по умолчанию для полученных файлов, спросит, использовать ли HTTPS для передачи, и т.д. Процесс простой и понятный. По завершении настройки конфигурация записывается в файл config.json в каталоге ~ / .config / qrcp (Linux).

Подробнее..

Zynq. Передача данных между процессорным модулем и программируемой логикой

27.12.2020 18:22:59 | Автор: admin
Как и обещал в предыдущей статье (Что такое Zynq? Краткий обзор), поговорим о передаче данных между процессорным модулем и программируемой логикой. В предыдущей статье упоминалось четыре способа передачи данных, в статье будут рассмотрены два способа, которые нашли большее применение. Подробности под катом. Осторожно, много картинок!

Содержание


1 Общие сведения
2 Передача данных в режиме PIO
2.1 Аппаратная часть
2.2 Программная часть
2.3 Результаты
3 Передача данных в режиме DMA
3.1 Аппаратная часть
3.2 Программная часть
3.3 Результаты
4 Заключение
5 Используемые источники

1 Общие сведения


В общем случае, передача данных между процессорным модулем и программируемой логикой возможна в двух режимах:

  • PIO, используется порт GP.
  • DMA, используется порт HP.

2 Передача данных в режиме PIO


В режиме PIO процессорный модуль работает с программируемой логикой как с набором регистров. Чтобы записать или прочитать определенный объем данных, нужно постоянное участие процессорного модуля. В режиме PIO инициатором всех транзакций является процессорный модуль. Подключение программируемой логики предполагает использование порта GP, где Master это процессорный модуль, Slave программируемая логика.


Структура проекта при использовании PIO

2.1 Аппаратная часть


  1. Создаем проект для Zybo в Vivado, тип микросхемы xc7z010clg400-1.
  2. Создаем block design. Во Flow Navigator => Create Block Design => имя ProcessingSystem => OK.
  3. Используя кнопку + на поле или сочетания клавиш Ctrl + I добавим процессорное ядро.

  4. Подключим необходимые выводы, нажав кнопку Run Block Automation => OK.
  5. Импортируем настройки процессорного модуля. Для этого выполним двойной клик на Zynq7 Processing System => Import XPS Setting => Укажем путь к файлу => OK => OK.
  6. Создаем периферийное ядро, которое будет реализовывать доступ к регистрам в программируемой логике. Tools => Create and Package New IP => Next => Create a new AXI4 peripheral => Next => Задаем имя ядра, например PIO_registers и указываем путь к каталогу для сохранения => Next => В этом окне можно выбрать количество регистров (4 хватит), тип интерфейса, в данном случае это Lite => Next => Add IP to the repository => Finish.

  7. После этих действий, созданное ядро появится в списке доступных для работы в IP каталоге. Можно его увидеть, если выбрать в Flow Navigator => IP Catalog.

  8. Добавим созданное ядро на рабочую область. Ctrl + I => PIO_registers.

  9. Отредактируем созданное ядро, добавив в него работу с перемычками и светодиодами. Для этого на блоке PIO_registers правой кнопкой мыши => Edit in IP Packager => OK. Откроется новое окно Vivado с созданным ядром.
  10. В файле PIO_registers_v1_0.vhd добавим входные и выходные порты и подключим их к внутреннему модулю:

    iSwitches: instd_logic_vector( 3 downto 0);oLeds: outstd_logic_vector( 3 downto 0);...iSwitches=> iSwitches,oLeds=> oLeds,
    

  11. В файле PIO_registers_v1_0_S_AXI.vhd добавим входные и выходные порты:

    iSwitches: instd_logic_vector( 3 downto 0);oLeds: outstd_logic_vector( 3 downto 0);
    

  12. Опишем обработку входов и выходов:

    signalSwitchesReg: std_logic_vector(31 downto 0);...process (SwitchesReg, slv_reg1, slv_reg2, slv_reg3, axi_araddr, S_AXI_ARESETN, slv_reg_rden)variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);begin    -- Address decoding for reading registers    loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);    case loc_addr is      when b"00" =>        reg_data_out <= SwitchesReg;      when b"01" =>        reg_data_out <= slv_reg1;      when b"10" =>        reg_data_out <= slv_reg2;      when b"11" =>        reg_data_out <= slv_reg3;      when others =>        reg_data_out  <= (others => '0');    end case;end process;process (S_AXI_ACLK) beginif (rising_edge(S_AXI_ACLK)) thenif (S_AXI_ARESETN = '0') thenSwitchesReg <= (others => '0');elseSwitchesReg( 3 downto 0) <= iSwitches;end if;end if;end process;process (S_AXI_ACLK) beginif (rising_edge(S_AXI_ACLK)) thenif (S_AXI_ARESETN = '0') thenoLeds <= (others => '0');elseoLeds <= slv_reg1( 3 downto 0);end if;end if;end process;
    

  13. Сохраняем vhd файлы, открываем вкладку Package IP PIO_registers. Обновим ядро с учетом изменённых файлов. Вкладка Compatibility меняем Life Cycle на Production. Вкладка File Groups => Merge changes from File Group Wizard. Вкладка Customization Parameters => Merge changes from Customization Parameters Wizard. Вкладка Review and Package => Re-Package IP => Yes. Vivado с созданным ядром закроется.
  14. В окне Block Design выбираем Report IP Status, в появившимся внизу окне выбираем Upgrade Selected => OK => Skip => OK.

  15. Подключим созданное ядро к процессору. Для этого нажимаем Run Connection Automation => OK.

  16. Подключим порты созданного ядра к портам block designa. Для этого выделяем порт, нажимаем правую кнопку => Make External.

  17. Переименуем полученные порты для удобства подключения iSwitches_0 => iSwitches. oLeds_0 => oLeds.

  18. Проверим полученный дизайн => Tools => Validate Design => Ok.
  19. File => Save Block Design.
  20. Переключаемся из режима работы с block design в режим работы с проектом, нажав во Flow Navigator => Project Manager.
  21. Смотрим, как описаны порты у полученного block designa. Для этого выбраем файл ProcessingSystem.bd, правой кнопкой => View Instantiation Template.

  22. Создаем vhd файл top-уровня и подключаем в нем полученный block design. File => Add Sources => Add or create design sources => Next => Create File => вводим имя файла и указываем путь до каталога => OK => Finish => OK => Yes.
  23. Заполняем файл:

    entity PioTransfer isport(DDR_addr: inout std_logic_vector(14 downto 0 );DDR_ba: inout std_logic_vector( 2 downto 0 );DDR_cas_n: inout std_logic;DDR_ck_n: inout std_logic;DDR_ck_p: inout std_logic;DDR_cke: inout std_logic;DDR_cs_n: inout std_logic;DDR_dm: inout std_logic_vector( 3 downto 0 );DDR_dq: inout std_logic_vector(31 downto 0 );DDR_dqs_n: inout std_logic_vector( 3 downto 0 );DDR_dqs_p: inout std_logic_vector( 3 downto 0 );DDR_odt: inout std_logic;DDR_ras_n: inout std_logic;DDR_reset_n: inout std_logic;DDR_we_n: inout std_logic;FIXED_IO_ddr_vrn: inout std_logic;FIXED_IO_ddr_vrp: inout std_logic;FIXED_IO_mio: inout std_logic_vector( 53 downto 0 );FIXED_IO_ps_clk: inout std_logic;FIXED_IO_ps_porb: inout std_logic;FIXED_IO_ps_srstb: inout std_logic;-- ControliSwitches: instd_logic_vector( 3 downto 0 );oLeds: outstd_logic_vector( 3 downto 0 ) );end PioTransfer;architecture Behavioral of PioTransfer isbeginPS : entity WORK.ProcessingSystemport map(DDR_addr=> DDR_addr,DDR_ba=> DDR_ba,DDR_cas_n=> DDR_cas_n,DDR_ck_n=> DDR_ck_n,DDR_ck_p=> DDR_ck_p,DDR_cke=> DDR_cke,DDR_cs_n=> DDR_cs_n,DDR_dm=> DDR_dm,DDR_dq=> DDR_dq,DDR_dqs_n=> DDR_dqs_n,DDR_dqs_p=> DDR_dqs_p,DDR_odt=> DDR_odt,DDR_ras_n=> DDR_ras_n,DDR_reset_n=> DDR_reset_n,DDR_we_n=> DDR_we_n,FIXED_IO_ddr_vrn=> FIXED_IO_ddr_vrn,FIXED_IO_ddr_vrp=> FIXED_IO_ddr_vrp,FIXED_IO_mio=> FIXED_IO_mio,FIXED_IO_ps_clk=> FIXED_IO_ps_clk,FIXED_IO_ps_porb=> FIXED_IO_ps_porb,FIXED_IO_ps_srstb=> FIXED_IO_ps_srstb,-- ControliSwitches=> iSwitches,oLeds=> oLeds );end Behavioral;
    

  24. Добавляем используемые входы и выходы в файл пользовательских ограничений. File => Add sources => Add or create constrains => Next => Create File => вводим имя файла и указываем путь до каталога => OK => Finish.

  25. Заполняем файл согласно принципиальной схеме:

    #Switchesset_property PACKAGE_PIN G15 [get_ports {iSwitches[0]}]set_property PACKAGE_PIN P15 [get_ports {iSwitches[1]}]set_property PACKAGE_PIN W13 [get_ports {iSwitches[2]}]set_property PACKAGE_PIN T16 [get_ports {iSwitches[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {iSwitches[*]}]#LEDs#IO_L23P_T3_35set_property PACKAGE_PIN M14 [get_ports {oLeds[0]}]set_property PACKAGE_PIN M15 [get_ports {oLeds[1]}]set_property PACKAGE_PIN G14 [get_ports {oLeds[2]}]set_property PACKAGE_PIN D18 [get_ports {oLeds[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {oLeds[*]}] 
    

  26. Соберем проект. Для этого во Flow Navigator => Generate Bitstream => OK. Появившиеся окно, что создание прошивки успешно завершено, закрываем.
  27. Экспортируем полученные файлы для разработки приложения на процессорном модуле. Для этого выбираем File => Export => Export Hardware => вводим имя файла и указываем путь до каталога => OK. Получаем на выходе файл .xsa


2.2 Программная часть


Теперь нужно написать приложение, работающее на процессорном модуле, которое будет читать данные из программируемой логики и писать данные в программируемую логику. Необходимо запустить среду разработки Vitis и создать приложение по шаблону Hello World, пример этого показан в предыдущей статье[1].

Адрес созданного ядра для обращения со стороны процессорного модуля можно посмотреть в Vivado. В Flow Navigator => Open Block Design => Вкладка Address Editor. В данном случае адрес равен 0x43C0_0000. По этому адресу расположен регистр, в котором хранится признак, в каком состоянии находятся переключатели. Соответственно, по адресу 0x43C0_0004 расположен регистр, который подключен к светодиодам.

В Vitis откроем файл helloworld.c и заполним:

int main(){init_platform();u32 Status = 0x00;u32 Command = 0x00;xil_printf("Hello World\n\r");while (1){Status = Xil_In32(0x43C00000);xil_printf("Status %x\n\r", Status);if (Status == 0x01 || Status == 0x02 || Status == 0x04 || Status == 0x08){Command = 0x01;}else if (Status == 0x03 || Status == 0x5 || Status == 0x06 || Status == 0x9 || Status == 0xA || Status == 0x0C){Command = 0x03;}else if (Status == 0x7 || Status ==  0x0B || Status == 0x0D || Status == 0x0E){Command = 0x7;}else if (Status == 0x0F){Command = 0x0F;}else{Command = 0x00;}xil_printf("Command %x\n\r", Command);Xil_Out32(0x43C00004, Command);usleep(1000000);}cleanup_platform();return 0;} 

Где функция Xil_In32 используется для чтения 4х байт данных из программируемой логики, а Xil_Out32 соответственно для записи 4х байт данных в программируемую логику.

2.3 Результаты


Собираем приложение, создаем файл прошивки и заливаем в плату. Описано в предыдущей статье[1].

Запускаем, смотрим в мониторе com-порта:

Xilinx First Stage Boot Loader Release 2019.2Dec  9 2020-15:16:52Silicon Version 3.1Boot mode is QSPISUCCESSFUL_HANDOFFFSBL Status = 0x1Hello WorldStatus 0Command 0Status 8Command 1Status CCommand 3Status DCommand 7Status FCommand F

Все работает корректно.

Таким образом, для доступа в режиме PIO к программируемой логике, необходимо в программируемой логике реализовать один из интерфейсов связи с процессорным модулем, где инициатором является процессорный модуль. Такой интерфейс представлен только портом GP.

Посмотрим, как быстро обрабатываются запросы к программируемой логике через порт GP. Для этого в приложении, работающем на процессорном модуле, добавим подряд несколько записей в регистр в программируемой логике, и измерим время между транзакциями в программируемой логике с помощью вытащенных в отладчик сигналов шины.

Когда шина Axi-Lite работает на частоте 100 МГц, пауза между запросами составляет в среднем 23 такта. Изменим частоту работы шины до 200 МГц. Пауза между запросами становится равной в среднем 33 такта.

Итого, 4 байта данных передаются на частоте 100 МГц 23 такта. Скорость составляет: 32/(23*10нс)= 139 130 434 байт/с 135 869 Кбайт/с 132 Мбайт/с.
Итого, 4 байта данных передаются на частоте 200 МГц 33 такта. Скорость составляет 32/(33*5нс)= 193 939 393 байт/с 189 393 Кбайт/с 184 Мбайт/с.
Таким образом, можно достичь скорости в 184 Мбайт/с, но при постоянном участии процессорного модуля.

Проект: github.com/Finnetrib/PioTransfer

3 Передача данных в режиме DMA


Передача данных в режиме DMA подразумевает, что процессорный модуль настраивает параметры обмена данными и не участвует непосредственно в обмене. Таким образом, достигается две цели: снижение нагрузки на процессорный модуль и увеличение скорости обработки данных. Платой за это является усложнение аппаратуры.

В Zynq возможно использование нескольких ip-ядер, реализующих функции DMA. В данной статье будет рассмотрено ядро AXI DMA [2].

В AXI DMA есть два канала MM2S и S2MM. Канал MM2S (Memory-mapped to stream) используется для передачи данных из процессорного модуля в программируемую логику. Канал S2MM (Stream to memory-mapped) используется для передачи данных из программируемой логики в процессорный модуль. Каналы работают независимо друг от друга.

AXI DMA подразумевает два варианта использования:

  • Direct Register Mode
  • Scatter / Gather Mode

В Direct Register Mode используется один набор регистров, который позволяет передать один буфер из программируемой логики в процессорный модуль и наоборот. Например, для передачи буфера данных из программируемой логики в процессорный модуль, необходимо заполнить поля адреса и размера буфера и запустить DMA. В результате DMA заполнит один буфер в процессорном модуле и остановится.

В Scatter / Gather Mode используется список дескрипторов. DMA обрабатывает буфер, описанный в дескрипторе, и переходит к обработке буфера, описанного в следующем дескрипторе.

3.1 Аппаратная часть



Структура проекта при использовании DMA

Рассмотрим вариант, когда список дескрипторов хранится в программируемой логике. У блока DMA есть порт управления, который подключается к порту GP процессорного модуля. Также имеется порт HP, используемый для обращения к ОЗУ процессорного модуля. Список дескрипторов хранится в памяти дескрипторов. Доступ к памяти дескрипторов возможен как из DMA, так и из процессорного модуля. Процессорный модуль заполняет дескрипторы, DMA вычитывает дескрипторы.

  1. Создаем block design. Во Flow Navigator => Create Block Design => имя ProcessingSystem => OK.
  2. Используя кнопку + на поле или сочетания клавиш Ctrl + I добавим процессорное ядро.
  3. Подключим необходимые выводы, нажав кнопку Run Block Automation => OK.
  4. Импортируем настройки процессорного модуля. Для этого выполним двойной клик на Zynq7 Processing System => Import XPS Setting => Укажем путь к файлу => OK => OK
  5. Добавим на поле одно ядро AXI Direct Memory Access, два ядра AXI BRAM Controller, одно ядро Block Memory Generator.

  6. Двойной клик на ядре AXI Direct Memory Access, настроим ядро. Галка Enable Scatter Gather Engine включит режим работы по списком дескрипторов, оставляем. Галка Enable Control / Status Stream используется для работы совместно с ядром AXI Ethernet, снимаем. Поле With of Buffer Length Register задает количество разрядов, используемых при обработке размера буфера. Запишем в поле число 20, что даст максимальный размер буфера в 2^20 = 1 048 576 байт. Поле Address With задает разрядность адреса. Значения в 32 будет достаточно. Галки Enable Read Channel и Enable Write Channel позволяют включить каждый из каналов независимо друг от друга. Переключатель Enable Single AXI4 Data interface позволяет сократить количество линий связи на диаграмме, поэтому включим его. Нажимаем OK после настройки.

  7. Двойной клик на ядре AXI BRAM Controller. В поле Number of BRAM Interfaces выбираем значение 1. Нажимаем OK после настройки.

  8. Повторяем для второго ядра AXI BRAM Controller.
  9. Двойной клик на ядре Block Memory Generator. В поле Memory Type выбираем True Dual Port RAM. Нажимаем OK после настройки.

  10. Подключим полученный блок памяти к контроллерам памяти. Для этого нажимаем Run Connection Automation => Галку на axi_bram_ctrl_0 BRAM_PORTA => Галку на axi_bram_ctrl_1 BRAM_PORTA => OK.

  11. Подключим нулевой контроллер памяти к процессорному модулю. Для этого нажимаем Run Connection Automation => Галку на axi_bram_ctrl_0 S_AXI => Выбрать Master Interface /processing_system7_0/M_AXI_GP0 => OK. Таким образом, процессорный модуль получит доступ к памяти дескрипторов.

  12. Подключим первый контроллер памяти к ядру DMA. Для этого нажимаем Run Connection Automation => Галку на axi_bram_ctrl_1 S_AXI => Выбрать Master Interface /axi_dma_0/M_AXI_SG => OK. Таким образом, DMA контроллер также получит доступ к памяти дескрипторов.

  13. Подключим управление DMA к процессорному модулю. Для этого нажимаем Run Connection Automation => Галку на axi_dma_0 S_AXI_LITE => OK.

  14. Включим в процессорном модуле порт для доступа к оперативной памяти процессорного модуля HP и прерывания из программируемой логики. Для этого двойной клик на ядре Zynq7 Processing System => Вкладка PS-PL Configuration => Развернем HP Slave AXI Interface => Галку на S AXI HP0 Interface.


    Вкладка Interrupts => Развернем Fabric Interrupts => Развернуть PL-PS Interrupts Ports => Галку на Fabric Interrupts => Галку на IRQ_F2P => OK.

  15. Подключим DMA к порту для доступа к оперативной памяти. Для этого нажимаем Run Connection Automation => Галку на processing_system7_0 S_AXI_HP0 => Выбираем Master Interface /axi_dma_0/M_AXI => OK.

  16. Подключим прерывания от DMA к процессорному модулю. Для этого добавим на поле блок Concat через кнопку + или сочетание клавиш Ctrl + I.
  17. Наведем курсор на вывод mm2s_introut DMA, курсор примет форму карандаша. Кликаем на вывод mm2s_introut и не отпуская кнопку мыши тянем линию к входу In0 блока Concat. Доводим до блока, после появления зеленой галочки, отпускаем.

  18. Повторяем также для вывода s2mm_introut, который подключим к входу In1 блока Concat.
  19. Выход dout блока Concat таким же образом подключим к входу IRQ_F2P ядра Zynq7 Processing System.
  20. DMA подключено. Теперь необходимо подключить вход и выход DMA для данных. Так как обработка данных планируется за пределами Block Design, вытащим наружу тактовый сигнал и сигнал сброса. Для этого правый клик на свободном месте поля и выбираем Create Port или сочетание клавиш Ctrl + K. Заполняем имя порта, направление и тип => OK.

  21. Наведем курсор мыши на созданный порт и после появления карандаша подключим порт к выводу FCLK_CLK0 ядра Zynq7 Processing System.
  22. Подключим сигнал сброса. Для этого выделяем вывод peripheral_reset ядра Processor System Reset => правой кнопкой мыши => Make External.
  23. Клик на полученный порт, зададим новое имя порта и укажем, на каком тактовом сигнале необходимо обрабатывать данный сигнал.

  24. Подключим вход данных DMA. Для этого выделим порт S_AXIS_S2MM блока AXI Direct Memory Access => правой кнопкой мыши => Make External.
  25. Клик на полученный порт, зададим новое имя порта и укажем, на каком тактовом сигнале необходимо обрабатывать данный сигнал.

  26. Подключим выход данных DMA. Для этого выделим порт M_AXIS_MM2S блока AXI Direct Memory Access => правой кнопкой мыши => Make External.
  27. Клик на полученный порт, зададим новое имя порта и укажем, на каком тактовом сигнале необходимо обрабатывать данный сигнал.

  28. Подключим входы тактового сигнала для портов S_AXIS_S2MM и M_AXIS_MM2S у блока AXI Direct Memory Access. Для этого нажимаем Run Connection Automation => Галку на m_axi_mm2s_aclk и m_axi_s2mm_aclk => OK
  29. Теперь необходимо изменить адресное пространство так, чтобы при обращении к блоку памяти от процессорного модуля и от блока DMA адреса были одинаковы. Заодно и увеличим размер памяти для хранения дескрипторов. Вкладка Address Editor => processing_system7_0 / Data / axi_bram_ctrl_0 => Offset Address 0x4000_0000 => Range 32K. Далее axi_dma_0 / Data_SG / axi_bram_ctrl_1 => Offset Address 0x4000_0000 => Range 32K.

  30. Tools => Validate Design => OK. Полученная схема:

  31. File => Save Block Design.
  32. Переключаемся из режима работы с block design в режим работы с проектом, нажав во Flow Navigator => Project Manager.
  33. Смотрим, как описаны порты у полученного block designa. Для этого выбираем файл ProcessingSystem.bd, правой кнопкой => View Instantiation Template.
  34. Создаем vhd файл top-уровня и подключаем в нем полученный block design. File => Add Sources => Add or create design sources => Next => Create File => вводим имя файла и указываем путь до каталога => OK => Finish => OK => Yes.


  35. Заполняем файл:
    entity DmaTransfer isport(DDR_addr: inout std_logic_vector(14 downto 0);DDR_ba: inout std_logic_vector( 2 downto 0);DDR_cas_n: inout std_logic;DDR_ck_n: inout std_logic;DDR_ck_p: inout std_logic;DDR_cke: inout std_logic;DDR_cs_n: inout std_logic;DDR_dm: inout std_logic_vector( 3 downto 0);DDR_dq: inout std_logic_vector(31 downto 0);DDR_dqs_n: inout std_logic_vector( 3 downto 0);DDR_dqs_p: inout std_logic_vector( 3 downto 0);DDR_odt: inout std_logic;DDR_ras_n: inout std_logic;DDR_reset_n: inout std_logic;DDR_we_n: inout std_logic;FIXED_IO_ddr_vrn: inout std_logic;FIXED_IO_ddr_vrp: inout std_logic;FIXED_IO_mio: inout std_logic_vector(53 downto 0);FIXED_IO_ps_clk: inout std_logic;FIXED_IO_ps_porb: inout std_logic;FIXED_IO_ps_srstb: inout std_logic );end DmaTransfer;architecture Behavioral of DmaTransfer issignalRxData: std_logic_vector(31 downto 0);signalRxKeep: std_logic_vector( 3 downto 0);signalRxLast: std_logic;signalRxValid: std_logic;signalRxReady: std_logic;signalTxData: std_logic_vector(31 downto 0);signalTxKeep: std_logic_vector( 3 downto 0);signalTxLast: std_logic;signalTxValid: std_logic;signalTxReady: std_logic;signalclk: std_logic;signalrst: std_logic;signalFifoDataW: std_logic_vector(36 downto 0);signalFifoWrite: std_logic;signalFifoRead: std_logic;signalFifoDataR: std_logic_vector(36 downto 0);signalFifoEmpty: std_logic;signalFifoFull: std_logic;beginPS : entity WORK.ProcessingSystemport map(DDR_addr=> DDR_addr,DDR_ba=> DDR_ba,DDR_cas_n=> DDR_cas_n,DDR_ck_n=> DDR_ck_n,DDR_ck_p=> DDR_ck_p,DDR_cke=> DDR_cke,DDR_cs_n=> DDR_cs_n,DDR_dm=> DDR_dm,DDR_dq=> DDR_dq,DDR_dqs_n=> DDR_dqs_n,DDR_dqs_p=> DDR_dqs_p,DDR_odt=> DDR_odt,DDR_ras_n=> DDR_ras_n,DDR_reset_n=> DDR_reset_n,DDR_we_n=> DDR_we_n,FIXED_IO_ddr_vrn=> FIXED_IO_ddr_vrn,FIXED_IO_ddr_vrp=> FIXED_IO_ddr_vrp,FIXED_IO_mio=> FIXED_IO_mio,FIXED_IO_ps_clk=> FIXED_IO_ps_clk,FIXED_IO_ps_porb=> FIXED_IO_ps_porb,FIXED_IO_ps_srstb=> FIXED_IO_ps_srstb,-- Dma ChanneliDmaRx_tdata=> RxData,iDmaRx_tkeep=> RxKeep,iDmaRx_tlast=> RxLast,iDmaRx_tready=> RxReady,iDmaRx_tvalid=> RxValid,oDmaTx_tdata=> TxData,oDmaTx_tkeep=> TxKeep,oDmaTx_tlast=> TxLast,oDmaTx_tready=> TxReady,oDmaTx_tvalid=> TxValid,-- SystemoZynqClk=> clk,oZynqRst(0)=> rst );FifoDataW(31 downto  0) <= not TxData;FifoDataW(35 downto 32) <= TxKeep;FifoDataW(    36) <= TxLast;FifoWrite <= TxValid and not FifoFull;TxReady <= not FifoFull;EchFifo : entity WORK.SyncFifoBram37x1024port map(clk=> clk,srst=> rst,din=> FifoDataW,wr_en=> FifoWrite,rd_en=> FifoRead,dout=> FifoDataR,full=> open,empty=> FifoEmpty,prog_full=> FifoFull );RxData <= FifoDataR(31 downto  0);RxKeep <= FifoDataR(35 downto 32);RxLast <= FifoDataR(36);RxValid <= not FifoEmpty;FifoRead <= RxReady;end Behavioral; 
    
  36. Соберем проект. Для этого во Flow Navigator => Generate Bitstream => OK. Появившиеся окно, что создание прошивки успешно завершено, закрываем.
  37. Экспортируем полученные файлы для разработки приложения на процессоре. Для этого выбираем File => Export => Export Hardware => вводим имя файла и указываем путь до каталога => OK. Получаем на выходе файл .xsa



3.2 Программная часть


Теперь нужно написать приложение, работающее на процессорном модуле. Необходимо запустить среду разработки Vitis и создать приложение по шаблону Hello World, пример этого показан в предыдущей статье.

Формат дескрипторов для Axi DMA описан в документе на ядро [2]. Дескриптор имеет размер 52 байта, однако, адрес, по которому расположен дескриптор, должен быть выровнен на 64 байта.

Кратко по формату дескриптора:

  • NXTDESC адрес следующего дескриптора;
  • NXTDESC_MSB старшие 32 бита адреса следующего дескриптора;
  • BUFFER_ADDRESS адрес буфера;
  • BUFFER_ADDRESS_MSB старшие 32 бита адреса буфера;
  • RESERVED не используется;
  • RESERVED не используется;
  • CONTROL задает размер буфера, признаки начала и конца пакета;
  • STATUS показывает, сколько байт принято/передано, обработан/не обработан;
  • APP0 используется для работы с каналом Control/Status Stream;
  • APP1 используется для работы с каналом Control/Status Stream;
  • APP2 используется для работы с каналом Control/Status Stream;
  • APP3 используется для работы с каналом Control/Status Stream;
  • APP4 используется для работы с каналом Control/Status Stream.

Адреса в программируемой логике для обращения со стороны процессорного модуля можно посмотреть в Vivado. В Flow Navigator => Open Block Design => Вкладка Address Editor. В данном случае адрес DMA равен 0x4040_0000. Адрес начала области памяти для дескрипторов равен 0x4000_0000.

  1. В Vitis откроем файл helloworld.c и подключим следующие библиотеки

    #include <xil_io.h>#include "sleep.h"#include "xil_cache.h"#include "xil_mem.h"
    
  2. Каждый дескриптор должен начинаться с адреса, кратного 64 байтам. Следовательно, в 32Кбайта поместятся 32 768 / 64 = 512 дескрипторов. По 256 на прием и 256 на передачу.

    #define DESC_COUNT 256... /** Descriptors for receive */struct SGDesc RxDesc[DESC_COUNT];/** Descriptors for transmit */struct SGDesc TxDesc[DESC_COUNT];
    
  3. Выключим работу кэша, чтобы не думать, когда его сбросить.

    /** Flush Cache */Xil_DCacheFlush();/** Disable Cache */Xil_DCacheDisable();
    

  4. Заполним буферы, которые будут передаваться в программируемую логику.

    for (u16 desc = 0; desc < DESC_COUNT; desc++){for (u32 i = 0; i < BUFFER_SIZE; i++){TxBuffer[desc][i] = desc + i;}}
    
  5. Заполним список дескрипторов для передачи.

    for (u16 i = 0; i < DESC_COUNT; i++){TxDesc[i].NXTDESC = &TxDesc[i];TxDesc[i].NXTDESC_MSB = 0x0;TxDesc[i].BUFFER_ADDRESS = &TxBuffer[i][0];TxDesc[i].BUFFER_ADDRESS_MSB = 0x0;TxDesc[i].RESERVED0 = 0x0;TxDesc[i].RESERVED1 = 0x0;TxDesc[i].CONTROL = 0xC000000 + sizeof(TxBuffer[i]);TxDesc[i].STATUS = 0x0;TxDesc[i].APP0 = 0x0;TxDesc[i].APP1 = 0x0;TxDesc[i].APP2 = 0x0;TxDesc[i].APP3 = 0x0;TxDesc[i].APP4 = 0x0;}
    
  6. Скопируем дескрипторы передачи в память дескрипторов, которая расположена в программируемой логике.

    DescAddr = 0x40000000;for (u16 i = 0; i < DESC_COUNT; i++){Xil_MemCpy(DescAddr, &TxDesc[i], sizeof(TxDesc[i]));DescAddr += 0x40;}
    
  7. Запишем указатель на следующий элемент в списке дескрипторов.
    /** Write pointer to next pointer */DescAddr = 0x40000000;for (u16 i = 0; i < DESC_COUNT - 1; i++){Xil_Out32(DescAddr, DescAddr + 0x40);DescAddr += 0x40;}/** Write pointer for last descriptor */Xil_Out32(DescAddr, DescAddr);
    
  8. Повторим для списка дескрипторов приема.

    /** Fill descriptor to receive */for (u16 i = 0; i < DESC_COUNT; i++){RxDesc[i].NXTDESC = &RxDesc[i];RxDesc[i].NXTDESC_MSB = 0x0;RxDesc[i].BUFFER_ADDRESS = &RxBuffer[i][0];RxDesc[i].BUFFER_ADDRESS_MSB = 0x0;RxDesc[i].RESERVED0 = 0x0;RxDesc[i].RESERVED1 = 0x0;RxDesc[i].CONTROL = sizeof(RxBuffer[i]);RxDesc[i].STATUS = 0x0;RxDesc[i].APP0 = 0x0;RxDesc[i].APP1 = 0x0;RxDesc[i].APP2 = 0x0;RxDesc[i].APP3 = 0x0;RxDesc[i].APP4 = 0x0;}/** Copy receive descriptor for memory of descriptors */DescAddr = 0x40000000 + 0x4000;for (u16 i = 0; i < DESC_COUNT; i++){Xil_MemCpy(DescAddr, &RxDesc[i], sizeof(RxDesc[i]));DescAddr += 0x40;}/** Write pointer to next pointer */DescAddr = 0x40000000 + 0x4000;for (u16 i = 0; i < DESC_COUNT - 1; i++){Xil_Out32(DescAddr, DescAddr + 0x40);DescAddr += 0x40;}/** Write pointer for last descriptor */Xil_Out32(DescAddr, DescAddr); 
    
  9. Запустим DMA на передачу. DMA начинает обрабатывать данные после записи в регистр значения хвоста списка дескрипторов.

    /** Reset DMA and setup *//** MM2S */Xil_Out32(0x40400000, 0x0001dfe6);Xil_Out32(0x40400000, 0x0001dfe2);/** S2MM */Xil_Out32(0x40400030, 0x0001dfe6);Xil_Out32(0x40400030, 0x0001dfe2);/** PL => PS */Xil_Out32(0x4040003c, 0x00000000);Xil_Out32(0x40400038, 0x40004000);Xil_Out32(0x40400030, 0x0001dfe3);Xil_Out32(0x40400044, 0x00000000);Xil_Out32(0x40400040, 0x40007FC0);/** PS => PL */Xil_Out32(0x4040000C, 0x00000000);Xil_Out32(0x40400008, 0x40000000);Xil_Out32(0x40400000, 0x0001dfe3);Xil_Out32(0x40400014, 0x00000000);Xil_Out32(0x40400010, 0x40003FC0); 
    
  10. Подождем, пока будет обработан последний дескриптор на приеме и посчитаем время обработки. Конечно, можно использовать прерывания, но для тестовой задачи это излишне.

    /** Wait ready in last descriptor */while (1){status = Xil_In32(0x40003FDC);if ((status & 0x80000000) == 0x80000000){break;}else{countWait++;usleep(100);}}xil_printf("Time %x \n\r", countWait);
    

3.3 Результаты


Собираем приложение, создаем файл прошивки и заливаем в плату. Описано в предыдущей статье[1].

Запускаем, смотрим в мониторе com-порта:

Xilinx First Stage Boot LoaderRelease 2019.2  Dec 16 2020-15:11:44Silicon Version 3.1Boot mode is QSPISUCCESSFUL_HANDOFFFSBL Status = 0x1Hello WorldTime 10F

Таким образом, для обмена данными между процессорным модулем и программируемой логикой, в программируемой логике необходимо реализовать один из интерфейсов связи с процессорным модулем, где инициатором является программируемая логика. Такие интерфейсы представлены портами GP, HP, ACP. В предыдущей статье [1] они все были рассмотрены.

Посчитаем скорость передачи данных: (256 раз * 102400 байт) / (271 * 100 мкс) 967 321 033 байт/с 944 649 Кбайт/с 922 Мбайт/с.
Битовая скорость 7 738 568 264 бит/с.
Теоретическая скорость составляет 32 бита * 250 МГц = 8 000 000 000 бит/с.

Также, существует возможность хранить дескрипторы не в памяти программируемой логики, а в оперативной памяти, подключенной к процессорному модулю. В таком случае порт M_AXI_SG подключается к порту HP Zynq.

Рассмотрим первый вариант, когда для доступа DMA к данными и к дескрипторам в оперативной памяти процессорного модуля используются разные порты HP. Модифицируем прошивку в программируемой логике, чтобы получилась следующая схема:


Доступ к данными и дескрипторами через разные порты

Исходный код приложения приводить не будем. Отличия лишь в том, что дескрипторы не нужно копировать в память программируемой логики. Однако, необходимо учесть условие, чтобы адрес каждого дескриптора был выровнен на 64 байта.

После запуска приложения, в мониторе com-порта увидим, что время выполнения копирования буфера данных не поменялось, также 271 * 100 мкс.

Рассмотрим второй вариант, когда для доступа к DMA и к дескрипторам в оперативной памяти процессорного модуля используется один и тот же порт. Модифицируем прошивку в программируемой логике, чтобы получилась следующая схема:


Доступ к данными и дескрипторами через один и тот же порт

Исходный код приложения не поменялся относительно предыдущего варианта.
После запуска приложения, в мониторе com-порта увидим новое время выполнения операции копирования буфера: 398 * 100 мкс.

В результате, скорость обработки составит: (256 раз * 102400 байт) / (398 * 100 мкс) 658653266 байт/с 643216 Кбайт/с 628 Мбайт/с.
Битовая скорость 5269226128 бит/с.

Проект: github.com/Finnetrib/DmaTransfer

4 Заключение


В этой статье мы рассмотрели два реализации обмена данными между процессорным модулем и программируемой логикой. Режим PIO прост в реализации и позволяет получить скорость до 184 Мбайт/с, режим DMA несколько посложнее, но и скорость выше до 628 Мбайт/с.

5 Используемые источники


  1. habr.com/ru/post/508292
  2. www.xilinx.com/support/documentation/ip_documentation/axi_dma/v7_1/pg021_axi_dma.pdf
Подробнее..

Передача данных на расстояние до 20 км по обычным проводам? Легко, если это SHDSL

17.06.2020 10:12:43 | Автор: admin
Несмотря на повсеместное распространение сетей Ethernet, технологии связи на основе DSL не теряют своей актуальности и по сей день. До сих пор DSL можно встретить в сетях последней мили для подключения абонентского оборудования к сетям Интернет-провайдера, а в последнее время технология все чаще используется при построении локальных сетей, например, в промышленных приложениях, где DSL выступает в качестве дополнения к Ethernet или к полевым сетям на основе RS-232/422/485. Подобные промышленные решения активно применяются в развитых европейских и азиатских странах.

DSL представляет из себя семейство стандартов, которые изначально задумывались для передачи цифровых данных по телефонным линиям связи. Исторически это стало первой технологией широкополосного доступа в Интернет, придя на смену DIAL UP и ISDN. Большое разнообразие существующих в настоящий момент стандартов DSL связано с тем, что многие компании, начиная с 80-х годов, старались разработать и продвинуть на рынок собственную технологию.

Все эти разработки можно разделить на две большие категории асимметричные (ADSL) и симметричные (SDSL) технологии. Под асимметричными понимаются те, в которых скорость входящего соединения отличается от скорости исходящего трафика. Под симметричными понимается, что скорости на прием и передачу равны.

Наиболее известными и распространенными асимметричными стандартами являются, собственно, ADSL (в последней редакции ADSL2+) и VDSL (VDSL2), симметричными HDSL (устаревший профиль) и SHDSL. Друг от друга все они отличаются тем, что работают на разных частотах, используют разные способы кодирования и модуляции на физической линии связи. Также отличаются способы коррекции ошибок, благодаря чему обеспечивается разный уровень помехоустойчивости. Как итог, каждая технология имеет свои пределы в скорости и дистанции передачи данных, в том числе в зависимости от типа и качества проводника.


Предельные параметры различных стандартов DSL

В любой DSL-технологии скорость передачи данных падает с увеличением длины проводника. На предельных дистанциях возможно получить скорость в несколько сот килобит, но при передаче данных на 200-300 м доступна максимально возможная скорость.

Среди всех технологий у SHDSL есть серьезное преимущество, которое делает возможным ее применение в промышленных приложениях, высокая помехоустойчивость и возможность использования для передачи данных любого типа проводника. В асимметричных стандартах такого нет, и качество связи сильно зависит от качества линии, используемой для передачи данных. В частности, рекомендуется использовать витой телефонный кабель. В этом случае более надежным решением вместо ADSL и VDSL оказывается использовать оптический кабель.

Для SHDSL подходит любая пара изолированных друг от друга проводников медных, алюминиевых, стальных и пр. В качестве среды передачи может выступать старая электропроводка, старые телефонные линии, колючая проволока заборов и пр.


Зависимость скорости передачи данных SHDSL от дистанции и типа проводника

Из графика зависимости скорости передачи данных от дистанции и типа проводника, приведенного для SHDSL, можно увидеть, что проводники с большим сечением позволяют передавать информацию на большую дистанцию. Благодаря технологии возможно организовать связь на дистанцию до 20 км при максимально возможной скорости 15.3 Мб/с для 2-проводного кабеля или 30 Мб для 4-проводного. В реальных приложениях скорость передачи может быть выставлена вручную, что необходимо в условиях сильных электромагнитных помех или плохого качества линии. В этом случае для увеличения дистанции передачи необходимо снизить скорость работы SHDSL-устройств. Для точного расчета скорости в зависимости от дистанции и типа проводника можно использовать бесплатные программные средства, такие как SHDSL-калькулятор от Phoenix Contact.

За счет чего SHDSL обладает высокой помехоустойчивостью?

Принцип работы приемопередатчика SHDSL можно представить в виде блок-диаграммы, в которой выделяют специфическую и независимую (инвариантную) с точки зрения приложения часть. Независимая часть состоит из функциональных блоков PMD (Physical Medium Dependent) и PMS-TC (Physical Medium-Specific TC Layer), в то время как специфическая часть включает уровень TPS-TC (Transmission Protocol-Specific TC Layer) и интерфейсы пользовательских данных.

Физическая линия связи между приемопередатчиками (STU) может существовать в виде однопарного или нескольких однопарных кабелей. В случае нескольких пар кабелей STU содержит несколько независимых блоков PMD, связанных с единственным PMS-TC.


Функциональная модель SHDSL-приемопередатчика (STU)

Модуль TPS-TC зависит от приложения, в котором используется устройство (Ethernet, RS-232/422/485 и пр.). В его задачу входит преобразование пользовательских данных в формат SHDSL, выполняется мультиплексирование/демультиплексирование и корректировка по времени нескольких каналов пользовательских данных.

На уровне PMS-TC производится формирование кадров SHDSL и их синхронизация, а также скремблирование и дескремблирование.

Модуль PMD выполняет функции кодирования/декодирования информации, модуляции/демодуляции, эхоподавления, согласования параметров на линии связи и установления соединения между приемопередатчиками. Именно на уровне PMD выполняются основные операции, обеспечивающая высокую помехоустойчивость SHDSL, включая TCPAM кодирование (Треллис кодирование с аналого-импульсной модуляцией), механизм совместного кодирования и модуляции, при котором улучшается спектральная эффективность сигнала по сравнению с раздельным способом. Принцип работы модуля PMD также можно представить в виде функциональной диаграммы.


Блок-диаграмма модуля PMD

В основе TC-PAM лежит использование сверточного кодера, формирующего избыточную последовательность битов на стороне SHDSL-передатчика. На каждом такте работы каждому биту, поступающему на вход кодера, ставится в соответствие двойной бит (дибит) на выходе. Таким образом, ценой сравнительно небольшой избыточности повышается помехоустойчивость передачи. Использование Треллис-модуляции позволяет уменьшить используемую полосу частоту передачи данных и упростить аппаратную часть при неизменном отношении сигнал/шум.


Принцип работы Треллис-кодера (TC-PAM 16)

Двойной бит формируется в результате логической операции сложения по модулю 2 (исключающее или) на основе входного бита x1(tn) и битов x1(tn-1), x1(tn-2) и т.д. (всего их может быть до 20), которые поступали на вход кодера до этого и остались храниться в регистрах памяти. На следующем такте работы кодера tn+1 произойдет смещение битов в ячейках памяти для выполнения логической операции: бит x1(tn) переместится в память, сдвинув всю хранящуюся там последовательность битов.


Таблицы истинности операции сложения по модулю 2

Для наглядности удобно использовать диаграмму состояния сверточного кодера, по которой можно увидеть, в каком состоянии находится кодер в моменты времени tn, tn+1 и т.д. в зависимости от входных данных. Под состоянием кодера в этом случае подразумевают пару значений входного бита x1(tn) и бита в первой ячейки памяти x1(tn-1). Для построения диаграммы можно использовать граф, в вершинах которого находятся возможные состояния кодера, а переходы из одного состояния в другое обозначены соответствующими входными битами x1(tn) и выходными дибитами $inline$y y (t )$inline$.


Диаграмма состояний и граф переходов сверточного кодера передатчика

В передатчике на основе полученных четырех битов (двух выходных битов кодера и двух битов данных) формируется символ, каждому из которых соответствует своя амплитуда модулирующего сигнала аналого-импульсного модулятора.


Состояние 16-разрядного АИМ в зависимости от значения четырехбитового символа

На стороне приемника сигнала происходит обратный процесс демодуляция и выделение из избыточного кода (двойных битов y0y1(tn)) нужной последовательности входных битов кодера x1(tn). Эту операцию выполняет декодер Витерби.

Алгоритм декодера основан на расчете метрики ошибок для всех возможных предполагаемых состояний кодера. Под метрикой ошибок понимают разницу между принимаемыми битами и предполагаемыми битами для каждого возможного пути. Если ошибок на приеме нет, то метрика ошибок истинного пути будет 0, потому что нет расхождения по битам. Для ложных путей метрика будет отличаться от нуля, постоянно нарастать и через какое-то время декодер перестанет рассчитывать ошибочный путь, оставив только истинный.


Диаграмма состояний кодера, вычисляемая декодером Витерби приемника

Но как этот алгоритм обеспечивает помехоустойчивость? Если предположить, что приемник принял данные с ошибкой, декодер продолжит рассчитывать два пути с метрикой ошибок 1. Пути с метрикой 0 уже не будет существовать. Но вывод о том, какой путь истинный, алгоритм сделает позже на основе следующих принимаемых двойных битов.

При появлении второй ошибки, будет несколько путей с метрикой 2, но правильный путь выявится позже на основе метода наибольшего правдоподобия (то есть минимальной метрики).


Диаграмма состояний кодера, вычисляемая декодером Витерби, при приеме данных с ошибками

В описанном выше случае для примера был рассмотрен алгоритм 16-разрядной системы (TC-PAM16), обеспечивающей передачу в одном символе трех бит полезной информации и дополнительного бита для защиты от ошибок. В TC-PAM16 достижима скорость передачи данных от 192 до 3840 кбит/с. При увеличении разрядности до 128 (современные системы работают с TC-PAM128) в каждом символе передается шесть бит полезной информации, а максимально достижимая скорость составляет от 5696 кбит/с до 15,3 Мб/с.

Использование аналого-импульсной модуляции (PAM) роднит SHDSL с рядом популярных стандартов Ethernet, таких как гигабитный 1000BASE-T (PAM-5), 10-гигабитный 10GBASE-T (PAM-16) или перспективный на 2020 год промышленный однопарный Ethernet 10BASE-T1L (PAM-3).

SHDSL в сетях Ethernet

Различают управляемые и неуправляемые SHDSL-модемы, но в подобной классификации мало общего с привычным разделением на управляемые и неуправляемые устройства, которое существует, например, для Ethernet-коммутаторов. Разница заключается в средствах конфигурирования и мониторинга. Управляемые модемы настраиваются через веб-интерфейс и могут диагностироваться по SNMP, а неуправляемые при помощи дополнительного ПО через консольный порт (для Phoenix Contact это бесплатная программа PSI-CONF и mini-USB интерфейс). В отличии от коммутаторов неуправляемые модемы могут работать в сети с кольцевой топологией.

В остальном управляемые и неуправляемые модемы являются абсолютно идентичными, включая функционал и возможность работать по принципу Plug&Play, то есть без всякого предварительного конфигурирования.

Дополнительно на модемы могут возлагаться функции защиты от импульсных перенапряжений c возможностью ее диагностики. Сети SHDSL могут образовывать очень протяженные сегменты, и проводники могут проходить в местах, где возможно образование импульсных перенапряжений (наведенной разности потенциалов, вызванной грозовыми разрядами либо короткими замыканиями в близлежащих кабельных линиях). Наведенное напряжение может вызвать протекание разрядных токов величиной в килоамперы. Поэтому для защиты оборудования от подобных явлений в модемы встраиваются УЗИП в виде съемной платы, которая в случае необходимости может быть заменена. Именно к клеммнику этой платы подключается линия SHDSL.

Топологии

С помощью SHDSL в Ethernet возможно строить сети с любой топологией: точка-точка, линия, звезда и кольцо. При этом, в зависимости от типа модема для подключения можно использовать как 2-проводные, так и 4-проводные линии связи.


Топологии сети Ethernet на основе SHDSL

Также можно строить распределенные системы с комбинированной топологией. Каждый сегмент SHDSL-сети может насчитывать до 50 модемов и, учитывая физические возможности технологии (расстояние между модемами в 20 км), длина сегмента может достигать 1000 км.

Если в голове каждого такого сегмента установить управляемый модем, то целостность сегмента можно диагностировать по SNMP. Помимо этого, управляемые и неуправляемые модемы поддерживают технологию VLAN, то есть позволяют разбивать сеть на логические подсети. Также устройства способны работать с протоколами передачи данных, применяемыми в современных системах автоматизации (Profinet, Ethernet/IP, Modbus TCP и пр.).


Резервирование каналов связи с помощью SHDSL

SHDSL используют для создания резервных каналов связи в сети Ethernet, чаще всего оптического.

SHDSL и последовательный интерфейс

SHDSL-модемы с последовательным интерфейсом позволяют преодолеть ограничения по дистанции, топологии и качеству проводника, которые существуют для традиционных проводных систем на основе асинхронных приемопередатчиков (UART): RS-232 15 м, RS-422 и RS-485 1200 м.

Существуют модемы с последовательными интерфейсами (RS-232/422/485) как для универсальных приложений, так и для специализированных (например, для Profibus). Все подобные устройства относятся к категории неуправляемых, поэтому настраиваются и диагностируются при помощи специального ПО.

Топологии

В сетях с последовательным интерфейсом при помощи SHDSL возможно строить сети с топологией точка-точка, линия и звезда. В рамках линейной топологии возможно объединить в одну сеть до 255 узлов (для Profibus 30).

В системах, построенных с использованием только устройств на интерфейсе RS-485, отсутствуют какие-либо ограничения по применяемому протоколу передачи данных, но топологии типа линия и звезда являются нетипичными для RS-232 и RS-422, поэтому работа конечных устройств в SHDSL-сети с подобными топологиями возможна только в полудуплексном режиме. Одновременно в системах с RS-232 и RS-422 на уровне протокола должна обеспечиваться адресация приборов, что нехарактерно для интерфейсов, чаще всего применяемых в сетях точка-точка.

При объединении через SHDSL устройств с разными типами интерфейсов необходимо учитывать факт отсутствия единого механизма для установления соединения (рукопожатия) между устройствами. Однако организовать обмен в этом случае все равно возможно для этого необходимо выполнение следующих условий:
  • согласование связи и управление передачей данных должно выполняться на уровне единого информационного протокола передачи данных;
  • все конечные устройства должны функционировать в полудуплексном режиме, что также должно поддерживаться информационным протоколом.

Наиболее часто встречающийся для асинхронных интерфейсов протокол Modbus RTU позволяет избежать всех описанных ограничений и строить единую систему с различными типами интерфейсов.


Топологии сети с последовательным интерфейсом на основе SHDSL

При использовании двухпроводного RS-485 на оборудовании Phoenix Contact можно строить более сложные структуры, объединяя модемы через одну шину на DIN-рейке. На этой же шине может быть установлен источник питания (в таком случае питание всех устройств осуществляется через шину) и оптические преобразователи серии PSI-MOS для создания комбинированной сети. Важным условием работы такой системы является одинаковая скорость всех приемопередатчиков.


Дополнительные возможности SHDSL в сети RS-485

Примеры применения

SHDSL-технология активно применяется в городском коммунальном хозяйстве в Германии. Более 50 компаний, обслуживающих городские коммунальные системы, используют старые медные провода, чтоб связать одной сетью распределенные по городу объекты. На SHDSL строятся в первую очередь системы управления и учета в водо-, газо- и энергоснабжении. Среди таких городов Ульм, Магдебург, Ингольштадт, Билефельд, Франкфурт-на-Одере и многие другие.

Самая масштабная система на основе SHDSL была создана в городе Любеке. Система имеет комбинированную структуру на основе оптического Ethernet и SHDSL, объединяет 120 удаленных друг от друга объектов и использует более 50 модемов Phoenix Contact. Вся сеть диагностируется по SNMP. Самый протяженный сегмент от коммуны Калькхорст до аэропорта Любека имеет длину 39 км. Причина, по которой компания-заказчик выбрала SHDSL, заключалась в том, что реализация проекта целиком на оптике была экономический невыгодна с учетом наличия старых медных кабелей.


Передача данных через контактное кольцо

Интересным примером является передача данных между движущимися объектами, как например, это сделано в ветрогенераторах или в крупных промышленных крутильных машинах. Подобная система используется для информационного обмена между контроллерами, расположенными на роторе и статоре установок. В этом случае для передачи данных используется скользящий контакт через контактное кольцо. Подобные примеры показывают, что необязательно иметь статический контакт для передачи данных по SHDSL.

Сравнение с другими технологиями

SHDSL vs GSM
Если сравнивать SHDSL с системами передачи данных на основе GSM (3G/4G), то в пользу DSL говорит отсутствие эксплуатационных расходов, связанных с регулярной платой оператору за доступ к мобильной сети. При SHDSL мы не зависим от зоны покрытия, качества и надежности мобильной связи на промышленном объекте, включая устойчивость к электромагнитным помехам. В SHDSL отсутствует необходимость в конфигурировании оборудования, что ускоряет ввод объекта в эксплуатацию. Для беспроводных сетей характерны большие задержки в передаче данных и сложность с передачей данных, использующих мультикастовый трафик (Profinet, Ethernet IP).

В пользу SHDSL говорит информационная безопасность в силу отсутствия необходимости передачи данных через Интернет и необходимости конфигурирования для этого VPN-соединений.

SHDSL vs Wi-Fi
Многое из сказанного для GSM можно отнести и к промышленному Wi-Fi. Против Wi-Fi говорит низкая помехоустойчивость, ограниченная дистанция передачи данных, зависимость от топологии местности, задержки при передаче данных. Самый главный недостаток информационная безопасность сетей Wi-Fi, потому как любой человек имеет доступ к среде передачи данных. При помощи Wi-Fi уже возможно передавать данные Profinet или Ethernet IP, что было бы затруднительно для GSM.

SHDSL vs оптика
Оптика в подавляющем большинстве обладает большим преимуществом перед SHDSL, но в ряде приложений SHDSL позволяет экономить время и средства на прокладку и сварку оптического кабеля, сокращая время на ввод объекта в эксплуатацию. Для SHDSL не требуется специальных разъемов, потому как кабель связи просто подключается на клемму модема. Из-за механических свойств оптических кабелей их применение ограничено в приложениях, связанных с передачей информации между движущимися объектами, где большее распространение получили медные проводники.
Подробнее..

Перевод Завершен перевод систематизированного обзора литературы по военным SDN-сетям

04.05.2021 08:16:25 | Автор: admin

В марте этого года я анонсировал перевод этого обзора. Сегодня публикую результат, получилось 70 страниц.

Традиционная просьба: прошу сообщать о замеченных огрехах, они наверняка есть, так как документ переводился и верстался в одно лицо. Обзор оформлен в виде pdf-документа, линк для скачивания: https://vk.cc/c1BQwV

Всем приятного чтения!

Подробнее..

Передача файлов по воздуху через камеру смартфона

04.01.2021 12:22:00 | Автор: admin


Проблема


Штрихкод классная штука для маркировки всего на свете, от товаров до людей. Сейчас в ходу около двух десятков стандартов двумерных штрихкодов, и ещё десятки неудачных, трагически непонятых, самопальных и внутренних корпоративных вариантов, большинство из которых с треском проигрывает обычному QR-коду. Распространённость и простота реализации сделали его самым популярным среди двумерных штрихкодов, но и у него есть недостаток, характерный для всех линейных собратьев: он вмещает очень мало информации. В 2-3 килобайта можно уместить ссылку или небольшой отрывок текста, но даже небольшая картинка или обычный документ уже не влезут даже в самый большой код.


Понятно, что вместимость обычного QR-подобного квадратика можно увеличить, увеличивая размер матрицы, добавляя цвета и играясь с формой ячеек. Единого стандарта для таких расширенных кодов нет, кроме проприетарного Microsoft Tag (HCCB) с неясными перспективами развития и использования. Расширение палитры и изменение пикселей также усложняет чтение кода в сложных условиях (плохая печать, цветное или недостаточное освещение), но всё равно даёт очень ограниченное увеличение ёмкости и не позволяет без боли передать даже мегабайт данных.

Хороший пример такого самодельного стандарта Jabcode

Решить проблему уже давно предложили радикально: в отличие от линейных штрихкодов, QR встречаются не только в напечатанном виде, но и на экранах устройств в приложениях и на сайтах. Значит, если чем-то в стандарте придётся поступиться, пусть это будет возможность физической печати кода сделаем его анимированным! Таким образом моментально превращаем статичный квадратик в источник неограниченного объёма данных, которые можно будет передавать по воздуху без подключения к любым сетям. Разумеется, скорость передачи будет невысокой, и обычная считывалка QR не сможет обработать такой код, но принцип раскодирования почти тот же и изобретать велосипед не придётся.

TXQR


Первой готовой и продуманной реализацией, из всех, что мне удалось найти, стал TXQR от Ивана Данилюка (блог, GitHub). В проекте есть спецификация и PoC на Go с приложением под iOS.



Сначала код TXQR просто прокручивал обычные QR-коды в цикле, а телефон старался их считать как можно точнее, получая коррекцию ошибок только при следующем повторении цикла. В тестах автор гонял файл на 13 килобайт, получив пиковую скорость 9 KB/s. В следующей итерации формат стал использовать фонтанные коды (точнее, Luby transform code), чтобы через избыточность позволить выполнять коррекцию ошибок в любых фреймах, не дожидаясь прокрутки цикла:



Если вкратце, исходные данные делятся на блоки, которые рандомно XOR-ятся в закодированные блоки, которые уже отправляются в фреймы. Некоторые блоки могут не склеиваться, что уменьшает оверхед. На клиенте получаемые из фреймов блоки XOR-ятся с уже полученными данными, в итоге получается проверенная на ошибки исходная структура данных. Больше почитать можно на вики и в статье Ивана про переход на фонтанные коды. В общем, несмотря на существенный оверхед, скорость декодирования данных существенно возросла:



Теперь в пике TXQR выдаёт около 25 KB/s при низком уровне коррекции ошибок. Запомним это значение и перейдём к его преемнику, созданному двумя годами позже. Встречайте,

Cimbar


Cimbar (Color Icon Matrix bar codes) ещё больше отошёл от стандарта QR-кода, сохранив только визуальное сходство. Этот формат выжимает как можно большую пропускную способность, используя сразу цвета, иконки 8х8 вместо обычных пикселей и, разумеется, анимацию. В одну клетку кодируется 4 бита информации, и еще 2 или 3 бита добавляется за счёт использования цветовой схемы (на 4 или 8 цветов), позволяя хранить до 7 бит в одной клетке:



Кодирование в cimbar происходит по алгоритму, схожему с хэшированием изображений: декодер сравнивает тайл 4х4 со словарем из 16 ожидаемых тайлов и выбирает тот, у которого оказывается самый близкий хэш. Аналогично, для каждого тайла берётся средний цвет и сравнивается со словарём ожидаемых цветов, затем выбирается ближайший. Затем полученные данные проходят проверку ошибок по комбинации кода Рида Соломона, для фонтанных кодов используется wirehair. В текущем (не окончательном) формате размер сетки 1024х1024 символа, и при использовании на маленьких экранах или с плохой камерой код не всегда читается хорошо, поэтому разработчик обдумывает вариант пожертвовать пропускной способностью в угоду универсальности.

Выглядит итоговая картинка довольно жутко и эпилептично, но позволяет добиться при обычном уровне коррекции стабильных 700-800 KB/s! Это в 32 раза быстрее чем пиковая скорость TXQR при заниженной коррекции ошибок, и в этом можно убедиться самостоятельно:

  1. Заходим на cimbar.org и загружаем файл потяжелее. Сначала лучше не уходить в крайности, я разок попробовал загрузить 10-мегабайтный .apk и устал держать телефон на весу, пока он качался, поэтому начинать стоит с 500KB-2MB.
  2. Качаем приложение под Android
  3. Включаем режим полёта и сканируем код. Не забудьте выбрать нужную цветовую палитру, по умолчанию на сайте и в приложении стоит 4 цвета.
  4. Наслаждаемся магией!




Заключение


Пока проект существует как PoC, но разработчик явно хочет довести его до ума и развить в полезный стандарт. Доки и реализация на питоне лежат в основном репозитории, оптимизированная библиотека на C/C++ живёт отдельно, мобильное приложение здесь. На сайте cimbar.org кодировщик работает через wasm, репо найти не удалось.

Air-gapped передача данных это круто и всегда весело придумывать сценарии использования для них. Я уже попробовал передавать приложения через cimbar и вижу в этом много интересных возможностей. Если у вас тоже появились оригинальные идеи, обсудим в комментариях.



На правах рекламы


Наша компания предлагает аренду VPS для совершенно любых проектов. Предлагаем широкий выбор тарифных планов, максимальная конфигурация позволит разместить практически любой проект 128 ядер CPU, 512 ГБ RAM, 4000 ГБ NVMe!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru