I'm having problems running a serial communication between a NodeMCU ESP8266 and an Arduino Uno. I'm using the "standard" SUART setup, i.e. pins D1&D2 on the ESP are hooked up with GPIOs 2&3 on the UNO; the tx from UNO to ESP is fed through a voltage divider to step it down to 3.3V.

The setup used to work fine; suddently - yeah I've read it before, my setup suddently doesn't work, but honestly that's what happened - data is being corrupted. The devices exchange a json formatted string:


and it just worked. Now what I receive is something like:


Both SUART are on 115200 baudrate, physical connections have been checked and are fine, both devices are grounded on the same reference level.

I've tried swapping the ESP with another one and changing TX/RX pins on the UNO - no results.

So I'm looking for suggestions what to do next to debug the issue, what to check and what could be wrong. Thank you in advance.

Below are UNO and ESP code snippets.


SoftwareSerial SUART(4, 5);

int16_t last_fetch = 0;
int16_t last_serial = 0;

double azimut, elevation;


void setup() {
  Serial.begin(115200);  //enable Serial Monitor
  SUART.begin(115200);   //enable SUART Port

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {


void loop() {
  if (secs() - last_fetch >= DATA_FETCH_TIME_INT) {
    last_fetch = secs();

  if (secs() - last_serial >= SERIAL_TRASMISSION_TIME_INT) {
    last_serial = secs();

void fetchData() {
  //connects to server and fetches data

void sendDataViaSerial() {
  int lat_i = (int) elevation;
  int lon_i = (int) azimut;
  int checksum = lat_i + lon_i;

  const int capacity = 200;
  StaticJsonDocument<capacity> doc;

  doc["action"] = "position";
  doc["lat"] = lat_i;
  doc["lon"] = lon_i;
  doc["cksum"] = checksum;

  Serial.println("Sending data via serial: ");
  serializeJson(doc, Serial);

  //serializeJson(doc, SUART);
  // works the same

  String outstring;
  serializeJson(doc, outstring);


SoftwareSerial SUART(2, 3);
#define arraySize 150
char inData[arraySize];

void setup() {
  digitalWrite(STATUS_LED, HIGH);


  Serial.println("Ready to go.\n");

void loop() {

void readSerial() {
  short index = 0;
  char inChar;

  if (SUART.available() > 0) {
    while (SUART.available() > 0 && index < arraySize - 1) {
      inChar = SUART.read();    
      inData[index] = inChar;

      inData[index] = '\0';  // Add a null at the end

    String myData = (String)inData;

    // consume data
  • 3
    use 9600 baud. AVR SoftwareSerial can't reliably listen at 115200 baud
    – Juraj
    Jan 14, 2020 at 10:29
  • I have used SoftwareSerial for MIDI (which is 31.250 baud) and it didn't work reliable, so indeed 9600 seems a good starting point, probably you cannot go much higher. Jan 14, 2020 at 11:24

1 Answer 1


As @Juraj mentions in the comments, don't use 115200 baud with SoftwareSerial.

The problem is that the AVR isn't fast enough to handle incoming data at that speed reliably. Yes, it can receive a byte fine at that speed, but what it can't necessarily do is store that byte away in the receive buffer in time to be ready to receive the next byte - so it misses the first few bits and corruption ensues.

Running at a lower baud rate (such as 9600 baud) simply gives it more time to process the data as it arrives.

  • Both you and @Juraj were right. So.. thanks! Lowering the baudrate (now using 38400) fixed the corruption problem. However, adding delay(5); at the end of the receiver while loop seems to help as well. Again, thanks guys. Remains to be seen why it worked at 115200 and then suddently stopped.
    – veveve
    Jan 14, 2020 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.