Комментарии 46
А профибас-дп сможете так просканировать?
Я Profibus DP не сталкивался.
Что можно почитать про физический уровень Profibus DP?
Инфы море, хоть с официального сайта, хоть в свободном доступе. Но этот протокол работает поверх всё той же спецификации RS-485. Линия сбалансированная и в состоянии покоя на проводниках поддерживается стандартное напряжение, чтобы устройства не считывали помехи, когда никто не передаёт. Так что ничего занулять для сканирования нельзя.
Нет такой шины RS-485. Это физический уровень. А протокол может быть любой. Поэтому какую вы там шину сканировали вообще не понятно.
ModBus тоже использует RS-485 и там всего 255 устройств возможно.
я использовал однобайтный адрес и сканировал перебором.
но даже для многобайтного, раз уж все равно требуется поддержка со стороны слейва, можно придумать какой-нибудь протокол позволяющий сканировать отправкой байтов, а не поднятием ножки. Скажем "отправляем запрос, отвечают все у кого адреса совпали с маской, если слышим мусор значит таких больше одного, увеличить маску на один бит и продолжить.
Скажем "отправляем запрос, отвечают все у кого адреса совпали с маской, если слышим мусор значит таких больше одного, увеличить маску на один бит и продолжить.
Отличное предложение! Но как драйвер UART на стороне мастера поймет что идет мусор?
Все мусор, если запрос идёт на широковещательный адрес. Главное тут есть этот мусор или нет. А дальше классический бинарный поиск: https://ru.wikipedia.org/wiki/Двоичный_поиск
Мусор — мастер примет какие-то байты, но при этом контрольная сумма не сойдется.
Теоретически, правда, есть шанс что при наличии parity bit ничего принято не будет, но тут могу представить три варианта — отключить parity bit (всегда так делаю, так что дальше уже мои гипотезы), проверять parity error (если мастер мк а не комп), сделать ответ подлиннее, тогда хоть у одного байта да сойдется.
Делал и видел множество вариантов RS485 устройств. И вижу, что в статье чушь.
1) RS485 это стандарт физического уровня. В нём тупо нет ни то, что адресов, но и даже пакетов. Он заканчивается уровнем байта (8 бит плюс минус ) https://ru.wikipedia.org/wiki/RS-485
2) Всё, что тут написано, написано про какую-то реализацию протокола поверх RS485, но не самого распространённого - не modbus, потому что modbus имеет только 1 байт адреса (иногда больше, но это уже не очень кошерный modbus) https://en.wikipedia.org/wiki/Modbus
3) и, вишенка на торте! Указаный алгоритм побитного прощупования тупо противоречит стандарту modbus и стандарту RS485.
Hidden text
Вообще по уровню самоуверенности этой чуши возникает ощущение, что пишет либо плохой, но настырный студент, либо ИИ.
Писал как то утилю которая с 1 до 255 на всех общепринятых скоростях\чётностях сканирует. Модбас и околомодбасные протоколы - сканирует хорошо. Автор пишет не про RS485 а про какой-то протокол, при этом название протокола не говорит. Это какой то квест?)
Автор сам явно не определился с протоколом:
"Трудность в том что адреса устройств RS485 имеют существенно более высокую разрядность, как правило это 32 бита (4байта) или MAC адреса по 48бит (6 байт)"
Автор пишет не про RS485 а про какой-то протокол, при этом название протокола не говорит.
Это технология, которая может быть реализована в любом протоколе, который работает поверх RS-485. Будь до ModBus или xModem.
Не может. В ModBus не принято говорить хором. Так что только перебор по конкретным адресам. Еще мастер может послать сообщение всем устройствам через широковещательный адрес но ответ на него не предусмотрен. Теоретически можно предусмотреть очередность ответа через <адрес> * 100ms, но поддерживать это будут ваши два с половиной устройства. И это уже будет не ModBus.
Не может. В ModBus не принято говорить хором.
Смотрите,
https://habr.com/ru/companies/wirenboard/articles/737402/
в контроллерах Wiren Board тоже есть одновременный ModBus ответ на сканирование
Я, например, реализовал асинхронный протокол похожий с на UDP/TCP поверх RS485 с разрешением колизий (когда начинают передавать несколько устройств на шине) и автоматической раздачей однобайтового адреса каждому устройству на шине по его MAC адресу. С авто-дисковери, пингами и тп. В нем не нужно сканирование =)
Зачем использовать для RS-485 адрес длиной более 8 бит, если трансиверы RS-485 могут вытянуть в качестве нагрузки лучшем случае 256 аналогичных трансиверов, а часто — всего лишь 64, и это не считая ёмкости самих проводов? И уж тем более 32 или 48 бит? Гораздо актуальнее — автоматическое назначение адреса на шине, с идентификацией по тому же MAC или серийному номеру.
Зачем использовать для RS-485 адрес длиной более 8 бит, если трансиверы RS-485 могут вытянуть в качестве нагрузки лучшем случае 256 аналогичных трансиверов
Дело в том что в качестве адресов иногда используют MAC адреса устройств. А они в свою очередь являются производной серийного номера SN.
Поэтому адреса широкие хоть и узлов сети мало.
Вы правы, та же max485 регламентирует работу не более 128 микросхем на линии.
Но, возможно, какой-то производитель оборудования решил сделать 4 миллиарда устройств с заранее прошитым адресом, где каждое устройство с "завода" имеет уникальный номер.
1--Трудность в том что адреса устройств RS485 имеют существенно более высокую разрядность, как правило это 32 бита (4байта) или MAC адреса по 48бит (6 байт).
нет стандарта на 485 где бы описывалась адресацыя. да и не нужна здесь многобайтовость.
Этот простой алгоритм сканирования адресов на общей шине подойдет не только для RS485. Его можно реализовать для любого другого интерфейса с топологией общая шина. Это может быть и 1Wire, LIN или даже вовсе беспроводные интерфейсы типа LoRa или UWB.
ващета в 1варе поиск адреса устройства так и выполняеца, разработанный в конце 90-х годов фирмой Dallas.
Поздравляю с изобретением велосипеда.
ващета в 1варе поиск адреса устройства так и выполняеца, разработанный в конце 90-х годов фирмой Dallas.
Поздравляю с изобретением велосипеда.
Может тогда пришлете pdf c AppNote того как это там описывается?
Тут описание, но не у всех откроется без VPN: https://www.analog.com/en/app-notes/1wire-search-algorithm.html
Тут один из вариантов описания на русском: https://we.easyelectronics.ru/STM32/stm32-1-wire-poisk-ustroystv.html
Тут один из вариантов описания на русском
В тексте с we.easyelectronics.ru не такой же алгоритм сканирования как тут. Там даже таких слов как маска нет. И один бит там кодируют двумя битами.
У меня в протоколе сканирование выполнялось после определённой команды-бродкаста. Отвечали все устройства по очереди, с задержкой, пропорциональной их адресу.
На шине 3 устройства с адресам: 0x00000001, 0xFFFFFFFD. 0xFFFFFFFE.
Сначала отвечает первый потом пауза 13 лет и отвечают последние 2.))
В итоге мастер думает что на шине одно устройство с адресом 0x00000001
Отличное решение.
Ну у меня в протоколе адреса однобайтные, поэтому даже для адресов 1 и 255 это работает. Длительность сканирования примерно пропорциональна количеству устройств на линии.
А что мешает использовать двойную адресацию? Внешняя - 1-255, внутренняя - произвольная. Опрашиваются 255max адресов, слэйв в ответе пересылает свой внутренний адрес.
я может совсем тупой, но какой mac на rs485 ?
Много лет работал с 485-м, писал программы для работы с ним, делал устройства с разными протоколами, но у меня даже подозрений нет, с каким же устройством работает автор статьи. В большинстве случаев это были modbus-подобные протоколы, ну или dmx-подобные
Оборудование какого производителя использует 32 бит на адрес в 485 ?
Возможна любая реализация поверх 485. Пытались стандартизовать Modbus, но по прежнему куча производителей делает по своему.
И вообще может даже микроконтроллер не нужен на этой линии. Как-то с помощью микросхем 485/422 передавал сигнал с датчика холла на значительное расстояние в "шумном" оборудовании.
Оборудование какого производителя использует 32 бит на адрес в 485 ?
Нормальные производители таким онанизмом заниматься не будут, сделают нормальный способ задать 7-8битный адрес устройству
но приходилось как-то изобретать подобный велосипед для подключения кучи однотипных устройств по 485, для которых совсем не хотелось руками раздавать каждому логические адреса на шине (джамперами / в еепром), но у которых есть уникальный chip ID в МК, 64битный, по которому их можно различать, и, просканировав шину мастером при старте, раздать им соответствующие логические 128 адресов для последующей адресации на шине. некий убогий аналог dhcp для rs485.
собственно для 1wire всё уже давно придумано.
а слэйвам для этого надо только две команды:
1) отозваться хоть как-то, если присланный мастером ID больше чем собственный и плевать на коллизии, наличие просто стартового бита в ответе означает что на шине кто-то есть. и без дополнительного дергания IO.
2) получить свой логический однобайтный адрес и в дальнейшем перестать отзываться на запросы с ID, чтобы не мешать остальным.
дальше бинарый поиск.
RS485 - это интерфейс. По спецификации поддерживает подключение до 256 устройств, т.е. в 32-битном адресе нет смысла. О протоколе, к-рый (якобы) используется в данном опусе - ни слова. И при описанном алгоритме получить 100% результат - маловероятно. Причина банальна: помехи. Именно поэтому используются кодированный запрос/кодированный ответ.
Отличный механизм. От себя замечу, что можно в качестве подтверждения отправлять 0. Он примется УАРТом, пусть и с возможными ошибками. Нам же главное отклик. Заодно и скорость можно на лету оценить.
Положу закладочку.
Реализовывали похожий принцип. Только в нашем случае серийники были длинными, а в целях сокращения длины рабочих пакетов, адреса были короткими. И короткие адреса назначал мастер. Только у нас было чуть по другому. Протокол разбивался на две части: Протокол сканирования и протокол рабочего обмена (который, кстати, может быть любым. Даже модбасом) Отвечали устройства так же - затяжкой линии в ноль. Работало это так:
Запрос неадресованных устройств на шине. Если таковые были, отвечали нулём на шине. Мастер, обнаружив ноль, приступал к следующему этапу. А иначе, просто повторял запрос и обслуживал уже адресованные устройства.
Запрос в стиле "есть у кого в серийнике 31й бит, равный единице?". Если у кого-то есть, тот отвечает нулём. Мастер, поймав ответ, записывает у себя единицу в 31й бит. А если ответ так и не поступил, пишет ноль в 31й бит. После этого он посылает следующий запрос, но спрашивает уже за 30й бит и так далее, до нулевого. В итоге, у него получается серийник одного из устройств.
Мастер отправляет этому устройству пакет с коротким адресом, используя его серийник. Устройство получив короткий адрес, прекращает отвечать на запросы битов серийника и на запрос недресованных устройств и переходит в рабочий режим. После чего, мастер начинает обслуживание этого устройства и переходит в пункт 1. Такой цикл повторяется всякий раз, когда имеется ответ на пакет из первого пункта.
Периодически, мастер интересуется на предмет появления новых устройств на шине, посылая запрос на наличие неадресованных устройств.
Чтобы пересканировать шину заново, используется пакет начала сканирования. Услышав его, все устройства сбрасывают свои адреса и переходят в режим сканирования. Обычно он отправляется мастером, если его база найденных устройств пуста.
Таким образом мы решили вопрос горячей замены устройств без каких либо манипуляций с прописыванием адресов. Воткнул устройство в шину и оно тут же обнаружилось мастером.
Запрос в стиле "есть у кого в серийнике 31й бит, равный единице?". Если у кого-то есть, тот отвечает нулём. Мастер, поймав ответ, записывает у себя единицу в 31й бит. А если ответ так и не поступил, пишет ноль в 31й бит. После этого он посылает следующий запрос, но спрашивает уже за 30й бит и так далее, до нулевого. В итоге, у него получается серийник одного из устройств.
Здорово!
Только почему Вы начинаете сканировать именно с MSB (31 бита). Не лучще ли начинать сканирование с LSB?
Имеет смысл расширять маску от младших битов, ибо младшие единичные биты точно есть у всех адресов, а вот старших единичных битов может и не быть.
Да и серийник может быть не 32 бита, а 64 бита.
Я забыл об одном важном нюансе. В пункте два, у кого были нули в запрошенных битах и при этом на шине проскакивал ответ на запрос мастера, прекращали отвечать на запросы следующих битов до следующего пакета из 1 пункта. Таким образом, опрашивая со старших битов, из процесса извлечения очередного серийника устройства выбывают крупные группы устройств.
То есть, имеем три устройства со следующими серийниками (пусть серийники будут 4-битными для упрощения)
А - 0110
В - 1001
С - 1111
На запрос 3 бита ответят устройства В и С, а устройство А, услышав этот ответ, замолкает до следующего пакета "есть ли кто неадресованный?"
На запрос второго бита ответит устройство С, а устройство В замолкнет.
На запрос первого и нулевого битов ответит только устройство С.
Таким образом у мастера получится серийник устройства С. Он назначит ему адрес и оно перестанет участвовать в сканировании.
При очередном запросе неадресованных устройств, устройства А и В выйдут из режима молчания.
На запрос 3 бита ответит устройство В, а устройство А, услышав ответ В, замолкнет.
При запросе 2 бита, оба устройства не ответят, но при этом устройство В, не услышав ответа продолжит отвечать на последующие запросы. То же самое будет и при запросе 1 бита и мастер запишет у себя два нуля. И уже на запрос нулевого бита, устройство В ответит. Так у мастера сформируется серийник устройства В.
При последующих итерациях отвечать будет только устройство А.
Идея эта была не нова и честно была украдена у протокола 1-Wire
Делали такое сканирование. Но шина у нас была не RS485, а некое подобие LIN. Задача стояла быстро раздать адреса кучке устройств и поддержка их горячей замены. У каждого устройства был свой серийный номер. Он же служил и в качестве MAC адреса на этапе сканирования. Сами же рабочие адреса были размером в один байт. Команды делились на широковещательные и адресованные. Из широковещательных были команды сброса адресов, запрос на наличие неадресованных устройств, запрос с маской серийника (по сути, это запрос с номером интересующего бита в серийнике). Из адресованных только назначение адреса устройству. Протокол позволял назначить адрес устройству и без процедур поиска, при условии, что его серийник известен.
Сканирование шины RS485