Взаимодействие с контроллером температуры Eurotherm 2416 через Modbus RS232

Я пытаюсь реализовать библиотеку Modbus, написанную smarmengol, для чтения значений процесса и установки новых заданных значений (например, температуры) на контроллере Eurotherm. Скетч Arduino выглядит так:

/**
* Мастер-устройство Modbus, пример 2:
* Целью этого примера является запрос нескольких наборов данных.
* от внешнего ведомого устройства Modbus.
* В качестве средства связи может использоваться USB или RS232.
*
* Рекомендуемое ведомое устройство Modbus:
* Diagslave http://www.modbusdriver.com/diagslave.html
*
* В системе Linux запустите
* "./diagslave /dev/ttyUSB0 -b 9600 -d 8 -s 1 -p none -m rtu -a 1"
* Это:
* последовательный порт /dev/ttyUSB0 на скорости 9600 бод 8N1
* Режим RTU и адрес @1
*/

#include <ModbusRtu.h>
#include <SoftwareSerial>

SoftwareSerial mySerial (3,5);

uint16_t au16data[16]; //!< массив данных для совместного использования сети Modbus
uint8_t u8state; //!< состояние машины
uint8_t u8query; //!< указатель на запрос сообщения

/**
 *  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); // это мастер и RS-232 или USB-FTDI

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

unsigned long u32wait;

void setup() {
  // телеграмма 0: чтение регистров
  telegram[0].u8id = 1; // адрес подчиненного устройства
  telegram[0].u8fct = 3; // код функции (это чтение регистров)
  telegram[0].u16RegAdd = 1; // начальный адрес в подчиненном устройстве
  telegram[0].u16CoilsNo = 1; // количество элементов (обмоток или регистров) для чтения
  telegram[0].au16reg = au16data; // указатель на массив памяти в Arduino

  // телеграмма 1: записываем один регистр
  telegram[1].u8id = 1; // адрес подчиненного устройства
  telegram[1].u8fct = 6; // код функции (это запись одного регистра)
  telegram[1].u16RegAdd = 2; // начальный адрес в подчиненном устройстве
  telegram[1].u16CoilsNo = 250; // (Setpoint) количество элементов (обмоток или регистров) для чтения
  telegram[1].au16reg = au16data+4; // указатель на массив памяти в Arduino

  Serial.begin(9600);
  master.begin( &mySerial, 9600); // скорость передачи данных 9600

  master.setTimeOut( 5000 ); // если ответа не будет в течение 5000 мс, перевернуться
  u32wait = millis() + 1000;
  u8state = u8query = 0; 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // состояние ожидания
    break;
  case 1: 
    master.query( telegram[u8query] ); // отправляем запрос (только один раз)
    u8state++;
    u8query++;
    if (u8query > 2) u8query = 0;
    break;
  case 2:
    master.poll(); //проверяем входящие сообщения
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 1000; 
    }
    break;
  }
   Serial.print(au16data[O]);

  au16data[4] = analogRead( 0 );

}

Я очень хорошо могу прочитать значения процесса с помощью телеграммы[0] (температура и/или заданное значение), но я не могу изменить заданное значение с помощью телеграммы[1]. Если я запускаю код, он отображает текущую температуру на последовательном мониторе, но сбрасывает заданные значения, измененные вручную, на ноль. Где ошибка? Должен ли я записать значение уставки в формате HEX или DEC? Что на самом деле делает последняя команда?

Спасибо!

, 👍0

Обсуждение

1) telegram[1].u16CoilsNo = похоже, что это должно быть 1, а не 250 (запись одного 16-битного регистра); 2) вы пишете в тот же регистр/установку, которую прочитали в Telegram[0]? если да, то почему адрес u16RegAdd отличается?, @Flanker

@Flanker Вы правы, это должно быть 1 (один регистр), а не 250. Решением моей проблемы было установить для au16data[4] фиксированное значение, например 250, или что-то в этом роде. Я думаю, что au16data[4] можно установить в интерактивном режиме, отправив любое число через последовательный аппаратный порт, поскольку analogRead(0) — это Rx на Arduino. Начальный адрес для установки (записи) уставки равен 2 и 1 для чтения того же значения (уставки). Вот чем отличается au16RegAdd. Спасибо за ответ!!, @Viktor Scherf


1 ответ


1

Вы также можете взглянуть на этот проект на GitHub: https://github.com/ukos-git/arduino-eurotherm2416

Он специально разработан для той цели, о которой вы просите. По сути, он включает в себя модуль с именем «Температура» и возможность его установки или чтения:

Temperature.set(100)
t = Temperature.getTemperature()

Посмотрите https://github.com/ukos-git/arduino -eurotherm2416/blob/master/app/app.ino.

,