0

I am trying to implement the modbus library written by smarmengol to read process values and to set new setpoints (e.g. temperature) on a Eurotherm controller. The Arduino sketch looks like this:

/**
 *  Modbus master example 2:
 *  The purpose of this example is to query several sets 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 9600 -d 8 -s 1 -p none -m rtu -a 1"
 *  This is:
 *      serial port /dev/ttyUSB0 at 9600 baud 8N1
 *      RTU mode and address @1
 */

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

SoftwareSerial mySerial (3,5);

uint16_t au16data[16]; //!< data array for modbus network sharing
uint8_t u8state; //!< machine state
uint8_t u8query; //!< pointer to message query

/**
 *  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); // this is master and RS-232 or USB-FTDI

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

unsigned long u32wait;

void setup() {
  // telegram 0: read registers
  telegram[0].u8id = 1; // slave address
  telegram[0].u8fct = 3; // function code (this one is registers read)
  telegram[0].u16RegAdd = 1; // start address in slave
  telegram[0].u16CoilsNo = 1; // number of elements (coils or registers) to read
  telegram[0].au16reg = au16data; // pointer to a memory array in the Arduino

  // telegram 1: write a single register
  telegram[1].u8id = 1; // slave address
  telegram[1].u8fct = 6; // function code (this one is write a single register)
  telegram[1].u16RegAdd = 2; // start address in slave
  telegram[1].u16CoilsNo = 250; // (Setpoint) number of elements (coils or registers) to read
  telegram[1].au16reg = au16data+4; // pointer to a memory array in the Arduino

  Serial.begin(9600);
  master.begin( &mySerial, 9600); // baud-rate at 9600

  master.setTimeOut( 5000 ); // if there is no answer in 5000 ms,roll over
  u32wait = millis() + 1000;
  u8state = u8query = 0; 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    master.query( telegram[u8query] ); // send query (only once)
    u8state++;
    u8query++;
    if (u8query > 2) u8query = 0;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 1000; 
    }
    break;
  }
   Serial.print(au16data[O]);

  au16data[4] = analogRead( 0 );

}

I can read process values with telegram[0] very well (temperature and/or setpoint), but I cannot change the setpoint with telegram[1]. If I run the code, it puts the current temperature to serial monitor but resets manually changed setpoints to zero. Where is the error? Should I write the value for the setpoint as HEX or DEC? What does the last command do actually?

Thank you!

2
  • 1) telegram[1].u16CoilsNo = looks like this must be 1 NOT 250 (writing single 16 bit register); 2) are you writing to the same register / setpoint you read in telegram[0]? if so why u16RegAdd address is different?
    – Flanker
    Aug 6, 2016 at 17:55
  • @Flanker You are right, it must be 1 (single register) and not 250. The solution for my problem was to set au16data[4] to a fixed value, e.g 250, or something like that. I think that au16data[4] can be set interactively by sending any number thru a hardware serial, since analogRead(0) is Rx on Arduino. The start address for setting (writing) a setpoint is 2 and 1 for reading of the same value (setpoint). That is why au16RegAdd differs.Thank You for an answer!! Aug 7, 2016 at 15:40

1 Answer 1

1

You could also take a look at this github project: https://github.com/ukos-git/arduino-eurotherm2416

It is specifically designed for the purpose you ask for. It basically includes Module named Temperature and a possibility to set or read it:

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

Look at https://github.com/ukos-git/arduino-eurotherm2416/blob/master/app/app.ino.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.