We have been using Microcontroller Development Boards like Arduino, Raspberry Pi, NodeMCU, ESP8266, MSP430, etc. for a long time now in our small projects where most of the times distance between the sensors and board is not more than few centimeters at max and at these distances, the communication between the different sensor modules, relays, actuators, and controllers can be easily done over simple jumper wires without us being worried about the signal distortion in the medium and the Electrical noises creeping into it. But if you are building a control system with these development boards over a distance greater than 10 to 15 meters, then you should take the noise and signal power into consideration because if you want your system to work reliably, then you cannot afford to lose the data while transferring.
There are many different types of serial communication protocols like I2C and SPI which can be easily implemented with Arduino and today we are going to look at another most commonly used protocol called RS485 which is very commonly used in high noise industrial environments to transfer the data over a long distance. In this tutorial, we are going to learn about the RS485 communication protocol and how to implement it with the two Arduino Nano we have with us and how to use the MAX485 RS485 to UART conversion Module. Previously we have also performed MAX485 communication with Arduino and also MAX485 Communication with Raspberry pi, you can also check them out if interested.
Difference between UART and RS485 Communication
Most of the low-cost sensors and other modules like GPS, Bluetooth, RFID, ESP8266, etc. which are commonly used with Arduino, Raspberry Pi in the market uses UART TTL based communication because it only requires 2 wires TX(Transmitter) and RX (Receiver). It is not a standard Communication protocol, but it is a physical circuit with which you can transmit and receive serial data with other peripherals. It can only transmit/receive data serially, so it first converts the parallel data into serial data and then transmits the data.
UART is an Asynchronous transmission device hence there is no clock signal to sync the data between the two devices instead it uses start and stop bits at the start and end of each data packet respectively to mark the extremities of the data being transferred. UART transmitted data is organized into packets. Each packet contains 1 start bit, 5 to 9 data bits (depending on the UART), an optional parity bit, and 1 or 2 stop bits. It is very well documented and widely used and it also has a parity bit to allow for error checking. But there are some limitations to it as it cannot support multiple slaves and multiple masters and the maximum data frame is limited to 9 bits. For the transfer of data, the baud rates of both Master and Slave must be between 10% of each other. Shown below is the example of how a character is a transmitter over a UART data line. Signal High and Lows are measured against the GND level so shifting the GND level will have a disastrous effect on the data transfer.
On the other hand, RS485 is more industry-based communication which is developed for a network of multiple devices that can be used over long distances and at greater speeds too. It operates on a differential signaling method of measurement rather than voltage measurement wrt GND pin. The RS485 signals are floating and each signal is transmitted over a Sig+ line and a Sig- line.
The RS485 receiver compares the voltage difference between both lines, instead of the absolute voltage level on a signal line. This works well and prevents the existence of ground loops, a common source of communication problems. The best results are achieved if the Sig+ and Sig- lines are twisted as twisting nullify the effect of electromagnetic noise induced in a cable and provide a much better immunity against the noise which allows the RS485 to transmit the data up to 1200m of range. Twisted pair also allows the transmission speeds to be much higher than what is possible with straight cables. At small transmission distances speeds up to 35Mbps can be realized with RS485 although the transmission speed will decrease with distance. At 1200m of transmission speed, you can use only 100kbps of transmission speed. You need a special Ethernet cable for realizing this communication protocol. There are many categories of Ethernet cables we can use like CAT-4, CAT-5, CAT-5E, CAT-6, CAT-6A, etc. In our tutorial, we are going to use CAT-6E cable which has 4 twisted pairs of 24AWG wires and can support up to 600MHz. It is terminated at both ends by an RJ45 connector. Typical line voltage levels from the line drivers are a minimum of ±1.5 V to a maximum of about ±6 V. Receiver input sensitivity is ±200 mV. Noise in the range of ±200 mV is essentially blocked due to common-mode noise cancellation. An example of how a byte(0x3E) is transferred over the two lines of RS485 Communication.
Components Required
- 2×MAX485 Converter Module
- 2×Arduino Nano
- 2×16*2 Alphanumeric LCD
- 2×10k Wiper Potentiometers
- Cat-6E Ethernet Cable
- Breadboards
- Jumper Wires
Circuit Diagram for Long Distance Wired Communication
The below image shows the transmitter and receiver circuit diagram for Arduino's long-distance wired communication. Do note that both transmitter and receiver circuits look identical the only thing that differs is the code written into it. Also for the demonstration, we are using one board as a transmitter and one board as a receiver, but we can easily program the boards to work as both transmitter and receiver with the same set-up
The connection diagram for the above circuit is also given below.
As you can see above there are two near identical pairs of circuits with each having an Arduino nano, 16*2 Alphanumeric LCD, and MAX485 UART to RS485 converter IC connected to each end of an Ethernet Cat-6E cable via an RJ45 connector. The cable which I have used in the tutorial is 25m in length. We will send some data from the transmitter side over the cable from the Nano which is converted to RS485 signals via MAX RS485 Module working in Master Mode.
At the receiving end, the MAX485 converter module is working as a Slave, and listening to the transmission from the Master it again converts the RS485 Data it received to the standard 5V TTL UART signals to be read by the receiving Nano and displayed on 16*2 Alphanumeric LCD connected to it.
MAX485 UART-RS485 Converter Module
This UART-RS485 Converter module has an on-board MAX485 chip which is a low-power and slew-rate-limited transceiver used for RS-485 communication. It works at a single +5V power supply and the rated current is 300 μA. It works on half-duplex communication to implement the function of converting the TTL level into RS-485 level which means it can either transmit or receive at any time, not both, it can achieve a maximum transmission rate of 2.5Mbps. MAX485 transceiver draws a supply current of between 120μA and 500μA under the unloaded or fully loaded conditions when the driver is disabled. The driver is limited for short-circuit current and the driver outputs can be placed at a high impedance state through the thermal shutdown circuit. The receiver input has a fail-safe feature that guarantees logic high output if the input is open circuit. In addition, it has strong anti-interference performance. It also has onboard LEDs to display the current state of the chip i.e. whether the chip is powered or its transmitting or receiving data making it easier to debug and use.
The circuit diagram given above explains how the onboard MAX485 IC is connected to various components and provide 0.1-inch standard spacing headers to be used with breadboard if you like.
Ethernet CAT-6E Cable
When we think of long-distance data transfer, we instantly think about connecting to the internet via Ethernet cables. Nowadays, we mostly use Wi-Fi for internet connectivity but earlier we used to use Ethernet cables going to each personal computer to connect it to the internet. The main reason behind using these Ethernet Cables over normal wires is that they provide much better protection against noise creeping in and distortion of the signal over high distances. They have Shielding Jacket over the insulation layer to protect against the Electromagnetic Interference and also each pair of wires is twisted together to prevent any current loop formation and thus much better protection against the noise. They are often terminated with 8 pin RJ45 connectors at either end. There are many categories of Ethernet cables we can use like CAT-4, CAT-5, CAT-5E, CAT-6, CAT-6A, etc. In our tutorial, we are going to use CAT-6E cable which has 4 twisted pairs of 24AWG wires and can support up to 600MHz.
Picture showing how a pair of wires are twisted inside the Insulation Layer of CAT-6E Cable
RJ-45 Connector Meant for CAT-6E Ethernet Cable
Arduino Code Explanation
In this project, we are using two Arduino Nano, one as a transmitter and One as a receiver each driving a 16*2 Alphanumeric LCD to display the results. So, in the Arduino code, we will focus on sending the data and display that sent or received data on the LCD screen.
For Transmitter Side:
We start with including the standard library for driving the LCD and declare the D8 pin of the Arduino Nano as an output pin which we will later use to declare the MAX485 Module as a transmitter or Receiver.
int enablePin = 8; int potval =0 ; #include <LiquidCrystal.h> //Include LCD library for using LCD display functions LiquidCrystal lcd(2,3,4,5,6,7); // Define LCD display pins RS,E,D4,D5,D6,D7
Now coming to the setup part. We will pull the enable pin high to put the MAX485 module in transmitter mode. As it is a half-duplex IC hence it cannot both transmit and receive at the same time. We will also initialize the LCD here and print a welcome message.
Serial.begin(9600); // initialize serial at baudrate 9600: pinMode(enablePin, OUTPUT); lcd.begin(16,2); lcd.print("CIRCUIT DIGEST"); lcd.setCursor(0,1); lcd.print("Transmitter Nano"); delay(3000); lcd.clear();
Now in the loop, we write a continuously increasing integer value on the Serial lines which is then transmitted to the other nano. This value is also printed on the LCD for display and debugging.
Serial.print("Sent Value= "); Serial.println(potval); //Serial Write POTval to RS-485 Bus lcd.setCursor(0,0); lcd.print("Sent Value"); lcd.setCursor(0,1); lcd.print(potval); delay(1000); lcd.clear(); potval+=1;
Receiver Side:
Here again, we start with including the standard library for driving the LCD and declare the D8 pin of the Arduino Nano as an output pin which we will later use to declare the MAX485 Module as a transmitter or Receiver.
int enablePin = 8; #include <LiquidCrystal.h> //Include LCD library for using LCD display functions LiquidCrystal lcd(2,3,4,5,6,7); // Define LCD display pins RS,E,D4,D5,D6,D7
Now coming to the setup part. We will pull the enable pin high to put the MAX485 module in receiver mode. As it is a half-duplex IC hence it can not both transmit and receive at the same time. We will also initialize the LCD here and print a welcome message.
Serial.begin(9600); // initialize serial at baudrate 9600: pinMode(enablePin, OUTPUT); lcd.begin(16,2); lcd.print("CIRCUIT DIGEST"); lcd.setCursor(0,1); lcd.print("Receiver Nano"); delay(3000); digitalWrite(enablePin, LOW); // (Pin 8 always LOW to receive value from Master)
Now in the loop, we check if there is anything available on the serial port and then read the data and since the incoming data is an integer, we parse it and display on the connected LCD.
int pwmval = Serial.parseInt(); //Receive INTEGER value from Master throught RS-485 Serial.print("I got value"); Serial.println(pwmval); lcd.setCursor(0,0); lcd.print("Received Value"); lcd.setCursor(0,1); lcd.print(pwmval); delay(1000); lcd.clear();
Conclusion
The test setup we used for this project can be found below.
The complete working of this project can be found in the video linked below. This method is one of the simple and easy to implement methods to transfer the data over long distances. In this project, we have only used a baud rate of 9600 which is well under the maximum transfer speed we can achieve with the MAX-485 Module but this speed is suitable for most of the sensor modules out there and we don’t really need all the maximum speeds while working with Arduino and other development boards unless you are using the cable as an ethernet connection and require all the bandwidth and transfer speed you can get. Do play around with transfer speed on your own and give a try to other ethernet cable types too. If you have any questions, leave them in the comment section below or use our forums and I will try my best answering them. Till then, adios!
int enablePin = 8; int potval =0 ; #include <LiquidCrystal.h> //Include LCD library for using LCD display functions LiquidCrystal lcd(2,3,4,5,6,7); // Define LCD display pins RS,E,D4,D5,D6,D7 void setup() { Serial.begin(9600); // initialize serial at baudrate 9600: pinMode(enablePin, OUTPUT); lcd.begin(16,2); lcd.print("CIRCUIT DIGEST"); lcd.setCursor(0,1); lcd.print("Transmitter Nano"); delay(3000); lcd.clear(); digitalWrite(enablePin, HIGH); // (always high as Master Writes data to Slave) } void loop() { Serial.print("Sent Value= "); Serial.println(potval); //Serial Write POTval to RS-485 Bus lcd.setCursor(0,0); lcd.print("Sent Value"); lcd.setCursor(0,1); lcd.print(potval); delay(1000); lcd.clear(); potval+=1; } int enablePin = 8; #include <LiquidCrystal.h> //Include LCD library for using LCD display functions LiquidCrystal lcd(2,3,4,5,6,7); // Define LCD display pins RS,E,D4,D5,D6,D7 void setup() { Serial.begin(9600); // initialize serial at baudrate 9600: pinMode(enablePin, OUTPUT); lcd.begin(16,2); lcd.print("CIRCUIT DIGEST"); lcd.setCursor(0,1); lcd.print("Receiver Nano"); delay(3000); digitalWrite(enablePin, LOW); // (Pin 8 always LOW to receive value from Master) } void loop() { while (Serial.available()) //While have data at Serial port this loop executes { int pwmval = Serial.parseInt(); //Receive INTEGER value from Master throught RS-485 Serial.print("I got value"); Serial.println(pwmval); lcd.setCursor(0,0); lcd.print("Received Value"); lcd.setCursor(0,1); lcd.print(pwmval); delay(1000); lcd.clear(); } }
Comments
Thanks dor sharing, i want to
Thanks dor sharing, i want to ask about rj45 module. Whats name of module?
its wonderfull indeed my big…
its wonderfull indeed
my big issue is solved due to ur article
my sketch is diff
i am sending a button_click value to slave and asking for running clock (stopwatch) reading as string
how and when to change the mode of 'enablePin' in running loop
i tried a lot in many ways, but not getting it
please, TIA
can I use the same setup for 30 meters also?