В статье речь пойдет об одном из видов соединений на 1 уровне обеспечения связи, то есть на физическом, о интерфейсе используемом для промышленных устройств, а именно о RS-485. RS-485 используется скажем для MODBUS или ProfiBUS.
Расскажу о принципах работы, о реализации соединения и само собой об особенностях при эксплуатации. Начнем.
Принцип передачи данных RS-485
Интерфейс RS-485 является продолжением RS-232 и это значит, что его можно "вешать" на банальный USART любого микроконтроллера.
При этом физически он состоит из двух линий связи. А и B. Наличие земли желательно, но вовсе не обязательно. Отсутствие земли чаще всего чревато тем, что входящие данные будут иногда начинаться с нуля. Т.е. шлешь строку 0xBA 0xDF 0xF0 0x0D, а приходит 0х00 0xBA 0xDF 0xF0 0x0D, а дальше все нормально.
Так вот, первоначальный исходный входной сигнал дублируется зеркально, потом разделяется и эти два сигнала отправляются в путь по витой паре.
В итоге по линии А идет прямой UART, как он есть, а по линии В его "отражение". В ресивере один из сигналов переворачивается до состояния второго, однако здесь переворачиваются и помехи, вместе с ним. Далее они суммируются, и получается так, что помехи "съели" сами себя. Единственное уровень сигнала становится выше в 2 раза. Это чем-то напоминает балансное подключение
В общем здесь сразу два плюса, избавляемся от помех и второе, падение сигнала связанное с сопротивлением линии может быть вновь восстановлено, так как сигнал увеличивается в два раза.
По такому же принципу, дифференциальной линии, делают очень многие критичные к помехам цепи. USB, Ethernet, LVDS да много где… где-то линия одна, как в USB, где то их несколько, как в Ethernet или LVDS. Но суть остается той же.
Естественно по данной линии связи передача может идти только в одну сторону. Т.е. RS485 у нас полудуплексный. Мы вначале в него орем, а потом слушаем что нам ответили с другой стороны. Общаться в обе стороны, как в UART по Rx и Tx не выйдет. Ну или придется пускать уже четыре провода, одна для передачи, другая для приема.
В обычно в трансивере 485 интерфейса передатчик и приемник в одном корпусе, на одной линии, а направление выбирается ногой, уровень на которой определяет в каком режиме микросхема в приеме или в передаче.
На одной линии может висеть несколько приемников и передатчиков. Они подключаются просто параллельно.
Разумеется общаться они могут строго по одному и общий галдеж в линии приведет к полной неработоспособности всей сети. Никакого аппаратного арбитража на основе «приоритета нуля», как в I2C тут нет.
Способы разрешения конфликтов тут исключительно программно-логические. Например, все участники договариваются, что общаются по очереди и каждый после передачи выдает спец сообщение, говорящее о том, кто следующий имеет право сообщить в линию, как микрофон передают в зале по кругу. Если принявшему свой номер сказать нечего, то он обязан передать хотя бы служебное сообщение о том, что теперь может говорить следующий.
Когда передатчик один, а остальные приемники, как часто бывает у меня, то вначале шлем адрес, все его принимают и только тот кому адресовано это сообщение его обрабатывает, остальные же отправляют его в никуда. Короче, способов много и все это давно изобретено.
Используемые элементы для RS-485
Классической микросхемой такого интерфейса служит MAX485 или ST485, или ADM485… В общем, если видите на плате микросхему в 8 ног, с надписью что-то там 485, то скорее всего это оно и есть.
Она подключается к USART микроконтроллера и еще нужна одна нога, чтобы указывать направление обмена. Прием у нас или передача.
Кроме микросхемы конвертера, содержащей в себе два компаратора-усилителя, нужные еще два резистора подтяжки и один терминатор, они задают первоначальное смещение линии и подавляют отражение.
Разберемся сначала с резистором-терминатором.
Сигнал идет по проводу быстро, но не мгновенно, более того, он дойдя до конца линии может отразиться и пойти обратно. Как вода в желобе, пускаешь по желобу волну, волна дошла до стенки и пошла обратно. И эта волна может столкнуться с волной следующего импульса, смешаться и получить полную кашу на выходе. Разумеется эти эффекты возникают только при длинных линиях (В ТОЭ прям есть раздел такой — длинные линии, разбирающий все эти волновые эффекты), либо на высоких частотах. Так как с ростом частоты «длинной» может стать линия даже в 5см, например, когда речь идет о гигагерцах.
Поскольку у нас RS485 может работать до скорости вплоть до 10Мбит, а дальность свыше километра, то такие эффекты могут возникнуть. Чтобы подавить отраженную волну и нужен резистор-терминатор. Он стоит у приемника между линиями А и В. Его сопротивление обычно 120ом. Это не спроста так, все дело в том, что волновое сопротивление витой пары, как правило, 120 ом и чтобы погасить волну резистор должен быть с ней согласован.
Но если у вас скорость 9600, а дальность десяток метров, то на это можно смело забить. В этом случае терминатор может даже мешать, излишне нагружая линию низкоомным сопротивлением. Но я все равно всегда развожу его и если не нужно, то просто не впаиваю.
Теперь о подтяжках. Они, как бы, опциональные, будет работать и без них, но лучше их поставить. Хотя бы на первом и последнем устройстве линии. Чтобы линию не телепало помехами и не генерировало вам непонятные сообщения. Подтяжка защитит нас от хаотичных данных при обрыве линии, например.
Конечно у приемника есть гистерезис, примерно на 200мв, т.е. разность между А и В меньше 200мВ не учитывается как сигнал, и на выходе будет 1, но все равно лучше подстраховаться.
Линию А подтягиваем вверх, а линию В вниз. Через резисторы в 1.2кОм с обеих концов.
Единственно, что у такого решения есть минус — через эти резисторы будет всегда течь ток и увеличивать потребление. Что может быть критичным для систем с батарейным питанием, но использующем RS485. Странная экзотика, но чего в жизни не бывает?
В этом случае можно использовать микросхемы с системой true failsafe, например MAX3080. Она позволяет отказаться от резисторов смещения, т.к. они мало того, что встроены в микросхему, так еще и пороги срабатывания там другие. И при обрыве или КЗ линии будут гарантировано давать 1 на выходе.
Работа с помехами RS-485
Так как линия у нас длинная, то на нее наводится всякая фигня. И естественно она прилетает нам в схему, учиняя беспредел. Первое с чем стоить бороться — перенапряжения. Для защиты от этого применяют супрессоры. Это такие мощные стабилитроны, часто собранные в одном корпусе встречно друг другу. И при превышении напряжения они открываются и стравливают перенапряжение в землю или питание, смотря как включено. А там с этой энергией разберутся конденсаторы и блок питания.
Разумеется поможет это только от кратких перенапряжений, от помех. От длительных перенапряжений нужны уже предохранители. Плавкие или самовосстанавливающиеся. Т.е. если что-то начало нам гнать в линию высокое напряжение, то вначале сработает супрессор, высадив его на землю, а потом сгорит предохранитель. Используем SMBJ-5.0 супрессоры.
Также ставим варистор между А и В. Можно и двунаправленный супрессор поставить, но варистор компактней. Это резистор который пробивается на высоком напряжении. Резко уменьшая свое сопротивление с МОм до десяток Ом. А потом вновь становится обрывом. У меня под это дело что-то вроде JMV0805S5R6T661 который открывается от 5.6 вольт и способен пережить 40А в пике.
Последнее время я не экономлю и делаю полноценную развязку интерфейсной части. Ставя туда питание на AM1D-0505SZ и изолируя интерфейс через ADM2483. Это RS485 трансивер со встроенной опторазвязкой.
Работает!
Линия связи для RS-485
Вообще, на короткие расстояния, десятки метров, и при небольшой скорости, по 485 интерфейсу можно гнать сигнал через любое говно. Даже через старую, советскую плоскую телефонную лапшу. На практике же, для физического уровня приходится использовать все что под руку попадается и уже проложено на объекте. Например, кабель видеонаблюдения, с волновым сопротивлением в 75 Ом, но ему требуются низкоомные же терминаторы в 75 Ом, что снижает количество девайсов на одном сегменте — трансивер просто не вытащит по току. Второй популярный пример — витая пара, у ней волновое сопротивление 100Ом, что уже лучше. И сами кабели дешевые, но у них тонкая жила и по этому высокое сопротивление. Есть и специализированный кабель для RS485 с волновым сопротивлением в 120Ом, как по стандарту. Правда он дорогой, не всегда доступен и зачастую не нужен :)
Для улучшения качества передачи данных хорошо бы использовать экранированный провод. При этом оплетка кабеля подключается к заземлению, а к GND через резистор ом в сто (в случае опторазвязки — к изолированной GND) с одной стороны, только с одной стороны! Чтобы не было протекания разных токов по ней.
Если же у нас есть земляной провод, то можно задействовать и его. В данном случае его называют дренажным. Его задача уравнивать потенциалы земель. И он подключается к земле устройства (при опторазвязке к изолированной земле) через сопротивление в сотню ом. Резистор тут надо выбирать хотя бы на пол ватта.
Возможные траблы RS-485
Ну и напоследок еще парочка мелких граблей на которые можно наступить, так что лучше их сразу убрать. В момент передачи, микросхема MAX485 держит выход DO в HiZ, и вам туда может набрать разного "мусора". Поэтому линию RxD микроконтроллера подтягиваем к питанию. Либо включаем подтяжку внутри контроллера. Но я всегда это делаю внешним резистором. Надежней.
А линию DE/RE следует подтягивать к нулю. Зачем? А чтобы пока контроллер не стартанул, не проинициализировался и не привел свои ноги в нужный режим этот вывод не телепался без дела и не слал в линию разный мусор.
При перед передачей никогда не помешает сделать синхронизацию кадров. Т.е. передачи нет, все участники сети сидят и слушают. И вдруг какая-то помеха пробилась и сделал старт бит в линию. Естественно все «слушатели» начнут принимать данные и получат мусор. Да хоть тот самый ноль, о котором я выше говорил. Чтобы им и ограничилось крайне желательно сделать следующее. Переводим линию прием/передача в режим передачи, при этом у нас на TxD единичка, т.к. мы еще ничего не шлем. Но драйвер RS485 при этом выдаст уже уровни в линию. Ждем паузу, равную времени передачи двух трех байтов, чтобы весь мусор прошел и не затесался в нашу передачу и только после этого засылаем первый байт нашей передачи в UART. Это повышает надежность и качество передачи на порядок.