Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Обсуждение и вопросы по урокам Ардуино
Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 28 фев 2020, 08:32

Всем доброго дня
Пытаюсь реализовать простую передачу данных по RS485 при помощи библиотеки от Эдуарда.
Реализую минимальный функционал:
Есть некий массив с числами int. В перспективе он будет заполняться динамически, но пока пробую использовать заранее объявленный -
int myArray[6] = {27, 38, 72, 91, 16, 54};
Пока остальной функционал опустим, как и ответ slave'a, пытаюсь просто добиться передачи. Для приема "на том конце" использую программу QModBus.е
На данный момент большее, чего мне удалось добиться - числа отправляются, но в теле пакета разделены "00", т.е. блок даты в пакете выглядит так примерно: 18 00 26 00 48 00 5B 00 10 00 36 00 - так показывает QModBus. К слову, переодически зависает, просто "вылетает" и вообще софтина на мой взгляд не шибко стабильна.
Теперь мой код, который пытается выполнить поставленную выше задачу (код отладочный и кривой, прошу отнестись с пониманием):

Код: Выделить всё

#include <TimerOne.h>
#include <Tiny_ModBusRTU_Master.h>
volatile Tiny_ModBusRTU_Master master(8, 30, 13);
int regTable[6] = {27, 38, 72, 91, 16, 54};

void loop() {
 
 master.writeMultiple(2, regTable, 0, 6);
 while(master.state == 1) {}
   delay(500);
}

void timerInterrupt() {
  master.update();
}


В чем беда, или нужно обязательно описывать полный функционал?

Спасибо


Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 02 мар 2020, 16:06

Подозреваю, что не правильно понимаю, как работает master.state - отсюда и все беды. Не могу разобраться..

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Эдуард » 02 мар 2020, 17:02

Здравствуйте!
Выведите значение master.state в последовательный порт и посмотрите код ошибки.

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 02 мар 2020, 17:13

Эдуард, здравствуйте!
Пока все оставил на работе, завтра обязательно попробую и отпишу. Дома был 16х4 дисплей, попробую отыскать и тоже подкину

Спасибо

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 03 мар 2020, 08:11

Эдуард писал(а):Здравствуйте!
Выведите значение master.state в последовательный порт и посмотрите код ошибки.

Output.jpg


А вот моя программа (предприняты всевозможные попытки поправить ситуацию)):

Код: Выделить всё

// центральный контроллер с протоколом ModBus
#include <TimerOne.h>
#include <Tiny_ModBusRTU_Master.h>

volatile Tiny_ModBusRTU_Master master(8, 30, 13);

unsigned int regTable[6] = {21, 31, 41, 51, 61, 71}; // таблица регистров
unsigned int cyclCount= 0; // счетчик циклов
unsigned int errorCount= 0; // счетчик ошибок

void setup() {
  Timer1.initialize(500); // инициализация таймера 1, период 500 мкс
  Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
  Serial.begin(9600);
}

void loop() {

 // master.read(1, regTable, 0, 5); // чтение регистров хранения
  while(master.state == 1) {} // ожидание данных

  if(master.state == 0) {
    // данные получены
    cyclCount++; // счетчик циклов
  }
  else {
    // ошибка обмена
    errorCount++; // счетчик ошибок
  }

  master.writeMultiple(5, regTable, 0, 6); // запись регистра хранения
  while(master.state == 1) {} // ожидание данных
  if(master.state != 0) errorCount++;
  Serial.println(master.state);
  delay(5000);
}

//--------------------------- обработчик прерывания 500 мкс
void timerInterrupt() {
  master.update(); // проверка данных обмена
}


Если посмотреть, что приходит в QModBus - то вот он мой массив - 15 00 1f 00 29 00 33 00 3d 00 47

Схема у меня простая, ардуиня уно, в рх и тх соответственно DI и RO, на 13ом пине DE/RE, к USB свистку все это припаяно, что бы не лишний раз не ломать голову "где плохой контакт". Просто RS485 работает без библиотек

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 03 мар 2020, 08:50

Да, забыл добавить.
volatile Tiny_ModBusRTU_Master master(8, 30, 13); - поскольку я передаю аж 6 элементов массива, возможно тут нужно изменить время? Я играл с первыми двумя параметрами и скоростью порта, если объявить volatile Tiny_ModBusRTU_Master master(16, 60, 13); и Serial.begin(115200); - то QModBus перед тем как зависнуть успевает пару раз выдать response и даже слейвID определяет верно.

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Эдуард » 03 мар 2020, 09:26

Здравствуйте!
Попробуйте за основу взять последний скетч урока 58. Там все отрабатывается более корректно.
Для проверки завершения операции надо проверять младший бит master.state.
if( (mode & 1) == 0 ) {
После этого необходимо проверить другие биты на предмет ошибки.
0 - операция завершена успешно;
1 - идет операция;
2 - ошибка тайм-аута;
4 - ошибка данных;
8 - недопустимый адрес данных;
16 - код функции не поддерживается;
32 – другая ошибка.

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 03 мар 2020, 11:21

Эдуард писал(а):Здравствуйте!
Попробуйте за основу взять последний скетч урока 58. Там все отрабатывается более корректно.
Для проверки завершения операции надо проверять младший бит master.state.
if( (mode & 1) == 0 ) {
После этого необходимо проверить другие биты на предмет ошибки.
0 - операция завершена успешно;
1 - идет операция;
2 - ошибка тайм-аута;
4 - ошибка данных;
8 - недопустимый адрес данных;
16 - код функции не поддерживается;
32 – другая ошибка.

Эдуард, я взял Ваш скетч из урока 58, только заменил write.Single на write.Multiple и подставил свой, заранее объявленный массив.
QModBus успевает поймать два пакета и сразу крашится. Не знаю даже как отладиться :) Может все же беда с временем в Tiny_ModBusRTU_Master master(8, 30, 13); - не успевает завершить передачу, вот QModBus и помирает.
Скетч измененный на всякий случай:

Код: Выделить всё

// центральный контроллер с протоколом ModBus
#include <TimerOne.h>
#include <LiquidCrystal.h>
#include <Button.h>
#include <Tiny_ModBusRTU_Master.h>

Tiny_ModBusRTU_Master master(8, 30, 13);
LiquidCrystal disp(6, 7, 2, 3, 4, 5); // объект дисплей
Button button1(10, 30); // кнопка 1 подключена к выводу 10

unsigned int regTable[6]; // таблица регистров
unsigned int regTable2[6] = {21, 22, 23, 24, 25, 26};
unsigned int cyclCount= 0; // счетчик циклов
unsigned int errorCount= 0; // счетчик ошибок
byte mode=0; // режим: 0 - чтение, 1 - запись

void setup() {
  Timer1.initialize(500); // инициализация таймера 1, период 500 мкс
  Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
  Serial.begin(9600);
  disp.begin(20, 4); // инициализируем дисплей 4 x 20 символов
  master.read(1, regTable, 0, 5); // чтение регистров хранения
}

void loop() {

  if( (mode & 1) == 0 ) {
    // чтение регистров хранения
    if(master.state != 1) {
      // операция завершена
      if(master.state == 0) {
        // данные получены
        disp.clear(); // очистка экрана
        disp.print("C=");
        disp.print(cyclCount);
        disp.print(" E=");
        disp.print(errorCount);
        disp.setCursor(0, 1);
        disp.print("T=");
        disp.print(* ((float *)regTable),1);
        disp.print(" C U=");
        disp.print(* ( ((float *)regTable) +1 ),1);
        if ( (regTable[4] & 1) == 0) disp.print(" V B=F");
        else disp.print(" V B=P");
      }
      else {
        // ошибка обмена
        errorCount++; // счетчик ошибок
        disp.clear(); // очистка экрана
        disp.print("C=");
        disp.print(cyclCount);
        disp.print(" E=");
        disp.print(errorCount);
        disp.setCursor(0, 1);
        disp.print("ERROR= ");
        disp.print(master.state);
      }
    master.writeMultiple(6, regTable2, 0, 5); // запись регистра хранения (светодиод)
    mode++;
    }
  }

  else {
    // запись регистра хранения
    if(master.state != 1) {
      // операция завершена
      if(master.state != 0) errorCount++;
      master.read(1, regTable, 0, 5); // чтение регистров хранения
      mode++;
      cyclCount++; // счетчик циклов
    }
  }
  delay(500);
}

//--------------------------- обработчик прерывания 500 мкс
void timerInterrupt() {
  master.update(); // проверка данных обмена
  button1.scanState(); // обработка сигнала кнопки 1
}

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Эдуард » 03 мар 2020, 16:44

Можете попробовать увеличить время тайм-аута ответа ведомого устройства.
И выведите на дисплей значение master.state при ошибке. Или мастер ошибки не выдает?

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 03 мар 2020, 22:08

Завтра буду в отъезде (кстати в РнД)), смогу вернуться к платам в четверг. Master.state дает 2 - т.е. тайм аут, насколько я понял

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Эдуард » 03 мар 2020, 23:22

Значит мастер не получил ответ. Увеличите время тайм-аута ответа.

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 05 мар 2020, 08:15

Увы, то ли я не правильно пишу, то ли дело не в этом.
Тайм аут ставил пошагово 30 - 60 - 120 -240 - без изменений.
Serial.print(master.state); выдает в ком порт это
cmprt.jpg



Последний вариает программы:

Код: Выделить всё

#include <TimerOne.h>
#include <Tiny_ModBusRTU_Master.h>
Tiny_ModBusRTU_Master master(8, 30, 12);
int regTable[6] = {27, 38, 72, 91, 16, 54};
byte mode = 0;
void setup() {
Timer1.initialize(1000); // инициализация таймера 1, период 500 мкс
Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
Serial.begin(9600);
}

void loop() {
  if ((mode & 1) == 0) {
master.writeMultiple(2, regTable, 0, 6);
while(master.state == 1) {}
delay(500);
Serial.println(master.state);
}
}
void timerInterrupt() {

master.update();
}

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 05 мар 2020, 10:26

Нашел еще софтину-эмулятор slave устройства. Тут результат получше:
mdbsnew.jpg

в регистрах с 40003 по 40008 мои значения имеются. Но неясность с slave ID и остальными значениями.

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 05 мар 2020, 13:58

Жаль, не могу прошлые сообщения исправить, придется создавать еще одно.
И так, написал простейшие два скетча. Не исключаю, что "замылился глаз" и мог где-то наделать глупых ошибок.
Взял две ардуины. Одна мастер (отправляет массив), вторая слейв - должна принимать.
Код мастера:

Код: Выделить всё

#include <TimerOne.h>
#include <Tiny_ModBusRTU_Master.h>

Tiny_ModBusRTU_Master master(8, 30, 12);
int regTable[6] = {27, 38, 72, 91, 16, 54};
byte mode = 0;
void setup() {
Timer1.initialize(1000); // инициализация таймера 1, период 500 мкс
Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
Serial.begin(9600);
}

void loop() {
 if ((mode & 1) == 0) {
master.writeMultiple(2, regTable, 0, 6);
 }
delay(500);
}

void timerInterrupt() {
master.update();
}

C таким вариантом, программа, что постом выше, корректно получает 6 значений подряд из моего массива.

Теперь делаем "слейв" устройство (тоже минимум функционала)

Код: Выделить всё

#include <TimerOne.h>
#include <Tiny_ModBusRTU_Slave.h>
int rcvTable[6];
Tiny_ModBusRTU_Slave slave(2, 8, rcvTable, 6); // создаем объект, адрес 2, таймаут 4 мс, массив rcvTable, размер 6

void setup() {
  Timer1.initialize(500); // инициализация таймера 1, период 500 мкс
  Timer1.attachInterrupt(timerInterrupt, 500); // задаем обработчик прерываний
  Serial.begin(9600);
}

void loop() {
    for (int i = 0; i < 7; i++){
    Serial.println(rcvTable[i]);
    delay(500);
  }
}


void timerInterrupt() {
  slave.update();
}

В результате в сериале "слейва" ожидаю увидеть перебор полученного массива, но вижу только нули, т.е. ничего не получено.
Эдуард, выручайте, уже не знаю что еще пробовать. Обе библиотеки Ваши. mode проверяю перед началом отправки. Нет версий, как говориться :)

p.s. Да, чуть не забыл, не нашел где в slave объекте объявляется ножка для переключения режимов прием\передача. Или проглядел

UPDATE: Закинул управляющий пин на землю и передача пошла. Но нужно после первой передачи зажимать резет или отключать мастера, иначе валит мусор. И почему-то вылазит 7 элемент массива "256" - такого я не шлю. Вижу, что намудрил с таймингами и явно упустил какой-то метод, не пойму какой.

Poulton
Сообщения: 11
Зарегистрирован: 28 фев 2020, 08:12

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Poulton » 06 мар 2020, 15:49

.. В общем так и не разобрался. if( (mode & 1) == 0 ) - как работает эта конструкция, куда пришивать эти конструкции - if(master.state != 1) {
if(master.state != 0) - не понятно. Пробовал в различных вариациях их добавлять в код - эффекта нет, принт master.mode показывает "1"

Сделал просто после writeMultiple и добавил delay(500);
Вроде работает, но, подозреваю, что такой конструкцией считать данные из слейва не представляется возможным.. А хотелось бы

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Нужна помощь с библиотекой Tiny_ModBusRTU_Master

Сообщение Эдуард » 20 мар 2020, 19:56

Здравствуйте!
Посмотрите внимательно скетчи из урока 61. А также описания библиотек.
Вывод разрешения работы передатчика - последний параметр в конструкторе.
Tiny_ModBusRTU_Slave slave(1, 8, regTable, 6, 13); // создаем объект ModBus

Повторите скетчи из урока 61, подкорректируйте под свою задачу. Сделайте все заново внимательно. Останутся вопросы - пишите.


Вернуться в «Уроки Ардуино»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 7 гостей