Интерфейс RS-485
RS-485 является одним из наиболее распространенных интерфейсов передачи данных.
Для передачи сигнала используется всего два провода. Обычно применяется витая пара UTP, но можно использовать и простой кабель. Ну, а связка Arduino и RS-485 открывает большие возможности в различных DIY проектах.
Интересные факты о RS-485
Максимальная длина линии интерфейса RS-485 составляет 1200 метров и подключить к одному кабелю можно до 32 устройств. Предком интерфейса RS-485 является RS-232.
Преимущество связки Arduino RS-485
- Длина линии связи, которая может достигать 1200 метров.
- Подключение к одной линии до 32 устройств.
- Помехоустойчивость.
- Простота реализации.
- Любая Arduino может быть ведущим или ведомым устройством.
Недостатки RS-485
- Скорость уменьшается с увеличением длины провода.
- Полудуплексный режим, то есть прием и передача производится по одной паре проводов.
RS-485 на практике
При передачи данных на расстояние от 500 метров потребуется экранированный UTP кабель. Скорость может снизиться до 50 Кбит/с, но этого вполне достаточно для передачи показаний с датчиков.
Схема подключения Arduino по RS-485
Для подключения плат Arduino по интерфейсу RS-485 потребуется конвертирующий модуль на базе MAX485. Это

Модуль TTL to RS-485
Преобразователь логики Arduino в RS-485
Схема соединения двух Arduino UNO


Код программы для Arduino RS-485
Программа для одностороннего приема и передачи
Напомним, что в один момент времени устройство может либо принимать, либо отправлять данные. Для указания устройства в качестве приемника или передатчика на модулях присутствуют контакты DE и RE. Высокий уровень на контактах — режим передатчика, низкий — приёмника.
Программа для передатчика — Она будет отправлять в Serial Port строку «test» один раз в секунду.
Программа для приемника — При появлении в эфире строки «test» будет мигать светодиодом на плате Arduino (13 пин).
Код программы приемника
#define SerialTxControl 2 // Пин 2 будет переключать режим приёмник/передатчик
#define RS485Transmit HIGH
#define RS485Receive LOW
void setup(void) {
Serial.begin(9600); // задаем скорость последовательного порта
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Transmit); // переводим устройство в режим передатчика
}
void loop(void) {
Serial.print("test"); // отправляем текст
delay(1000); // Выставляем задержку в 1 секунду
}
Код программы передатчика
#define SerialTxControl 2 // Пин 2 будет переключать режим приёмник/передатчик
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100]; // Переменная для хранения данных из буфера
byte state = 0;
void setup(void) {
Serial.begin(9600); // задаем скорость последовательного порта
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive); // переводим устройство в режим приёмника
}
void loop(void) {
int i=0;
if( Serial.available() ){ // если в порт пришли какие-то данные
delay(5); // немного ждём, чтобы вся пачка данных была принята портом
while( Serial.available() ){
buffer[i++] = Serial.read(); // считываем данные и записываем их в буфер
}
}
if(i>0){ // если в буфере что-то есть
buffer[i++]='#define SerialTxControl 2 // Пин 2 будет переключать режим приёмник/передатчик
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100]; // Переменная для хранения данных из буфера
byte state = 0;
void setup(void) {
Serial.begin(9600); // задаем скорость последовательного порта
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive); // переводим устройство в режим приёмника
}
void loop(void) {
int i=0;
if( Serial.available() ){ // если в порт пришли какие-то данные
delay(5); // немного ждём, чтобы вся пачка данных была принята портом
while( Serial.available() ){
buffer[i++] = Serial.read(); // считываем данные и записываем их в буфер
}
}
if(i>0){ // если в буфере что-то есть
buffer[i++]='\0'; // превращаем содержимое буфера в строку, добавляя нулевой символ
if( strcmp(buffer, "test") ){ // если принятая строка равна тексту ping
digitalWrite(13, state); // мигаем светодиодом
state = !state;
}
}
}'; // превращаем содержимое буфера в строку, добавляя нулевой символ
if( strcmp(buffer, "test") ){ // если принятая строка равна тексту ping
digitalWrite(13, state); // мигаем светодиодом
state = !state;
}
}
}
Программа для двухстороннего приема и передачи данных
Код программы для первой платы Arduino
Теперь платы Arduino буду менять режим приемника/передатчика в момент отправки сообщения.
#define SerialTxControl 2
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100];
byte state = 0;
void setup(void) {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive);
}
void loop(void) {
int i=0;
if( Serial.available() ){
delay(5);
while( Serial.available() ){
buffer[i++] = Serial.read();
}
if(i>0){
buffer[i++]='#define SerialTxControl 2
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100];
byte state = 0;
void setup(void) {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive);
}
void loop(void) {
int i=0;
if( Serial.available() ){
delay(5);
while( Serial.available() ){
buffer[i++] = Serial.read();
}
if(i>0){
buffer[i++]='#define SerialTxControl 2
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100];
byte state = 0;
void setup(void) {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive);
}
void loop(void) {
int i=0;
if( Serial.available() ){
delay(5);
while( Serial.available() ){
buffer[i++] = Serial.read();
}
if(i>0){
buffer[i++]='\0';
if( !strcmp(buffer, "ping") ){
digitalWrite(13, state);
state = !state;
digitalWrite(SerialTxControl, RS485Transmit);
Serial.print("pong");
delay(10);
digitalWrite(SerialTxControl, RS485Receive);
}
}
}
}';
if( !strcmp(buffer, "ping") ){
digitalWrite(13, state);
state = !state;
digitalWrite(SerialTxControl, RS485Transmit);
Serial.print("pong");
delay(10);
digitalWrite(SerialTxControl, RS485Receive);
}
}
}
}';
if( !strcmp(buffer, "ping") ){
digitalWrite(13, state);
state = !state;
digitalWrite(SerialTxControl, RS485Transmit);
Serial.print("pong");
delay(10);
digitalWrite(SerialTxControl, RS485Receive);
}
}
}
}
Код программы для второй платы Arduino
#define SerialTxControl 2
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100];
byte state = 0;
void setup(void) {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive);
}
void loop(void) {
int i=0;
if( Serial.available() ){
delay(5);
while( Serial.available() ){
buffer[i++] = Serial.read();
}
if(i>0){
buffer[i++]='#define SerialTxControl 2
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100];
byte state = 0;
void setup(void) {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive);
}
void loop(void) {
int i=0;
if( Serial.available() ){
delay(5);
while( Serial.available() ){
buffer[i++] = Serial.read();
}
if(i>0){
buffer[i++]='#define SerialTxControl 2
#define RS485Transmit HIGH
#define RS485Receive LOW
char buffer[100];
byte state = 0;
void setup(void) {
Serial.begin(115200);
pinMode(13, OUTPUT);
pinMode(SerialTxControl, OUTPUT);
digitalWrite(SerialTxControl, RS485Receive);
}
void loop(void) {
int i=0;
if( Serial.available() ){
delay(5);
while( Serial.available() ){
buffer[i++] = Serial.read();
}
if(i>0){
buffer[i++]='\0';
if( !strcmp(buffer, "ping") ){
digitalWrite(13, state);
state = !state;
digitalWrite(SerialTxControl, RS485Transmit);
Serial.print("pong");
delay(10);
digitalWrite(SerialTxControl, RS485Receive);
}
}
}
}';
if( !strcmp(buffer, "ping") ){
digitalWrite(13, state);
state = !state;
digitalWrite(SerialTxControl, RS485Transmit);
Serial.print("pong");
delay(10);
digitalWrite(SerialTxControl, RS485Receive);
}
}
}
}';
if( !strcmp(buffer, "ping") ){
digitalWrite(13, state);
state = !state;
digitalWrite(SerialTxControl, RS485Transmit);
Serial.print("pong");
delay(10);
digitalWrite(SerialTxControl, RS485Receive);
}
}
}
}
Разновидности микросхем RS-485
Существуют различные микросхемы RS-485 — MAX485, ADM485, SP485, SN75176. Функциональные возможности которых идентичны, назначения выводов совершенно одинаковые.

Защита от помех
- Снижение скорости передачи данных повышает помехоустойчивость. Не устанавливайте скорость большую, чем требуется для нормального функционирования системы.
- Не прокладывайте сигнальный кабель вместе или вблизи силовых кабелей.
- В промышленных зонах рекомендуется применять экранированную витую пару с последующем заземлением экрана.
- Использование индуктивных фильтров для избавления системы от высокочастотных помех.
Заключение
Интерфейс RS-485 применяется в промышленных системах из-за устойчивости к помехам и возможностью передавать данные на большие расстояния.
Но этот интерфейс нашел применение в домашних системах Умного дома и проектах Arduino по тем же причинам.
RS-485 широко используется с протоколами ModBus и DMX512.
* ModBus — открытый коммуникационный протокол.
* DMX512 — протокол передачи данных между контроллерами и световым оборудованием.
Ссылки
Wikipedia: https://ru.wikipedia.org/wiki/RS-485
Datasheet MAX485: https://datasheets.maximintegrated.com/en/ds/MAX1487-MAX491.pdf