Modbus RTU и Arduino Nano

GoodRon

✩✩✩✩✩✩✩
14 Мар 2022
8
2
Доброго!
Есть устройство(приточная вентиляция) с возможностью управления по Modbus RTU RS485.
Цель: общаться с устройством и управлять им.
В инструкции описано, что устройство настроено как slave, адрес 247, 1sbit, even, 9600. И так же то что устройство можно подключить в SCADA систему.
Описаны параметры, для примера,
температура воздуха в приточке:
Адрес: 4002
Регион: 4х*
Доступ: r**
Тип данных:Uint8

Использую нано и модуль TTL to RS485.
Питаю пока что от usb и нанку и модуль.
Массы устройства и нанки соединены.
Пока что тестировал программный serial, чтоб иметь возможность получать данные в монитор порта. Для softSerial использовал пины D3 и D5.
RE DE на выходе из модуля мною соединены и подключены в D4.
Пробовал штук 5 разных готовых библиотек, но почему-то так и не смог получить от устройства никаких данных.
Направьте, пожалуйста, на путь истинный.
Пример кода ниже

PS к сожалению, опыта общения по шинам RS не имею

C++:
#include <ModbusRtu.h>
#include <SoftwareSerial.h>

// data array for modbus network sharing
uint16_t au16data[16];
uint8_t u8state;

SoftwareSerial mySerial(3, 5);//Create a SoftwareSerial object so that we can use software serial. Search "software serial" on Arduino.cc to find out more details.

/**
*  Modbus object declaration
*  u8id : node id = 0 for master, = 1..247 for slave
*  port : serial port
*  u8txenpin : 0 for RS-232 and USB-FTDI
*               or any pin number > 1 for RS-485
*/
Modbus master(0, mySerial); // this is master and RS-232 or USB-FTDI via software serial

/**
* This is an structe which contains a query to an slave device
*/
modbus_t telegram;

unsigned long u32wait;

void setup() {
  Serial.begin(9600);  
  mySerial.begin(9600);//use the hardware serial if you want to connect to your computer via usb cable, etc.
  master.start(); // start the ModBus object.
  master.setTimeOut( 5000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0;
}

void loop() {
  switch( u8state ) {
  case 0:
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1:
    telegram.u8id = 247; // slave address
    telegram.u8fct = 4; // function code (this one is registers read)
    telegram.u16RegAdd = 4002; // start address in slave
    telegram.u16CoilsNo = 1; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 2000;
        Serial.println(au16data[0]);//Or do something else!
    }
    break;
  }
}
 

Bruzzer

★★★★✩✩✩
23 Май 2020
756
232
У каждого свое понимание "путь истинный"
Я сторонник осознанного подхода, а не метода тыка. Можно не разбираться в деталях, но очевидные вещи надо замечать и проверять.

> В инструкции описано, что устройство настроено как slave, адрес 247, 1sbit, even, 9600
По хорошему, надо задать себе вопрос - где обеспечиваются данные требования 1sbit, even, 9600.
Ответ - 1sbit везде по умолчанию, 9600 вы указываете в begin, но even не поддерживается SoftwareSerial. Как решение можно предложить использование https://github.com/ljbeng/SoftwareSerialParity/tree/master

> RE DE на выходе из модуля мною соединены и подключены в D4
Но в коде у вас это нигде не указано. Наверное должно быть
Modbus master(0, mySerial, 4);
 
  • Лойс +1
Реакции: GoodRon

GoodRon

✩✩✩✩✩✩✩
14 Мар 2022
8
2
У каждого свое понимание "путь истинный"
Я сторонник осознанного подхода, а не метода тыка.
Полностью с Вами соглашусь, был использован метод "тыка", к моему сожалению, мне не повезло добиться результата таким методом.
Однако Ваши советы помогли мне получить первые пакеты информации от устройства. Спасибо Вам большое, хотя бы за то что не закидали ссаными тряпками)))

Осталось только все равно не очень понятно, что имеется ввиду под описанием "Регион"
 
  • Лойс +1
Реакции: Александр_1996

Александр_1996

✩✩✩✩✩✩✩
24 Авг 2025
1
0
@GoodRon, извиняюсь что влез в чужую тему) подскажите пожалуйста как вам это удалось? Уже неделю не могу победить адаптер котла который тоже по модбасу. Тоже собираю скетч "методом тыка"
 

GoodRon

✩✩✩✩✩✩✩
14 Мар 2022
8
2
вот мой код, возможно он вам поможет если нужен EVEN
C++:
#include <ModbusRtu.h>
#include <SoftwareSerialParity.h>

// data array for modbus network sharing
uint16_t au16data[16];
uint8_t u8state;

SoftwareSerialParity mySerial(7, 8);//Create a SoftwareSerial object so that we can use software serial. Search "software serial" on Arduino.cc to find out more details.
Modbus master(0, mySerial, 10); // this is master and RS-232 or USB-FTDI via software serial
modbus_t telegram;

unsigned long u32wait;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600, EVEN);//use the hardware serial if you want to connect to your computer via usb cable, etc.
  master.start(); // start the ModBus object.
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0;
}

void loop() {
  switch( u8state ) {
  case 0:
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1:
    telegram.u8id = 247; // slave address
    telegram.u8fct = 4; // function code (this one is registers read)
    telegram.u16RegAdd = 4002; // start address in slave
    telegram.u16CoilsNo = 1; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 2000;
      Serial.println(au16data[0]);//Or do something else!
    }
    break;
  }
}
 
  • Лойс +1
Реакции: Александр_1996