RS485 Arduino Network | Blogue de Guillaume DALLAIRE's Blog
RS485 Arduino Network
Recently I started wondering about the fact that most of my MCU based projects use a RS232 serial port to exchange data between my “base” computer and every modules. Since the number of serial ports is limited (normally 2) on a normal PC, this is a problem.
After some reading, I decided to try a RS485 bus: A multipoint serial communication channel that would be both simple and cheap to implement inside my projects. The first thing to do is to test this technology by prototyping a half-duplex RS485 bus with some Arduino MCU.
Let’s find a transceiver. Two chips seem to be commonly used : The MAX485 (or DS485, the Nationnal Semiconductor equivalent) and the SN75176BP. See this Maxim comparision page. I choose the SN75176BP, only 0.71$CAD.
Each MCU has its own 75176 connected to the UART (RO and DI). The RE and DE pins are connected together to a digital output allowing the MCU to control the “direction” of the data flow with the bus. When this line is LOW, the transceiver is in “receiving” mode. At a HIGH level, the transceiver switch to the “sending” mode.
Note that the RE/DE pins can be connected to any MCU’s digital output.
The RS485’s topology is multipoint. This means that every node in the network shares the same media, then without collision avoidance mechanism (which is relatively complex to implement), only one node can be defined as a master. The master sends commands or data and zero or more slaves respond to the master (It’s an important limitation).
I built my prototype around 1 master and 3 slaves:
The blue and white wires are the RS485 physical bus. Slave #1 has 2 sensors (barometric and RH), slave #2 and #3 are simple LED display. The master reads the sensors by sending slave’s #1 address, this slave sends the values (current RH+pressure), the master reads it and finally, it sets the displays by calling each slave’s (#2 and #3) address with the data to show. The RS485 transmit function looks like this:
void rs485TxMsg(char *msg) { Serial.flush(); digitalWrite(txPin, HIGH); delay(10); Serial.println(msg); delay(10); digitalWrite(txPin, LOW); }
The read function :
void rs485RxMsg(char *msg, byte msgLen) { byte i = 0; char val; msg[0] = 0; while(Serial.available()) { val = Serial.read(); if (val == '\r') msg[i++] = 0; if (val == '\n') { msg[i++] = 0; return; } msg[i++] = val; if (i>msgLen) return; } }
The “message” separator are the “\r\n” characters. A more elaborate format would be needed in production and CRC checking (or equivalent) would be also a good thing.
For now I succesfully got a working system very easily. RS485 is simple and cheap to implement for a MCU based system.
댓글