In this tutorial, we will learn how to perform RS485 serial communication between two Arduino boards using 5V MAX485 TTL to RS485 module. RS485 communication is used in industrial Modbus to communicate with various devices. We will follow the RS485 serial communication protocol and demonstrate it with two Arduino boards. One will act as an RS485 master node and the other will act as a slave node. The master will be connected with a potentiometer which will be used to vary ADC values. The slave node will receive this ADC data from the master over RS485 and control the brightness of an LED and also display a value on OLED. These ADC values will be transferred from the master to the slave via the RS485 module.
We have a similar guide with ESP32 and ESP8266:
RS485 Serial Communication
Serial communication concerns the transmission of data in a serial manner, meaning it is sent and received one bit at a time. It is the most basic form of electronic data transmission and was the primary form of communication between machines in the first generations of personal computers. Implementing serial communication functionality in an embedded system requires the developers and engineers involved to have an understanding of the underlying serial protocols used in this form of data transmission. The most common protocols you will come across are the RS232/RS422/RS485 standards.
The RS485 protocol is a form of asynchronous serial communication that allows communications bus to connect multiple devices simultaneously. The communication is at half duplex using two wires and common ground. It is faster and covers a wider range as compared to other standards like RS232 etc. Provides a maximum cable length of 1200m. Can connect to a maximum of 32 devices unlike RS232 that connects to a single device. Moreover, it is preferred in electrically noisy industrial environments as it is less prone to noise issues.
Differential signaling is used in this protocol to provide better noise immunity as well as recovering a lost signal at the end of a line. It works by putting the signal on 1 wire and the inverse of the signal on the other wire.
Apart from all the advantages listed above, the RS485 protocol successfully transfers data between devices over large distances making it an optimal choice to be used in industries.
MAX485 RS485 Transceiver Module
The MAX485 RS485 Transceiver Module is used when transferring data between Arduino boards. This transceiver module consisting of the Maxim MAX485 IC provides robust serial communication over long distances up to 1200m. The power efficient module transfers data in both directions at a maximum data rate of 2.5 Mbps.
Moreover, this 5V MAX485 TTL to RS485 module can easily be interfaced with microcontrollers for example Arduino as it uses 5V logic levels.
Some key features of the RS485 Module include:
- Differential signalling for better noise immunity
- Covers distances up to 1200 meters
- Maximum data rate of 2.5 Mbps
- Supports up to 32 devices on same bus
- Red power LED
- 5V operating voltage
- Low Power Consumption
MAX485 Module PinOut
The MAX485 transceiver module consists of 8 pins, 4 on each side. They are shown in the figure below:
Pin Name | Description |
---|---|
VCC | This is the power supply pin. It is connected with 5V that powers up the module. |
A | This is the non-inverting receiver input and driver output. It is connected with A on the other module. |
B | This is the inverting receiver input and driver output. It is connected with B on the other module. |
GND | This is the GND pin. It is connected with common ground. |
RO | This is the receiver output pin. It is connected with the RX pin of the microcontroller. |
RE | This is the receiver output enable pin. To enable, it is set at a LOW state. |
DE | This is the driver output enable pin. To enable, it is set at a HIGH state. |
DI | This is the driver input. It is connected with the TX pin of the microcontroller. |
The module also consists of 2 screw terminal blocks which are part of the output side.
A: This is the non-inverting receiver input and driver output. It is connected with A on the other module.
B: This is the inverting receiver input and driver output. It is connected with B on the other module.
Project: RS485 Serial Communication between two Arduino boards (Control LED Brightness)
Let us demonstrate an example of RS485 serial data transfer between two Arduino boards using the MAX485 TTL to RS-485 module. Our aim will be to send ADC values from the master Arduino connected with a potentiometer through the RS485 module to the slave Arduino. The slave Arduino will be connected with an LED and an OLED display. The brightness of the LED will vary with the ADC values generated by the potentiometer at the master side. Additionally, the OLED display will also print the current PWM values (0-255) as well.
Master and Slave Configuration Circuit Diagram
We will require the following components for this project:
Required Components
- 2 Arduino UNO boards
- 2 RS485 Modules
- 1 Potentiometer
- 1 LED
- 1 OLED display
- Connecting Wires
- Breadboard
In order to properly connect all the devices successfully follow the connections very carefully. Follow the schematic diagram below:
Master Arduino Side
Firstly, we will explain the connections between the Master Arduino side. The master Arduino is connected with a potentiometer and an RS485 module. Out of the eight pins of the RS485 module we have connected 6 pins with Arduino UNO board.
Below you can view the connections between the Arduino board and the transceiver module.
Arduino UNO | RS485 Module |
5V | VCC |
GND | GND |
pin 0 (RX) | RO |
pin 8 | RE & DE |
pin 1 (TX) | DI |
Connect the VCC pin of the RS485 module with 5 V from Arduino. Additionally connect both the grounds together. The RO pin will be connected to the serial RX pin of Arduino UNO which is pin 0. Likewise, the DI pin will be connected with the serial TX pin of Arduino UNO which is pin 1. The RE and DE pins will be connected together with any digital output pin of the Arduino board. We have used digital pin 8 to connect these two pins.
The rest of the two pins of the RS485 module: B and A are connected with the other RS485 module’s B and A pins respectively that is connected with the slave Arduino.
We have connected the potentiometer with the Analog pin A0 of our Arduino board. One terminal of the potentiometer is powered by 5V (red), the center terminal is connected to A0 and the last one is grounded (black).
Slave Arduino Side
Next, we will explain the connections of the Slave Arduino with the RS-485 module, LED and the OLED display. The connections of the Arduino with the RS485 module are the same. Just make sure to connect B and A of RS485 module (slave side) with B and A pins of RS485 module (master side) correctly.
Next, the OLED has four pins that we will connect with the Arduino. We will connect the VCC terminal of the OLED display with 5V which will be in common with the Arduino board. SCL of the display will be connected with the default SCL pin of the Arduino board that is A5. SDA of the display will be connected with the default SDA of the Arduino that is A4. Additionally the ground pins will be connected in common.
Arduino UNO | OLED |
GND | GND |
5V | VCC |
A5 | SCL |
A4 | SDA |
Moreover, we have connected the LED’s anode with digital pin 10 and cathode with common ground. You can use any other PWM pin of the Arduino board to connect with the LED as well.
Installing OLED Libraries in Arduino IDE
To use the OLED display in our project, we have to install the Adafruit SSD 1306 library and Adafruit GFX library in Arduino IDE. Follow the steps below to successfully install them.
Open Arduino IDE and click on Sketch > Library > Manage Libraries. Type ‘SSD1306’ in the search tab and install the Adafruit SSD1306 OLED library.
We will also require the Adafruit GFX library which is a dependency for SSD1306. Type ‘Adafruit GFX’ in the search tab and install it as well.
Arduino Sketch for Master
Open your Arduino IDE and go to File > New. A new file will open. Copy the code given below in that file and save it.
This sketch is for the Arduino that acts as the master. It will transfer ADC values through the RS485 module to the Slave Arduino.
int Enable_pin = 8;
int Analog_pin = A0;
int ADC_Value = 0 ;
void setup()
{
Serial.begin(115200);
pinMode(Enable_pin, OUTPUT);
pinMode(Analog_pin, INPUT);
delay(10);
digitalWrite(Enable_pin, HIGH);
}
void loop()
{
int ADC_Value = analogRead(Analog_pin);
Serial.println(ADC_Value); //Serial Write ADC_Value to RS-485 Bus
delay(100);
}
How the Code Works?
We will first define the Arduino digital pin that we have connected with DE and RE pins of the module. We have labelled it as the ‘Enable_pin’ and set the value 8 to it. This is the Arduino digital pin that we are using.
int Enable_pin = 8;
Secondly, we will define two more variables. One will hold the ADC pin A0 that we will connect with the potentiometer. The second one will be called ‘ADC_value’ and will save the ADC values. Initially we have set the value to zero. The values will vary from 0-1023.
int Analog_pin = A0;
int ADC_Value = 0 ;
Inside the setup() function, we will open the serial communication at a baud rate of 115200. Then we will configure the enable pin as an output pin and the Analog pin connected with the potentiometer as an input pin. This will be achieved by using the pinMode() function and passing the pin as the first parameter and INPUT/OUTPUT as the second parameter.
Moreover, we will set the Enable_pin state to HIGH. This will make sure that DE and RE pins are both set to HIGH to enable the driver.
void setup()
{
Serial.begin(115200);
pinMode(Enable_pin, OUTPUT);
pinMode(Analog_pin, INPUT);
delay(10);
digitalWrite(Enable_pin, HIGH);
}
Inside the loop() function, we will find out the ADC value according to the varying voltage using analogRead() after every 0.1 second. We will pass the ADC pin connected to the potentiometer as an argument inside it. This will be stored in the integer variable we defined previously ‘ADC_value.’ This will be sent to the RS-485 bus serially.
void loop()
{
int ADC_Value = analogRead(Analog_pin);
Serial.println(ADC_Value); //Serial Write ADC_Value to RS-485 Bus
delay(100);
}
Arduino Sketch for Slave
Open your Arduino IDE and go to File > New. A new file will open. Copy the code given below in that file and save it.
This sketch is for the Arduino that acts as the slave. It will receive the ADC values through the RS485 module serially from the Master Arduino and control the LED brightness and OLED display accordingly.
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
int Enable_pin = 8;
int LED_pin = 10;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire, -1);
void setup()
{
Serial.begin(115200);
pinMode(LED_pin, OUTPUT);
pinMode(Enable_pin, OUTPUT);
digitalWrite(Enable_pin, LOW); // (LOW to receive value from Master)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(100);
display.clearDisplay();
display.display();
display.setTextColor(WHITE);
}
void loop()
{
while (Serial.available())
{
display.clearDisplay();
int PWM_master = Serial.parseInt(); //Receive INT value from Master throught RS-485
int duty_cycle = map(PWM_master, 0, 1023, 0, 255); //Map that value
Serial.println(duty_cycle);
analogWrite(LED_pin, duty_cycle); //PWM_master write to LED
display.setCursor(0, 0);
display.setTextSize(2);
display.print("MASTER PWM");
display.setCursor(50, 30);
display.setTextSize(4);
display.print(duty_cycle);
display.display();
delay(100);
}
}
How the Code Works?
Firstly, we will include the OLED libraries that we previously installed for the proper functionality of the OLED display.
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Then we will create an integer variable for the Arduino digital pin that we have connected with DE and RE pins of the module. We have labelled it as the ‘Enable_pin’ and set the value 8 to it. This is the Arduino digital pin that we are using.
int Enable_pin = 8;
We will define the Arduino PWM pin that we have connected with the LED’s anode.
int LED_pin = 10;
Now, we will create an object named display which will be handling the OLED display and specifying the width, height, I2C instance (&Wire), and -1 as parameters inside it.’ -1′ specifies that the OLED display which we are using does not have a RESET pin. If you are using the RESET pin then specify the GPIO through which you are connecting it with your development board.
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire, -1);
Inside the setup() function, we will open the serial communication at a baud rate of 115200. Then we will configure both the enable pin and the LED pin defined previously as output pins. This will be achieved by using the pinMode() function and passing the pin as the first parameter and INPUT/OUTPUT as the second parameter.
Moreover, we will set the Enable_pin state to LOW. This will make sure that DE and RE pins are both set to LOW to enable the receiver.
Serial.begin(115200);
pinMode(LED_pin, OUTPUT);
pinMode(Enable_pin, OUTPUT);
digitalWrite(Enable_pin, LOW); // (LOW to receive value from Master)
We will initialize the OLED display by using display.begin(). Make sure you specify the correct address of your display. In our case, it is 0X3C.
Then, we will clear the buffer by using clearDisplay() on the Adafruit_SSD1306 object. Additionally, we will set the colour of the text as white.
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(100);
display.clearDisplay();
display.display();
display.setTextColor(WHITE);
loop()
Inside the loop() function, we will check if any data is available at the serial port. While the data is available, we will first clear the buffer of the display. Then we will map the ADC values received from the master Arduino from 0-1023 to values from 0-255. This will be stored in the integer variable ‘duty_cycle.’ The value will also get printed on our serial monitor.
while (Serial.available())
{
display.clearDisplay();
int PWM_master = Serial.parseInt();
int duty_cycle = map(PWM_master, 0, 1023, 0, 255);
Serial.println(duty_cycle);
The analogWrite() function will be called that will generate a PWM signal corresponding to the duty cycle value. The value of the duty cycle can vary between 0 and 255. That means, when the duty cycle value is 0, the LED will not glow at all, and similarly when it is 255, LED will glow with full brightness.
analogWrite(LED_pin, duty_cycle);
The following section of code displays this PWM value sent by the master that was previously converted to 0-255, on the OLED display.
display.setCursor(0, 0);
display.setTextSize(2);
display.print("MASTER PWM");
display.setCursor(50, 30);
display.setTextSize(4);
display.print(duty_cycle);
display.display();
delay(100);
Demonstration
To see the demonstration of this project, upload the master and slave code to the respective Arduino boards. But, before uploading code, make sure to select the Arduino from Tools > Board and also select the correct COM port to which the Arduino board is connected from Tools > Port.
Once the code is uploaded to Arduino, turn the knob of the potentiometer and the brightness of the LED will vary. Increasing input values from the potentiometer act as increasing duty cycle hence the brightness of the LED increases. The OLED will display the current PWM values in the range 0-255 acquired from the master Arduino board as well.
Video demo:
Other Arduino tutorials, you may like to read:
How would we assign a slave number, if more than one slaves were connected to the master Arduino?