Модуль RS485 некорректно принимает данные

Создал небольшое устройство на Меге для упрощение своей работы, принцып работы: отправка запроса по 485 прием ответа, обработка и запись на карту памяти. Все работает приемлемо и очень помогает но иногда замечаю при некоторых входных данных пробегает ошибка контрольной суммы (не одиночная, а зависимая от входных данных).
Теперь решил добавить функционал и вживую столкнулся с тем что подозревал: отправил запрос - а ответ приходит неверный.
Конкретнее: шина 485, подключено мое устройство на меге и адаптер 485 с Али, управляемое (заводское) устройство, адаптер usb-485 для котроля ситуации через терминал на ПК.
Отправляю запрос 4 байта (вижу его на ПК ка положено) а в ответ приходит не то что видит терминал. Ардуина: 64 C2 60 C0 4C 18 93 Терминал (правильные данные) : 23 09 02 01 18 02 18 93.
Как видим совпадают только 2 последние байта, и общее количество байт тоже не то.
Проблема вылазит только при некоторых конкретных входных данных в 90% случаев все нормально работает.
Вопрос: где искать виновника такого поведения? В коде, ардуинке, или же скорее всего сам адаптер (проверял на 2-х одинаковых)

Без кода и описания протокола, обсуждение бессмысленно

Может проблема как та, что столкнулся я ? Ссылка

Судя по запросам и ответам железок ТС’а, там у него нифига не Modbus

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

Протокол называют SOVVA (кажется) - общение железок которые передают номер RFID карточки.
Вот часть кода которая отвечает за передачу / прием

digitalWrite(TX_485_PIN, 1);    /
  delay(10);
  while (Serial1.available())    
  {
    Serial1.read();
  }

  for (int i = 0; i < 52; i++) {
    SerialData[i] = 0xFF;
  }

  for (int i = 0; i < outLen; i++) {
    Serial1.write(msgOut[i]);               
    Serial.println (msgOut[i], HEX);
  }
  if (msgOut[2] == 0x12)  delay(5);
 else  delay(2);
   digitalWrite(TX_485_PIN, 0);
   delay(100);
  TelLen = 0;
  Serial.println();
  Serial.println("Vidpovid RAW");
  if (Serial1.available()) {
    while (Serial1.available()) {
      SerialData[TelLen] = (char)Serial1.read();
      Serial.print(SerialData[TelLen], HEX);
      TelLen++;

лог терминала:

Zapros
33
FF
8
79

Vidpovid RAW
239844D89D5F2  // правильный прием пакета
Data In
239844D89D5F2
Addr - 9
Serial N - 9515721668
Zapros
33
9
2
34

Vidpovid RAW
64C260C04C1893  // неправильный прием пакета
Data In
64C260C04C1893FF 
SW ver - 76192

Отключение прерывания не помогает. результат тот же.

Как я написал в первом сообщении: такие ошибки вылазят только при конкретных входных данных. Просто эти данные с датчиков постоянно меняются и я списывал на помехи в линии. А в конкретном случае есть конкретный ответ который не принимается правильно ардуинкой, вот хочу как то разобратся кто тут виноват.

Линия последовательно обходит все элементы сети? Не звезда?
Терминаторы по 120 Ом на на концах линии стоят?
Я у себя помех не видел в принципе, ни одного искаженного пакета, правда после доработки в плане запрещения приема на момент переключения прием/передача и передачи.

1 лайк

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

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

Если аппаратный переключатель TX/RX 485-го, то норм.

Извините. Но каким боком тут винда? Мы говорим о ардуинке.

1 лайк

о, звиняйте, не въехал сразу при чем тут ПК

Вижу что идей как бы нет… Вот новые данные:
Вынес обмен пакетами в отдельный скетч, и вот что получилось:

  1. при запросе с ардуинки ответ так и не читается нормально;
  2. при запросе с терминала все читается правильно;
  3. при посылке того же пакета с терминала также все нормально;

скетч:


byte msgOut[4]  {0x33, 0x09, 0x02, 0x34};
# define TX_485_PIN 42
#include <Keypad.h>
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
char key;
byte rowPins[ROWS] = {41, 39, 37, 35};
byte colPins[COLS] = {33, 31, 29, 27};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup() {

  pinMode(TX_485_PIN, OUTPUT);
  Serial1.begin(19200); //порт RS485
  Serial.begin(115200);
}

void loop() {
  key = keypad.getKey();
  if (key == '0')  request();
  if (key == 'D')  request1();
}

void request1() {
  Serial.println();
  Serial.println("RAW");
  if (Serial1.available()) {
    while (Serial1.available()) {
      Serial.print(Serial1.read(), HEX);
      Serial.print(' ');
    }
  }
  Serial.println();
}

void request()
{
  Serial.println("Zapros");
  digitalWrite(TX_485_PIN, 1);
  delay(10);
  while (Serial1.available())  {
    Serial1.read();
  }
  for (int i = 0; i < 4; i++) {
    Serial1.write(msgOut[i]);
    Serial.print (msgOut[i], HEX);
    Serial.print(' ');
  }
  delay(2);
  digitalWrite(TX_485_PIN, 0);
  delay(100);
  Serial.println();
  Serial.println("RAW");
  if (Serial1.available()) {
    while (Serial1.available()) {
      Serial.print(Serial1.read(), HEX);
      Serial.print(' ');
    }
  }
  Serial.println();
}

Скрин терминала

Монитор порта:

Zapros
33 9 2 34 
RAW
64 C2 60 C0 4C 18 93 

RAW
33 9 2 34 23 9 2 1 18 2 18 93 

RAW
23 9 2 1 18 2 18 93 

Фото модуля RS485 можете сюда запостить ? И одинаковые модули стоят на обоих концах? В линии связи используете только 2 модуля, или есть ещё устройства сидящие на линии?

У меня был случай с внезапным нагревом простецкого модуля RS485-UART. После этого весь модбас пошёл с CRC error.

сомневаюсь, проблема вылазит сразу при включении, неуспевает он нагреватся

image
вот такое чудо.

общая длинна линии (на текущий момент, на столе) ок 20см. сопротивление линии 60 Ом, в линии 3 устройства: Ардуино через адаптер (на фото), устройство RFID, и USB to RS485 (на фото ниже).

image

Ошибку в передачу данных вносит комповый адаптер. У меня такое бывало. Иногда, это выяснял по еле тлеющему светодиоду или Rx или Tx уже не помню. Попробуй замени этот навороченный комповый адаптер на обыкновенный черный