Arduino library 路 Communication

SoftwareSerial: a second serial port on any two pins

An Uno or Nano has one hardware UART, and it is already busy with USB and the Serial Monitor. SoftwareSerial, which ships with the Arduino AVR core, makes another serial port out of two ordinary pins so a sketch can talk to an HC-05 or HC-06 Bluetooth module, a NEO-6M GPS, a SIM800L or an ESP-01 while still printing to the computer.

Built in on Mokxi: #include <SoftwareSerial.h> and it builds, with nothing to install. Free, and no account needed.

What SoftwareSerial does

It works by timing every bit in software. Receiving starts on a pin-change interrupt at the start bit and then samples eight bits in a tight timed loop with interrupts off; sending does the same in the other direction. So only one SoftwareSerial port can receive at a time, it cannot send and receive at once, and while a byte is moving, millis() and other interrupts wait.

In practice 9600 baud is the safe choice, 38400 usually works and 115200 is unreliable on a 16 MHz board. On a Mega or Leonardo not every pin can receive, because RX needs a pin-change interrupt; on the Mega use Serial1 to Serial3 instead when you can.

Library Manager nameSoftwareSerial
AuthorArduino
Include#include <SoftwareSerial.h>
BoardsArduino Uno, Arduino Nano, Arduino Mega 2560, Arduino Leonardo, SparkFun Pro Micro, Arduino Micro, Arduino Pro Mini 3.3 V, ESP8266 NodeMCU, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesBluetooth serial module, HC-05, GPS module, NEO-6M, RS-485 module, MAX485, RS-232 transceiver, MAX232

Install it

It builds on Arduino Uno, Arduino Nano, Arduino Mega 2560, Arduino Leonardo, SparkFun Pro Micro, Arduino Micro, Arduino Pro Mini 3.3 V, ESP8266 NodeMCU, ESP32 DevKit, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, ESP32-S3-DevKitC-1, Seeed XIAO ESP32-S3, Arduino Nano ESP32.

In Mokxi it is built in: #include <SoftwareSerial.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board it comes with the board package (Arduino), so the Arduino IDE has it as soon as the board is installed: there is nothing to add from the Library Manager.

Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 Arduino Pro Mini 3.3 V 路 ESP8266 NodeMCU 路 ESP32 DevKit 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 ESP32-S3-DevKitC-1 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32

The calls you will use

In the order a sketch meets them.

SoftwareSerial bt(2, 3);

A port with RX on pin 2 and TX on pin 3. The module鈥檚 TX goes to your RX pin and its RX to your TX pin.

bt.begin(9600)

Starts the port at a baud rate, which must match the module鈥檚: 9600 for most HC-06 and GPS modules, 38400 for an HC-05 in AT mode.

bt.available()

How many received bytes are waiting in the 64-byte buffer.

if (bt.available()) Serial.write(bt.read());
if (Serial.available()) bt.write(Serial.read());

bt.read()

Takes the next byte from the buffer, or -1 when it is empty.

bt.print("AT")

Sends text, like Serial.print(). println() adds a carriage return and line feed, which many AT command sets want.

gps.listen()

With two SoftwareSerial ports, picks the one that receives. The other drops anything that arrives while it is not listening.

bt.isListening()

True for the port that is currently receiving.

bt.overflow()

True if bytes were lost because the buffer was full; reading it clears the flag.

Example: HC-06 Bluetooth chat

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino 路 Arduino Uno R3
// HC-06 Bluetooth chat: the four-pin module on a SoftwareSerial port.
//
//   HC-06 TXD  -> pin 2   (the sketch's RX)
//   HC-06 RXD  <- pin 3   (the sketch's TX)
//   HC-06 VCC  -> 5V, GND -> GND
//
// Simulated Bluetooth: a phone in Mokxi, not a real radio. Press Run, open
// the Bluetooth tab, pair with the HC-06 (PIN 1234) and connect, the way a
// phone's terminal app does. Then send 1 or 0 and the LED on pin 13 follows.
//
// An HC-06 comes out of the bag with nothing connected, and until something
// connects, whatever the sketch sends it is an AT command: the hello below
// is only sent once a phone is there to read it.

#include <SoftwareSerial.h>

SoftwareSerial BTSerial(2, 3); // RX, TX

char line[32];
byte length = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  BTSerial.begin(9600);
  Serial.println("HC-06 chat ready at 9600 baud. Connect from the Bluetooth tab.");
}

// A whole line from the phone. The answer waits until the line has ended:
// SoftwareSerial cannot listen while it talks.
void command() {
  line[length] = '\0';
  if (strcmp(line, "1") == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
    BTSerial.println("LED on");
  } else if (strcmp(line, "0") == 0) {
    digitalWrite(LED_BUILTIN, LOW);
    BTSerial.println("LED off");
  } else {
    BTSerial.println("Send 1 or 0 for the LED.");
  }
  length = 0;
}

void loop() {
  if (BTSerial.available()) {
    char c = BTSerial.read();
    Serial.write(c);
    if (c == '\n') {
      command();
    } else if (c != '\r' && length < sizeof(line) - 1) {
      line[length++] = c;
    }
  }
}

Open it in the editor, wired and ready to run 路 HC-06 Bluetooth chat: the project page

Common errors and how to fix them

Only garbage characters arrive from the module

The baud rate in begin() does not match the module. Try 9600 first, then 38400; an HC-05 in AT mode is 38400 and most GPS modules ship at 9600. Also check the module and the Arduino share GND.

Nothing arrives at all

RX and TX are usually crossed wrong. The module鈥檚 TX pin goes to the Arduino pin you named as RX (the first number), and its RX to your TX. On a 3.3 V module, put a divider on the Arduino鈥檚 TX line.

With two SoftwareSerial ports, one of them never receives

Only one instance listens at a time, and begin() makes the last one started the listener. Call listen() on the port you want to read before waiting for its data.

Characters go missing at 115200 baud or during long prints

Software timing cannot keep up at high rates, and the 64-byte buffer overflows while the sketch is busy. Drop to 9600 or 38400, read the port often, or use a hardware serial port on a board that has a spare one.

Try SoftwareSerial without installing anything

Open the example, change the sketch, and keep your version in a free account.