RS485 - Beginners problems wiring up the shield

I have a Mega Arduino and also this TTL-RS485 shield.
here which is built around the Max485 chipset. I am no doubt going to need help at various stages but the first step is in wiring it up to the RS485 device I want to control.

There are 8 pins on the RS485 shield. I understand that

RO - Receiver out
RE - Receiver enable (enabled when this pin is LOW)
DE - Driver enable (enabled when this pin is HIGH)
DI - Driver in (the transmitter pin)
GND - (0V)
A -
B -
Vcc - +5V

There are also 2 screw-down terminals for A and B. What I don't understand is the relationship between the A/B terminals and the A/B pins. Presumably I connect my RS485 device to the screw-down terminals. So:

  1. How do I know which terminal is + and which is -?
  2. What is the purpose of the A/B pins and do I need to use them?
  3. I only need to transmit so I am wiring TX1 to DI and TX2 to DE - is this right?
  1. There is no real + and -. Because one is high and the other low to represent a 0 and the other way around to represent a 1. A and B is the term Maxim uses in there datasheet and what most RS485 documentation uses. But because the output is a 1 when A > B, A is sometimes called +- (or annoyingly just +) and B called D- (or -).

  2. You never know sure with Chinese modules but I would say the screw terminals and the header pins both have the same signal just for easy access. Not sure, but easy to check :wink:

ML999:
I have a Mega Arduino and also this TTL-RS485 shield.
here which is built around the Max485 chipset. I am no doubt going to need help at various stages but the first step is in wiring it up to the RS485 device I want to control.

There are 8 pins on the RS485 shield. I understand that

RO - Receiver out
RE - Receiver enable (enabled when this pin is LOW)
DE - Driver enable (enabled when this pin is HIGH)
DI - Driver in (the transmitter pin)
GND - (0V)
A -
B -
Vcc - +5V

There are also 2 screw-down terminals for A and B. What I don't understand is the relationship between the A/B terminals and the A/B pins. Presumably I connect my RS485 device to the screw-down terminals. So:

  1. How do I know which terminal is + and which is -?
  2. What is the purpose of the A/B pins and do I need to use them?
  3. I only need to transmit so I am wiring TX1 to DI and TX2 to DE - is this right?

If you are just going to use this adapter to transmit, I would connect it like this:

  • RO not connected
  • RE High, connected to VCC
  • DE to an Arduino pin
  • DI to Arduino TX pin
  • VCC to Arduino VCC
  • GND to Arduino GND AND connected to your RS485 Device GND
  • A connected to your RS485 Device A
  • B connected to your RS485 Device B

Chuck.

And if it's the only transmitter (and it probably is if you don't check the line) you can connect DE to Vcc as well.

septillion:
And if it's the only transmitter (and it probably is if you don't check the line) you can connect DE to Vcc as well.

Nope,
the bus is simplex, If you permanently enable the TX driver, none of the other devices on the bus can use it. If the device is actually RS422 with independent TX and RX buses then possibly.

Chuck.

Thank you everyone for your helpful comments. I will try Chuck's wiring above.

Hi,
What is the application?

Tom... :slight_smile:

chucktodd:
If you are just going to use this adapter to transmit, I would connect it like this:

  • RO not connected
  • RE High, connected to VCC
  • DE to an Arduino pin
  • DI to Arduino TX pin
  • VCC to Arduino VCC
  • GND to Arduino GND AND connected to your RS485 Device GND
  • A connected to your RS485 Device A
  • B connected to your RS485 Device B

Chuck.

How do I connect the VCC on Arduino to both RE and VCC on the shield? Is it a case of splicing a jumper wire into two or is there a neater way? Breadboard not appropriate here.

Also, what is the reason why you say connect the VCC to RE and not a digital output that I can set to High?

thanks

chucktodd:
Nope,
the bus is simplex, If you permanently enable the TX driver, none of the other devices on the bus can use it.

Yes, then it's simplex. That's what I said, if it's the only transmitter you can keep the module in transmit

If a breadboard is not "appropriate" I doubt jumper wires are. So consider soldering it all on a proto board. Otherwise, yes, slice it. If you doné have a socket left in your room you use a power strip as well don't you?

ML999:
Also, what is the reason why you say connect the VCC to RE and not a digital output that I can set to High?

He say if you only want to use it as a transmitter you can do that. Because what is the use to connect it to a Arduino pin when you never change it? If you also want to receive then yes, you need to connect RE to a digital pin.

TomGeorge:
Hi,
What is the application?

Tom... :slight_smile:

I want to connect it to both the HAI home automation system through a serial connection, and to a Somfy RS485 transmitter to control automated shades.

So I've wired it up, written a simple test sketch and...nothing happens. Tried swapping A and B over with no joy. I'm not even sure where to begin troubleshooting and if the problem is in the wiring or not - here is what I wrote:
The arduino is a mega.
Pin 18 goes to DI
Pin 7 goes to DE
3.3v goes to RE
GND goes to GND on shield
GND goes to GND of RS485 device
5v goes to VCC

/*-----( Import needed libraries )-----*/

//pin 7 DE -need to set high
//pin 18 DI- Serial1 TX Pin


/*-----( Declare Constants and Pin Numbers )-----*/

#define Pin13LED         13
#define DEpin 7


/*-----( Declare Variables )-----*/

byte dataframedown[13]={0x7f,0xf2,0xfa,0x01,0x00,0x00,0x49,0x55,0xfa,0xfb,0xfd,0x05,0xfc}; /

void setup()   {

 pinMode(Pin13LED, OUTPUT);   
 pinMode(DEpin,   OUTPUT);
 digitalWrite(DEpin,HIGH); //enable rs485 transmission on shield
 
 // Start the software serial port, to another device

 Serial1.begin(4800,SERIAL_8O1);   // set the data rate & odd parity on Serial1 (pin 18)

  for(int i=0;i<13;i++)
  {
      
   Serial1.write(dataframedown[i]);          // Send byte stream to Remote device
   delay (100);
  }
     

}//--(end setup )---


void loop()   
{
   digitalWrite(Pin13LED, HIGH);  // Show activity
   delay(1000);
   digitalWrite(Pin13LED, LOW);  // Show activity    
  delay(1000);
 
}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/

//NONE
//*********( THE END )***********

ML999:
So I've wired it up, written a simple test sketch and...nothing happens. Tried swapping A and B over with no joy. I'm not even sure where to begin troubleshooting and if the problem is in the wiring or not - here is what I wrote:
The arduino is a mega.
Pin 18 goes to DI
Pin 7 goes to DE
3.3v goes to RE
GND goes to GND on shield
GND goes to GND of RS485 device
5v goes to VCC

/*-----( Import needed libraries )-----*/

//pin 7 DE -need to set high
//pin 18 DI- Serial1 TX Pin

/-----( Declare Constants and Pin Numbers )-----/

#define Pin13LED         13
#define DEpin 7

/-----( Declare Variables )-----/

byte dataframedown[13]={0x7f,0xf2,0xfa,0x01,0x00,0x00,0x49,0x55,0xfa,0xfb,0xfd,0x05,0xfc}; /

void setup()   {

pinMode(Pin13LED, OUTPUT);  
pinMode(DEpin,   OUTPUT);
digitalWrite(DEpin,HIGH); //enable rs485 transmission on shield

// Start the software serial port, to another device

Serial1.begin(4800,SERIAL_8O1);   // set the data rate & odd parity on Serial1 (pin 18)

for(int i=0;i<13;i++)
 {
     
  Serial1.write(dataframedown[i]);          // Send byte stream to Remote device
  delay (100);
 }

Remove the delay()

for(int i=0;i<13;i++){
  Serial1.write(dataframedown[i]);
  }
Serial1.flush(); // this command will hang until all of the data is shifted out the UART
digitalWrite(DEpin,LOW); // release BUS

ML999:

}//--(end setup )---

void loop()  
{
  digitalWrite(Pin13LED, HIGH);  // Show activity
  delay(1000);
  digitalWrite(Pin13LED, LOW);  // Show activity    
 delay(1000);

}//--(end main loop )---

/-----( Declare User-written Functions )-----/

//NONE
//( THE END )**

I would start by changing your wiring a little, I would connect the rx (RO) to pin 19 of the MEGA, connect RE to GND. This will allow you to monitor the RS485 buss. everything that is transmitted on the buss, even your commands will show up. I would read the Serial1 UART and set that input out to the Serial monitor.

static unsigned long timeout=0; // an example how to delay without actually using delay()

void loop(){

char buf[10];
bool printed=false;

while(Serial1.available()){
  sprintf(buf,"0x%02X ",Serial1.read());
  Serial.print(buf);
  printed=true;
  }
if(printed) Serial.println();
if(millis()-timeout>1000) {
   digitalWrite(13,!digitalRead(13)); // blink pin every second
   timeout = millis(); // new timeout 
   }
}// end loop

Chuck.

p.s. ML999, if you use the quote button in you replies, your reply shows up in my unread message list. else I have to specifically reread all messages i have commented on to find your reply.

chucktodd:
p.s. ML999, if you use the quote button in you replies, your reply shows up in my unread message list. else I have to specifically reread all messages i have commented on to find your reply.

Hi Chuck,
I made those code and wiring changes and also added another command string to send just in case. I also tried swapping the A and B connections over with no result.

//pin 7 DE -need to set high
//pin 18 DI- TX Pin


/*-----( Declare Constants and Pin Numbers )-----*/

#define RS485Transmit    HIGH
#define RS485Receive     LOW

#define Pin13LED         13
#define DEpin 7


/*-----( Declare Variables )-----*/
byte dataframeup[13]={0x7f,0xf2,0xfa,0x01,0x00,0x00,0x49,0x55,0xfa,0xfb,0xfe,0x05,0xfd}; //note that this has already been checksummed and inverted
byte dataframedown[13]={0x7f,0xf2,0xfa,0x01,0x00,0x00,0x49,0x55,0xfa,0xfb,0xfd,0x05,0xfc}; //note that this has already been checksummed and inverted
static unsigned long timeout=0; // an example how to delay without actually using delay()

void setup()   /****** SETUP: RUNS ONCE ******/
{
 
  pinMode(Pin13LED, OUTPUT);   
  pinMode(DEpin,   OUTPUT);
  digitalWrite(DEpin,HIGH); //enable rs485 transmission on shield
  Serial.begin (9600);
  // Start the software serial port, to another device
  Serial1.begin(4800,SERIAL_8O1);   // set the data rate & odd parity on Serial1 (pin 18)

   for(int i=0;i<13;i++)
   {
    String a =String(dataframedown[i],HEX);
    Serial.println (a);          // Send byte stream to USB debug
    
    Serial1.write(dataframedown[i]);          // Send byte stream to Remote device

   }
    Serial1.flush(); // this command will hang until all of the data is shifted out the UART
    digitalWrite(DEpin,LOW); // release BUS 
   delay (30000);

 digitalWrite(DEpin,HIGH); //enable rs485 transmission on shield
   for(int i=0;i<13;i++)
   {

    String b =String(dataframeup[i],HEX);
    Serial.println (b);          // Send byte stream to USB debug
    Serial1.write(dataframeup[i]);          // Send byte stream to Remote device

   }
   Serial1.flush(); // this command will hang until all of the data is shifted out the UART
    digitalWrite(DEpin,LOW); // release BUS 
  
 
}//--(end setup )---

void loop(){

char buf[10];
bool printed=false;

while(Serial1.available()){
  sprintf(buf,"0x%02X ",Serial1.read());
  Serial.print(buf);
  printed=true;
  }
if(printed) Serial.println();
if(millis()-timeout>1000) {
   digitalWrite(13,!digitalRead(13)); // blink pin every second
   timeout = millis(); // new timeout 
   }
}// end loop 
/*-----( Declare User-written Functions )-----*/

//NONE
//*********( THE END )***********

The output on the serial monitor is:

7f
f2
fa
1
0
0
49
55
fa
fb
fd
5
fc
7f
f2
fa
1
0
0
49
55
fa
fb
fd
5
fc

which is what I would expect.

Do you have any other suggestions?
Thanks
Mika

ML999:
Hi Chuck,
I made those code and wiring changes and also added another command string to send just in case. I also tried swapping the A and B connections over with no result.

Mika,

is this bus also used for the original controller? I was hoping that you could monitor the 'official' control sequences send between the controller and heater.

I was hoping to see some response from your device.

Something is not correct. if your Mega is using the code you listed, your output does not match.

your program should produce this output.

7f
f2
fa
1
0
0
49
55
fa
fb
fd
5
fc
0x7F 0xF2 0xFA 0x01 0x00 0x00 0x49 0x55 0xFA 0xFB 0xFD 0x05 0xFC

Are you sure you connected pin 19 and RO and grounded RE? from your output, the loop() never read any data from Serial1().

Your output looks like the Mega ran setup() twice. The Mega never received any data back from the RS485 bus.

put a couple of more debug printlines in setup

// after Serial.begin(9600);
Serial.println("Starting setup");
// after Serial1.flush();
Serial.println("Flushed Serial1.\nCharacters waiting in Serial1 input queue:");
Serial.println(Serial1.available(),DEC);

What version of the Arduino IDE are you using?

Chuck.

chucktodd:
Mika,

is this bus also used for the original controller? I was hoping that you could monitor the 'official' control sequences send between the controller and heater.

I was hoping to see some response from your device.

Something is not correct. if your Mega is using the code you listed, your output does not match.

your program should produce this output.

7f

f2
fa
1
0
0
49
55
fa
fb
fd
5
fc
0x7F 0xF2 0xFA 0x01 0x00 0x00 0x49 0x55 0xFA 0xFB 0xFD 0x05 0xFC




Are you sure you connected pin 19 and RO and grounded RE? from your output, the loop() never read any data from Serial1(). 

Your output looks like the Mega ran setup() twice. The Mega never received any data back from the RS485 bus. 

put a couple of more debug printlines in setup

I have added in the debug lines below and I changed the byte stream to one that gets a response from the device ('otherdata').

/*-----( Declare Constants and Pin Numbers )-----*/

#define RS485Transmit    HIGH
#define RS485Receive     LOW

#define Pin13LED         13
#define DEpin 7


/*-----( Declare Variables )-----*/
byte dataframeup[13]={0x7f,0xf2,0xfa,0x01,0x00,0x00,0x49,0x55,0xfa,0xfb,0xfe,0x05,0xfd}; //note that this has already been checksummed and inverted
byte dataframedown[13]={0x7f,0xf2,0xfa,0x01,0x00,0x00,0x49,0x55,0xfa,0xfb,0xfd,0x05,0xfc}; //note that this has already been checksummed and inverted
byte otherdata[12]={0x5f,0xf3,0xf9,0x01,0x00,0x00,0x49,0x55,0xfa,0xff,0x04,0xe3}; 
static unsigned long timeout=0; // an example how to delay without actually using delay()

void setup()   /****** SETUP: RUNS ONCE ******/
{
 
  pinMode(Pin13LED, OUTPUT);   
  pinMode(DEpin,   OUTPUT);
  digitalWrite(DEpin,HIGH); //enable rs485 transmission on shield
  Serial.begin (9600);
  // after Serial.begin(9600);
Serial.println("Starting setup");

  // Start the software serial port, to another device
  Serial1.begin(4800,SERIAL_8O1);   // set the data rate & odd parity on Serial1 (pin 18)

   for(int i=0;i<12;i++)
   {
    String a =String(otherdata[i],HEX);
    Serial.println (a);          // Send byte stream to USB debug
    
    Serial1.write(otherdata[i]);          // Send byte stream to Remote device

   }
    Serial1.flush(); // this command will hang until all of the data is shifted out the UART
    // after Serial1.flush();
  Serial.println("Flushed Serial1.\nCharacters waiting in Serial1 input queue:");
  Serial.println(Serial1.available(),DEC);
    digitalWrite(DEpin,LOW); // release BUS 

}//--(end setup )---

void loop(){

char buf[10];
bool printed=false;

while(Serial1.available()){
  sprintf(buf,"0x%02X ",Serial1.read());
  Serial.print(buf);
  printed=true;
  }
if(printed) Serial.println();
if(millis()-timeout>1000) {
   digitalWrite(13,!digitalRead(13)); // blink pin every second
   timeout = millis(); // new timeout 
   }
}// end loop 
/*-----( Declare User-written Functions )-----*/

//NONE
//*********( THE END )***********

and the output is

Starting setup
5f
f3
f9
1
0
0
49
55
fa
ff
4
e3
Flushed Serial1.
Characters waiting in Serial1 input queue:
0

Yes, pin 19 is definitely connected to RO and RE is definitely grounded.

ML999:
I have added in the debug lines below and I changed the byte stream to one that gets a response from the device ('otherdata').

and the output is

Starting setup

5f
f3
f9
1
0
0
49
55
fa
ff
4
e3
Flushed Serial1.
Characters waiting in Serial1 input queue:
0




Yes, pin 19 is definitely connected to RO and RE is definitely grounded.

Something is wrong, As you indicated.

If your RS485 adapter is connected like this:

Then anytime any data is sent on the RS485 bus, the data will appear in the Serial1 read buffer.

The data you send out using Serial1.write() should have been read by the Receiver section and echoed back into Serial1.

Since this did not happen, there are three possible failure modes:

  • RE is not grounded, it is HIGH, this will disable the receiver circuit
  • RO is not connected to pin19, no path for data to the UART
  • component failure the MAX485 is damaged, the Arduino's Serial1 RX circuit is damaged.

I would start by testing the Arduino Mega:

  • disconnect the Mega from the RS485 circuit
  • jumper 18 to 19
  • run the current sketch
  • If the output matches my example the Arduino is ok

Test the RS485 adapter:

  • Connected the Mega to the RS485 circuit
  • put a 120ohm resistor between A <-> B
  • put a 680ohm resistor between A <-> VCC
  • put a 680ohm resistor between B <-> GND
  • if the output matches my example the RS485 adapter is ok

Chuck.

chucktodd:
Something is wrong, As you indicated.

If your RS485 adapter is connected like this:

Then anytime any data is sent on the RS485 bus, the data will appear in the Serial1 read buffer.

The data you send out using Serial1.write() should have been read by the Receiver section and echoed back into Serial1.

Since this did not happen, there are three possible failure modes:

  • RE is not grounded, it is HIGH, this will disable the receiver circuit
  • RO is not connected to pin19, no path for data to the UART
  • component failure the MAX485 is damaged, the Arduino's Serial1 RX circuit is damaged.

I would start by testing the Arduino Mega:

  • disconnect the Mega from the RS485 circuit
  • jumper 18 to 19
  • run the current sketch
  • If the output matches my example the Arduino is ok

Test the RS485 adapter:

  • Connected the Mega to the RS485 circuit
  • put a 120ohm resistor between A <-> B
  • put a 680ohm resistor between A <-> VCC
  • put a 680ohm resistor between B <-> GND
  • if the output matches my example the RS485 adapter is ok

Chuck.

I will do the tests but something occurred to me - NB: this is the first thing I have ever done with an Arduino, so sorry if it is a silly question - Presumably setup() runs completely before loop() so surely by the time that sprintf(buf,"0x%02x ",Serial1.read()) runs, the buffer has been flushed and there is nothing to read in? Also, the device is 4800 8O1- for the Serial1.read() does this need to be changed to 9600 8N1?
thanks

ML999:
I will do the tests but something occurred to me - NB: this is the first thing I have ever done with an Arduino, so sorry if it is a silly question - Presumably setup() runs completely before loop() so surely by the time that sprintf(buf,"0x%02x ",Serial1.read()) runs, the buffer has been flushed and there is nothing to read in? Also, the device is 4800 8O1- for the Serial1.read() does this need to be changed to 9600 8N1?
thanks

Serial.flush() does not empty the receive buffer, it just waits for the TX buffer to be completely sent.

Back when the Arduino was first created (before version 1.0) Serial.flush() just emptied the receive (RX) buffer.

When DE is High the MAX485 is transmitting, if RE is LOW at the same time the info going out TX is echoed back into RX. The MEGA uses two, 63 byte buffers for each SERIAL, one for transmitting, one for receiving. When Serial1.flush() returns, the TX buffer is empty and the last byte has completely shifted out of the UART (serial hardware). And, since all of the data was echoed back into the RX pin, the RX section of the UART placed a copy of all of transmitted data into the RX buffer. The Serial1.available() call calculates how many bytes of data are in the RX buffer. If the hardware is functioning correctly, every byte that was sent out the TX pin, came back in the RX pin. Therefore the RX buffer will contain a complete copy of everything that was send.
If more than 63 bytes of data was send out, only the first 63 are saved in the RX buffer, anything else is lost.

the Serial.begin() config applies to both the TX side and the RX side of the UART.

Serial.begin() sets the config for TX pin 1, RX pin 2.
Serial1.begin() sets the config for TX1 pin 18, RX1 pin 19.

they are independent of each other.

Chuck.

chucktodd:
Serial.begin() sets the config for TX pin 1, RX pin 2.
Serial1.begin() sets the config for TX1 pin 18, RX1 pin 19.

they are independent of each other.

Chuck.

When I connect the loopback between tx1 and rx1 the output is indeed

Starting setup
7f
f2
fa
1
0
0
49
55
fa
fb
fe
5
fd
Flushed Serial1.
Characters waiting in Serial1 input queue:
13
0x7F 0xF2 0xFA 0x01 0x00 0x00 0x49 0x55 0xFA 0xFB 0xFE 0x05 0xFD

I currently only have 1k resistors and need to get the ones you specify to test the RS485 shield. Thanks again.

On the rs-485 A goes to A and /B goes to /B. Make sure your baud rate is correct. Don't forget your terminating resistors at each end of the rs-485. Should be 120 ohm at each end between A and /B.