RS485 board/First messages/09. Two Unos over one pair
First messages · 09 of 11

Two Unos over one pair

Two Arduino Unos, each with a MAX485 5V board, joined by A, B and GND. One sends ping, the other answers pong, and both take turns on the same pair. The Uno's one hardware UART is its USB link, so the bus goes through SoftwareSerial on pins 10 and 11.

What you need

  • Two Arduino Unos (a Nano works the same, on the same pins).
  • Two MAX485 5V boards, headers soldered.
  • Three wires between the terminals: A, B and GND. A metre of twisted pair makes the point better than three jumpers, but either works.

Wire it

Each Uno to its own board:

BoardUno
GNDGND
5V5V
TXpin 10
RXpin 11
DEpin 2

The Uno's pins 0 and 1 are its hardware UART, and they are also the USB link to the Serial Monitor, so the bus goes on SoftwareSerial instead.

Taking turns

Taking turns on one pair
bus free
Talking
nobody
Uno 1 read
Uno 2 read
Press Ping and watch the pins. Only one of them is HIGH at any moment. If both were, the two drivers would fight over A and B and neither message would arrive.

Each Uno holds pin 2 LOW, listening, except inside send(). The talker raises it, sends a line, waits for the last byte and drops it. Only then can the listener raise its own and answer. At no moment are both pins HIGH, which is what half duplex asks.

What it prints

On the talker:

talker
reply pong 1
reply pong 2

On the listener:

listener
heard ping 1
heard ping 2

Every reply line is a message that crossed the pair twice, once each way, through both boards' drivers and both boards' receivers.

The code

rs485_ping_pong.ino

The same sketch goes on both Unos. Set TALKER to true on one and false on the other. The talker sends ping once a second; the listener answers each ping with pong and the same number.

// RS485 ping-pong between two Unos, MAX485 (5V) boards.
//
// Wiring, each Uno to its own board:
//   Board GND -> Uno GND     Board 5V -> Uno 5V
//   Board TX  -> Uno pin 10  (the board's TX is the chip's RO)
//   Board RX  -> Uno pin 11
//   Board DE  -> Uno pin 2   (RE is joined to DE on the board)
// Terminals: A to A, B to B, GND to GND.
// Keep both 120R fitted: two boards are the two ends.
//
// Arduino IDE: Tools > Board > Arduino AVR Boards >
// Arduino Uno, then Tools > Port. Serial Monitor 9600.
// SoftwareSerial comes with the IDE.
//
// Upload with TALKER true to one Uno, false to the other.

#include <SoftwareSerial.h>

const bool TALKER = true;
const int DIR = 2;

SoftwareSerial bus(10, 11);  // RX, TX
String line;
int count = 0;
unsigned long last = 0;

void send(const String &msg) {
  digitalWrite(DIR, HIGH);      // take the bus
  delayMicroseconds(200);
  bus.println(msg);
  bus.flush();
  digitalWrite(DIR, LOW);       // let go
}

void setup() {
  pinMode(DIR, OUTPUT);
  digitalWrite(DIR, LOW);       // listen first
  Serial.begin(9600);
  bus.begin(9600);
  Serial.println(TALKER ? "talker" : "listener");
}

void loop() {
  if (TALKER && millis() - last >= 1000) {
    last = millis();
    count++;
    send("ping " + String(count));
  }

  while (bus.available()) {
    char c = bus.read();
    if (c != '\n') {
      if (line.length() < 30) line += c;
      continue;
    }
    line.trim();
    if (!TALKER && line.startsWith("ping ")) {
      Serial.println("heard " + line);
      send("pong " + line.substring(5));
    } else if (TALKER && line.startsWith("pong ")) {
      Serial.println("reply " + line);
    }
    line = "";
  }
}

SoftwareSerial writes each byte bit by bit and returns only when its stop bit is out, so flush() is not strictly needed here. It stays in, because the same code on any hardware UART needs it.

When it does not work

The listener prints heard, but the talker never prints reply.

The pong is going out while the talker's pin is still HIGH, or the talker's board cannot hear. Check the talker's pin 2 reaches DE or RE, and that its board's TX goes to pin 10. A talker sketch that holds the pin HIGH after sending blocks every answer.

Neither Uno prints anything after its first line.

Nothing is crossing the pair. Swap A and B at one terminal, check both boards' TX go to pin 10 and RX to pin 11, and that the GND screw is wired between the terminals as well as A and B.

It works with both Unos on one computer and fails with one on a phone charger.

On one computer both Unos share the computer's ground through USB, which hides a missing GND wire. On separate supplies the grounds can sit volts apart. Run GND between the terminals alongside A and B.

Can one Uno be an ESP32 with a MAX3485 board instead?

Yes. The bus carries only the difference between A and B, and both chips make and read it the same way. Use the ESP32 sketch's pins and HardwareSerial on that side, with the same 9600 baud and the same ping and pong lines.

Where this goes next

Cable, ground and the shape of the run, once the boards leave the desk.

Wiring a real bus

Edit this page — content/books/rs485/two-unos.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

This page covers several products. Choose yours to see the right discussions.

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse Modules and blocks on the forum