Модуль Arduino RS-485

Arduino RS-485: Подключение, описание и примеры с кодами

Интерфейс 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. Это

Модуль Arduino RS-485

Модуль TTL to RS-485
Преобразователь логики Arduino в RS-485

Схема соединения двух Arduino UNO

Схема подключения RS-485 к RS-485
Подключение Arduino к Arduino через RS-485
Подключение Arduino к Arduino через RS-485

Код программы для 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. Функциональные возможности которых идентичны, назначения выводов совершенно одинаковые.

Микросхемы представлены в SOIC-8 и DIP-8 корпусах
Микросхемы представлены в SOIC-8 и DIP-8 корпусах.

Защита от помех

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

Заключение

Интерфейс 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