Сеть посредством RS485

Тема в разделе "Проводная и беспроводная связь", создана пользователем DrProg, 4 фев 2016.

  1. DrProg

    DrProg Вечный нерд

    Создаю протокол обмена данными между устройствами при помощи RS485. Принцип стандартный: один мастер, дает слово ведомым по очереди, одновременно посылая им команды. Ведомые получив право голоса отвечают мастеру своим состоянием и так по кругу. Дополнительно ведомые в момент своего спича должны уметь отправлять сообщение еще одному - двум ведомым устройствам.

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

    Вот пара картинок. Верхняя строка - мастер, вторая и третья - ведомые. В идеале должно быть так: на каждую команду ведущего поочередно срабатывает первый и второй ведомый. Пропуски это ошибки.
    Скорость 2400 показывает улыбку пьяного забулдыги:
    [​IMG]
    При 9600 не считая пары пробелов все хорошо:
    [​IMG]
    В остальном код тот же самый, разве что корректировался тайминг ведущего (чтобы ответы вписывались в отведенные для этого промежутки).

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

    Onkel Гуру

    не отношу себя к знатокам, но можно я?
    подтяжки и терминаторы нужны, иначе будут проскакивать нули.
    из рисунка не совсем понятно, где же сбой. я бы рекомендовал оттестить для начала 1:1. У меня через катушку провода (305 м) в тестах по 10^^8 байт ни одной ошибки обнаружено не было, посылки по 8 байт, 9600 и 38к.
    Прием данных по прерываниям или в теле цикла?
     
    DrProg нравится это.
  3. DrProg

    DrProg Вечный нерд

    Сбой там где ведущие не отвечают мастеру, на второй картинке видно всего два случая. Что значит оттестить 1:1?
    Грешу на отсутсвие подтяжек, больше вроде бы не на что, вот так сделать?
    [​IMG]

    Опрос в цикле, в тестовом варианте кроме связи больше ничего не происходит
     
  4. Onkel

    Onkel Гуру

    происходит. вроде прерывание по таймеру 0 происходят все время, это таймер отсчитывает мс.
    Подтяжка правильно, посмотрите , нет ли в дивайсах 1 и 2 терминатора 120 Ом - они должны быть только в конце и в начале.
     
    DrProg нравится это.
  5. Onkel

    Onkel Гуру

    сначала отладить на 1 мастер 1 слейв
     
  6. DrProg

    DrProg Вечный нерд

    Да вот знать бы что там есть в этом девайсе. Вот такой у меня как справа. Даташит нашел пока только на MAX485, но это не совсем то что надо. На схемах рисуют то подтяжку 20КОм к земле и +5 соответственно, то 470Ом. То есть, насколько я понял, надо на концах заглушить А и В резистором 120Ом, и где нибудь притянуть в произвольном месте к GND и +5V. А вот вдруг все это уже есть в модулях? Прозвонить попробовать что ли?

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

    Вообще, для целей зафиксировать изменения, которые происходят раз в полчаса-час уже более чем достаточно и в таком виде, ну поступит информация позже на 0,02 сек, никто не пострадает. Но случись применить на чем то более требовательном к скорости и начнутся проблемы. Лучше бы их решить заранее. И опять же перфекционизм душит. )
     
  7. Onkel

    Onkel Гуру

    для перфекционизма хорош терминал , я юзаю Hterm, включаю на сутки, потом сохраняю файл (можно сохранить с time stamps) и анализирую в ворде или экзеле макросом.
    В подтяжке я применяю по 1 кОм. В 485 шилдах уже впаян (по крайней мере у меня, можно его видеть в "что я сделал") 120 Ом, так что если этот шилд не в начале/конце - его лучше выпаять. Ну и прием байтов в uart через 485 лучше вести через прерывания с буфером на пару -тройку пакетов.
     
    DrProg и Alex19 нравится это.
  8. Alex19

    Alex19 Гуру

    Спасибо за информацию о правильном подключении, как-то соединил 1 раз по мануалу в сети, все работает и забыл.

    Правда у меня и сеть была простая 1 к 1, всего 200 метров на 115200. Ни каких проблем не замечал, но я изначально делал на прерываниях (только в конце, убрал таймер T2, перешел на micros()). Пришлось лишь подобрать временной интервал, после отправки последнего байта.

    Для моих целей мне понравились, кроме проблем с пайкой на некоторых экземпляров (иногда пины R.. или D.. объедены:)), с другими проблемами не сталкивался. Работаю как часы 1 на 1 расстояние 200 метров, скорость 115200.

    Если не сложно, можно пояснить, какая разница 1 к 1 или 1 к 32?

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

    Не понятна разница, у Вас в пакете есть id получателя, который должен дать ответ.
    Может требуется, что-то еще и я чего-то не знаю?
    Все таки опыта не было.
     
    Последнее редактирование: 5 фев 2016
    DrProg нравится это.
  9. DrProg

    DrProg Вечный нерд

    У меня так. Мастер отправляет пакет всего из 4 байтов. Первый стартовый, последний стоповый, второй с адресом девайса, третий с командой. Отправляет пакеты через millis() каждые, допустим, 20мс (подбирается в зависимости от скорости и тп). Пакет ушел, переходим в режим ожидания и чтения линии. Девайсы же большую часть времени проводят в прослушке линии. Получаемые ими байты складывают в массив длиной 4 байта в режиме "очередь", который постоянно проверятся ее на наличие стартового и стопового бита, а так же собственного адреса. Если все это присутствует, значит команда наша, выполняем ее и рапортуем в центр. Заодно можем под шумок передать еще один пакет другому слейву. Слевы отличают пакет мастера от пакета другого слейва по команде, для этого используются некоторые биты. Мастер получает отчет, игнорируя чужие письма, и переходит обратно в режим сканирования. Ждет заданную паузу, пинает следующий слейв и так по кругу. В принципе все работает как и задумано. Команды выполняются, ответы приходят, межслейвовые сообщения принимаются.

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

    Увеличил скорость, на глаз замечать перестал, что объяснимо, пакеты поперли плотнее, разбег сократился. Анализатор показал, что и пропусков с ростом скорости становится меньше. Почему? Не совсем понятен глубинный смысл изменений. Так же не понятна причина пропусков, то ли программная, то ли аппаратная.

    Думаю попробовать по примеру Алекса раскачать до 115200 и посмотреть что будет.

    PS: вот что я имею ввиду под пропусками, слейвы не замечают пакет адресованный им и ничего не делают (верхний мастер, ниже два слейва с разными задачами, скорость 2400):
    [​IMG]

    PPS: при скорости 19200 и выше, пропуски пропадают полностью:
    [​IMG]
     
    Последнее редактирование: 5 фев 2016
  10. DrProg

    DrProg Вечный нерд

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

    Модули прозвонил, между линиями никакой связи в них не нашел, подтяжек тоже. Скорее всего их там нет, оставили это на усмотрение конечного пользователя.
     
    Последнее редактирование: 5 фев 2016
  11. Onkel

    Onkel Гуру

    может дело в управлении ногами DE/!RE, не переключаются ли они раньше времени на прием? С анализатором можно просмотреть корелляцию неответа с несвоевременным переключением.
    можно еще так посмотреть - сделать, чтобы слейвы тупо повторяли полученные байты, тогда будет видно где потеря , не забываем отключать чтобы они отвечали не хором. Кстати странно если 1:1 все работало - откуда глюки при работе 1:2/3?
     
    Последнее редактирование: 5 фев 2016
  12. DrProg

    DrProg Вечный нерд

    Не должны они раньше времени переключаться, пока пакет полностью не получен и не опознан никаких переключений не происходит. Анализатором видно, что ответка начинается чуть позже запроса. Даже делал небольшую задержку чтобы развести эти процессы, разницы никакой. Да и пропадают сигналы без системы, одно и то же по кругу крутится, то есть сигнал то нет, никакой зависимости успеха или неудачи поймать не м
     
    Последнее редактирование: 5 фев 2016
  13. Onkel

    Onkel Гуру

    стохастика. Такого рода проблемы решаются методом деления пополам. Я бы для начала перешил слейвы так, чтобы они отвечали то, что получили, это даст ответ на вопрос "правильно ли читают слейвы данные от мастера".
     
  14. DrProg

    DrProg Вечный нерд

    Они читают правильно, кроме пропусков, иначе бы вообще не откликались не не выполняли бы команды.
     
  15. Onkel

    Onkel Гуру

    ключевое слово тут "кроме пропусков". Вот я и предлагаю разобраться, что же происходит при пропусках. Тут два варианта - не считывает правильно и не отвечает.
     
  16. DrProg

    DrProg Вечный нерд

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

    Onkel Гуру

    "почти уверен" надо подтвердить экспериментом.
    не странно, если предположить что при низких скоростях не успевает считать (или послать) и хвост посылки откусывается.
     
  18. DrProg

    DrProg Вечный нерд

    Поэксперементирую сегодня вечером и на выходных. Какие еще попробовать способы кроме отзеркаливания сообщений? Судя по тому что показывает анализатор, посылки не откусываются, там полно времени на передачу и прием (первая картинка). Кроме того, наблюдаю за линией на терминале через RS458-USB, пакеты от мастера выглядят хоть кракозяблами, но одинаково. Что бы еще попробовать?
     
  19. Onkel

    Onkel Гуру

    а вы смотрите в режиме hex, и будут не кракозябры, а цифирки.
    Ну и в таком случае надо смотреть, что в слейве- фиксить Тх и Rx вкупе с cигналом управления чипом 485.
     
  20. Alex19

    Alex19 Гуру

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

    А вот сама реализация, как я понял различается.
    У Вас вероятно используется библиотека Serial, которая получает и отправляет данные в цикле.

    Вот эту фразу не совсем понял.
    Мастер всегда получает ответ или нет?
    И как он переключается из режима прослушки в режим отправки, по получению ответа и/или по паузе.

    Моя реализация сделана немного иначе, она не лучше и не хуже Вашей, она специфична для конкретной задачи. Вкратце опишу ее и приведу ссылку на код (пусть не последней версии, но сам принцип там одинаков, просто без дополнений и оптимизации).
    1. Есть кольцевой буфер TX на отправку/прием данных.
    Для отправки данных используем прерывание UART по опустошению буфера. При отправке переводим модуль в режим передатчика.
    Код (C++):
    ISR(USART_UDRE_vect)
     
    2. Только на мастере, после того как отправка завершена, срабатывает прерывание по завершению отправки
    Код (C++):
    ISR(USART_TX_vect)
    Там происходит переход работы модуля RS485 из передатчика в приемник.

    На слейве в примере немного иначе, но можно и нужно добиться одинакового поведения. Cлейв использовал таймер T2, после перешел на micros(), тогда не разбирался, что да почему (мастер был на Mega 2560, слейв на Nano).
    3. Для получения данных используется еще 1 кольцевой буфер RX и прерывание по получению байта.
    Код (C++):
    ISR(USART_RX_vect)
    4. В цикле loop полученные данные переносятся из буфера RX, в буфер который используется для перевода пакета в структуру.

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

    Увы всего не помню, лучше гляньте код - http://forum.amperka.ru/threads/Реализация-uart-rs-485.6791/.
     
    Последнее редактирование: 5 фев 2016
    DrProg нравится это.