ModbusRTU, ModbusTCP Arduino и OWEN PLC

yden
Offline
Зарегистрирован: 30.01.2016

Подскажите плиз, как можно преодолеть ограничение в 29 регистров у ардуинки? Хотелось бы с датчиков ds18b20 температуру гонять.

 

благодарю

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Подключи 16 канальный мультиплексор. https://ru.aliexpress.com/item/CD74HC4067-16-Channel-Analog-Digital-Multiplexer-Breakout-Board-Module-For-Arduino/32787406285.html?spm=2114.13010308.0.0.BXYjS1

Схему и код можно найти на ютубе.

Кстати, если будешь заказывать на Алиэкспресс, то вот Тебе доп. скидка в 10,5% в виде возврата средств на телефон или вебмани первые 7 дней после регистрации. Вот ссылка для регистрации https://cashback.epn.bz/?inviter=qkxtcs и вводите промокод epnbest2017, который Вам даст на семь дней покупок возврат в 10,5%.

Также, если не зарегистрированы на Алиэкспресс, то кидайте мейл на почту, вышлю ссылку, получите на 300 руб купон на покупки и плюс кучу других купонов на скидку.

harbor
Offline
Зарегистрирован: 31.05.2016

yden пишет:

Ребята, а как можно обойти:

#define retry_count 10

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

благодарю

может быть попробовать поставить ноль или космическое число зарядить?

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

harbor пишет:

yden пишет:

Ребята, а как можно обойти:

#define retry_count 10

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

благодарю

может быть попробовать поставить ноль или космическое число зарядить?

Проще свой опрос написать, и опрашивать при каждом проходе. Плюс еще и в том, что с опытом будет больше знаний, будешь оптимизировать свой код получая постоянный результат в виде лучшей работы программы. А чужая библиотека - кот в мешке, и зависимость от нее в самом узком месте программы. Это же не опрос часов - тут важно все контролировать самому.

yden
Offline
Зарегистрирован: 30.01.2016

SIR пишет:

harbor пишет:

yden пишет:

Ребята, а как можно обойти:

#define retry_count 10

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

благодарю

может быть попробовать поставить ноль или космическое число зарядить?

Проще свой опрос написать, и опрашивать при каждом проходе. Плюс еще и в том, что с опытом будет больше знаний, будешь оптимизировать свой код получая постоянный результат в виде лучшей работы программы. А чужая библиотека - кот в мешке, и зависимость от нее в самом узком месте программы. Это же не опрос часов - тут важно все контролировать самому.

Возможно и так. Но для начала думаю все же готовые решения рассмотреть. Итак с rs485 с нового года на одном месте топчусь.

harbor
Offline
Зарегистрирован: 31.05.2016

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

на счет числа опросов можно как раз в самой библиотеке и поковыряться

yden
Offline
Зарегистрирован: 30.01.2016

Покритикуйте идею, плиз.

Для преодоления ограничения в количестве регистров ардуинки возможно ли для сохранения в регистре использовать текстовую или числовую строку данных.

Например, к ардуинке-слейву подключены 3 датчика температуры, пара реле. Она все эти данные пишет в один регистр в виде строки с разделением пробелом: 25 24 15 1 1. Читать как 25, 24, 15 - температуры, 1, 1 - сработка реле. Ардуинка-мастер эти данные берет, раскрывает и получаем отдельные значения.

Это возможно?

 

Благодарю

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

yden пишет:

Покритикуйте идею, плиз.

Для преодоления ограничения в количестве регистров ардуинки возможно ли для сохранения в регистре использовать текстовую или числовую строку данных.

Например, к ардуинке-слейву подключены 3 датчика температуры, пара реле. Она все эти данные пишет в один регистр в виде строки с разделением пробелом: 25 24 15 1 1. Читать как 25, 24, 15 - температуры, 1, 1 - сработка реле. Ардуинка-мастер эти данные берет, раскрывает и получаем отдельные значения.

Это возможно?

 

Благодарю

Аналоговые значения, если регистры идут последовательно, можно передать функцией 16, дискреты, если идут последовательно в приемнике, можно передать функцией 15.

В Modbus нет функций, позволяющих передавать за один пакет разные виды данных, но Вы можете отойти от этого стандарта и передавать свой пакет( (если не будете использовать бибилиотеки), привязать ему, например, функцию номер 33, под которой будете уже знать, что эти байты - туда, а эти - туда. Да и вообще придумать свой стандарт передачи - зачем Вам Modbus, если Вы не работаете с левыми устройствами, обязующими Вас использовать данный протокол. Посылайте слейвам свой пакет данных, идущих в нужной Вам последовательности, если слейвы больше ни с кем не "общаются", а в слейвах сортировать данные куда нужно и также собирать свой пакет для отправки.

SIR
SIR аватар
Offline
Зарегистрирован: 07.11.2016

Можно создать такой пакет в слейве: температура1, температура2, температура3, реле1, реле2, проверочный байт. Проверочный байт можете создать сложением всех 5 байтов. Ждете запроса от мастера своей комбинации байт, например 255. Получив данное число - кидаете свой пакет мастеру, читаете аналоги, дискреты и далее ждете нового запроса. Мастер принимает пакет, пишет в массив, складывает первые 5 байт и проверяет с 6 байтом - если числа равны - значит пакет получен, обрабатываем данные из массива как надо, если числа не равны - посылаем новый запрос.

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

А в чем проблема собственно? )) кто мешает постоянно генерировать пакет на оправку в цикле loop? Ведь retry_count - это число повторов, если слейв не ответил нам. Задаем ему например 2 пакета (10 пакетов вешает цикл отправки на одном пакете, 1 пакет не надежен, т.к. слейв может не услышать его полностью). Мастер отправит пакет, если нет ответа отправит его еще раз. Чтобы повторить эту процедуру просто инициализируем пакет Modbus не в Setup а в основном теле цикла. К примеру таким пакетом:  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS,    0, 1, 0);

Ардуино его соберет и попробует отправить, попыток будет 2, затем снова соберет и попробует отправить, и так бесконечно))))

Желательно между циклами генерации поставить задержку, чтобы они не генерировались с частотой процессора )) а то rs485 будет не успевать их преобразовывать на отправку, как придут новые данные.

jtahun
Offline
Зарегистрирован: 20.04.2017

Здравствуйте товарищи! Вопрос все о том же... Связь  аналогового модуля ОВЕН с ардуиной-мастер.

Задача - в браузере наблюдать измеренное значение. 

Использую: ардуино Уно, преобразователь RS485, ethernet модуль(enc28j60), ну и собственно Овен МВ110-2АС.

для опроса Овен на ардуине подключаю SimpleModbusMaster.h

В общем-то успех есть, но с оговорками. Возникают 2-е проблемы:

Измеренные значения не изменяются, даже если отсоединить сигнал от канала ОВЕН.

И инициализирутся только один Пакет, т.е. одним пакетом могу опросить 2 канала, а опросить каждый канал отдельным пакетом нет.

При опросе использовал и 3-ю, и 4-ю функции Modbus. Измеренные значения хранятся 0х100 - 1 канал, 0х101 - 2 канал. 

001 #include <SimpleModbusMaster.h>
002 #include <EtherCard.h>
003  
004 static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
005 static byte myip[] = { 192,168,1,203 };
006  
007 byte Ethernet::buffer[500];
008 BufferFiller bfill;
009  
010  
011 //////////////////// Макроопределения портов и настройки программы  ///////////////////
012 #define baud        9600 // скоростьобмена по последовательному интерфейсу. (UART)
013 #define timeout     1000 // Длительность ожидание ответа (таймаут modbus)
014 #define polling     200  // скорость опроса по modbus
015 #define retry_count 10   // количесво запросов modbus до ошибки и останова обмена
016 #define TxEnablePin 2    // Tx/Rx пин RS485
017 #define LED1        9    // светодиод 1
018 #define LED2        13   // светодиод 2
019  
020 // Общая сумма доступной памяти на master устройстве, для хранения данных
021 // не забудьте изменить макроопределение TOTAL_NO_OF_REGISTERS. Если из слейва
022 // запрашиваешь 4 регистра, то тогда в массиве reg должно быть не меньше 4х ячеек
023 // для хранения полученных данных.
024 #define TOTAL_NO_OF_REGISTERS 6
025  
026 // Масив пакетов modbus
027 // Для добавления новых пакетов просто добавте ихсюда
028 // сколько вам нужно.
029 int ch1,ch2;
030 enum
031 {
032   PACKET1,
033   PACKET2,
034   PACKET3,
035   PACKET4,
036   TOTAL_NO_OF_PACKETS // эту строку неменять
037 };
038  
039 // Масив пакетов модбус
040 Packet packets[TOTAL_NO_OF_PACKETS];
041  
042 // Массив хранения содержимого принятых и передающихся регистров
043 unsigned int regs[TOTAL_NO_OF_REGISTERS];
044  
045  static word homePage() {
046   
047   bfill = ether.tcpOffset();
048   bfill.emit_p(PSTR(
049     "HTTP/1.0 200 OK\r\n"
050     "Content-Type: text/html\r\n"
051     "Pragma: no-cache\r\n"
052     "\r\n"
053     "<meta http-equiv='refresh' content='1'/>"
054     "<title>ModBus Master</title>"
055     "<h1>$D::$D</h1>"),
056       regs[0],regs[1]);
057   return bfill.position();
058 }
059  
060 void setup()
061
062   Serial.begin(9600);
063   if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
064     Serial.println(F("Failed to access Ethernet controller"));
065   ether.staticSetup(myip);
066   
067  // Настраиваем пакеты
068  // Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет
069  // помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив reg
070   
071  // Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
072  modbus_construct(&packets[PACKET1], 16, READ_INPUT_REGISTERS, 256, 2, 0); // (slave адрес 16, регистр 0x100)
073 //modbus_construct(&packets[PACKET2],16, READ_HOLDING_REGISTERS, 257, 1, 2); // (slave адрес 16, регистр 0x101)
074   
075  // инициализируем протокол модбус
076  modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
077   
078  pinMode(LED1, OUTPUT);
079  pinMode(LED2, OUTPUT);
080 // конец void setup()
081  
082 //onwVersion of loop()
083 void loop()
084 {
085   modbus_update();  
086   word len = ether.packetReceive();
087   word pos = ether.packetLoop(len);
088   
089   if (pos)  // check if valid tcp data is received
090     ether.httpServerReply(homePage()); // send web page data
091     //ch1=regs[0];
092     //ch2=regs[1];
093      Serial.print(" ");
094      Serial.print(regs[0],DEC);
095      Serial.print(" ");
096      Serial.print(regs[1],DEC);
097      Serial.print(" ");
098      /*Serial.print(regs[2],HEX);
099      Serial.print(" ");
100      Serial.print(regs[3],HEX);  */
101      Serial.print("\n");
102      //delay(10);
103  
104 }

 

Tarantino
Offline
Зарегистрирован: 04.06.2017

alexval2007 пишет:
ModbusRTU, ModbusTCP Arduino и OWEN PLC

В этой теме я постараюсь описать свои эксперементы с промышленным протоколом Modbus для локальной сети и RS485 мне удалось как управлять ардуиной с ПЛК так и ардуиной управлять плк и модулями вводы вывода от овена.

позже добавлю еще про ардуино модбус мастер и модуль ввода как slave устройсво

небольшую статеечку окультурить нужно

Подтверждаете стабильность работы библиотеки?

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

"Измеренные значения не изменяются"  - а пробовали через программу ОВЕН Конфигуратор Мх110 посмотерть значения этих каналов? Там изменяются данны? Если да, то можно повесить снифер на СОМ порт и посмотреть какие пакеты обмена идут.

yden
Offline
Зарегистрирован: 30.01.2016

Здравствуйте.

За основу взял библиотеки SimpleModbusMaster.h и SimpleModbusSlave.h. Не "разговаривали" ардуинки по причине битых модулей на max485 (половину отбраковал).

Пробный стенд: 

К мастеру подключен дисплей TM1867 - на него должна приходить информация (температура) со слейва. Мастер посылает 1. К слейву подключен ds18b20. Слейв должен получить от мастера число, если это 1 то зажечь светик на ардуинке (13 пин), и посылает мастеру температуру и число (генерация случайным образом от 0 до 9). Мастер выводит температуру на TM1867 и если число от слейва = 1 то зажигает свой светик.

Что имеем: слейв отвечает мастеру, посылает ему случайное число и температуру, мастер это принимает, выводит на экран, мигает светиком. Но слейв информацию от мастера не получает, т.е 1 не приходит от мастера к слейву, соответственно он светиком не моргает. 

Help!

В мастере сбор пакетов в loop - чтобы в перспективе больше 30 параметров передавать\получать.

мастер:

//#include <iarduino_RTC.h>
#include <Wire.h>
#include <SimpleModbusMaster.h>
#include "TM1637.h"

#define CLK 6           // CLK -> pin D6
#define DIO 5           // DIO -> pin D5
TM1637 tm1637(CLK, DIO); // Семи сегментный индикатор, модуль на TM1637
#define brightness 7  // яркость индикатора, от 0 до 1

//iarduino_RTC time(RTC_DS3231);

int8_t TimeDisp[4];

//пакеты регистров Modbus
long previousMillis_regs = 0;  // храним время последнего формирования пакетов
long interval_regs = 5000;     //интервал
byte i = 0;

//////////////////// Макроопределения портов и настройки программы  ///////////////////
#define baud        19200 // скоростьобмена по последовательному интерфейсу. (UART)
#define timeout     1000 // Длительность ожидание ответа (таймаут modbus)
#define polling     200  // скорость опроса по modbus
#define retry_count 1000   // количесво запросов modbus до ошибки и останова обмена
#define TxEnablePin 4    // Tx/Rx пин RS485
#define LED1        13    // светодиод 1

#define TOTAL_NO_OF_REGISTERS 4

enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  TOTAL_NO_OF_PACKETS // эту строку неменять
};

Packet packets[TOTAL_NO_OF_PACKETS];

unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup()
{
 
  tm1637.init();           // инициализируем индикатор
  tm1637.set(brightness);  // включаем подсветку индикатора
  tm1637.point(POINT_ON);  // включаем точки

  pinMode(LED1, OUTPUT);

} // конец void setup()

void loop()
{
  unsigned long currentMillis_regs = millis();

  //--------------------------------------------------------------------------------------
  //сборка пакетов регистров Modbus
  if (currentMillis_regs - previousMillis_regs > interval_regs)
  {
    previousMillis_regs = currentMillis_regs;
    i++;
  }

  //пакет 1
  if (i == 1)
  {
    // Настраиваем пакеты
    // Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет
    // помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив reg

    // Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
    modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0); // чтение данных slave-master (slave адрес 1, регистр 0)
    modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 1, 1, 1); // чтение данных slave-master (slave адрес 1, регистр 1)
    // Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
    modbus_construct(&packets[PACKET3], 1, PRESET_MULTIPLE_REGISTERS, 2, 1, 2); // запись данных master-slave (slave адрес 1, регистр 2)
    modbus_construct(&packets[PACKET4], 1, PRESET_MULTIPLE_REGISTERS, 3, 1, 3); // запись данных master-slave (slave адрес 1, регистр 3)
    // инициализируем протокол модбус
    modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

    //modbus_update(); // запуск обмена по Modbus

    regs[2] = 1;
   
    i = 0;
  }

  modbus_update(); // запуск обмена по Modbus

  if (regs[1] == 1)
    {
      digitalWrite(LED1, HIGH);
    }
    else
    {
      digitalWrite(LED1, LOW);
    }

  //Serial.println(regs[0]);


  TimeDisp[0] = regs[0] / 10; 
  TimeDisp[1] = regs[0] % 10; 
  TimeDisp[2] = regs[1] / 10; 
  TimeDisp[3] = regs[1] % 10; 

  tm1637.display(TimeDisp); // воводим на индикатор

} // конец void loop()/*
 

слейв:

#include <SimpleModbusSlave.h>
#include <DallasTemperature.h>

//////////////////// Макроопределения портов и настройки программы  ///////////////////
#define TxEnablePin  4       // Tx/Rx пин RS485
#define baud         19200  // скоростьобмена по последовательному интерфейсу. (UART)
#define Slave_ID     1     // Адрес Slave устройсва
#define LED1         13    // светодиод 1

//////////////// Регистры вашего Slave ///////////////////
enum
{
  //Просто добавьте или удалите регистры. Первый регистр начинается по адресу 0
  reg_0,          //  исходящий 1
  reg_1,          //  исходящий 2
  reg_2,          //  входящий 1
  reg_3,          //  входящий 2
  HOLDING_REGS_SIZE // Это не удалять размер массива HOLDING_REGS.
  //общее количество регистров для функции 3 и 16 разделяет тотже самый массив регистров
  //т.е. то же самое адресное пространство
};
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // функции 3 и 16 массив регистров
////////////////////////////////////////////////////////////

//ds18b20
OneWire oneWire(3); // вход датчиков 18b20
DallasTemperature ds(&oneWire);
DeviceAddress ds_frosya = {0x28, 0xFF, 0x33, 0xD0, 0x72, 0x16, 0x5, 0x5A};

//подсчет времени
//опрос датчиков
long previousMillis_sensor = 0;  // храним время последнего опроса датчиков
long interval_sensor = 5000;     //интервал

//температура
int temp;
float i = 0;

void setup()
{
 

  modbus_configure(&Serial, baud, SERIAL_8N2, Slave_ID, TxEnablePin, HOLDING_REGS_SIZE, holdingRegs);
  modbus_update_comms(19200, SERIAL_8N2, 1);

  pinMode(LED1, OUTPUT);
 
}// конец void setup()

void loop()
{
 
  unsigned long currentMillis_sensor = millis();

  //--------------------------------------------------------------------------------------
  //ds
  if (currentMillis_sensor - previousMillis_sensor > interval_sensor)
  {
    previousMillis_sensor = currentMillis_sensor;
    i++;
  }

  //dallas подготовка
  if (i == 1)
  {
    ds.requestTemperatures(); // считываем температуру с датчиков
  }

  //dallas считывание
  if (i == 2)
  {
    if (ds.getTempC(ds_frosya) <= 50) temp = ds.getTempC(ds_frosya);
    i = 0;
  }
 
  modbus_update(); // запуск обмена по Modbus

  holdingRegs[reg_0] = temp;
  holdingRegs[reg_1] = random(9);
 
  if (holdingRegs[reg_3] == 0)
  {
    digitalWrite(LED1, LOW);
  }
  else
  {
    digitalWrite(LED1, HIGH);
  }

  //Serial.println(temp);

}// конец

*/

 

Court
Offline
Зарегистрирован: 08.07.2017

alexval2007 пишет:

Библиотеки стабильно работают. Вся работа библиотеки выполняется в фоновом режиме. Ваша программа выполнятся без задержек. Примеры и библиотеки хорошо прокомментированы и интуитивно понятны это позволит вам легко создать свой первый проект с Modbus.
Библиотеки написаны с применением объектно-ориентированного подхода, на языке C не используя C ++. Это облегчает портирование программного обеспечения библиотеки на другие платформы, который поддерживают компилятор C.

позже добавлю еще про ардуино модбус мастер и модуль ввода как slave устройсво

небольшую статеечку окультурить нужно

Есть новые версии или исправления к библиотекам ?

passenger21
Offline
Зарегистрирован: 14.11.2017

Организовал обмен - овеновский СПК107 (как мастер) + ардуино уно (как слейв). Библиотека slave RTU. На этой же шине висят два ПР200. Обмен норм, все стабильно. НО замечен такой момент:

#define Slave_ID     1     // Адрес Slave устройсва

пытаюсь переназначить адреса слейвов, при замене вышеуказанного ID ардуина упорно висит на первом адресе. Т.е. ставим 2 или 3 или 16, без разницы - она опрашивается мастером только по адресу слейва 1. В чем причина, кто-нибудь сталкивался? Баг пока не критичный, но как действовать при необходимости подцепить несколько ардуин на один канал? 

 

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

похоже на то что овеновский мастер дает запрос слейву №1, а если вы его переиминовали то такого нет, ему это не нравится ;) и вводит его в стопар

passenger21
Offline
Зарегистрирован: 14.11.2017

в том то и прикол, что ID меняешь, заливаешь в ардуину, опрашиваешь по новому адресу - нет ответа. Опрашиваешь по адресу 1, есть связь. Т.е. какой ID ни ставь - адрес у ардуины все-равно 1. Загадка...)

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

в мастере тоже меняешь ID?

passenger21
Offline
Зарегистрирован: 14.11.2017

да, конечно! Заливаю в ардуину #define Slave_ID     2;  

соответственно:

 modbus_configure(&Serial, baud, SERIAL_8E1, Slave_ID, TxEnablePin, HOLDING_REGS_SIZE, holdingRegs);

Мастером опрашиваю слэйв 2 - тишина. Опрашиваю слэйв 1 - идет обмен. Мистика

harbor
Offline
Зарегистрирован: 31.05.2016

может компилятор дуру гонит ? попробовать на другомм пк скомпилить

еще можно попробовать указать адрес без переменной  Slave_ID, напрямую.

а опрашиваете чем?

passenger21
Offline
Зарегистрирован: 14.11.2017

пробовал принудительно адрес писать, без Slave_ID. Заливал разными компиляторами, родным ардуиновским и через AtmelStudio. Нет эффекта...) Опрашиваю с СПК107, стандартная процедура, обмен корректный в обе стороны, ардуина бодро жужжит шаговым движком по команде мастера. НО ТОЛЬКО ПО ПЕРВОМУ АДРЕСУ! Странное дело) Буду разбираться дальше. Отпишусь, когда найду в чем прикол.

harbor
Offline
Зарегистрирован: 31.05.2016

надо в библиотеку смотреть, может там прписан 1-й адрес

Andrey_161
Offline
Зарегистрирован: 15.07.2016

Столкнулся с такой же фигней, только использовал две ардуины (мастер и слэйв), и тоже опрос шел только по первому адресу в независимости от того, какой адрес ставил слэйву.

passenger21
Offline
Зарегистрирован: 14.11.2017

Поковырялся в библиотеке, разобрался в чем дело)

В примере для Slave есть две строки, задающие параметры обмена:

  modbus_configure(&Serial, baud, SERIAL_8E1,Slave_ID, TxEnablePin, HOLDING_REGS_SIZE, holdingRegs); 

  modbus_update_comms(baud, SERIAL_8E1, 1);

последняя единица - это тоже адрес устройства, автор видимо ставил его принудительно, без переменной.

В такой редакции: modbus_update_comms(baud, SERIAL_8E1, Slave_ID); у меня обмен пошел по всем адресам.

Может кому поможет)

Life23
Offline
Зарегистрирован: 10.08.2013

Подскажите, как настроить эту библиотеку с работой через SoftawareSerial?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Приветствую всех.
А никто не пытался портировать это библиотеку под ESP32?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013
Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Есть кто живой в этой теме? =)

Я ее прочел. Многое понятно но так же не совсем ясно несколько моментов. Вот дупустим пример основанный на бибилиотеке данной. 

#include <SimpleModbusMaster.h>

#define baud        9600
#define timeout     1000
#define polling     200
#define retry_count 10
#define TxEnablePin 2   
#define TOTAL_NO_OF_REGISTERS 4

enum {
  PACKET1,
  PACKET2,
  TOTAL_NO_OF_PACKETS};
  
Packet packets[TOTAL_NO_OF_PACKETS];
unsigned int regs[TOTAL_NO_OF_REGISTERS];

void setup() {
  // Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS,    0, 1, regs[0]);
  modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 1, 1, regs[1]);
  modbus_configure(&Serial, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
}

void loop() {
  modbus_update();
  unsigned int temp1;
  unsigned int temp2;
  //regs[0] = analogRead(0);       // запись данных master-slave
  //analogWrite(LED, regs[0]>>2);  // чтение данных slave-master (ограничеть количесво бит данных числом 255)
  regs[0] = 255;   // запись данных master-slave (slave адрес 1, регистр 1)
  regs[1] = 255;   // запись данных master-slave (slave адрес 1, регистр 2) 
  temp1 = regs[2]; // чтение данных slave-master (slave адрес 1, регистр 3)  
  temp2 = regs[3]; // чтение данных slave-master (slave адрес 1, регистр 4) 
   if (temp1 == 255){digitalWrite(LED1, HIGH);}else{digitalWrite(LED1, LOW);}//если пришло 255 зажигаем светодиод
   if (temp2 == 255){digitalWrite(LED2, HIGH);}else{digitalWrite(LED2, LOW);}
}

Сначала суть. Есть готовое устроиства на базе кристала atmega2560. У данноо устроиства 9 дискретных выходов, 9 дискретных входов, 5 аналоговых входов, а так же на борту есть еще 2а реле и так же на плате разведено подключение МК к линии 485. делал я это для своей задачи своеобразной. Теперь решил к этому делую написать прошивку. Сначала хотел делать на библиотеке ModbusRTU, но не зашло че то) Потом почел про эту и вот не задача не понимаю несколько вещей:

1. В данной бибилиотеке если я использую кристал 2560 сколько я могу регистров хранить то используя данную бибилиотеку? (TOTAL_NO_OF_REGISTERS сколько максимуму может быть в данной библиотке)

2. Из вашего опыта как лучше организовать хранение значений с моих 23 портов? (я бы хотел чтобы все значения записывались в цикле в массив и уже оперировались дальше в цикле)

3. И не могли бы вы мне сказать как в данной библиотеки писать биты и байты и читать их? Я просто увидел примеры только в целом с регистрами. Т.е. не так как организованно например в библиотеки ModbusRTU. Может есть еще какой то функционал. Но в описании библиотеки я ниче не понял ибо не сильно разбираюсь в англиском=( Заранее спасибо за советы и ответы.

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Можете помочь с библиотекой кое что понять? Вроде понял всме кроме одного=( почему у меня не читаются регистры выше 4го??? скрины ниже. Код простой просто 7 регистров в каждый присваевается значение свое не важно какое. Так вот первые 4е читаются отлично. Выше же откажывается читать выдавая ошибку что типа не верный адресс.

#include <SimpleModbusSlave.h>
enum 
{     
  IN1,     
  IN2, 
  IN3,
  IN4,       
  HOLDING_REGS_SIZE
};
unsigned int holdingRegs[HOLDING_REGS_SIZE];
//----------------------------------------------ПЕРЕМЕННЫЕ СИСТЕМЫ (НЕ ИЗМЕНЯТЬ!!!!!!!!!!)-------------------------------
int INTPORT_1=5;
int INTPORT_2=6;
int INTPORT_3=7;
int INTPORT_4=8;
int INTPORT_5=9;
int INTPORT_6=10;
int INTPORT_7=12;
int IND_ST_CP=4;
int IND_SH_CP=3;
int IND_DS=11;
byte IND1=B00000000;
//----------------------------------------------ПЕРЕМЕННЫЕ ПОЛЬЗОВАТЕЛЯ----------------------------------------------------

//----------------------------------------------ПЕРВИЧНЫЕ НАСТРОЙКИ МК----------------------------------------------------
void setup() {
pinMode(INTPORT_1, INPUT_PULLUP); 
pinMode(INTPORT_2, INPUT_PULLUP); 
pinMode(INTPORT_3, INPUT_PULLUP); 
pinMode(INTPORT_4, INPUT_PULLUP); 
pinMode(INTPORT_5, INPUT_PULLUP); 
pinMode(INTPORT_6, INPUT_PULLUP); 
pinMode(INTPORT_7, INPUT_PULLUP); 
pinMode(IND_ST_CP, OUTPUT);
pinMode(IND_SH_CP, OUTPUT);
pinMode(IND_DS, OUTPUT);
  modbus_configure(&Serial, 9600, SERIAL_8N2, 2, 2, HOLDING_REGS_SIZE, holdingRegs);
  modbus_update_comms(9600, SERIAL_8N2, 2);
}
//----------------------------------------------ОСНОВНОЙ ЦИКЛ МК----------------------------------------------------
void loop() {
//IND1 |= (1 << 0);
//holdingRegs[1] = digitalRead(INTPORT_1);
//holdingRegs[2] = digitalRead(INTPORT_2);
//holdingRegs[3] = digitalRead(INTPORT_3);
//holdingRegs[0] = digitalRead(INTPORT_4);
//holdingRegs[4] = digitalRead(INTPORT_5);;
//holdingRegs[5] = digitalRead(INTPORT_6);
//holdingRegs[6] = digitalRead(INTPORT_7);
holdingRegs[0] = 22;
holdingRegs[1] = 33;
holdingRegs[2] = 44;
holdingRegs[3] = 55;
holdingRegs[4] = 66;
holdingRegs[5] = 77;
IND_UPDATE();

modbus_update();
//IND1 &= ~(1 << 0);
}

void IND_UPDATE(){
if (digitalRead(INTPORT_1)==0) {IND1 |= (1 << 7);} else {IND1 &= ~(1 << 7);}
if (digitalRead(INTPORT_2)==0) {IND1 |= (1 << 5);} else {IND1 &= ~(1 << 5);}
if (digitalRead(INTPORT_3)==0) {IND1 |= (1 << 3);} else {IND1 &= ~(1 << 3);}
if (digitalRead(INTPORT_4)==0) {IND1 |= (1 << 6);} else {IND1 &= ~(1 << 6);}
if (digitalRead(INTPORT_5)==0) {IND1 |= (1 << 4);} else {IND1 &= ~(1 << 4);}
if (digitalRead(INTPORT_6)==0) {IND1 |= (1 << 2);} else {IND1 &= ~(1 << 2);}
if (digitalRead(INTPORT_7)==0) {IND1 |= (1 << 1);} else {IND1 &= ~(1 << 1);}
  
  digitalWrite(IND_ST_CP, LOW);
  shiftOut(IND_DS, IND_SH_CP, MSBFIRST, IND1);
  digitalWrite(IND_ST_CP, HIGH);
  }

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Сколько передал в 37 строке HOLDING_REGS_SIZE, столько и получил.

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Не совсем понял((( можете пояснить? Та строка разбивается на:

parameters(HardwareSerial* SerialPort,
long baudrate,
unsigned char byteFormat,
unsigned char ID,
unsigned char transmit enable pin, 
unsigned int holding registers size,
unsigned int* holding register array)
 
что я должен где написать чтобы смог считать до 7го регистра включительно?
Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

А типа выше я должен был описать 7 регистров и закрыть их общим названием как я описал IN1  и т.д.?

harbor
Offline
Зарегистрирован: 31.05.2016

в enum 

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

уже понял спасибо. Скажите и сколько регистров я могу сделать для кристала 2560меги? 29 всего или больше?

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Ребят подскажите как Вы думаете как читать в данной библиотеке сразу два или более регистров 1 пакетом? Т.е. как бы понимаю что функция меняю но где в конце пакета надо указать локальное хранилище данных там что надо регистры через запятаю писат ьили как? Нет примера, не найду. Заранее спасибо

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Очень нужна ваша подсказка. В данной библиотеке я так и не понял по инструкции как запросить сразу 7 регистров. ТОчнее не понял как их сохранить в локальное харнилище в массив? можете строчку написать. И второй вопрос про буфер в 29 регистров. Я не понял это имеется ввиду что за раз не может больше 29 запросить? или хранить не может больше 29ти значений. У меня мастер на кристале атмега 2560 но не ардуина а своя плата без загрузчика и т.д. Просто уже две неделе бьюсь. Слейвы сделал работают отчлино! А вот с мастером беда какая то. Три устроиства и желательно сделать три пакета к каждому чтобы не делать 14 пакетов. А как сохранять не ясно.

Заранее спасибо за ответ. 

ADE_RDX
Offline
Зарегистрирован: 06.10.2018

Добрый день, очень нужна ваша помощь по билиотеке Simple Modbus. Написал тестовый скетч, при обрыве связи, попытки обмена прекращаются через заданное число раз, и все. Как получить информацию о том что обмен остановлен? в описании к библиотеке есть упоминание соответствующих переменных но как обращатся к ним, как считать данные?

Цитата:

"Как уже упоминалось, пакет содержит всю информацию, необходимую FSM. Информация и различныесчетчики могут быть доступны пользователю для каждого пакета. Счетчики информации могут использоваться для диагностических целях. Ниже приводится краткое объяснение:

запросы - содержит общие запросы к подчиненному
success_requests - содержит итоговые успешные запросы
failed_requests - общие ошибки кадра, сбои контрольной суммы и отказы буфера. Это приведет к
тайм-аут.
retries - содержит количество попыток
exception_errors - содержит конкретный счетчик ответов на исключение modbus. Обычно они являются незаконными
функции, незаконного адреса, незаконного значения данных или разного рода ошибок."
 
В примерах к старым версиям этой библиотеки есть вот что :
"
  /* You can check or alter the internal counters of a specific packet like this:
     packet1->requests;
     packet1->successful_requests;
     packet1->failed_requests;
     packet1->exception_errors;
     packet2->requests;
     packet2->successful_requests;
     packet2->failed_requests;
     packet2->exception_errors;
  */
"
 
 
 
/*
   Пример будет использовать packet1, чтобы считать регистр из адреса 0 (значение adc ch0)
   от arduino раба (id=1). Это будет тогда использовать это значение, чтобы скорректировать яркость
   из вовлеченного контакт 9 использований PWM.
   Это будет тогда использовать packet2, чтобы записать регистр (его собственное значение adc ch0), чтобы адресоваться 1 
   на arduino рабе (id=1) корректировка яркости вовлеченного контакт 9 использований PWM.
*/
#include <SimpleModbusMaster.h>
//////////////////// Макроопределения портов и настройки программы  ///////////////////
#define baud        230400 // скоростьобмена по последовательному интерфейсу. (UART)
#define timeout     1000 // Длительность ожидание ответа (таймаут modbus)
#define polling     200  // скорость опроса по modbus
#define retry_count 10   // количесво запросов modbus до ошибки и останова обмена 
#define TxEnablePin 20    // Tx/Rx пин RS485

const unsigned char serialInterval = 30;        // интервал отправки в SERIAL в милис\10 ( В ПРОГРАММЕ УМНОЖАЕТСЯ НА 10)МАКС ЗНАЧЕНИЕ 255 (ИЛИ 2550 милис.) сейчас 300мс.
unsigned long serialTime;                   // переменная хранения времени для отпраки в порт.

// Общая сумма доступной памяти на master устройстве, для хранения данных
// не забудьте изменить макроопределение TOTAL_NO_OF_REGISTERS. Если из слейва 
// запрашиваешь 4 регистра, то тогда в массиве reg должно быть не меньше 4х ячеек 
// для хранения полученных данных.
#define TOTAL_NO_OF_REGISTERS 20

// Масив пакетов modbus
// Для добавления новых пакетов просто добавте ихсюда
// сколько вам нужно.
enum
{
  PACKET1,
  PACKET2,
  PACKET3,
  PACKET4,
  PACKET5,
  PACKET6,
  PACKET7,
  PACKET8,
  PACKET9,
  PACKET10,
  PACKET11,
  PACKET12,
  PACKET13,
  PACKET14,
  PACKET15,
  PACKET16, // резерв
  PACKET17, // резерв
  PACKET18, // резерв
  PACKET19, // резерв
  PACKET20, // резерв
  TOTAL_NO_OF_PACKETS // эту строку неменять
};

// Масив пакетов модбус
Packet packets[TOTAL_NO_OF_PACKETS];

// Массив хранения содержимого принятых и передающихся регистров
unsigned int regs[TOTAL_NO_OF_REGISTERS];

int ERR = 0;

//////////////////////////////////////////////////////////////////////////
int volt = 0;         //  переменная хранения вычисленного значения напряжения в вольтах. делить на 100.
int Boost1 = 0;       //  переменная хранения вычисленного значения Boost1 в барах. делить на 100.
int Boost2 = 0;       //  переменная хранения вычисленного значения Boost2 в барах. делить на 100.
int Press1 = 0;       //  переменная хранения вычисленного значения Press1 в барах. делить на 100.
int temp1 = 0;             //  переменная хранения вычисленного значения temp1 сенсора.
int temp2 = 0;             //  переменная хранения вычисленного значения temp2 сенсора.

/////////////////////////////////////////////////////////// MAX31855.
int EGT = 0;           // переменная хранения EGT сенсора.
int intemp = 0;        // переменная хранения внутренней температуры MAX31855.

/////////////////////////////////////////////////////////// ds18b20
int temp11 = 0;  // измеренная температура ds18b20 нужно делить на 10.
int temp22 = 0;  // измеренная температура ds18b20 нужно делить на 10.
int temp33 = 0;  // измеренная температура ds18b20 нужно делить на 10.



void setup()
{
 // Настраиваем пакеты
 // Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет 
 // помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив reg
  
 // Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
 modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS,    0, 1, 0); // чтение данных slave-master (slave адрес 1, регистр 0) 
 modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS,    1, 1, 1); // чтение данных slave-master (slave адрес 1, регистр 1)
 modbus_construct(&packets[PACKET3], 1, READ_HOLDING_REGISTERS,    2, 1, 2); // чтение данных slave-master (slave адрес 1, регистр 2)
 modbus_construct(&packets[PACKET4], 1, READ_HOLDING_REGISTERS,    3, 1, 3); // чтение данных slave-master (slave адрес 1, регистр 3)
 modbus_construct(&packets[PACKET5], 1, READ_HOLDING_REGISTERS,    4, 1, 4); // чтение данных slave-master (slave адрес 1, регистр 4)
 modbus_construct(&packets[PACKET6], 1, READ_HOLDING_REGISTERS,    5, 1, 5); // чтение данных slave-master (slave адрес 1, регистр 5)
 modbus_construct(&packets[PACKET7], 1, READ_HOLDING_REGISTERS,    6, 1, 6); // чтение данных slave-master (slave адрес 1, регистр 6)
 modbus_construct(&packets[PACKET8], 1, READ_HOLDING_REGISTERS,    7, 1, 7); // чтение данных slave-master (slave адрес 1, регистр 7)
 modbus_construct(&packets[PACKET9], 1, READ_HOLDING_REGISTERS,    8, 1, 8); // чтение данных slave-master (slave адрес 1, регистр 8)
 modbus_construct(&packets[PACKET10], 1, READ_HOLDING_REGISTERS,    9, 1, 9); // чтение данных slave-master (slave адрес 1, регистр 9)
 modbus_construct(&packets[PACKET11], 1, READ_HOLDING_REGISTERS,    10, 1, 10); // чтение данных slave-master (slave адрес 1, регистр 10)
 modbus_construct(&packets[PACKET12], 1, READ_HOLDING_REGISTERS,    11, 1, 11); // чтение данных slave-master (slave адрес 1, регистр 11)
 modbus_construct(&packets[PACKET13], 1, READ_HOLDING_REGISTERS,    12, 1, 12); // чтение данных slave-master (slave адрес 1, регистр 12)
 modbus_construct(&packets[PACKET14], 1, READ_HOLDING_REGISTERS,    13, 1, 13); // чтение данных slave-master (slave адрес 1, регистр 13)
 modbus_construct(&packets[PACKET15], 1, READ_HOLDING_REGISTERS,    14, 1, 14); // чтение данных slave-master (slave адрес 1, регистр 14)
 
 // Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
 //modbus_construct(&packets[PACKET3], 1, PRESET_MULTIPLE_REGISTERS, 2, 1, 2); // запись данных master-slave (slave адрес 1, регистр 2)
 //modbus_construct(&packets[PACKET4], 1, PRESET_MULTIPLE_REGISTERS, 3, 1, 3); // запись данных master-slave (slave адрес 1, регистр 3)
 
 // инициализируем протокол модбус
 modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
 Serial.begin(9600);
  

} 

void loop()
{

  SerialPrint();      // функция отправки в порт.
  modbus_update(); // запуск обмена по Modbus
  
 volt = regs[0] / 100;      // чтение данных slave-master (slave адрес 1, регистр 0)
 Boost1 = regs[1] / 100;    // чтение данных slave-master (slave адрес 1, регистр 1)
 Boost2 = regs[2] / 100;
 Press1 = regs[3] / 100;
 temp1 = regs[4];
 temp2 = regs[5];
/////////////////////////////////////////////////////////// MAX31855.
 EGT = regs[6];      
 intemp = regs[7];   
/////////////////////////////////////////////////////////// ds18b20
temp11 = regs[8] / 10;  
temp22 = regs[9] / 10; 
temp33 = regs[10] / 10;

ERR = PACKET1->exception_errors;

//regs[2] = 255;           // запись данных master-slave (slave адрес 1, регистр 2), запись константы
//regs[3] = analogRead(0); // запись данных master-slave (slave адрес 1, регистр 3), значение из аналогового входа 0

} // конец void loop()



/////////////////////////////////////////////////////////////////////////////////////////////////////////////
void SerialPrint()           //функция отправки в порт.
{ 
if (millis() - serialTime > serialInterval * 10) {   // проверяем если больше serialInterval.   
  
  Serial.print(" t11= ");  // отправляем в порт.
  Serial.print(temp11);  // отправляем в порт.
  Serial.print(" ");
  Serial.print(" t22= ");  // отправляем в порт.
  Serial.print(temp22);  // отправляем в порт.
  Serial.print(" ");
  Serial.print(" t33= ");  // отправляем в порт.
  Serial.print(temp33);  // отправляем в порт.
  Serial.println(" ");

  Serial.print(" volt = ");
  Serial.print(volt);
  Serial.println("V");
  
  Serial.print(" Boost1 = ");
  Serial.print(Boost1);

  Serial.print(" Boost2 = ");
  Serial.print(Boost2);

  Serial.print(" Press = ");
  Serial.print(Press1);

  
  Serial.print(" t1 = ");
  Serial.print(temp1);
  Serial.print("C");
  Serial.print(" t2 = ");
  Serial.print(temp2);
  Serial.println("C");
  
  Serial.print(" Intepm = ");
  Serial.print(intemp);
  Serial.print(" EGT = ");
  Serial.println(EGT);
  
  Serial.println(" ------------------------------------------- ");
  Serial.print (ERR);
  Serial.println(" ------------------------------------------- ");
  
  
  serialTime = millis();   //присваеваем переменной, значение счетчика милисекунд.
 }
}


  /* You can check or alter the internal counters of a specific packet like this:
     packet1->requests;
     packet1->successful_requests;
     packet1->failed_requests;
     packet1->exception_errors;
     packet2->requests;
     packet2->successful_requests;
     packet2->failed_requests;
     packet2->exception_errors;
  */

При компиляции выдает ошибку в строке проверки ошибки :

Arduino: 1.8.5 (Windows 7), Плата:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

 
C:\Users\Werwolf\Desktop\MasterArduino\MasterArduino.ino: In function 'void loop()':
 
MasterArduino:134: error: base operand of '->' is not a pointer
 
 ERR = PACKET1->exception_errors;
 
              ^
 
exit status 1
base operand of '->' is not a pointer
 

 

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

В чем воопрос как читать ошибки? их количество или в том что у вас ошибка при компиляции?

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Я просто чуть в шоке) спрошу так вы сами знаете почему не компилируется? вы понимаете что Вам компилятор написал)???

ADE_RDX
Offline
Зарегистрирован: 06.10.2018

Вопрос был как читать переменные ошибок ( синтаксис).

Но кажется я нашел решение:

на забугорном сайте пишут- вы можете увидеть полный статус каждого пакета со следующим синтаксисом:

packets[PACKET_NUMBER].requests
packets[PACKET_NUMBER].successful_requests
packets[PACKET_NUMBER].failed_requests
packets[PACKET_NUMBER].exception_errors
packets[PACKET_NUMBER].retries
packets[PACKET_NUMBER].connection


unsigned int c = packets[PACKET1].failed_requests;  // переменная c содержит теперь количество неудачных запросов

 

Два дня голову ломал....

 

 

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Ну как бы вы все верно написали изначально только применили эт овсе не правильно. Такого -> оператора нет))) То что вы щас написали последнее является правильным применением для данной библиотеки.

ADE_RDX
Offline
Зарегистрирован: 06.10.2018

Seltvik пишет:

Я просто чуть в шоке) спрошу так вы сами знаете почему не компилируется? вы понимаете что Вам компилятор написал)???

я просто понял, что ему не нравится строка, в которой я пытался получить значение переменной с ошибками. "ERR = PACKET1->exception_errors;"    -синтаксис не верен, спрашивал как правильно написать.

В русскоязычном сегменте интернета я упоминания и примеров не нашел. Может кому пригодится....

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Добрый день скажите. Использую в своем проекте библиотеки SimpleModbusSlave и SimpleModbusMaster. Вопрос в данной бибилотеке мастера не постоянно слать заранее подготовленные контструкции. Т.е. чтобы МК какую то часть данных каждый цикл запрашивал и обновлял а то что касается управления чтобы по кнпоке когда надо отправлял запрос. Просто никак не въеду. Заранее спасибо

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Скажите есть ли опыть отправлять данные по команде а не в цикле. Я про библиотеку SimpleModbusMaster.

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

тут есть живые в этой ветке?

harbor
Offline
Зарегистрирован: 31.05.2016

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

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

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

МОжно подробнее? У меня все пашет как бы но смысл в том что библа эта как то не очень работает очень много проходов. Т.е. если я разово запускаю функцию modbus.update то нифига не уходит ничего а если в цикле то все пашет .Как это поправить? Или в чем может быть беда тут?

harbor
Offline
Зарегистрирован: 31.05.2016

Ну тут не телепаты сидят, выкладывай свой код, может кто-нибудь и поможет

Seltvik
Seltvik аватар
Offline
Зарегистрирован: 24.10.2013

Суть такая кто работал с данной библиотекой думаю сразу все поймут.

Я в setup делаю ка кобычно предустановку пакетов вот она:

  modbus_construct(&packets[PACKET1], 11, PRESET_MULTIPLE_REGISTERS, 0, 1, 22);//Формаирование пакета  (Данные к выключителя 11)
  modbus_construct(&packets[PACKET2], 12, PRESET_MULTIPLE_REGISTERS, 0, 1, 23);//Формаирование пакета  (Данные к выключителя 11)
  modbus_construct(&packets[PACKET3], 13, PRESET_MULTIPLE_REGISTERS, 0, 1, 24);//Формаирование пакета  (Данные к выключителя 11)
  modbus_construct(&packets[PACKET4], 14, PRESET_MULTIPLE_REGISTERS, 0, 1, 25);//Формаирование пакета  (Данные к выключителя 11)
  modbus_construct(&packets[PACKET5], 15, PRESET_MULTIPLE_REGISTERS, 0, 1, 26);//Формаирование пакета  (Данные к выключителя 11)
  modbus_construct(&packets[PACKET6], 16, PRESET_MULTIPLE_REGISTERS, 0, 1, 27);//Формаирование пакета  (Данные к выключителя 11)
  modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);

и в loop я делаю просто обмен modbus_update(); Так вот все работает как и надо но есть две проблемы:

1. Работает с задержкой в 3-5 секунд

2. Если делаю отдельно по кнопке modbus_update(); то вообще не срабатывает или срабатывает с 3-10 раза почему? не ясно.

Но интересно то что если я подключаю комп как мастер через 485-USB адаптер то все шустр ои быстро без задержек делается. Вот и не могу понять как решить эти две проблемы