Difficulty talking to VFD over modbus.

I have a variable frequency drive (VFD) for driving a three phase motor (on a pump). It has an RS485 modbus RTU interface (page 162) and decent documentation (download PDF here: Dropbox - KOC100 Series User Manual--20150119(V1.1).pdf - Simplify your life).

I’m aware of the various modbus libraries that are available, but right now I’m just tying to verify that I can get things to work. I’ve got an arduino hooked to a TTL/RS485 module (like this: http://yourduino.com/sunshop2/index.php?l=product_detail&p=323), which in turn is connected to the VFD.

I’ve gone through the controls and set up the VFD:
To take communication from over modbus - page 37, b0-02 set to 2
To run at 1200 baud - page 52, bA-01 set to 2
To use 8N1 serial - page 52, bA-02 set to 3
To have address 1 - page 52, bA-03 set to 1

I’ve written a little bit of code to try to send the forward start command (general interface described from page 162, start command at top of page 167).

#include <SoftwareSerial.h>
// Define the pins on which RS485 is connected
#define RO  3
#define DI  5
#define DE  4   // RE is connected here too

byte buffer[8];

SoftwareSerial RS485(RO, DI);   // RX, TX

void setup() {
  pinMode(DE, OUTPUT);           // set pin to input
  Serial.begin(9600);
  RS485.begin(1200);
  
  digitalWrite(DE, LOW);

  delay(200);   // Let serial come up and give stable DE high

  // Create message
  buffer[0] = 0x01;   // Address
  buffer[1] = 0x06;   // Command - write
  buffer[2] = 0x20;   // Function code H
  buffer[3] = 0x00;   // Function code L
  buffer[4] = 0x00;   // Function number H
  buffer[5] = 0x01;   // Function number L
  buffer[6] = 0xCA;   // CRC H
  buffer[7] = 0x43;   // CRC L
}

void loop() {
  Serial.println("Waiting...");
  delay(50);
  Serial.println("Sending now...");
  
  digitalWrite(DE, HIGH);   // Pull up DE
  delay(50);
  int bytesSent = RS485.write(buffer, 8);   // Write the message

  delay(50);               // Delay to allow message to finish
  digitalWrite(DE, LOW);    // Drop DE

  Serial.print("Sent ");
  Serial.print(bytesSent);
  Serial.println(" bytes");

  // Now let's do nothing, forever...
  while (true) {
  }
}

As you can see I’m bringing up the DE pin (which is shorted to the RE pin) on my RS485 module in order to start sending data. Using the scope I can see that when the DE/RE pins are LOW I get about -2.5V, when I bring those pins up, i get 0V. When I run the code above, I can see the bytes transmitted between -2.5 and 2.5V. This all looks good, and I’m using a nice slow baud rate because I’m aware of issues with softwareserial at higher rates.

Note that I’ve pulled the bytes for the message from the manual, and I’ve calculated the CRC here:

So I expect the VFD to start, but it isn’t. Any thoughts?

I managed to get the hardware side of this working by reading LOTS more about RS485 and balancing the lines. I then had more a problem making sense of the VFDs response, so in case anyone is interested, the post about that is here: http://forum.arduino.cc/index.php?topic=345885.0

Hello !,

I’m sorry, I read documentation forum, google, but I can not start / stop / change OMRON MX2 frequency inverter via RS485 Arduino UNO and Arduino.

In the picture you can see how I have the hardware connections and RS485 Arduino Arduino Uno.

The code I use is as follows:

/**

  • 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,9); // 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;
}
}

Thanks !