Modbus RS485 to GS1 VFD

Hello all,

I am trying to control a GS1 VFD (variable frequency drive) via the modbus port.

Hardware

  • Arduino Mega with RS485 shield (
    -RS485 shield set to 5V
    -RS485 shield set to TX_CTRL
  • Mega pin TX1 connected to P3 (TX)
  • Mega pin RX1 connected to P4 (RX)
  • RS485 shield terminal A connected to GS+
  • RS485 shield terminal B connected to GS- (have switched multiple times to check polarity)

I have verified that the the drive is wired to the motor correctly as i can control via the keypad.

GS1 settings
Motor parameters set and working
Parameter Description Setting Description
P3.00 Source of Operation command 4 Operation controlled via RS485
P4.00 Source of Frequency command 5 Frequency determined via RS485
P9.00 Communication address 1 modbus address 1
P9.01 Transmission speed 1 9600baud
9.02 Communication protocol 0 modbus ASCII (7data, no parity, 2 stop)

Software
To start with i just wanted to try and spin the motor to ensure the comms and and packets were all set right.

Debugging

  • As you can see from the software i am outputting out serial 1 (USB) to check the values are being displayed correctly and the program is running.
  • I have used a "Bitscope" to see the data coming out of the RS485 shield. It shows packets but they arent being displayed correctly

Attachments
Code - below
GS1 user manual chapter 5 communications
Photo of wiring
Screenshot from Bitscope

/*
Author : David 4dice

Interfacing VFD with Arduino Via RS485 using MODBUS Protocol
MODBUS protocol 
- Start, stop and Frequency to VFD sent through modbus RS485

Modbus data format
-------------------------------------------------------------------------
| Start Bit | Address | Function_Command | DATA | LRC or CRC | Stop bit |
| :         | 2bytes  | 2 bytes          |      | 2 bytes    | \r\n |
-------------------------------------------------------------------------

Function Code : The format of data characters depend on function codes
The available function codes are described as follows:
0x03 : Read data from register
0x06 : Write single data to register
0x10 : Write multiple data to registers

MODBUS Protocol ASCII mode

HARDWARE: Arduino Mega using ATmega 1280
          RS485 shield,   
          GS1 VFD

*/

//commands values

#define SSerialTxControl 3          //RS485 Direction control pin
#define RS485Transmit    HIGH     //RS485 comms mode (high = transmit, low = receive)
#define RS485Receive     LOW

char speed_vfd[] = ":00060310001EC8\r\n";                       //VS1 frequency 30Hz 1E in hex
/*
 * 01 = address constant
 * 06 = write single register
 * 0310 = register address
 * 001E = 30 hz
 * C8 = manual lrc calc
 */



const char start_vfd[] = ":0006091B0001D4\r\n";       //VS1 drive hard coded signal
/*
 * 01 = address constant
 * 06 = write single register
 * 091B = register address
 * 0001 = value to write to address
 * D4   = manual lRC calc
 */


const char stop_vfd[] = ":0006091B0000D5\r\n";      //VS1 drive hard coded signal
/*
 * 01 = address constant
 * 06 = write single register
 * 2000 = register address
 * 0011 = value to write to address
 * C8   = manual lRC calc
 */


const char start_n_freq[] = ":0110091B000204025800015A66\r\n";        //from user manual, set speed to 60hz and set to run. Tried this as another option with no luck

void setup(){
Serial.begin(9600);         //initialse USB
Serial1.begin(9600);        //initialise RS485
pinMode(SSerialTxControl, OUTPUT);        //initilise comms enable pin not currently being used, just have jumper set to TX
Serial.println("Modbus VFD Controller \n");


}//end of setup


void loop(){
digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
delay(50);
Serial1.print(start_vfd);                    //converts to ascii, sends start command to VFD
Serial1.println();
delay(100);
digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit 
Serial.println("VFD start command sent\r\n");                 //debug output to ensure output is changing
Serial.print(start_vfd);
Serial.println();

delay(5000);


digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
delay(50);
Serial1.print(speed_vfd);                 //converts to ascii, sends start command to VFD
Serial1.println();
delay(100);
digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit 
Serial.println("VFD frequency sent\r\n");                 //debug output to ensure output is changing
Serial.print(speed_vfd);
Serial.println();

delay(5000);

}//end of loop

Here is a link to the Modbus protocol. http://modbus.org/docs/PI_MBUS_300.pdf

This is just an idea. Where you have the \r\n replace with 0D0A. Then eliminate the Serial1.println().

From the Modbus manual:
In ASCII mode, messages start with a ‘colon’ ( : ) character (ASCII 3A hex), and
end with a ‘carriage return – line feed’ (CRLF) pair (ASCII 0D and 0A hex).:

const char start_vfd[] = ":0006091B0001D4\r\n";       //VS1 drive hard coded signal

I think you need to delete the Serial1.println() completely since it will send extra characters into the interface.

Hi,

Thanks for the input. I have modified the code and given it ago, unfortunately i haven't had any luck. I noticed the RS485 shield seems to have a termination resistor built in. My cable is ~1m long, would i need one at the other end to balance the network?

I havent got one at the moment as the VFD has a RJ12 plug, so i will have to cut and modify the cable to try and add one in.

/*
Author : David Fordyce

Interfacing VFD with Arduino Via RS485 using MODBUS Protocol
MODBUS protocol 
- Start, stop and Frequency to VFD sent through modbus RS485

Modbus data format
-------------------------------------------------------------------------
| Start Bit | Address | Function_Command | DATA | LRC or CRC | Stop bit |
| :         | 2bytes  | 2 bytes          |      | 2 bytes    | \r\n |
-------------------------------------------------------------------------

Function Code : The format of data characters depend on function codes
The available function codes are described as follows:
0x03 : Read data from register
0x06 : Write single data to register
0x10 : Write multiple data to registers

MODBUS Protocol ASCII mode

HARDWARE: Arduino Mega using ATmega 1280
          RS485 shield,   
          GS1 VFD

*/

//commands values

#define SSerialTxControl 3          //RS485 Direction control pin
#define RS485Transmit    HIGH     //RS485 comms mode (high = transmit, low = receive)
#define RS485Receive     LOW

char speed_vfd[] = ":00060310001EC80D0A";                       //VS1 frequency 30Hz 1E in hex
/*
 * 01 = address constant
 * 06 = write single register
 * 0310 = register address
 * 001E = 30 hz
 * C8 = manual lrc calc
 */



const char start_vfd[] = ":0006091B0001D40D0A";       //VS1 drive hard coded signal
/*
 * 01 = address constant
 * 06 = write single register
 * 091B = register address
 * 0001 = value to write to address
 * D4   = manual lRC calc
 */


const char stop_vfd[] = ":0006091B0000D50D0A";      //VS1 drive hard coded signal
/*
 * 01 = address constant
 * 06 = write single register
 * 2000 = register address
 * 0011 = value to write to address
 * C8   = manual lRC calc
 */


const char start_n_freq[] = ":0110091B000204025800015A660D0A";        //from user manual, set speed to 60hz and set to run. Tried this as another option with no luck

void setup(){
Serial.begin(9600);         //initialse USB
Serial1.begin(9600);        //initialise RS485
pinMode(SSerialTxControl, OUTPUT);        //initilise comms enable pin not currently being used, just have jumper set to TX
Serial.println("Modbus VFD Controller \n");


}//end of setup


void loop(){
digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
delay(50);
Serial1.print(start_vfd);                    //converts to ascii, sends start command to VFD
//Serial1.println();
delay(100);
digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit 
Serial.println("VFD start command sent\r\n");                 //debug output to ensure output is changing
Serial.print(start_vfd);
Serial.println();

delay(5000);


digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
delay(50);
Serial1.print(speed_vfd);                 //converts to ascii, sends start command to VFD
//Serial1.println();
delay(100);
digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit 
Serial.println("VFD frequency sent\r\n");                 //debug output to ensure output is changing
Serial.print(speed_vfd);
Serial.println();

delay(5000);

}//end of loop