#1 2024-12-09 12:57:31

tss69
Учасник
Зареєстрований: 2017-02-26
Повідомлень: 6

Задержка связи по RS485

Соединил две ардуины через модули TTL-RS485 по стандартной схеме. Одна ардуина измеряет напряжение на переменном резисторе и передаёт на вторую. Передача только в одну сторону. Связь работает, но при изменении напряжения приёмник  принимает данные с задержкой 20 секунд. Приём и передачу контролирую в мониторе. Скорость связи менял 4800, 9600, 19200 - результат - задержка не изменилась. При изменении данных на передатчике через 10 секунд разрывал линию - на приёмнике с задержкой показания менялись! То-есть, приёмник принимает данные сразу, но "отдаёт" с задержкой 20 секунд. В приёмнике реализовано только приём данных и просмотр(контроль) в мониторе. Линия связи - витая пара, 40 м.

Остання редакція tss69 (2024-12-09 12:58:53)

Неактивний

#2 2024-12-09 19:54:51

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 221

Re: Задержка связи по RS485

MAX485 не містить ніякої логіки і буферів. Якщо затримка 20 секунд, але дані таки приходять, то вони десь мають зберігатись. Це явно програмна помилка. Потрібно розуміти, на якій із сторін відбувається ця затримка. Не завадило би подивитись на код приймача і передавача.

Неактивний

#3 2024-12-09 20:46:55

tss69
Учасник
Зареєстрований: 2017-02-26
Повідомлень: 6

Re: Задержка связи по RS485

Я  це розумію, тому і питаю, можливо хтось мав досвід? Код дуже простий.
Приймач:

#include <SoftwareSerial.h>
SoftwareSerial RS485(6,7);
#define DE_RE 10 // управление модулем RS485 прием-передача

float R2;

void setup()
{
  Serial.begin(9600);
  RS485.begin(4800);
  pinMode(DE_RE,OUTPUT);
  digitalWrite(DE_RE,LOW); //приемник
}

void loop()
{
  R2=RS485.read();
  Serial.print("Zadanie = ");
  Serial.println(R2,0);
  delay(200);
 
}

Передавач:
#include <SoftwareSerial.h>
SoftwareSerial RS485(6,7);
#define DE_RE 10
float R;
float R1;

void setup()
{
  Serial.begin(9600);
  RS485.begin(4800);
  pinMode(DE_RE,OUTPUT);
  digitalWrite(DE_RE,HIGH); //передатчик
}

void loop()
{
  R1 = analogRead(A0);
  R =(R1+1)/4;
  Serial.print("ZADANIE = ");
  Serial.println(R,0);
  RS485.write(R);
  delay(10); 
}

Остання редакція tss69 (2024-12-09 20:48:10)

Неактивний

#4 2024-12-09 20:58:11

tss69
Учасник
Зареєстрований: 2017-02-26
Повідомлень: 6

Re: Задержка связи по RS485

Мені здається що затримка у приймачі. Як я описував, поведінка приймача така, що при зміні показів із затримкою в 5-10 секунд я фізично роз"єдную дроти, але приймач із затримкою потім показує принятий вірний результат.

Остання редакція tss69 (2024-12-09 20:59:03)

Неактивний

#5 2024-12-09 23:14:17

tss69
Учасник
Зареєстрований: 2017-02-26
Повідомлень: 6

Re: Задержка связи по RS485

Знайшов причину затримки. У кінці коду приймача є команда затримки  delay(200). Після заміни на delay(10) затримка зникла. Якщо замінити на delay(100), тоді затримка становить 10 секунд. Таку затримку використовув коли для налагодження роботи підключав тимчасово дисплей 1602.

Неактивний

#6 2024-12-10 00:32:16

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 221

Re: Задержка связи по RS485

tss69 пише:

Код дуже простий.

Простий не значить правильний.

1. В приймачі ви намагаєтесь читати дані навіть коли їх нема. SofSoftwareSerial::read() при цьому повертає -1.
2. В передавачі затримка між посилками 10мс (+ якийсь час на виконання інших функцій). В приймачі затримка між спробами читання 200 мс. Приймач навіть теоретично не встигатиме читати всі відправлені передавачем дані. Навіщо взагалі в приймачі ця затримка 200 мс?
3. Кожну ітерацію в UART пишеться більше десятка байт ("Zadanie = " плюс саме значення та r). На 9600 бод їх передача займає  більше 10 мс. В передавачі з часом внутрішній буфер Serial заповнюється і Serial.print() блокує виконання поки буфер не звільниться.
До проблеми не відноситься, але все ж:
4. Навіщо там використання типу float?

Я би порадив для початку відлагодити комунікацію при безпосередньому TTL-зʼєднанні приймача з передавачем. Тільки після того як все працюватиме правильно, зʼєднувати по RS485.

Неактивний

#7 2024-12-10 00:36:39

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 221

Re: Задержка связи по RS485

tss69 пише:

Якщо замінити на delay(100), тоді затримка становить 10 секунд.

Навіщо там взагалі delay()? В 99.9% випадків, якщо в коді delay(), значить щось не так із кодом або алгоритмом в цілому.

Неактивний

#8 2024-12-10 01:15:35

tss69
Учасник
Зареєстрований: 2017-02-26
Повідомлень: 6

Re: Задержка связи по RS485

У деяких прикладах при роботі з analogRead(A0) використовували delay(10) перед зчитуванням.
Використання  serial.println() потрібно було для контролю, у готовому приладі використовуватись не буде.
Тип float - під час випробувань приєдннував 1602, простіше(без перетворювання типів змінних) у використанні.

Остання редакція tss69 (2024-12-10 01:17:18)

Неактивний

#9 2024-12-10 04:15:27

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 221

Re: Задержка связи по RS485

tss69 пише:

У деяких прикладах при роботі з analogRead(A0) використовували delay(10) перед зчитуванням.

Затримка перед читанням ADC мала би сенс після вмикання внутрішнього джерела опорної напруги, щоб воно встигло стабілізуватись. Даташит говорить про час стабілізації 40-70 мікросекунд.
Ардуіно, по-перше, в якості опорної напруги за замовчуванням використовує Vcc; по-друге, конфігурує ADMUX всередині analogRead(). Так що затримка перед analogRead() не має жодного сенсу. Просто зробіть одне читання в setup() та проігноруйте його результат.

Якщо передавач має зчитувати та відправляти дані з певною частотою, то краще вже використовуйте millis().
На приймачі взагалі ніяких затримок не потрібно.

tss69 пише:

Використання  serial.println() потрібно було для контролю, у готовому приладі використовуватись не буде.

Просто майте на увазі, що відправлені в Serial дані хоч і буферизуються, але їх передача з буфера потребує часу. Щоб мінімізувати вплив дебажного вивода на роботу, використовуйте вищий бітрейт, наприклад 115200.

tss69 пише:

Тип float - під час випробувань приєдннував 1602, простіше(без перетворювання типів змінних) у використанні.

1602 - це алфавітно-цифровий дисплей? Не дуже зрозумілий його звʼязок з float. Ну то таке.

Неактивний

#10 2024-12-10 14:09:18

ihor
Гість

Re: Задержка связи по RS485

Використовуйте SoftwareSerial.available(), а синхронізація на delay() це дуже погано.

#11 2024-12-10 17:27:04

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 221

Re: Задержка связи по RS485

ihor пише:

Використовуйте SoftwareSerial.available()

Якщо читати посимвольно, то і available() не потрібно.

int c = serial.read();
if (c != -1) {
...
}

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму