Max485 with Arduino Modbus

Hello colleagues,

I am hoping someone has some guidance:

I had the code below working via an RS232/485 shield in conjunction with an Arduino AT Mega 2560. I could write dozens of parameters, worked perfectly for proof of concept on a new control system I'm developing.

Of course, for scalability price-wise, I am looking to shift towards using the Mega with the MAX485 TTL (replace the shield with just the module).

Connections:
5V -> 5V
Ground -> Ground
A-> (unchanged)
B-> (unchanged)
DI-> TX
RO->RX
DE+RE -> Arduino pin 4

Original code:

//INCLUDE LIBRARIES
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>

//ESTABLISH DEVICE ADDRESSES
byte VFD_Address = 0x32;              //this must match VFD setting
byte Arduino_Address = 0x35;          //arbitrary (needed if multiple arduinos are networked)

//ESTABLISH REGISTERS USED BY THE VFD
uint16_t reg8192;
uint16_t reg8448;
uint16_t reg8449;

//GLOBAL VARIABLES
int SwitchState;                      //int
int VFD_Status = 0;                   //status of VFD... 0 off, 1 boost, 2 = run, 3 = coast, 4 = brake
int VFD_PrevState = LOW;              //previous state of the VFD (OFF/ON)
long PauseTime = 90000;                //set amount of time to wait between runs in ms
int StartUpTime = 10000;              //set time for startup
int i;                                //indicator intialization
//int RecoverTime;                      //max amount of time allowed for reset to continue where program was

//SET FLAGS
int StartFlag = 0;                    //create a flag enabling the start of the VFD

//SET VISUAL INDICATORS
int RedLight = 22;
int GreenLight = 26;
int YellowLight = 24;
int BlueLight = 28;
int BlueLight2 = 30;
int ledState = LOW;             // ledState used to set the LED (arbitrary)

int ParameterReadAddress[27] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1C, 0x1D};
int ParameterReadValue[27];
int ParameterWriteAddress[44] = {0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x60, 0x61, 0x64, 0x69, 0x72, 0x7D};

int ParameterWriteValue[1][44] = {
  { 230, 280, 300, 300, 280, 5, 1, 5, 1200, 900, -1, -1, -1, -1, 2800, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 100, -1, -1, -1, 495, -1, -1, 1, 30, -1, -1, -1, 3, -1, 0}
 };

void setup() {
  //ESTABLISH PINS
  pinMode(RedLight, OUTPUT);              //establish pin 22 as output for light
  pinMode(GreenLight, OUTPUT);            //establish pin 26 as output for light
  pinMode(YellowLight, OUTPUT);           //establish pin 24 as output for light
  pinMode(BlueLight, OUTPUT);             //establish pin 28 as output for light

  //START SERIAL COMMUNICATIONS
  Serial.begin(9600);
  Serial1.begin(9600);
ModbusRTUClient.begin(9600);              //start arduino modbus client (client = master)
}

void loop() {
  for (i = 0; i < 44; i++) {
    if (ParameterWriteValue[1][i] >= 0) {
      ModbusRTUClient.holdingRegisterWrite(VFD_Address, ParameterWriteAddress[i], ParameterWriteValue[TubeType][i]);
    }
  }
}   //END LOOP

New code incorporated the following into global variables & setup (respectively):

int EnablePin = 4;                    //enable pin for max 485 

pinMode(EnablePin, OUTPUT);
digitalWrite(EnablePin, HIGH);

Yet this does not work anymore. What am I doing wrong?

Yet this does not work anymore. What am I doing wrong?

ArduinoRS485 and ArduinoModbus have to know about that enable pin. The default is 2 so if you use pin 4 you have to tell that to ArduinoRS485 library:

 RS485.setPins(1, 4, -1);

pylon:
ArduinoRS485 and ArduinoModbus have to know about that enable pin. The default is 2 so if you use pin 4 you have to tell that to ArduinoRS485 library:

 RS485.setPins(1, 4, -1);

Hi pylon,
unfortunately that was unsuccessful. I also tried utilizing pin 2 per your information.
The code is now down to:

//INCLUDE LIBRARIES
#include <ArduinoModbus.h>
#include <ArduinoRS485.h>

//ESTABLISH DEVICE ADDRESSES
byte VFD_Address = 0x32;              //this must match VFD setting
byte Arduino_Address = 0x35;          //arbitrary (needed if multiple arduinos are networked)

//ESTABLISH REGISTERS USED BY THE VFD
uint16_t reg8192;
uint16_t reg8448;
uint16_t reg8449;

int EnablePin = 2;                    //enable pin for max 485
int ParameterReadAddress[27] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1C, 0x1D};
int ParameterReadValue[27];
int ParameterWriteAddress[44] = {0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x60, 0x61, 0x64, 0x69, 0x72, 0x7D};

void setup() {
  //ESTABLISH PINS
  pinMode(EnablePin, OUTPUT);
  //RS485.setPins(1, 4, -1);                 //commented out to test pin 2 after unsuccessful attempt on pin 4

  //START SERIAL COMMUNICATIONS
  Serial.begin(9600);
  Serial1.begin(9600);

  digitalWrite(EnablePin, HIGH);

  //START MODBUS COMMUNICATIONS
  ModbusRTUClient.begin(9600);              //start arduino modbus client (client = master)

  //reset logic cmd
  ModbusRTUClient.holdingRegisterWrite(VFD_Address, 8192, 8);
  //write logic cmd
  ModbusRTUClient.holdingRegisterWrite(VFD_Address, 8192, 16657);

  ParameterWriteValue[0][PresetFrequency0] = 600;
  ModbusRTUClient.holdingRegisterWrite(VFD_Address, ParameterWriteAddress[PresetFrequency0], ParameterWriteValue[0][PresetFrequency0]);


}   //END SETUP
void loop() {
  digitalWrite(EnablePin, HIGH);
  ParameterWriteValue[0][PresetFrequency0] = ParameterWriteValue[0][PresetFrequency0] + 100;
  ModbusRTUClient.holdingRegisterWrite(VFD_Address, ParameterWriteAddress[PresetFrequency0], ParameterWriteValue[0][PresetFrequency0]);
  digitalWrite(EnablePin, LOW);
  delay(5000);
}   //END LOOP

Any additional suggestions?

Edit:
I have also tried using RS485.setPins() to establish new DE & RE pins that aren't tethered

pylon:
ArduinoRS485 and ArduinoModbus have to know about that enable pin. The default is 2 so if you use pin 4 you have to tell that to ArduinoRS485 library:

 RS485.setPins(1, 4, -1);

Hello again, sorry for the incredible number of messages. This is resolved!
Ended up using:

 RS485.setPins(1, 4, 5);

I mentioned that I did this in an edit of an earlier comment. I did that, but it helps to have the proper connection to the slave :slight_smile:
FYI, the following still does not work.

 RS485.setPins(1, 4, -1);
1 Like

So you connected RE to pin5? You didn't write that. If the RE pin is set to -1 it's ignored and only DE pin is set to HIGH for writing, LOW otherwise. This should work if RE and DE are connected.

pylon:
So you connected RE to pin5? You didn't write that. If the RE pin is set to -1 it's ignored and only DE pin is set to HIGH for writing, LOW otherwise. This should work if RE and DE are connected.

That was not my initial setup. My initial setup is described in the initial post above.
attempts

Pylon suggestion:
DE+RE -> Pin 4

RS485.setPins(1, 4, -1);

From Pylon info:
DE+RE -> Pin 2
DE+RE -> Pin 2

RS485.setPins(1, 2, -1);

From playing around (success):
DE -> Pin 4
RE -> Pin 5

RS485.setPins(1, 4, 5);

Either way, thank you! Could not have done it without Pylon. I am simply trying to share what I learned through the process.

Your results doesn't make sense to me looking at the RS485 code. Setting RE pin to -1 and connecting the signal to DE pin must work at least with the latest version of the library (I didn't check older versions). DE pin is HIGH only during writes, LOW all the other time.

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