Создал небольшое устройство на Меге для упрощение своей работы, принцып работы: отправка запроса по 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 Ом на на концах линии стоят?
Я у себя помех не видел в принципе, ни одного искаженного пакета, правда после доработки в плане запрещения приема на момент переключения прием/передача и передачи.
Длинна линии около 20см в данный момент. Пока работает на столе. Я раньше тоже грешил на искажение, но тепеь больше склоняюсь что модуль или ардуинка неправильно воспринимает конкретный пакет. В логе выше видно: первый пакет принимается правильно а второй нет. Даже если поменяю запросы местами то тот что сейчас второй придет в том же виде. Сколько не повторяй - ничего не меняется. И при том что терминал подключеный паралельно линии видит правильный пакет!
Виндда не система реального времени, чтобы не пропускать данных по виртуальному ком-порту требуются специальные драйвера этих самых портов.
Если аппаратный переключатель TX/RX 485-го, то норм.
Извините. Но каким боком тут винда? Мы говорим о ардуинке.
о, звиняйте, не въехал сразу при чем тут ПК
Вижу что идей как бы нет… Вот новые данные:
Вынес обмен пакетами в отдельный скетч, и вот что получилось:
- при запросе с ардуинки ответ так и не читается нормально;
- при запросе с терминала все читается правильно;
- при посылке того же пакета с терминала также все нормально;
скетч:
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.
сомневаюсь, проблема вылазит сразу при включении, неуспевает он нагреватся
вот такое чудо.
общая длинна линии (на текущий момент, на столе) ок 20см. сопротивление линии 60 Ом, в линии 3 устройства: Ардуино через адаптер (на фото), устройство RFID, и USB to RS485 (на фото ниже).