Arduino Mega 2560 Master в сети ModBus RTU

Shamil
Offline
Зарегистрирован: 03.08.2015

Доброго времени суток. Прочитав не мало статей про протокол ModBus RTU, так и не смог понять как заставить Arduino отправлять запрос ведомому устройству. Использую библиотеку ModbusRtu, открываю пример из этой же библиотеки. Просьба указать путь в нужном напровлении (какие параметры изменить и куда вбивать то, что нужно отправить) 

#include <ModbusRtu.h>

Modbus master(0, 1, 18);

modbus_t telegram;

uint16_t au16data[16];

uint8_t u8state;
unsigned long u32wait;

void setup() {
  master.begin( 9600 );
  master.setTimeOut( 2000 );
  u32wait = millis() + 1000;
  u8state = 0;
}

void loop() {
  switch ( u8state ) {
    case 0:
      if (millis() > u32wait) u8state++;
      break;
    case 1:
      telegram.u8id = 1;
      telegram.u8fct = 6;
      telegram.u16RegAdd = 1;
      telegram.u16CoilsNo = 4;
      telegram.au16reg = au16data;

      master.query( telegram );
      u8state++;
      break;
    case 2:
      master.poll();
      if (master.getState() == COM_IDLE) {
        u8state = 0;
        u32wait = millis() + 100;
      }
      break;
  }

}

 

 

Shamil
Offline
Зарегистрирован: 03.08.2015

Вот что получилось(нашел куда и что вписывать)

#include <ModbusRtu.h>

uint16_t au16data[16];
uint8_t u8state;
Modbus master(0,1,22);

modbus_t telegram;

unsigned long u32wait;

void setup() {
  master.begin( 9600 );
  master.setTimeOut( 2000 );
  u32wait = millis() + 1000;
  u8state = 0; 
  au16data[0] = 1;// данные выглядят как 0x0001
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++;
    break;
  case 1: 
    telegram.u8id = 1; 
    telegram.u8fct = 6;
    telegram.u16RegAdd = 40960; // номер регистра выглядит как 0xA000
    telegram.u16CoilsNo = 4;
    telegram.au16reg = au16data;

    master.query( telegram );
    u8state++;
    break;
  case 2:
    master.poll();
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 100; 
    }
    break;
  }
}

 

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

Отлично! я тут голову ломаю уже 4-й день над тем что за int данные подставляются в массив пакета... оказывается это числа в dec системе, которые надо прикинуть какие будут в hex системе ))) Ну это пол беды )) а как теперь полученный ответ отправить в serial порт? У меня Мега, на ней 4 серийных порта. Для 485чипа я пользую 1й (Serial1) а Serial пользую для компа. Теперь надо в Serial отправить то что получила ардуина по модбасу. Как?? ))

Alexey-kipia
Alexey-kipia аватар
Offline
Зарегистрирован: 14.03.2016

Dr_grizzly пишет:

Отлично! я тут голову ломаю уже 4-й день над тем что за int данные подставляются в массив пакета... оказывается это числа в dec системе, которые надо прикинуть какие будут в hex системе ))) Ну это пол беды )) а как теперь полученный ответ отправить в serial порт? У меня Мега, на ней 4 серийных порта. Для 485чипа я пользую 1й (Serial1) а Serial пользую для компа. Теперь надо в Serial отправить то что получила ардуина по модбасу. Как?? ))

Вы уже разобрались?

Полученные данные по ModBus лежат в массиве ранее объявленном для обмена по ModBus. К примеру

uint16_t au16data[16];  //!< data array for modbus network sharing

Только нужно учесть, что они шестнадцатибитные и необязательно dec. Нужно преобразовать в нужный вид и отправить в Serial или по половинке. Например сначала младший байт потом старший.
RizONE
Offline
Зарегистрирован: 22.03.2018

Alexey-kipia пишет:

Только нужно учесть, что они шестнадцатибитные и необязательно dec. Нужно преобразовать в нужный вид и отправить в Serial или по половинке. Например сначала младший байт потом старший.

Подскажите пожалуйста как если известно, что прочитанные данные типа float?

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

Я не встречал еще float данных по модбас... к примеру терморегулятор Autonics отправляет данные о температуре 14.5(dec) С  как 91(hex). Частотник Mitsubishi частоту 48.60Гц отправляет как 12FC, т.е. 4860(dec). А у вас что за данные?

RizONE
Offline
Зарегистрирован: 22.03.2018

В документации к вакуумметру ВМЦ написано, что данные о давлении (Па) читаются из регистра ввода 1000 и они типа float

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Тип float занимает 4 байта или 2 слова, т.е. 2 регистра modbus. Бывает прямой и обратный (инверсный) float. У инверсного регистры имеют обратный порядок.
Чтобы получить значение во float, нужно сохранить в памяти оба регистра modbus (они должны находиться рядом), далее нужно получить указатель на первый и них, затем преобразовать его в указатель на float и разыменовать его. Это один из возможных способов. Есть и другие варианты.

Dr_grizzly
Dr_grizzly аватар
Offline
Зарегистрирован: 07.12.2015

Могу ошибиться, но вроде мы обсуждали подобное в этом топике http://arduino.ru/forum/proekty/modbusrtu-modbustcp-arduino-i-owen-plc?page=1#comment-237810

RizONE
Offline
Зарегистрирован: 22.03.2018

Создал новую тему http://arduino.ru/forum/programmirovanie/rabota-s-vakuummetrom-vmts-po-m...

если не трудно, просьба отвечать там