0

I need help with this code:

/**
*  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,2); // this is master and RS-232 or USB-FTDI, PIN 9 PARA INDICAR QUE TRASMITO

/**
* 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 = 5; // function code (this one is registers read)
   telegram.u16RegAdd = 0; // 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

   // PARA EL VARIADOR OMRON MX1: MODBUS RTU 01 05 00 00 FF 00 -> START
   // 01 -> SLAVE (VFD OMRON)
   // 05 -> WRITE COIL
   //  00 00 -> ADDRESS COIL
   // FF 00 -> VALUES TO WRITE IN COIL FOR RUN

   telegram.au16reg[0] = 0;
   telegram.au16reg[1] = 0;
   telegram.au16reg[2] = 0;
   telegram.au16reg[3] = 0;
   telegram.au16reg[4] = 0;
   telegram.au16reg[5] = 0;
   telegram.au16reg[6] = 0;
   telegram.au16reg[7] = 0;

   telegram.au16reg[8] = 1;
   telegram.au16reg[9] = 1;
   telegram.au16reg[10] = 1;
   telegram.au16reg[11] = 1;
   telegram.au16reg[12] = 1;
   telegram.au16reg[13] = 1;
   telegram.au16reg[14] = 1;
   telegram.au16reg[15] = 1;


   master.query( telegram ); // send query (only once)
   delay(3500);

   telegram.u8id = 1; // slave address
   telegram.u8fct = 6; // function code (this one is registers read)
   telegram.u16RegAdd = 1; // start address in slave
   telegram.u16CoilsNo = 4; // number of elements (coils or registers) to read
   //telegram.au16reg = au16data; // pointer to a memory array in the Arduino
   //telegram.au16reg = 0000000111110100;

   // PARA EL VARIADOR OMRON MX1: MODBUS RTU 01 06 00 01 01 F4 -> CHANGE FQ
   // 01 -> SLAVE (VFD OMRON)
   // 06 -> WRITE IN REGISTE
   // 00 01 -> REGISTER ADDRESS
   // 01 F4 -> VALUE TO WRITE IN THE REGISTER TO CHANGE THE MOTOR FREQUENCY

   telegram.au16reg[0] = 0;
   telegram.au16reg[1] = 0;
   telegram.au16reg[2] = 0;
   telegram.au16reg[3] = 0;
   telegram.au16reg[4] = 0;
   telegram.au16reg[5] = 0;
   telegram.au16reg[6] = 0;
   telegram.au16reg[7] = 1;

   telegram.au16reg[8] = 1;
   telegram.au16reg[9] = 1;
   telegram.au16reg[10] = 1;
   telegram.au16reg[11] = 1;
   telegram.au16reg[12] = 0;
   telegram.au16reg[13] = 1;
   telegram.au16reg[14] = 0;
   telegram.au16reg[15] = 0;

   master.query( telegram ); // send query (only once)
   delay(3500);
   telegram.u8id = 1; // slave address
   telegram.u8fct = 5; // function code (this one is registers read)
   telegram.u16RegAdd = 1; // 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

   // PARA EL VARIADOR OMRON MX1: MODBUS RTU 01 05 00 00 00 00 -> STOP
   // 01 -> ESCLAVO (VARIADOR OMRON)
   // 05 -> ESCRIBIR EN UNA BOBINA
   // 00 00 -> DIRECCION DE LA BOBINA
   // 00 00 -> VALOR A ESCRIBIR EN LA BOBINA PARA STOP

   telegram.au16reg[0] = 0;
   telegram.au16reg[1] = 0;
   telegram.au16reg[2] = 0;
   telegram.au16reg[3] = 0;
   telegram.au16reg[4] = 0;
   telegram.au16reg[5] = 0;
   telegram.au16reg[6] = 0;
   telegram.au16reg[7] = 0;
   telegram.au16reg[8] = 0;
   telegram.au16reg[9] = 0;
   telegram.au16reg[10] = 0;
   telegram.au16reg[11] = 0;
   telegram.au16reg[12] = 0;
   telegram.au16reg[13] = 0;
   telegram.au16reg[14] = 0;
   telegram.au16reg[15] = 0;
   master.query( telegram ); // send query (only once)
   delay(3500);
   u8state++;
   break;
 case 2:
   master.poll(); // check incoming messages
   if (master.getState() == COM_IDLE) {
     u8state = 0;
     u32wait = millis() + 100;
   }
   break;
 }
}

I've managed to send RUN command to VFD but i can't (so far) send the change frequency command "01 06 00 01 01 F4" + CRC check.

When I connect logic analyzer with modbus rtu decoder, it shows "Device ID:'1' Function Write single coil ('5') Addr: '0' value: '65280' Chksum: '14988'.

The problem is that it pass only 1 telegram (array of packets) for command "RUN" but no the two others. Any help will be appreciated.

This is the link for VFD Omron MX: https://industrial.omron.us/en/media/I570-E2-02B_3G3MX2_UsersManual_tcm849-112721.pdf

TIA

7
  • first you should update the comments and remove unused settings like the count fields for request with one value (function 5 and 6). you do not set the value into au16reg like you have it in PARA EL VARIADOR OMRON MX comments
    – Juraj
    Commented Jun 4, 2018 at 14:17
  • In this sketch, i don't know how this telegram with the vfd commands made of. For example:telegram.u8id = 0x01; // slave address telegram.u8fct = 0x06; // function code (this one is registers read) telegram.u16RegAdd = 0x01; // start address in slave telegram.u16CoilsNo = 0x04; // number of elements (coils or registers) to read //telegram.au16reg = au16data; // pointer to a memory array in the Arduino //telegram.au16reg = 0000000111110100; What those 0's and 1's do? Commented Jun 4, 2018 at 15:43
  • en.wikipedia.org/wiki/Modbus#Supported_function_codes
    – Juraj
    Commented Jun 4, 2018 at 17:06
  • au16reg are the data to be send. ignore the binary format from the example, send data required by the documentation
    – Juraj
    Commented Jun 4, 2018 at 17:08
  • After clean those telegram.au16reg you said, i 've managed to pass the second and 3rd packet. How can i pass the appropriate value to the frequency? For example: How can i pass the value 40Hz to it?Any way you saved me a lot of searching time! Thank you! Commented Jun 4, 2018 at 19:41

1 Answer 1

1

You should update the comments and remove unused settings like the count fields for request with one value (function 5 and 6).

au16reg are the data to be send. ignore the binary format from the example.

To send a value of the coil or register set the value to telegram.au16reg[0].

For the Modbus message protocol see for example the Wikipedia article.

3
  • When i call the last code i gave, it works well and i get the correct message. When i call this code with "master.query( telegram[0] ); // send query (only once)" call, the program doesn't work. What i've missed? Is it a good way to check button statements and send modbus rtu commands to vfd? Commented Jun 9, 2018 at 10:20
  • I do not see a problem with sending Modbus request triggered by button, but your code is still a mess. you can't do it if you can't understand and write code.
    – Juraj
    Commented Jun 9, 2018 at 11:12
  • It looks like that i have a conflict when i call this telegram command then. Although i've test many modbus libraries but none works well. Also i can't achieve good timing with the modbus poll software and i got time error reports. Is it possible to help me with a code snippet to catch the missing point? Commented Jun 9, 2018 at 11:19

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.