Работа с Modbus RTU

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Здравствуйте. Имеется частотный преобразователь, подключаемый по интерфейсу RS485 и работающий по протоколу Modbus RTU. Так же имеется USB to RS485 Converter. С помощью программы QModbus, мне удалось прочитать нужный мне регистр и получить значение.

Так же имеется Arduino Uno и преобразователь MAX 485, RS485 TTL.

Подключал по вот такой вот схеме:

Только у меня не задействованы провода на VCC и GND, так как когда я их подключаю, перестает работать соединение с ПЧ. 

Вот фото подключения:

Можно ли вообще с помощью Arduino, считать нужный мне регистр и вывести его через Serial.Print в мониторе порта Arduino?

Подключение RS485 в ПЧ подключается 2 проводами виой пары, на A+ и B-, так же там имеются входа под 5V и GND, но они не задействованы.

nik182
Offline
Зарегистрирован: 04.05.2015

Что значит "имеются входа под 5V и GND, но они не задействованы."? Как без них передача будет работать? 

А считать можно с помощью библиотеки modbusrtu.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Это значит что к ПЧ подключено 2 провода + и - и этого достаточно, чтобы работал RS 485 интерфейс. Возможно я что то не так делаю)

nik182
Offline
Зарегистрирован: 04.05.2015

Нет не достаточно. + - или А В это сигнальные. Питание на том же разёме крайние пины. Микросхему интерфейса запитать надо. Как на схеме.

 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Вот так сейчас выглядит моё подключение.

Но когда я подсоединяю VCC и GND к Arduino, перестает работать USB конвертер и больше не передает данные.

Можете подсказать, как правильно подключить? Я так понял нужно из самого ПЧ брать 5V и GND, присоединять к MAX485 и уже от него на ардуину?

Logik
Offline
Зарегистрирован: 05.08.2014

Плату USB to RS485 Converter питать необходимо. Связывать её землю и питание с соответствующими ПЧ ненужно. Первая схема в #1 верная. Назначение разема USB с зеленым раземчиком какое? Если для запитки  USB to RS485 Converter то чего подключили на A и B?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

...

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Вот какой парадокс. Когда я не питаю USB to RS485 и он подключен как на схеме, всё работает. Как только я даю питание на ардуино, USB to RS485 перестает работать.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

В общем запитал 5V и GND ПЧ с MAX485, всё заработало. Работает как USB to RS485, так и сам Arduino.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

А если питаю MAX485 от питания Arduino, USB to RS485 перестает работать)

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Вроде бы разобрался. Теперь нужен скетч для теста. Никто не подскажет, где можно найти пример, опроса допустим 29 регистра Modbus?

nik182
Offline
Зарегистрирован: 04.05.2015

В примерах библиотеки есть чтение регистра. Достаточно свой номер подставить.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

А можно ссылочку на библиотеку? (:

nik182
Offline
Зарегистрирован: 04.05.2015

https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino

simple_master.ino

telegram.u16RegAdd = 1; // start address in slave = Yours adress
telegram.u16CoilsNo = 4; // number of elements (coils or registers) to read

 

 

 

 
VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Еще глупый вопрос, как вывести в монитор порта Arduino, то что он принимает? :)

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

И что нужно здесь указывать? :)

Modbus master(0,0,0); // this is master and RS-232 or USB-FTDI

 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

В общем попытаюсь описать всё подробно.

У меня ПЧ висит на 4 COM порте, ардуино висит на 3 COM порте.

Всё соеднинено через MAX485, как на фото которые выше.

ПЧ имеет BUS адрес #2.

Как мне правильно обратиться к ПЧ через Arduino, считать 29 регистр и вывести его в мониторе порта Arduino?

Logik
Offline
Зарегистрирован: 05.08.2014

VaDoSiQ пишет:

У меня ПЧ висит на 4 COM порте, ардуино висит на 3 COM порте.

Отэто поворот сюжета )))

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

В каком смысле?)))

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

В общем вот что получилось:

Скетч:

/**
 *  Modbus master example 1:
 *  The purpose of this example is to query an array of data
 *  from an external Modbus slave device. 
 *  The link media can be USB or RS232.
 *
 *  Recommended Modbus slave: 
 *  diagslave http://www.modbusdriver.com/diagslave.html
 *
 *  In a Linux box, run 
 *  "./diagslave /dev/ttyUSB0 -b 19200 -d 8 -s 1 -p none -m rtu -a 1"
 *   This is:
 *    serial port /dev/ttyUSB0 at 19200 baud 8N1
 *    RTU mode and address @1
 */

#include <ModbusRtu.h>

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

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

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

unsigned long u32wait;

void setup() {
  master.begin( 9600 ); // baud-rate at 19200
  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 = 1; // slave address
    telegram.u8fct = 3; // function code (this one is registers read)
    telegram.u16RegAdd = 29; // start address in slave
    telegram.u16CoilsNo = 2; // 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() + 100; 
    }
    break;
  }
}

Терминал Termite:

Терминал Arduino:

Я так понимаю, приём идет, так как и RX на Arduino мигает.

Но как перевести эту T, в значение? Должно быть не T, а 1,500.

nik182
Offline
Зарегистрирован: 04.05.2015

У вас в программе нет вывода в терминал ардуины. Откуда там что берётся? С линии 485? Так там живут не буквы а двоичные данные. В инициализации третий параметр - номер ноги разрешения передачи модуля 485. На схеме провод есть в инициализации 0. Подключить модуль 485 к ардуине и одновременно к компьютеру можно при условии установки 1к резисторов между модулем и ардуиной. Иначе будет конфликт. Но и потом будет конфликт передачи. 485 надо вешать на софтком, если хотите получать с него данные на ардуину и выводить их в буквенном виде на компьютер. 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Вот смотрите:

/**
 *  Modbus master example 1:
 *  The purpose of this example is to query an array of data
 *  from an external Modbus slave device. 
 *  The link media can be USB or RS232.
 *
 *  Recommended Modbus slave: 
 *  diagslave http://www.modbusdriver.com/diagslave.html
 *
 *  In a Linux box, run 
 *  "./diagslave /dev/ttyUSB0 -b 19200 -d 8 -s 1 -p none -m rtu -a 1"
 *   This is:
 *    serial port /dev/ttyUSB0 at 19200 baud 8N1
 *    RTU mode and address @1
 */

#include <ModbusRtu.h>

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

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

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

unsigned long u32wait;

void setup() {
  master.begin( 9600 ); // baud-rate at 19200
  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 = 1; // slave address
    telegram.u8fct = 3; // function code (this one is registers read)
    telegram.u16RegAdd = 29; // start address in slave
    telegram.u16CoilsNo = 2; // 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() + 1000; 
    }
    break;
  }
}
    telegram.u16RegAdd = 29; // Это адрес регистра, который легко читается через USB to RS485 в программе QModBus
    telegram.u16CoilsNo = 2; // Это номер поля, в котором видно параметр 1500, как на скриншоте сверху.

Что я делаю неправильно?

Вот что пишет в Termite:

Я так понимаю это запрос который отправляется на мой ПЧ, а как увидеть ответ самого ПЧ?

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Подключал и через резистор на 1кОм и на 120 Ом. Толку нет.

nik182
Offline
Зарегистрирован: 04.05.2015

Да. Это ваш запрос. Если нет ответа, то скорее всего ваш запрос не доходит до устройства. Может быть по тому, что у него адрес 2 , а у вас в запросе 1?

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Раньше был 2, сейчас 1.

MaksVV
Offline
Зарегистрирован: 06.08.2015

предлагаю мой вариант как считать из модбаса и отправить на сериал. Только зачем тут конвертер usb to RS485?

Подключаем по схеме 

Скетч мастера 

// Модбас подключить к софтсериалу
#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);   // 7 - Rx;   8 - Tx; 

// Ниже переменные для модбаса

int _modbusMasterDataTable_4_reg_1[1];
int _modbusMasterAddressTable_4_reg_1[1] = {29};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {2000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};



// тут уже наши переменные 

int Frequency = 0;      // переменная частоты, куда будет записываться данные из регистра 29 Holding Registers модбаса


long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 1; // время интервала обновления информации в сериал порте, сек -  1c


void setup()
{
Serial.begin (9600); // для монитора порта - используем железный порт ардуино
Serial100.begin(19200); // софтсериал модбаса
pinMode(10, OUTPUT);   // пин DE RE RS-485 НЕ МЕНЯТЬ!
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}

void loop()
{




//Плата:1
Frequency = (_modbusMasterDataTable_4_reg_1[0]);   // чтение данных из регистра 29 Holding Registers модбаса и запись в переменную

///// периодически скидываем переменную Frequency  в монитор порта
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) { Serial.println (Frequency);
        previousMillis = currentMillis;}  


////// всё что ниже - для модбаса


switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 1;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 29;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 0;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(3);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 3 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

Baks
Baks аватар
Offline
Зарегистрирован: 11.01.2016

почитайте тему может поможет вам, я долго сам ковырялся с модбас пока до меня дошло что и к чему

http://arduino.ru/forum/programmirovanie/modbus-rtu

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Я его не использую в подключении. Я имею ввиду, что на прямую, он работает. А ардуино нет. Вот моя схема подключения.

MaksVV
Offline
Зарегистрирован: 06.08.2015

всё же попробуйте по моей схеме и скетч. Должно заработать

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Сейчас попробую и отпишусь.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Подключил по Вашей схеме, залил скетч.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Вот подключил к USB to RS485 на А+ и B- без питания и земли. Работает и показывает значение.

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Если я считываю регистр №29, здесь в скобках тоже его прописывать?

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

 

nik182
Offline
Зарегистрирован: 04.05.2015

В ардуине мало памяти, поэтому в скобках прописываются не номера регитров, а количество, которое будет в обработке. У вас два регистра. Т.е.достаточно [2]. При этом 29 регистр будет иметь индекс массива [0], 1500 будет лежать в [1]. Во всех приведённых вами скечах я ни разу не видел вывода из ардуины в компьютер данных. Как вы собираетесь понять - получила ардуина что то или нет? И как отправлять дальше в комп?

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

VaDoSiQ пишет:

Вот подключил к USB to RS485 на А+ и B- без питания и земли. Работает и показывает значение.


Мне кажется или там у вас на картинке 0 показывает в регистре 29? Дак что же вам не нравится в моем варианте? 0 и должен быть. Считайте по моему методу регистр 30 и получите свои 1500

MaksVV
Offline
Зарегистрирован: 06.08.2015

вот тебе скетч твоего мастера

// Модбас подключить к софтсериалу
#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);  //  Rx-7;  Tx-8

int _modbusMasterDataTable_4_reg_1[2];
int _modbusMasterAddressTable_4_reg_1[2] = {29, 30};  // тут адреса регистров. 4_reg означает что это Holding Registers

// т.е. на _modbusMasterDataTable_4_reg_1[0] будет 29 адрес, на _modbusMasterDataTable_4_reg_1[1] будет 30 адрес

byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {2000}; // интервал обмена со слейвом (2 сек)
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};


int Register_29 = 29;
int Register_30 = 30;

long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 2; 


void setup()
{
Serial.begin (9600); // для монитора порта - используем железный порт ардуино
Serial100.begin(19200); // софтсериал для модбаса
pinMode(10, OUTPUT);    //пин DE-RE     RS-485 НЕ МЕНЯТЬ!
digitalWrite(10, LOW);  //пин DE-RE     RS-485 НЕ МЕНЯТЬ!
// ниже требуха для функционирования модбаса
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}

void loop()
{

unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) { 
Serial.print ("Reg29: "); Serial.print (Register_29); 
Serial.print ("  Reg30: "); Serial.println (Register_30);
previousMillis = currentMillis;}  


Register_29 = (_modbusMasterDataTable_4_reg_1[0]);
Register_30 = (_modbusMasterDataTable_4_reg_1[1]);


// ниже требуха для функционирования модбаса

switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 2;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 29;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 0;
break;
case 2:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 30;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 1;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(3);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 3 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Всё подключил по схеме, результата нет.

 

Я не знаю почему оно показывает данные в 30 регистре. Вообще по даташиту, должны храниться в 29 регистре. Если через QModBus я указываю считать 30 регистр, выбивает ошибку. Если указываю считать 29 регистр и выставляю 2 Coils, оно показывает.

MaksVV
Offline
Зарегистрирован: 06.08.2015

В строке 41 попробуй выставить скорость сериала порта 9600 бод. Сюдя по картинке у тебя 9600. Незнаю почему я 19200 поставил. 

Вот так надо 

041 Serial100.begin(9600); // софтсериал для модбаса

 И еще у тебя точно адрес слейва "1" ?

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Да. Тут проблема с самим регистром.

Вот твой код, и мой другой регистр. Считало без проблем. Спасибо огромное за это тебе, кстати.

// Модбас подключить к софтсериалу
#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);   // 7 - Rx;   8 - Tx; 

// Ниже переменные для модбаса

int _modbusMasterDataTable_4_reg_1[1];
int _modbusMasterAddressTable_4_reg_1[1] = {1039};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {2000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};



// тут уже наши переменные 

int Frequency = 0;      // переменная частоты, куда будет записываться данные из регистра 29 Holding Registers модбаса


long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 10; // время интервала обновления информации в сериал порте, сек -  1c


void setup()
{
Serial.begin(9600); // для монитора порта - используем железный порт ардуино
Serial100.begin(9600); // софтсериал модбаса
pinMode(10, OUTPUT);   // пин DE RE RS-485 НЕ МЕНЯТЬ!
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}

void loop()
{




//Плата:1
Frequency = (_modbusMasterDataTable_4_reg_1[0]);   // чтение данных из регистра 29 Holding Registers модбаса и запись в переменную

///// периодически скидываем переменную Frequency  в монитор порта
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) { Serial.println (Frequency);
        previousMillis = currentMillis;}  


////// всё что ниже - для модбаса


switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 1;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1039;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 0;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(3);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 3 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Подскажите пожалуйста, вот попытался считать 2 регистра сразу. Вроде бы делал всё как у Вас, но оно читает только один, во втором пишет: 0. Если по одному, тогда считывает норм.

Вот код:

// Модбас подключить к софтсериалу
#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);   // 7 - Rx;   8 - Tx; 

// Ниже переменные для модбаса

int _modbusMasterDataTable_4_reg_1[2];
int _modbusMasterAddressTable_4_reg_1[2] = {1019, 1039};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {2000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};



// тут уже наши переменные 


float Power = 0;
int Frequency = 0;

long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 5; // время интервала обновления информации в сериал порте, сек -  5c


void setup()
{
Serial.begin(9600); // для монитора порта - используем железный порт ардуино
Serial100.begin(9600); // софтсериал модбаса
pinMode(10, OUTPUT);   // пин DE RE RS-485 НЕ МЕНЯТЬ!
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}

void loop()
{
///// периодически скидываем переменную Frequency  в монитор порта
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) {
Serial.print("Motor Power: ");  Serial.print(Power, 0);
Serial.println();
Serial.print("Motor Frequency: ");  Serial.print(Frequency);
Serial.println();
        previousMillis = currentMillis;} 
Power = (_modbusMasterDataTable_4_reg_1[0]);
Frequency = (_modbusMasterDataTable_4_reg_1[1]);
////// всё что ниже - для модбаса


switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 1;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1019;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 0;
break;
case 2:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1039;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 1;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(3);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 3 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Попробуй этот код 

#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);

int _modbusMasterDataTable_4_reg_1[2];
int _modbusMasterAddressTable_4_reg_1[2] = {1019, 1039};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {1000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};



int Power_1019 ;
int Frequency_1039 ;

long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 2; 

void setup()
{
Serial.begin (9600);
Serial100.begin(9600);
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}
void loop()
{


unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) {
Serial.print("Motor Power: ");  Serial.print(Power_1019, 0);
Serial.println();
Serial.print("Motor Frequency: ");  Serial.print(Frequency_1039);
Serial.println();
        previousMillis = currentMillis;} 


Power_1019 = (_modbusMasterDataTable_4_reg_1[0]);
Frequency_1039 = (_modbusMasterDataTable_4_reg_1[1]);




switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 2;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1019;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 0;
break;
case 2:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1039;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 1;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(5);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 5 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

в твоем скетче ошибка в строке 115, у тебя там temp=1, а должно быть temp=2

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Не помогло. Скетч считывает всё нужные мне регистры. Но по одному, если добавляю еще какой то, не работает.

MaksVV
Offline
Зарегистрирован: 06.08.2015

а ты скетч из сообщения #40 тоже попробовал?

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Ну да, скрин из него и сделал.

Вот допустим когда вот так, оно работает, если вывожу в терминал другин переменные, нули пишет.

// Модбас подключить к софтсериалу
#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);   // 7 - Rx;   8 - Tx; 

// Ниже переменные для модбаса

int _modbusMasterDataTable_4_reg_1[3];
int _modbusMasterAddressTable_4_reg_1[3] = {29,1019,1039};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {2000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};



// тут уже наши переменные 


long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 5; // время интервала обновления информации в сериал порте, сек -  5c


void setup()
{
Serial.begin(9600); // для монитора порта - используем железный порт ардуино
Serial100.begin(9600); // софтсериал модбаса
pinMode(10, OUTPUT);   // пин DE RE RS-485 НЕ МЕНЯТЬ!
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}

void loop()
{
int Power = (_modbusMasterDataTable_4_reg_1[0]);
int Frequency = (_modbusMasterDataTable_4_reg_1[1]);
int Frequency2 = (_modbusMasterDataTable_4_reg_1[2]);
///// периодически скидываем переменную Frequency  в монитор порта
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) {
Serial.print("Local Reference: ");  Serial.print(Frequency);
Serial.println();
        previousMillis = currentMillis;} 
////// всё что ниже - для модбаса


switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 1;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 29;
_modbusTelegramm.numbeRegs = 2;
_modbusTelegramm.valueIndex = 0;
break;
case 2:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1019;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 1;
break;
case 3:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1039;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 2;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(3);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 3 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак как так то?  у тебя опять в строке 111 temp =1, ты точно скетч из сообщения #40 взял? Там у меня temp=2. Это число должно быть равно числу считываемых регистров. Т.е. для последнего выложенного тобой скетча должно быть temp =3  

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Вот смотри сам.

// Модбас подключить к софтсериалу
#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);   // 7 - Rx;   8 - Tx; 

// Ниже переменные для модбаса

int _modbusMasterDataTable_4_reg_1[3];
int _modbusMasterAddressTable_4_reg_1[3] = {29,1019,1039};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {2000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};

int Power = 0;
int Frequency = 0;
int Frequency2 = 0;

long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 5; // время интервала обновления информации в сериал порте, сек -  5c


void setup()
{
Serial.begin(9600); // для монитора порта - используем железный порт ардуино
Serial100.begin(9600); // софтсериал модбаса
pinMode(10, OUTPUT);   // пин DE RE RS-485 НЕ МЕНЯТЬ!
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}

void loop()
{
Power = (_modbusMasterDataTable_4_reg_1[0]);
Frequency = (_modbusMasterDataTable_4_reg_1[1]);
Frequency2 = (_modbusMasterDataTable_4_reg_1[2]);
///// периодически скидываем переменную Frequency  в монитор порта
unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) {
Serial.print("Value_1: ");  Serial.print(Frequency);
Serial.println();
Serial.print("Value_2: ");  Serial.print(Power);
Serial.println();
Serial.print("Value_3: ");  Serial.print(Frequency2);
Serial.println();
        previousMillis = currentMillis;} 
////// всё что ниже - для модбаса


switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 3;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 29;
_modbusTelegramm.numbeRegs = 2;
_modbusTelegramm.valueIndex = 0;
break;
case 2:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1019;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 1;
break;
case 3:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1039;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 2;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(3);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 3 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

MaksVV
Offline
Зарегистрирован: 06.08.2015

Щас последний раз скетч выложу для трех регистров, если не поможет, я пас. 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Хорошо)

MaksVV
Offline
Зарегистрирован: 06.08.2015

код для 3 регистров

#include <SoftwareSerial.h>
SoftwareSerial Serial100(7, 8);

int _modbusMasterDataTable_4_reg_1[3];
int _modbusMasterAddressTable_4_reg_1[3] = {29, 1019, 1039};
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterLastRec = 0;
long _modbusMasterStartT35;
byte _modbusMasterBuffer[64];
byte _modbusMasterCurrentReg = 0;
byte _modbusMasterCurrentVariable = 0;
struct _modbusMasterTelegramm {
  byte slaveId;        
  byte function;        
  int startAddres;   
  int numbeRegs;   
  int valueIndex;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {1000};
const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16};
int Frequency; //Frequency1          1
int Frequency2; //Frequency2          2
int Power; //Power               3

long previousMillis = 0;    // храним время последнего обновления вывода в сериал порт
long interval = 5; // время интервала обновления информации в сериал порте, сек -  5c

void setup()
{
Serial.begin (9600);
Serial100.begin(9600);
pinMode(10, OUTPUT);
digitalWrite(10, LOW);
for(int i=0; i<1; i++) {_startTimeMasterRegs[i] =  millis();}
}
void loop()
{


unsigned long currentMillis = millis();

if(currentMillis - previousMillis > interval*1000) {
Serial.print("Value_1: ");  Serial.print(Frequency);
Serial.print("   Value_2: ");  Serial.print(Power);
Serial.print("   Value_3: ");  Serial.println(Frequency2);
        previousMillis = currentMillis;}

//Плата:1
Power = (_modbusMasterDataTable_4_reg_1[0]);
Frequency = (_modbusMasterDataTable_4_reg_1[1]);
Frequency2 = (_modbusMasterDataTable_4_reg_1[2]);




switch ( _modbusMasterState ) {
    case 1:
      _nextModbusMasterQuery();
      break;
    case 2:
      pollModbusMaster();
      break;
  }
}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }
int modbusCalcCRC(byte length, byte bufferArray[])
{
  unsigned int temp, temp2, flag;
  temp = 0xFFFF;
  for (unsigned char i = 0; i < length; i++) {
    temp = temp ^ bufferArray[i];
    for (unsigned char j = 1; j <= 8; j++) {
      flag = temp & 0x0001;
      temp >>= 1;
      if (flag)   temp ^= 0xA001;
    }
  }
  temp2 = temp >> 8;
  temp = (temp << 8) | temp2;
  temp &= 0xFFFF;
  return temp;
}
void _nextModbusMasterQuery()
{
_selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable);
if (_modbusMasterCurrentReg == 0)  return;
_createMasterTelegramm();
_modbusMasterSendQuery();
}
void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar)
{
bool isNeeded = 1;
if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;}
if (!(_isTimer  ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;}
if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}}
if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;}
byte temp;
switch (oldReg) {
case 1:
temp = 3;
 break;
 }
if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;}
_startTimeMasterRegs[oldReg -1] = millis();
if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} 
_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;
}
void _createMasterTelegramm()
{
switch (_modbusMasterCurrentReg) {
case 1:
_modbusTelegramm.slaveId = 1;
switch (_modbusMasterCurrentVariable) {
case 1:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 29;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 0;
break;
case 2:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1019;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 1;
break;
case 3:
_modbusTelegramm.function = 3;
_modbusTelegramm.startAddres = 1039;
_modbusTelegramm.numbeRegs = 1;
_modbusTelegramm.valueIndex = 2;
break;
}
break;
}
}
void _modbusMasterSendQuery()
{
byte currentIndex = _modbusTelegramm.valueIndex;
  _modbusMasterBuffer[0]  = _modbusTelegramm.slaveId;
  _modbusMasterBuffer[1] = _modbusTelegramm.function;
  _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres );
  _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres );
  switch ( _modbusTelegramm.function ) {
case 3:
 _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs );
      _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs );
      _modbusMasterBufferSize = 6;
      break;
}
  _modbusMasterSendTxBuffer();
  _modbusMasterState = 2;
}
void _modbusMasterSendTxBuffer()
{
 byte i = 0;
int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer );
  _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8;
_modbusMasterBufferSize++;
 _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff;
 _modbusMasterBufferSize++;
digitalWrite(10, 1 );
delay(5);
Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize );
digitalWrite(10, 0 );
Serial100.flush();
  _modbusMasterBufferSize = 0;
  _modbusMasterSendTime = millis();
}
void pollModbusMaster()
{
if (_modbusTelegramm.slaveId == 0) {   _modbusMasterState = 1;   return;}
  if (_isTimer(_modbusMasterSendTime, 1000)) {
    _modbusMasterState = 1;
    return;
  }
  byte avalibleBytes = Serial100.available();
  if (avalibleBytes == 0) return;
  if (avalibleBytes != _modbusMasterLastRec) {
    _modbusMasterLastRec = avalibleBytes;
    _modbusMasterStartT35 = millis();
    return;
  }
  if (!(_isTimer(_modbusMasterStartT35, 5 ))) return;
  _modbusMasterLastRec = 0;
  byte readingBytes = _modbusMasterGetRxBuffer();
  if (readingBytes < 5) {
    _modbusMasterState = 1;
    return ;
  }
byte exeption = validateAnswer();
  if (exeption != 0) {
 _modbusMasterState = 1;
    return;
  }
 switch ( _modbusMasterBuffer[1] ) {
 case 3:
 get_FC3(4);
break;
}
  _modbusMasterState = 1;
  return;
}
byte _modbusMasterGetRxBuffer()
{
boolean bBuffOverflow = false;digitalWrite(10, LOW );
 _modbusMasterBufferSize = 0;
  while (Serial100.available() ) {
    _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read();
    _modbusMasterBufferSize ++;
    if (_modbusMasterBufferSize >= 64) bBuffOverflow = true;
  }
  if (bBuffOverflow) {return -3;}
  return _modbusMasterBufferSize;
}
byte validateAnswer()
{
uint16_t u16MsgCRC =    ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]);
  if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; }
  if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;}
  boolean isSupported = false;
  for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) {
    if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) {
      isSupported = 1;

      break;
    }
  }
  if (!isSupported) {return 1;}
  return 0;
}
void get_FC3(byte table)
{
int currentIndex = _modbusTelegramm.valueIndex;
  byte currentByte = 3;
int value;
  for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) {
   value = word( _modbusMasterBuffer[ currentByte],   _modbusMasterBuffer[ currentByte + 1 ]);
switch ( _modbusMasterCurrentReg ) {
case 1 :
if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;}
break;
}
    currentByte += 2;
  } 
}

 

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

Я так понимаю, Вы пас?)))