Documentation

MAX485 TTL to RS485 Converter Module for Arduino, ESP32, STM32 & Raspberry Pi | ShillehTek Product Manual
Documentation / MAX485 TTL to RS485 Converter Module for Arduino, ESP32, STM32 & Raspberry Pi | ShillehTek Product Manual

MAX485 TTL to RS485 Converter Module for Arduino, ESP32, STM32 & Raspberry Pi | ShillehTek Product Manual

shillehtek

Overview

The MAX485 module converts a microcontroller's TTL serial into RS-485 — the differential bus standard that industrial equipment has trusted for decades. Instead of one signal wire referenced to ground, RS-485 sends every bit as a voltage difference across a twisted pair (A and B). Noise hits both wires equally and cancels out, which is how RS-485 runs reliably across factory floors, long cable trays, and electrically hostile environments where plain UART gives up after a few meters: think 1200 meters at modest baud rates, with up to 32 devices sharing one pair.

The board is the classic C25B layout: the MAX485 transceiver in SOIC-8, a green screw terminal plus header pins for the A/B bus, a power LED, and a 120-ohm termination resistor (R7) already fitted between A and B. The TTL side breaks out RO (receive out), DI (drive in), and the two enables — RE and DE — which you tie together and treat as one direction pin: high to transmit, low to receive. That one wire is the whole trick of half-duplex RS-485.

Use a pair of these to link two microcontrollers across a building, poll Modbus RTU devices like power meters and VFDs, network a chain of sensor nodes, or drive DMX-style lighting experiments. It runs from 5V (and works with 3.3V logic on the ESP32/Pi side with the usual precaution on RO), and needs nothing but three data wires per end plus the twisted pair between them.

At a Glance

Transceiver
MAX485 (half-duplex)
Bus
RS-485 differential A/B
Range
Up to ~1200 m
Devices per Bus
Up to 32
Supply Voltage
5V DC
Direction Control
RE+DE tied → one GPIO

Specifications

Parameter Value
Transceiver IC MAX485 (or equivalent), half-duplex RS-485/RS-422
Supply Voltage 5V DC (logic inputs 3.3V-compatible)
Data Rate Up to 2.5 Mbps (short runs); 9600-115200 baud typical
Range vs Speed ~1200 m at 9600-100k baud; shorter as speed rises
TTL Pins RO (receiver out), RE (receiver enable, active low), DE (driver enable), DI (driver in)
Bus Pins A (Data+), B (Data-) on screw terminal and header
Termination 120 ohm (R7) fitted between A and B
Nodes per Segment 32 unit loads
Common-Mode Range -7V to +12V
Current Draw ~300 uA idle, ~50 mA transmitting into terminated bus
Indicator Power LED (D1)

Pinout Diagram

Left header, top to bottom: RO, RE, DE, DI — the TTL side. Right side: VCC, B, A, GND on the header, with A and B duplicated on the green screw terminal for field wiring. R7 is the 120-ohm load resistor between A and B; it stays for the two modules at the ends of a long bus and comes off for middle nodes.

MAX485 TTL to RS485 converter module pinout diagram showing RO RE DE DI pins, A B bus terminals, 120 ohm load resistor and power LED

Wiring Guide

In every hookup: tie RE and DE together into one "direction" GPIO, cross A→A and B→B between modules with twisted pair, and join grounds between nodes when they run from separate supplies.

Arduino Wiring (SoftwareSerial)

MAX485 Pin Arduino Pin Details
VCC / GND 5V / GND
RO D10 SoftwareSerial RX
DI D11 SoftwareSerial TX
RE + DE (tied) D3 HIGH = transmit, LOW = receive
A / B Twisted pair to far module A-A, B-B
Tip: If nothing arrives, swap A and B first — reversed polarity is the #1 RS-485 gremlin and completely harmless to try.

ESP32 Wiring (hardware UART2)

MAX485 Pin ESP32 Pin Details
VCC / GND VIN (5V) / GND Logic pins accept 3.3V highs
RO GPIO 16 (RX2) Through 1k series resistor (see note)
DI GPIO 17 (TX2)
RE + DE GPIO 4 Direction control
A / B Bus pair
Warning: RO swings to 5V when the module runs at 5V. A 1k series resistor (or a 2k/3.3k divider) into the ESP32's RX pin keeps things polite. Alternatively run the module's VCC at 3.3V — it loses a little drive strength but works fine for short-to-medium runs.

Raspberry Pi Wiring (UART0)

MAX485 Pin Pi Pin Details
VCC / GND Pin 2 (5V) / Pin 6 (GND)
RO Pin 10 (GPIO 15, RXD) Via 1k series resistor
DI Pin 8 (GPIO 14, TXD)
RE + DE Pin 11 (GPIO 17) Direction control
A / B Bus pair
Tip: Enable the UART with sudo raspi-config → Interface Options → Serial: login shell OFF, serial hardware ON. The port is then /dev/serial0.

Raspberry Pi Pico Wiring (UART0)

MAX485 Pin Pico Pin Details
VCC / GND VBUS (5V) / GND
RO GP1 (UART0 RX) Via 1k series resistor
DI GP0 (UART0 TX)
RE + DE GP2 Direction control
A / B Bus pair

Code Examples

The examples implement the same simple protocol — a sender that transmits a numbered message once a second and switches back to receive to await an "ACK". Flash the sender code on one board and adapt the receive loop on the other (roles are symmetric).

Arduino

max485_arduino.ino
// MAX485 RS-485 - Arduino Example (sender + listener)
// RO->D10, DI->D11, RE+DE->D3, VCC->5V

#include <SoftwareSerial.h>

const int DIR_PIN = 3;                  // HIGH = TX, LOW = RX
SoftwareSerial rs485(10, 11);           // RX, TX
unsigned long counter = 0;

void setTransmit(bool tx) {
  digitalWrite(DIR_PIN, tx ? HIGH : LOW);
  delayMicroseconds(50);                // let the driver settle
}

void setup() {
  Serial.begin(115200);
  rs485.begin(9600);
  pinMode(DIR_PIN, OUTPUT);
  setTransmit(false);
  Serial.println("RS-485 node ready");
}

void loop() {
  // --- send one message ---
  setTransmit(true);
  rs485.print("MSG ");
  rs485.println(counter++);
  rs485.flush();                        // wait until fully shifted out
  setTransmit(false);

  // --- listen for replies for 1 second ---
  unsigned long t0 = millis();
  while (millis() - t0 < 1000) {
    if (rs485.available()) {
      String line = rs485.readStringUntil('\n');
      Serial.print("Received: ");
      Serial.println(line);
    }
  }
}

ESP32 (Arduino IDE, UART2)

max485_esp32.ino
// MAX485 RS-485 - ESP32 Example (hardware UART2)
// RO->GPIO16, DI->GPIO17, RE+DE->GPIO4

const int DIR_PIN = 4;
unsigned long counter = 0;

void setTransmit(bool tx) {
  digitalWrite(DIR_PIN, tx ? HIGH : LOW);
  delayMicroseconds(50);
}

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, 16, 17);   // RX=16, TX=17
  pinMode(DIR_PIN, OUTPUT);
  setTransmit(false);
  Serial.println("RS-485 node ready");
}

void loop() {
  setTransmit(true);
  Serial2.printf("ESP32 MSG %lu\n", counter++);
  Serial2.flush();
  setTransmit(false);

  unsigned long t0 = millis();
  while (millis() - t0 < 1000) {
    if (Serial2.available()) {
      String line = Serial2.readStringUntil('\n');
      Serial.print("Received: ");
      Serial.println(line);
    }
  }
}

Raspberry Pi (Python)

max485_rpi.py
#!/usr/bin/env python3
# MAX485 RS-485 - Raspberry Pi Example
# RO->GPIO15(RXD), DI->GPIO14(TXD), RE+DE->GPIO17
# Install: pip3 install pyserial ; enable UART in raspi-config

import serial
import time
import RPi.GPIO as GPIO

DIR_PIN = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(DIR_PIN, GPIO.OUT, initial=GPIO.LOW)

port = serial.Serial("/dev/serial0", 9600, timeout=0.2)

def send(msg):
    GPIO.output(DIR_PIN, GPIO.HIGH)
    time.sleep(0.0001)
    port.write((msg + "\n").encode())
    port.flush()
    time.sleep(0.002)                 # drain the UART FIFO
    GPIO.output(DIR_PIN, GPIO.LOW)

counter = 0
print("RS-485 node ready")
try:
    while True:
        send("PI MSG {}".format(counter))
        counter += 1

        t0 = time.time()
        while time.time() - t0 < 1.0:
            line = port.readline()
            if line:
                print("Received:", line.decode(errors="ignore").strip())
except KeyboardInterrupt:
    GPIO.cleanup()
    print("Stopped by user")

Raspberry Pi Pico (MicroPython)

max485_pico.py
# MAX485 RS-485 - Pico MicroPython Example
# RO->GP1, DI->GP0, RE+DE->GP2

from machine import UART, Pin
import time

uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
dir_pin = Pin(2, Pin.OUT, value=0)     # 0 = receive

def send(msg):
    dir_pin.value(1)
    time.sleep_us(100)
    uart.write(msg + "\n")
    # wait for the frame to leave the shift register
    time.sleep_ms(2 + len(msg))
    dir_pin.value(0)

counter = 0
print("RS-485 node ready")
while True:
    send("PICO MSG {}".format(counter))
    counter += 1

    t0 = time.ticks_ms()
    while time.ticks_diff(time.ticks_ms(), t0) < 1000:
        if uart.any():
            line = uart.readline()
            if line:
                print("Received:", line.decode().strip())

Frequently Asked Questions

Both boards run but nothing is ever received. Checklist?
1) Swap A/B on one end — reversed pairs are the classic. 2) Confirm RE and DE are tied together and driven by the pin your code toggles. 3) Match baud rates. 4) If the nodes run from different supplies, connect their grounds (RS-485 tolerates offset but not unlimited). 5) Verify the direction pin actually goes high during send — a stuck-low pin means the driver never turns on.
Why do I receive garbage or my own message echoed back?
Garbage usually means baud mismatch or the direction pin switching to receive before the last byte finished — that's why every example flushes and briefly waits before dropping DE. Seeing your own frames is normal if RE is low while transmitting (receiver stays enabled); either ignore self-frames in software or keep RE high during TX by driving both enables together, as wired here.
When do I remove the 120-ohm resistor (R7)?
Termination belongs only at the two physical ends of the bus. Two modules linked point-to-point: leave both fitted — perfect. A chain of three or more: keep R7 on the two end modules and unsolder it from every middle node, otherwise the bus is over-loaded and drive levels sag. For short desk-length experiments, honestly, nobody notices either way.
Can I do Modbus RTU with this?
Yes — this is exactly the physical layer Modbus RTU expects. Pair it with a Modbus library (ModbusMaster on Arduino/ESP32, pymodbus or minimalmodbus on the Pi) and point the library's pre/post-transmission callbacks at the RE+DE pin. You can then poll energy meters, VFDs, solar inverters, and PLCs — mind the device's required baud/parity (9600 8E1 is common).
How far and how fast, really?
The RS-485 rule of thumb: cable length (m) x data rate (bps) ≤ ~10^8. So 9600 baud is comfortable at 1000+ m, 115200 to ~500 m, and megabit rates only for tens of meters. Use twisted pair (one pair of Cat5 is ideal), keep stubs off the main line short, and terminate the ends — do that and RS-485 is astonishingly robust.
Is it safe with 3.3V boards?
Driving DI/RE/DE from 3.3V works — the MAX485 registers anything above 2V as high. The only 5V hazard is RO, the module's output back to your RX pin: use the 1k series resistor (or divider) shown in the ESP32/Pi/Pico tabs, or power the module at 3.3V. There are also native 3.3V transceivers (MAX3485) if you're designing a PCB.
Can more than one node transmit at the same time?
Not simultaneously — half-duplex RS-485 is one talker at a time, and two active drivers fight (harmlessly briefly, corrupting data). Every practical protocol solves this with master/slave polling (Modbus), token passing, or timed slots. Keep every node's DE low except while it's actually sending — the examples' send() helpers already enforce that discipline.

Related Tutorials