Не работает связь по rs485

Алексей Н
Offline
Зарегистрирован: 02.01.2016

Добрый день, участники форума!

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

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

Следующим шагом хочу добавить возможность связи по rs485. Для первых шагов хочу подключить просто к компьютеру, послать простое сообщение и посмотреть, как это работает. Использую самые распространенные и дешевые конвертер TTL-RS485 и переходник с USB на RS485. Не уверен надо ли изображение этих модулей (маркировки на них нет).

Ардуино - китайский клон Про микро, который определяется как Леонардо. R0 модуля подключен на RX ардуины (0 пин), DI на TX ардуины (1 пин), DE и RE соединены. В коде, соответственно, использую "хардваррный" сериал порт. Связь rs485 по двум КСПВ проводам длиной 15 см (отлаживаю просто на столе).

На компьютере для мониторинга порта использую программу Putty. В ней вроде минимум настроек: номер порта и скорость.

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

То ли отправляю неправильно, то ли принимаю неправильно. То ли вообще все делаю неправильно. Из подозрительного: диод TX на ардуине не мигает, хотя, по идее, должен мигать при отправке сообщений.

Собственно простыня кода приведена ниже. Код отправки сообщений, с которым не могу справиться, в строках 80-84 и 109-113.

Буду благодарен за помощь и пинки в нужном направлении.

/*
  Скетч для управления шторами
  ============================
  При нажатии на кнопку, шторы отрываются/закрываются. Если во
  время открытия/закрытия нажать на любую кнопку шторы останавливаются.
  Для изменения направления движения используется электромагнитное реле.
  Для подачи напряжения на дигатель используется твердотельное реле.
  Через модуль rs484 осуществляется обратная связь с Распберри.
*/

// Определяем пины для подключенных кнопок:
#define BUTTON_PIN_1 2
#define BUTTON_PIN_2 3

// Определяем пин для переключения модуля в режим передачи:
#define ENABLE_RS485_PIN 6

// Определяем пины для переключения реле на открытие/закрытие:
#define PIN_OPEN_CLOSE 14

// Определяем пины для подачи напряжения на дигатель:
#define PIN_START_STOP 15

// контакт 6 будет переключать режим приёмник/передатчик
#define SerialTxControl 6
#define RS485Transmit HIGH
#define RS485Receive LOW

// Тут вписываем переменные – это меняющиеся значения:
int button1State = 0;         // текущее состояние первой кнопки
int lastButton1State = 0;     // предыдущее состояние первой кнопки
int button2State = 0;         // текущее состояние второй кнопки
int lastButton2State = 0;     // предыдущее состояние второй кнопки

// Флаг движения штор
int action_flag = 0;

// Массивы для приема и передачи по rs485. 1 - ID данного модуля
byte bufOpen[2] = {1, 1};
byte bufClose[2] = {1, 0};
byte recivebuf[2];

// Переменная для хранения точки отсчета таймера
unsigned long timing;

void setup() {
  // инициализируем контакт для кнопки как входной контакт:
  pinMode( BUTTON_PIN_1, INPUT_PULLUP );
  pinMode( BUTTON_PIN_2, INPUT_PULLUP );
  // инициализируем контакты для управления реле как выходные контакты:
  pinMode( PIN_OPEN_CLOSE, OUTPUT );
  digitalWrite( PIN_OPEN_CLOSE, LOW );
  pinMode( PIN_START_STOP, OUTPUT );
  digitalWrite( PIN_START_STOP, LOW );


  Serial.begin(9600);            // Запуск последовательного соединения на скорости 9600:
  pinMode( ENABLE_RS485_PIN, OUTPUT ); // Устанавливаем состояние управляющего пина
  digitalWrite( ENABLE_RS485_PIN, LOW ); // в низкое значение для приема
}


void loop() {
  // считываем данные с входного «кнопочного» контакта:
  button1State = digitalRead( BUTTON_PIN_1 );
  button2State = digitalRead( BUTTON_PIN_2 );

  // сравниваем текущее состояние (button1State) с предыдущим:
  if ( button1State != lastButton1State ) {
    if ( button1State == LOW ) {
      // Если нажата кнопка "открыть" и движения нет
      if ( action_flag == 0 ) {
        // Переключаем реле на открытие
        digitalWrite( PIN_OPEN_CLOSE, HIGH );
        // Подаем напряжение
        delay ( 10 );
        digitalWrite( PIN_START_STOP, HIGH );
        timing = millis();
        action_flag = 1;
        // Отправить сообщение по rs485
        digitalWrite( ENABLE_RS485_PIN, HIGH );
        Serial.write( bufOpen, 2 );
        Serial.flush();
        digitalWrite( ENABLE_RS485_PIN, LOW );
      }
      // Если нажата кнопка "открыть" и движение есть
      else {
        //Остановить движение
        digitalWrite( PIN_OPEN_CLOSE, LOW );
        digitalWrite( PIN_START_STOP, LOW );
        action_flag = 0;
      }
    }
    delay ( 300 );
  }

  // сравниваем текущее состояние (button2State) с предыдущим:
  if ( button2State != lastButton2State ) {
    if (button2State == LOW) {
      // Если нажата кнопка "закрыть" и движения нет
      if ( action_flag == 0 ) {
        // Переключаем реле на закрытие
        digitalWrite( PIN_OPEN_CLOSE, LOW );
        delay ( 10 );
        // Подаем напряжение
        digitalWrite( PIN_START_STOP, HIGH );
        timing = millis();
        action_flag = 1;
        // Отправить сообщение по rs485
        digitalWrite( ENABLE_RS485_PIN, HIGH );
        Serial.write( bufClose, 2 );
        Serial.flush();
        digitalWrite( ENABLE_RS485_PIN, LOW );
      }
      // Если нажата кнопка "закрыть" и движение есть
      else {
        //Остановить движение
        digitalWrite( PIN_OPEN_CLOSE, LOW );
        digitalWrite( PIN_START_STOP, LOW );
        action_flag = 0;
      }
    }
    delay (300);
  }

  // для прогона через следующий цикл
  // делаем текущее состояние предыдущим
  lastButton1State = button1State;
  lastButton2State = button2State;

  // Если флаг движения установлен, отсчитываем время до отключения реле
  if ( action_flag == 1 ) {
    if ( millis() - timing > 10000 ) { // Вместо 10000 подставьте нужное вам значение паузы
      digitalWrite( PIN_START_STOP, LOW );
      delay (10);
      digitalWrite( PIN_OPEN_CLOSE, LOW );
      action_flag = 0;
    }
  }
  // Отслеживаем сообщения по rs485
  if (Serial.available() >= 2) {  // если есть доступные данные
    // считываем 2 байта
    recivebuf[2] = Serial.read();
    if ( recivebuf[0] == 1 ) { // если сообщение адресовано шторам в спальне (1)
      if ( recivebuf[1] == 1 ) { // и если сообщение содержит команду "открыть"
        // Переключаем реле на открытие
        digitalWrite( PIN_OPEN_CLOSE, HIGH );
        // Подаем напряжение
        delay ( 10 );
        digitalWrite( PIN_START_STOP, HIGH );
        timing = millis();
        action_flag = 1;
      }
      else if ( recivebuf[1] == 0 ) { // и если сообщение содержит команду "закрыть"
        // Переключаем реле на закрытие
        digitalWrite( PIN_OPEN_CLOSE, LOW );
        delay ( 10 );
        // Подаем напряжение
        digitalWrite( PIN_START_STOP, HIGH );
        timing = millis();
        action_flag = 1;
      }
    }
  }
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

у Leonardo, Serial относится к последовательному соединению USB (например отладка в терминал и загрузка скетчей). Последовательное соединение через выводы 0 и 1 осуществляется через Serial1.

nik182
Offline
Зарегистрирован: 04.05.2015

Что ж вы такую программу накрутили? Вы ж 485 отлаживаете. Попробуйте по шагам. Сначала коротенькую программку просто отправка символа из ардуины к putty. Только честно. Переключение линии на передачу, посылка строки символов, отключение передачи, пауза. Если получите на ПК посылку, можно переходить к отправке символов из ардуины по получению символа от ПК. Когда обмен будет отлажен, можно переходить к управлению ногами. 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Алексей Н пишет:

Следующим шагом хочу добавить возможность связи по rs485. 

Ну и хоти!

А через что? Где схема?

Может я хер хочу 30см,но комплекция не позволяет...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

нахрена тебе RS485?  Поставь две JDY-40 и ходи по дому, в проводах не путаясь. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

mykaida пишет:

Может я хер хочу 30см,но комплекция не позволяет...

Ну, дык - http://www.med-rf.ru/directions/urology_andrology_microsurgery/andrology/1/

Алексей Н
Offline
Зарегистрирован: 02.01.2016

ЕвгенийП, а электронике можно также научиться?

Тупо поменять в коде "Serial" на "Serial1" ничего не дало. Придется, видимо, разбираться по шагам.

Вот простенький код. Если в этом коде использовать Serial, то в монитор порта, встроенного в IDE, передаются данные. Все работает. Если заменить "Serial" на "Serial1", то ничего не происходит вообще.

void setup() {

  Serial1.begin(9600);
  pinMode(7, OUTPUT);
}
void loop() {
  digitalWrite(7, HIGH);
  Serial1.write(1);
  Serial1.print(1);
  Serial1.print("A");
  digitalWrite(7, LOW);
  delay(500);
}

Еще раз про подключение.

конвертер TTL-RS485 - https://aliexpress.ru/item/32348018283.html

Переходник с USB на RS485 - https://aliexpress.ru/item/32428596578.html

R0 модуля подключен на RX ардуины (0 пин), DI на TX ардуины (1 пин), DE и RE соединены и подключены к 7 пину ардуино. Выход А конвертера соединяю с А переходника, В с В.

Беспроводную связь соображалка не потянет. С двумя проводами-то разобраться не могу.

 

nik182
Offline
Зарегистрирован: 04.05.2015

А можно полную схему? Со всеми соединениями. Даже теми, через которые заливается скетч. Если что то прибегает в монитор ИДЕ то надо понять путь, как туда попадают символы.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Алексей Н пишет:

Беспроводную связь соображалка не потянет. С двумя проводами-то разобраться не могу.

JDY-40 тем и хорош, что прикидывается и работает так же просто как обычный Сериал, тока без проводов.  Ничего в программе переделывать не надо, создать SoftSerial, на его выводы подключить JDY и слать в софтсериал данные.  А на приемнике так же забирать их из софтсериала.  2021 на носу, эволюция же.  Пришло время ужасных чудес. 

Алексей Н
Offline
Зарегистрирован: 02.01.2016

Вот"схема". Реле не удались. Все-таки хотелось бы именно проводную связь. Пробовал когда-то nrf24l01, esp... в общем осадочек остался.

С Serial все действия происходят через тот же шнурок, по которому заливается скетч. Serial1 уже хотелось бы отсылать через конвертер TTL RS485

 

 

nik182
Offline
Зарегистрирован: 04.05.2015

Из описания платы : . Обратите внимание, что на Micro класс Serial относится к (CDC) соединению; для последовательного TTL соединения на выводах 0 и 1 используйте класс Serial1. В компе надо смотреть порт, который поднимается после коннекта 485 адаптера.

Алексей Н
Offline
Зарегистрирован: 02.01.2016

nik182 пишет:
Из описания платы : . Обратите внимание, что на Micro класс Serial относится к (CDC) соединению; для последовательного TTL соединения на выводах 0 и 1 используйте класс Serial1

Ага, выше уже MaksVV мне на это указал. В комментарии №6 я попытался написать простенький код, который должен был работать с Serial1. Но он не работает. Видимо, что-то не то я все равно делаю.

sadman41
Offline
Зарегистрирован: 19.10.2016

Если есть вторая ардуина, то можно ею послушать Микру - шлет она что-нить в Serial1 или нет.

Алексей Н
Offline
Зарегистрирован: 02.01.2016

sadman41 пишет:

Если есть вторая ардуина, то можно ею послушать Микру - шлет она что-нить в Serial1 или нет.

Кстати, можно попробовать. Могу в качестве приемника даже взять Нано, чтобы не заморачиваться с разными сериалами. Имеется ввиду, что надо убрать все конвертеры и просто соединить две ардуины через rx и tx пины? Код из комментария №6 пойдет в качестве передатчика?

sadman41
Offline
Зарегистрирован: 19.10.2016

На Нану пример TwoSerial (или как-то так) из библиотеки SoftwareSerial.

Передатчик подойдёт.

Алексей Н
Offline
Зарегистрирован: 02.01.2016

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

ардуино про микро               ардуино нано

     0 пин (TX)      <->        8 пин (софтварный RX)

     1 пин (RX)      <->        9 пин (софтварный TX)

Код передатчика (про микро)

void setup() {

  Serial1.begin(9600);
  pinMode(7, OUTPUT);
}
void loop() {
  digitalWrite(7, HIGH);
  Serial1.write(1);
  Serial1.print(1);
  Serial1.print("A");
  digitalWrite(7, LOW);
  delay(500);
}

Код приемника (нано)

#include <SoftwareSerial.h>
// software serial #1: RX = digital pin 8, TX = digital pin 9
SoftwareSerial portOne(8, 9);

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  // Start each software serial port
  portOne.begin(9600);
}

void loop() {
  // By default, the last intialized port is listening.
  // when you want to listen on a port, explicitly select it:
  portOne.listen();
  Serial.println("Data from port one:");
  // while there is data coming in, read it
  // and send to the hardware serial port:
  while (portOne.available() > 0) {
    char inByte = portOne.read();
    Serial.print(inByte);
  }

  // blank line to separate data from the two ports:
  Serial.println();
}

Передатчик питается от зарядки. Приемник подключен к USB порту компьютера. В мониторе последовательного порта выдает следующее:

Data from port one:

Data from port one:
⸮⸮
Data from port one:

Data from port one:

То есть в порт пишется строка "Data from port one:", как собственно и следует из кода. И периодически проскакивают непечатаемые символы, которые, по-видимому, получаются от передатчика по Serial1. Если отсоединить передатчик, то этих символов в мониторе порта не появляется.

sadman41
Offline
Зарегистрирован: 19.10.2016

18ю строку я бы выкинул, а inByte печатал в HEX (см. описание Serial.print) и далее пробел для понятности.

Алексей Н
Offline
Зарегистрирован: 02.01.2016

sadman41 пишет:
18ю строку я бы выкинул, а inByte печатал в HEX (см. описание Serial.print) и далее пробел для понятности.

Сделал. В мониторе порта выводится следующее:

Data from port one:
FFFFFFFD FFFFFFFF
Data from port one:
FFFFFFFF FFFFFFFF
Data from port one:
Data from port one:
FFFFFFFF FFFFFFFB
Data from port one:
FFFFFFFA FFFFFFFF
Data from port one:
Data from port one:
FFFFFFDF FFFFFFFF
Data from port one:

Все-таки это мусор, а не данные с передатчика.

 

Всех с наступившим НГ!

MaksVV
Offline
Зарегистрирован: 06.08.2015
Алексей Н пишет:
Ага, выше уже MaksVV мне на это указал. В комментарии №6 я попытался написать простенький код, который должен был работать с Serial1. Но он не работает. Видимо, что-то не то я все равно делаю.
  
дак может,  так попробовать? 
 
void setup() 
{
  Serial1.begin(9600);
  Serial.begin(9600);
  pinMode(7, OUTPUT);
}

void loop() 
{
// принимаем данные из шины и отправляем их для просмотра в терминал
  if (Serial1.available()) {Serial.write(Serial1.Read());}


// раз в секунду с ардуины посылаем в шину  данные:
static uint32_t prevtime = 0;
if (millis() - prevtime > 1000)
 {
   prevtime = millis();
   digitalWrite(7, HIGH);
   Serial1.write(1);
   Serial1.print(1);
   Serial1.print("A");
   digitalWrite(7, LOW);
 }

}

 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

И предлагаю в эксперименте с двумя ардуинами убрать адаптеры rs485 и соединить uart ы напрямую

Алексей Н
Offline
Зарегистрирован: 02.01.2016

Вот код передатчика, с которым все заработало.

int ID = 1;
int Open = 1;
int Close = 0;
byte recivebuf[2];

void setup() {
  Serial1.begin(9600);

}
void loop() {
  Serial1.write(5);
  Serial1.print('<'); // start marker
  Serial1.print(ID);
  Serial1.print(','); // comma separator
  Serial1.print(Open);
  Serial1.println('>'); // end marker
  delay(500);
  
  Serial1.write(5);
  Serial1.print('<'); // start marker
  Serial1.print(ID);
  Serial1.print(','); // comma separator
  Serial1.print(Close);
  Serial1.println('>'); // end marker
  delay(500);
  
}

Причем работает как с ардуино в качестве приемника, так и с адаптером, подключенным к ПК. На ПК в мониторе СОМ-порта вижу все данные. Хотя принципиальных отличий от предыдущего своего кода я не вижу. Какие-то новогодние чудеса. Мне не очень понятно как происходит передача, потому что я не подаю сигнал на пины DI и RO конвертера. Или они по умолчанию настроены на передачу?

С отправкой в целом разобрался. Еще немного поковыряюсь и буду разбираться с приемом. Буду продолжать в этой же теме.

FoxJone
Offline
Зарегистрирован: 19.04.2019

Алексей Н пишет:

Код передатчика (про микро)

void setup() {

  Serial1.begin(9600);
  pinMode(7, OUTPUT);
}
void loop() {
  digitalWrite(7, HIGH);
  Serial1.write(1);
  Serial1.print(1);
  Serial1.print("A");
  digitalWrite(7, LOW);
  delay(500);
}

Уж сколько раз твердили - на простых чипах 485 прежде чем выключать передачу (  digitalWrite(7, LOW);), дождись, пока сигнал уйдет в линию. На умных чипах этого делать не надо, а на тупых китайских надо. То есть после отправки посылки вы должны подождать, пока чип их отправит и УЖЕ ПОСЛЕ этого выключать передачу. У вас скорость передачи вами же задана и чип не может передавать быстрее, чем вы ему указали. А атмега работает на порядок быстрее и и обрывает передачу. Для скорости 9600 надо ставить задержку 1200-1250 миллисекунд на один посланный байт.

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

Алексей Н
Offline
Зарегистрирован: 02.01.2016

FoxJone пишет:

дождись, пока сигнал уйдет в линию. На умных чипах этого делать не надо, а на тупых китайских надо.

.......

Для скорости 9600 надо ставить задержку 1200-1250 миллисекунд на один посланный байт.

А Serial.flush() для этого использовать не более правильно?

 

FoxJone
Offline
Зарегистрирован: 19.04.2019

Алексей Н пишет:

FoxJone пишет:

дождись, пока сигнал уйдет в линию. На умных чипах этого делать не надо, а на тупых китайских надо.

.......

Для скорости 9600 надо ставить задержку 1200-1250 миллисекунд на один посланный байт.

А Serial.flush() для этого использовать не более правильно?

Может и лучше, но совсем не очевидно... Этот flush очень странно работает: делает не всегда то, что в описании написано. Не говоря уже о том, что меняет свой функционал на прямо противоположный в разных версиях Ардуины ИДЕ. Так что, во избежание будущих багов и глюков я им не пользуюсь. Да и вручную поставить задержку на переключение прием/передача никаких проблем нету. Я вообще стараюсь не пользовать сторонние библиотеки там, где можно самому написать пару строчек.

Ну и правило номер два: по сериалу не шлют символы, строки или там флоаты... Там шлют только и исключительно байты. Поэтому рекомендую использовать только write и read, без всяких print или (упаси боже) println. Потому что иногда они лишнее цепляют к отправляемой посылке (конец строки, перевод каретки и тд) - и потом с этим лишним на этот форум люди приходят)

Алексей Н
Offline
Зарегистрирован: 02.01.2016

FoxJone пишет:

Ну и правило номер два: по сериалу не шлют символы, строки или там флоаты... Там шлют только и исключительно байты. Поэтому рекомендую использовать только write и read, без всяких print или (упаси боже) println. Потому что иногда они лишнее цепляют к отправляемой посылке (конец строки, перевод каретки и тд) - и потом с этим лишним на этот форум люди приходят)

А вот тут не понял. Я считал, что по сериалу вся информация уходит в виде двоичного кода - ноликов и единичек. А вот как в коде это прописано, это исключительно для удобства восприятия на глаз.

И, кстати, задержка в 1,2 секунды на байт это не многовато?

FoxJone
Offline
Зарегистрирован: 19.04.2019

Ну это правильно, нули и единички. Для удобства объединяем их в байты. Но! Когда вы шлете командой write(5) один байт, то на линию уходит ровно 8 бит (байт=5) и ничего лишнего (ну кроме стоповых битов, которые в любом случае будут). А если вы шлете в сериал println(5), то на линию уйдет байт=53 (символ 5 в ascii) +байт окончания строки +байт перевода каретки. Итого 3 байта. Если это то, что вы хотели, то все нормально. Но очень часто сюда приходят люди с претензией "я послал 5, а оно мне шлет какой то мусор".

Не 1,2 секунды, а 0,0012 секунд. Моя вина - хотел написать микросекунд.

Алексей Н
Offline
Зарегистрирован: 02.01.2016

Спасибо за разъяснения. Стало понятнее. В принципе, такой код даже более логичен.

Я чуть забегу вперед. Я планирую делать двухстороннюю связь с распберри и уже сейчас столкнулся с тем, что данные проходят не в 100% случаев. Наводки, помехи, не совсем удачные временные провода... причин может быть много. Но совершенно понятно, что для более-менее надежной связи необходимо подтверждение получения данных. Вы можете дать совет как это лучше реализовать? Я представляю себе так:

Отправили данные

Взвели флаг отправки данных

   Повтор 5 раз

Ждем подтверждения две секунды

Если подтверждение получено, то сбрасываем флаг отправки данных и выходим из цикла

Если подтверждение не получено, то снова отправляем данные

Если 5 раз отправка данных неудачна, то сбрасываем флаг отправки данных

 

FoxJone
Offline
Зарегистрирован: 19.04.2019

Форум (движок, а не сообщество) тут полный отстой - свои сообщения искать практически невозможно... Где то я уже писал развернуто про то как надо работать в 485, попробую найти... Потому что повторно писать лень)

rkit
Offline
Зарегистрирован: 23.11.2016

rs485 изначально спроектирован как стандарт связи в дико агрессивной индустриальной среде на расстояния больше километра,  и если у тебя в обычной комнате данные не доходят, то это значит, что ты делаешь что-то очень-очень-очень неправильно.

FoxJone
Offline
Зарегистрирован: 19.04.2019

rkit пишет:

rs485 изначально спроектирован как стандарт связи в дико агрессивной индустриальной среде на расстояния больше километра,  и если у тебя в обычной комнате данные не доходят, то это значит, что ты делаешь что-то очень-очень-очень неправильно.

Ага-ага... Вот только изначально его проектировали 50+ лет назад и для скоростей порядка 200-500 кбит/с. И даже при этом во всех протоколах присутствует проверка на ошибки. На скорости 9600 и выше ошибки будут обязательно! Что не отменяет того, что стандарт удобный и пользоваться им можно - к примеру, миллионы автобусов, трамваев и троллейбусов в стране возят на себе информатор (мастер) и по 3-4 табло (слейвы), связанных по 485 да еще и на скорости 115200 (я участвовал в разработке, поэтому гарантирую). А проводка там даже не витая пара, по большей части просто 2 провода кидают где могут.

FoxJone
Offline
Зарегистрирован: 19.04.2019

Алексей Н пишет:

Но совершенно понятно, что для более-менее надежной связи необходимо подтверждение получения данных. Вы можете дать совет как это лучше реализовать?

Не нашел свой текст, поэтому в двух словах: у вас 2 варианта - взять готовый протокол (например ModBus) или написать свой. Если честно, то я настолько ленивый, что когда у меня встал вопрос работать с устройствами под ModBus, то мне оказалось проще написать свою обработку, чем искать и курить чужие библиотеки, а с вашими шторами модбас явное излишество.

А как реализовать простой и надежный обмен я вот тут коротко расписывал https://arduino.ru/forum/apparatnye-voprosy/konverter-max485-podklyuchenie#comment-559270

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

FoxJone, напишы мне, согласен работать за еду на любых твоих условиях. Даж не пить согласен. Совсем у мня жопа. :( 

Завтра удалю это. 

rkit
Offline
Зарегистрирован: 23.11.2016

FoxJone пишет:

 для скоростей порядка 200-500 кбит/с.

На скорости 9600 и выше ошибки будут обязательно!

Вообще-то 100к максимум по стандарту. И даже это в 10 раз больше 9600. Фуфло какое-то несешь.

FoxJone
Offline
Зарегистрирован: 19.04.2019

DetSimen пишет:

Дед, удаляй прям щас! Завтра отпишусь, сейчас ужо пить начал...

FoxJone
Offline
Зарегистрирован: 19.04.2019

rkit пишет:

FoxJone пишет:

 для скоростей порядка 200-500 кбит/с.

На скорости 9600 и выше ошибки будут обязательно!

Вообще-то 100к максимум по стандарту. И даже это в 10 раз больше 9600. Фуфло какое-то несешь.

Максимум - это пропускная способность. Ошибки могут (а раз могут, то и будут) быть на любых скоростях и на любых каналах связи, даже если это веревочный телеграф, то пробегающая крыса может за веревку хвостом дернуть. Ошибки передачи - это нормально. Ненормально если их больше допустимого уровня и ненормально, если их никто не отсеивает.

nik182
Offline
Зарегистрирован: 04.05.2015

FoxJone пишет:
Ага-ага... Вот только изначально его проектировали 50+ лет назад и для скоростей порядка 200-500 кбит/с. И даже при этом во всех протоколах присутствует проверка на ошибки. На скорости 9600 и выше ошибки будут обязательно! Что не отменяет того, что стандарт удобный и пользоваться им можно - к примеру, миллионы автобусов, трамваев и троллейбусов в стране возят на себе информатор (мастер) и по 3-4 табло (слейвы), связанных по 485 да еще и на скорости 115200 (я участвовал в разработке, поэтому гарантирую). А проводка там даже не витая пара, по большей части просто 2 провода кидают где могут.

Вот вот, у меня на 115200 на 30 метров в условиях сильных импульсных наводок по 485 бегает почти без ошибок через MODBUS, которой в случае ошибок требует повтора пакета.