SoftwareSerial works FIRST time, but not on SUBSEQUENT attempts

Hi All,

I’m baffled here and thought I’d get out to the community and ask. I should prefix this post and say that I think the hardware on my project is fine because if I upload a blank sketch and do serial passthrough on the hardware serial from the terminal, it works as intended (remembering to ‘cross the streams’ when using this method).

I’m connecting an ESP-01 Wifi module to an Arduino Uno. Pins 2,3 are software serial to the device. Plenty of power is supplied to the device using a 3.3v LM3940 regulator and CH_PD is pulled high. When i transmit the first command to the ESP, it returns the response as would be expected. However, when i repeat the same command immediately after (by duplicating the same code_, nothing happens…ever. Doesn’t matter what command, whether i’ve coded it into flash, or used the terminal relaying the data between hardware and software ports.

The code is below. I’ve simplified it removing all the unrelated bits. I’ve placed all the code in the setup area as i’m not concerned with looping in this demonstration. In my main program i send a command in the setup section and let the serial reflector/relay in the loop work to pass the data back to the terminal via the serial port. In this case, the first command in the setup section works, as does the reflector back to the terminal, and then that’s it. No other commands sent from the program or terminal work. Yes, there are buffer overruns in the code below, but the same behaviour occurs in the main program where there isn’t any that I’m aware of.

#include <SoftwareSerial.h>

SoftwareSerial device(2,3); // Rx, Tx

void setup() {
  Serial.begin(9600);   // Serial port for connection to host
  device.begin(9600);   // Serial port for connection to serial device
  while (!Serial);       // wait for serial ports to connect. Needed for native USB port only


  // THIS CODE SNIPPET DOES WORK
  device.println("AT+GMR");
  Serial.println("AT+GMR command FIRST attempt, sent to ESP, waiting 3s...");
  delay(3000);                                                                    // THIS DELAY CAUSES BUFFER OVERRUN, BUT NOT THE ISSUE
  if(device.available()){
    Serial.println("Message received from ESP, it follows:");
    Serial.println("--------------------------------------");
    while(device.available())
    {
      Serial.write(device.read());
    }
    Serial.println("\r\n--------------------------------------");
    Serial.println("Read of ESP AT+GMR No.1 completed.\r\n\r\n");
  } else {
    Serial.println("\r\nERROR! No response received!\r\n\r\n");
  }



  // THIS DUPLICATE CODE SNIPPET DOES NOT WORK BECAUSE IT'S NOT THE FIRST TIME
  device.println("AT+GMR");
  Serial.println("AT+GMR command SECOND attempt, sent to ESP, waiting 3s...");
  delay(3000);                                                                    // THIS DELAY CAUSES BUFFER OVERRUN, BUT NOT THE ISSUE
  if(device.available()){
    Serial.println("Message received from ESP, it follows:");
    Serial.println("--------------------------------------");
    while(device.available())
    {
      Serial.write(device.read());
    }
    Serial.println("\r\n--------------------------------------");
    Serial.println("Read of ESP AT+GMR No.2 completed.\r\n\r\n");
  } else {
    Serial.println("\r\nERROR! No response received!\r\n\r\n");
  }


  delay(5000);


  Serial.println("Exiting Setup");

  
}

void loop() {

}

The response I get in the terminal using the above code is below. It just doesn’t make sense.

AT+GMR command FIRST attempt, sent to ESP, waiting 3s…
Message received from ESP, it follows:

AT+GMR

AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:

Read of ESP AT+GMR No.1 completed.

AT+GMR command SECOND attempt, sent to ESP, waiting 3s…

ERROR! No response received!

Exiting Setup

I’ve even done the serial reflector and this doesn’t do anything on the terminal. I find, serial communication only works on the first use in the setup section

/**
 * SerialReflector
 */
#include <SoftwareSerial.h>

SoftwareSerial device(2,3); // Rx, Tx

void setup() {
  Serial.begin(9600);   // Serial port for connection to host
  device.begin(9600);  // Serial port for connection to serial device
}

void loop() {
  if(device.available())
  {
    Serial.write(device.read());
  }
  if(Serial.available())
  {
    device.write(Serial.read());
  }
}

If anyone can provide some advice, I would greatly appreciate it!

Thanks!

Rob

It may or may not be causing you problems, but those AT commands should be terminated with "/r/n".

Thanks for the reply arduarn. I think that the printLN version of the print function tacks on the "\r\n".

It's not clear how you determined that the buffer overflow was not the problem.

Does the problem occur with other commands or just "AT+GMR"?

Sorry, I should have made that bit more clear. This is just a demonstration to reproduce the problem. My main program has the byte transfer in the main loop to transfer 1 byte at a time between serial ports. No other overheads in the loop, So no overflow that I am aware of.

All commands are affected, even the basic AT one. When doing just the simple serial reflector at the end of my post, that gets nothing on the terminal. If i add a single command to the startup code section of the program, say AT+GMR, I get the full response back in the main serial reflector loop, and then nothing back on subsequent attempts using the terminal

Here’s the most barebones reproduction of the problem I can do. Code below, and response in the terminal is after. The initial command sent from the setup function works fine, but no commands from the terminal work after the initial response is received. I’ve also tried it on pins 6 and 7 of the uno to no avail.

<code>
#include <SoftwareSerial.h>

SoftwareSerial device(2,3); // Rx, Tx

void setup() {
 Serial.begin(9600);   // Serial port for connection to host
 device.begin(9600);  // Serial port for connection to serial device
 while (!Serial);       // wait for serial ports to connect. Needed for native USB port only


 device.println("AT+GMR");
}

void loop() {
 if(device.available())
 {
   Serial.write(device.read());
 }
 if(Serial.available())
 {
   device.write(Serial.read());
 }
}

The response from the ESP-01 is below, the first line is the Echo:

AT+GMR

AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
Ai-Thinker Technology Co. Ltd.
Jun 13 2016 11:29:20
OK

I've also tried it on pins 6 and 7 of the uno to no avail.

Try AltSoftSerial on pins 8 and 9.

Hi -dev,

Thanks for the tip, hadn’t thought of that. Updated for AltSoftSerial as suggested, but got same behaviour. Am going back to regular softserial just to keep the debug process consistent.

I’ve worked out a bit more now. If I reset the ESP-01 (the device), i get more communication as per below:

AT+GMR

AT version:1.1.0.0(May 11 2016 18:09:56)
SDK version:1.5.4(baaeaebb)
Ai-Thinker Technology Co. Ltd.
Jun 13 2016 11:29:20
OK

<scrambled garbage that always comes through at 74880 baud upon reboot in this area and then more below>

Ai-Thinker Technology Co. Ltd.

ready
WIFI CONNECTED
WIFI GOT IP

but commands entered into the terminal still don’t get a response from the ESP-01 device after this reset of the device.

So this says to me the following:

  1. The Arduino is not hung up
  2. The device is not hung up
  3. Device Tx to Arduino Rx after first command = OK
  4. Arduino Hardware Tx to Computer terminal after first command = OK

From earlier debugging, when sending a command to the ESP-01 via terminal, I got it to send a stream back to the terminal to see that it got the command in the first place, so:

  1. Computer terminal Tx to Arduino hardware Rx after first command = OK

So I think the problem lies in the Arduino Tx to ESP-01 Rx maybe???

Its possible that the ESP-01 needs the AT commands sent with no gaps between the characters.
When you send the command like this
device.println("AT+GMR");
the Arduino sends the commands at full speed, ie no gaps between chars, but when you send the commands by typing from the terminal, there are large gaps between the chars, and the AT command parser in the ESP-01 times out as the command is taking too long to be received.

Hello All,

Just an update, I've figured it out. It was because my voltage divider to reduce the 5V arduino Tx to the 3.3V ESP-01 RX was made from 22k and 10k resistors. After all this troubleshooting and your help to give me the confidence the programming was OK, I thought it may be because the resistance values were too high, so I changed the voltage divider to use a 2.2k and 3.8k resistor (based on what I had lying around) and now it works perfectly.

I was just thrown because the HW serial port worked fine, and the SW serial port worked up until 800 us from start up. It wasn't because it was just the first command, but any command within the first 800 us would work.

Crisis over, but thanks again for all of your help. Ultimately, this post really belongs in the Hardware side, not the software side.

Cheers and thanks to you all,

Rob