Arduino + RS485

Hi to all .
i have one VFD unit (Sako SKI600/650 series) that would like to experiment with it and drive it through Arduino - RS485

i have found some default commands from the manual for some functions

the basic setup is one Arduino Nano with the Arduino MAX485 Module RS-485 TTL To RS485 MAX485CSA Converter Module (https://img.joomcdn.net/e175facf206b3d418cac9633d51c5cf02a79ad41_original.jpeg) and 6 buttons for 6 commands to send via RS485 to the VFD

  1. start run
    2 )Start reverse
  2. start at 40HZ
  3. start at 50Hz
  4. Start at 20hs
  5. Stop
/*

   ModBus RTU control VFD

   Address               : 01H  (is the address of the VFD)
   Function              : 06H  (write function code)
   Starting data address : 20H
                         : 00H  (2000H  is the address of control command)
   Data(2Byte)           : 00H
                         : 01H  (0001H is forward command)
   CRC CHK Low           : 43H
   CRC CHK High          : CAH   (43CAH (is 16bits CRC check code)




  From manual vfd Forward command = 01H 06H 2000H 0001H 43CAH

  The 'H' postfix is translated into a '0x' prefix in the Arduino world, so '2000H' gets '0x2000'.

      modbus rtu output
  SKI600 VFD      Arduino RS485 Module

  +485    ---------    A
  -485    ---------    B
  Gnd    ---------    Gnd

*/




#include <SoftwareSerial.h>

#define SSerialRX        10  //Serial Receive pin
#define SSerialTX        11  //Serial Transmit pin
//#define SSerialRX        0  //Serial Receive pin
//#define SSerialTX        1  //Serial Transmit pin
#define SSerialTxControl 3   //RS485 Direction control
#define RS485Transmit    HIGH
#define RS485Receive     LOW
#define Pin13LED         13

byte Fw_Button = 4; //  push button Forward
byte Rev_Button = 5; //  push button Forward
byte Fw40_Button = 6; //  push button Forward
byte Fw50_Button = 7; //  push button Forward
byte Fw20_Button = 8; //  push button Forward
byte Stop_Button = 9; //  push button Forward

byte led = 12;
// From manual vfd Forward command = 01H 06H 2000H 0001H 43CAH

// From manual vfd Stop command = 01H 06H 2000H 0003H C20BH

byte request1[] = {0x01, 0x06, 0x20, 0x00, 0x00, 0x01, 0x43, 0xCA}; // start Forward

byte request2[] = {0x01, 0x06, 0x20, 0x00, 0x00, 0x09, 0x04, 0x20}; // Start Reverse

byte request3[] = {0x01, 0x06, 0x20, 0x01, 0x0F, 0xA0, 0xD6, 0x42}; // start Forward 40 HZ

byte request4[] = {0x01, 0x10, 0x20, 0x00, 0x00, 0x02, 0x04, 0x00, 0x01, 0x13, 0x88, 0x36, 0xFB}; // start Forward 50 HZ

byte request5[] = {0x01, 0x10, 0x20, 0x00, 0x00, 0x02, 0x04, 0x00, 0x01, 0x13, 0x88, 0x07, 0xD0}; // start Forward 20 HZ

byte request6[] = {0x01, 0x06, 0x20, 0x00, 0x00, 0x03, 0xC2, 0x0B}; // Stop

SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // RX, TX
byte byteSend;

void setup()
{
  // Start the built-in serial port, probably to Serial Monitor
  Serial.begin(9600, SERIAL_8E1);
  Serial.println("SerialRemote");  // Can be ignored

  pinMode (Fw_Button, INPUT_PULLUP);      //Define the pin as input
  pinMode (Rev_Button, INPUT_PULLUP);      //Define the pin as input
  pinMode (Fw40_Button, INPUT_PULLUP);      //Define the pin as inpu
  pinMode (Fw50_Button, INPUT_PULLUP);      //Define the pin as input
  pinMode (Fw20_Button, INPUT_PULLUP);      //Define the pin as input
  pinMode (Stop_Button, INPUT_PULLUP);      //Define the pin as input
  pinMode(Pin13LED, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(Pin13LED, OUTPUT);
  pinMode(SSerialTxControl, OUTPUT);

  // digitalWrite(SSerialTxControl, RS485Receive);  // Init Transceiver


  RS485Serial.begin(9600);


}
void loop()
{
  


  if (digitalRead(Fw_Button) == LOW)
  {
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request1, sizeof(request1));
    Serial.println("Send start command Forward");
    digitalWrite(led, HIGH);
  }
  else if (digitalRead(Fw_Button) == HIGH)
  {
    digitalWrite(led, LOW);
  }

 if (digitalRead(Rev_Button) == LOW)
  {
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request2, sizeof(request2));
    Serial.println("Send start command Reverse");
    digitalWrite(led, HIGH);
  }
  else if (digitalRead(Rev_Button) == HIGH)
  {
    digitalWrite(led, LOW);
  }
 
  if (digitalRead(Fw40_Button) == LOW)
  {
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request3, sizeof(request3));
    Serial.println("Send start command 40HZ");
    digitalWrite(led, HIGH);
  }
  else if (digitalRead(Fw40_Button) == HIGH)
  {
    digitalWrite(led, LOW);
  }
  if (digitalRead(Fw50_Button) == LOW)
  {
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request4, sizeof(request4));
    Serial.println("Send start command 50HZ");
    digitalWrite(led, HIGH);
  }
  if (digitalRead(Fw20_Button) == LOW)
  {
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request5, sizeof(request5));
    Serial.println("Send start command 20HZ");
    digitalWrite(led, HIGH);
  }
  if (digitalRead(Stop_Button) == LOW)
  {
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request6, sizeof(request6));
    Serial.println("Stop command");
    digitalWrite(led, LOW);
  }


}

My problems :

A) For some reason when i power up the Nano from a usb phone charger, i have to keep pressing constantly the start button for the vfd to start drive the motor i have connected ... if i leave the button then stop the motor as if i had press the stop button.

Now if i connect my Nano to get power from my pc usb i have to press only once the start button in order my motor run continuously until press the stop button (send stop command)

what is wrong here? in the case of pc connection it works like even if i have the arduino IDE closed or open

B) For the moment i have manage to make it work with only 2 buttons... the star run command and stop command.
The command for reverse doesn't work as and with the commands with speed (HZ) and i am not sure if it is fault of the VFD or (probably) me not understanding what have to do :stuck_out_tongue: :stuck_out_tongue:

here are some pictures from the vfd manual about setting the commands.. if someone can understand more .
i am not sure if i have translate right the commands...

one more tip is that i have try all the above with the transmission response parameter in the vfd on and off

pictures :

I don't calculate the checksum to check which one but one of these two request at least is wrong. The command part is identical just the checksum differs. In both commands the frequency is set to 50Hz.

Why are request 3 and 4 different in length?
As far as you have stated, they only differ in the VFD frequency.

thanks for the answer... it is a typo error forget to change the values
but the problem is that in both situations doesn't work. only the first command is working

it is as it was from different examples in the user manual (but as i mentioned only the first command drives the vfd.. the other ones dont do anything :frowning:

the manual say :

forward and communicate reference frequensy at 50hz
send frame : 01H 10H 2000H 0002H 04H 0001H 1388H 36F8H
Return frame : 01H 10H 2000H 0002H 4A08H

after transmitting RS485 serial data you should call RS485Serial.flush()l to ensure all the bytes have been transmitted from the serial buffers

I think it may be that you need to do it in 2 steps:

Step 1, send the set frequency command as in the 3rd picture (all in hex, but I've not calculated the checksum):
01
06, address of driver and write function code
2001
0FA0 (this is number 4000 in hex, for 40Hz)
checksum

All this does is tell the drive what frequency you have chosen.

Step 2, you will need to tell the drive to run, presumably forwards:
01
06
2000
0001 (forward)
checksum

Now here, I am confused. I don't see
01 10
as the starting numbers for any of the pages from the manual that you have uploaded.
Do you have a link to the full manual?

Hi, sorry for my ignorance but it is the first time that i am coming across to that function Serial.flush()

i just add it after each Serial.write() command in my code :

 if (digitalRead(Fw_Button) == LOW) {
  
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request1, sizeof(request1));
    RS485Serial.flush();
    
    Serial.println("Send start command Forward");
    digitalWrite(led, HIGH);
  }
 
  if (digitalRead(Rev_Button) == LOW) {
    
    digitalWrite(SSerialTxControl, RS485Transmit);
    RS485Serial.write(request2, sizeof(request2));
    RS485Serial.flush();
    
    Serial.println("Send start command Reverse");
    digitalWrite(led, HIGH);
  }

but unfortunately nothing seem to change in the functions

hi...

the first number 01H or 0x01 is the address of the vfd.
The 10H or 0x10 is the write multiple parameters continuously code ( 06H or 0x06 is just to write only one parameter i think )

the manual can be found here : SAKO_SKI600_Manual_EN.pdf - Google Drive

the Chapter 5 for the comunication protocol start from 152 page

i am still little confused why when the arduino is connected to my laptop i have to press only one time the buttons in order the vfd start working (start and stop working only) but when i power on my arduino from a usb mobile charger then it stops every time i leave the buttons (have to press them continuously

I would suggest using the 06H parameter, since you only need to write the frequency to the drive once.

I would suggest completing the troubleshooting with your laptop, and then later try to figure out the other issue. Likely related to power supply noise.

So, please try my recommendations in post 7 above, and let us know if it is working.
For 60Hz, you would use 1770H, I think

1 Like

Hello folks, I have an interesting problem.
I have an RS485 sensor that communicates over modbus. When the sensor is connected to the PC via a USB to 485 converter , I send the sensor a request and I get a correct reply. I then connect the sensor to my Arduino (WAN 1310) , send it the same request frame and I get the correct reply back. Strange thing is, this nice behaviour only works with the sensors default address 01. As soon as I give the sensor any other address, it communicates well on the PC (I send a request and I get a correct response) but I get no response what so ever from the Arduino.
I used my oscilloscope to read the modbus messages and as you can see, when the address is 01, I manage to send a request and get a valid reply back. But, as soon as I change the address to 02, say, only the first four bytes of the request are transmitted, the other four bytes are missing, and, as a consequence, I get no valid reply. Has anyone come across this behaviour before or has any idea of what could be going on? If so, if you wouldn’t mind sharing the details on how to resolve the issue, that would be much appreciated. Thank you.


Do not cross-post!

Hello,

I am getting data from CNC machines using MAX485 with Nodemcu. However, I only get value over the parameter I specified and Slave Id. How can I get all the data at once? without entering any parameters. Then I will transfer and filter with MQTT.

    if (!mb.slave()) {
      mb.readHreg(2, 2450, val0, 1, cb); // Slave id is 1 and register address is 3926 and
      //we are reading 2 bytes from the register and saving in val
      while (mb.slave()) { // Check if transaction is active
        mb.task();
        delay(100);
      }
      Serial.println("Register Values ");
      dtostrf(val0[0], 0, 0, str0);
    }
    Serial.println(val0[0]);
    delay(500);
    
  }

You might want to start a new discussion with your own title to get a better response from the community.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.