Investigating the ESP8266–Serial Killing

The ESP8266 is a potentially revolutionary new, small WIFI module costing under £3 ($4). Revolutionary because it will allow small microcontrollers to interface with the web without a) a costly ETHERNET card, b) a more costly traditional WIFI unit and c) without a costly (in terms of storage) library for Ethernet – which can take up half of, say an Arduino UNO’s FLASH memory.

The ESP8266 units work serially – i.e. you talk to them via serial in and they talk back via serial out. They require +3.3v and ground. Regardless of whether you are using a 5V processor or 3v3, the serial output will work with both – but you may consider a level shifter to talk from the processor to the WIFI board if the former uses 5v. This can be as simple as a resistive divider. I am using just in fact a series resistor – but then – my one and only board doesn’t work properly.

Initial translations and blogs out there suggest you need serial in and out – and SOME of tem suggest you also need to take a pin called  CH_PD to +3.3v. The problem is that there are identical looking boards some of which have that pin and NEED it connecting high – others don’t have that pin.  Check out here and here.

So – most of the common code you see will instruct you that the units need 115,200 baud data – and that you start the ball rolling with a reset command. They usually show the use of the Arduino serial port – sending out the command – and an option I’d never used before to analyse the result.. i.e. Serial.find()

So – armed with my new chip I went off and tried this – everyone in the web is using an Arduino with only one serial port – I prefer the Atmega1284 which is the same but better and has 2 serial ports – so when you see me refer to Serial1.find() you’ll realise I’m talking about the second serial port.

So to start the ball rolling you send this…

Serial1.println(“AT+RST”);

And you get (or I get) this rubbish back if you care to look at it.

OK

Eh? What’s this – that’s not what I SAW – it’s what pasted into this blog. What I SAW was this..

OK

  ets Jan  8 2013,rst cause:4, boot mode:(3,7)tail 12
chksum 0xe0
ho 0 tail 12 room 4
load 0x3ffe8000, len 3168, room 12
tail 4
chksum 0x93
load 0x3ffe8c60, len 4956, room 4
tail 8
chksum 0xbd
csum 0xbd

ready

How can this be? Why can’t I paste the lot?  This happened over and over – the copy and paste from the COM window to Windows Live Writer would not work – I ignored it – software bug.

But herein lies the rub…here’s the code I used…

Serial1.setTimeout(5000);
Serial1.begin(115200); // for debugging
delay(1000);

Serial1.println(“AT+RST”); // reset and test if module is ready
my=millis()+2000;
while (my>millis()) { if (Serial1.available()>0){  Serial.print((char)Serial1.read()); my=millis()+2000; } }

Why on EARTH would the result be spit up like that above…

So – here’s what everyone else is using with a variation, I’m looking for (OK) – others look for “ready” – bear with me..… we’ll not repeat the initialisation code here.

Serial1.println(“AT+RST”); // reset and test if module is ready
if (Serial1.find(“OK”)) Serial.println(“Got OK”);

I’d never used this before.. send the data out and wait 5 seconds OR return if you get the sequence OK.

But – what of the REST of the result.. all that crap that comes after ok? SURELY the find() function must wait SOME time and get rid of it – or is it  going to be sitting there waiting to ambush future checks?

And it gets worse.. because the ABOVE works! But this which others are using, doesn’t.

Serial1.println(“AT+RST”); // reset and test if module is ready
if (Serial1.find(“ready”)) Serial.println(“Got ready”);

How can that be – everyone else couldn’t possibly be wrong – how can they find “ready”?  So I made this combination..

Serial1.println(“AT+RST”); // restet and test if module is redy
if (Serial.find(“OK”)) Serial.println(“Got OK”);

my=millis()+2000;
while (my>millis()) { if (Serial1.available()>0){  Serial.print((char)Serial1.read()); my=millis()+2000; } }

So this time I’d trap OK – and then look to see if there was anything left… and little surprise there. All the stuff following OK came flying into view!!

So I tried this – as the data all comes within a second or so – surely a delay after sending would ensure the whole lot was in the buffer ready for checking?

Serial1.println(“AT+RST”); // reset and test if module is ready
delay(3000);
if (Serial1.find(“OK”)) Serial.println(“Got OK”);

my=millis()+2000;
while (my>millis()) { if (Serial1.available()>0){  Serial.print((char)Serial1.read()); my=millis()+2000; } }

Erm, NO!!

Got OK

ets Jan  8 2013,rst cause:4, boot mode:(3,7

Exactly – by now I was thinking of taking up woodwork… the OK was trapped but not only was some of the stuff left in the buffer – but the text “ready” was missing off the end!! A light bulb turned on… Could some of this  have to do with fact that the Serial buffer in Arduino is only 64 bytes long?? There’s more than 64 bytes here…  So presumably by waiting, I’d LOST the remainder.

Then I twigged – if you’re waiting for “ready” you might never get it if the buffer fills up and does not discard what’s there… and that would account for the result above – how on EARTH are others getting this to work?

Then I remembered something about increasing the default buffer size for serial.

In HardwareSerial.cpp – which is located at  hardware/cores/standard  or in my case as I’m using the 1284 chip and have a special setup for it the file is located under my documents at hardware\mighty-1284p\cores\standard

Sure enough – I increased the size of the SERIAL_BUFFER_SIZE from 64 to 512 bytes (I have 16K Ram on the 1284) and the LOST DATA problem above went away.

But it STILL would not find “ready” – at which point I thought – you know – I’ve invested 512 bytes of RAM and this is getting WAY too messy – I’ve never used .find() before – so it won’t be missed  – I could only assume there must be a special character in there somewhere stopping me finding “ready”

And sure enough – it would find OK but not reset or ANY word after that OK area – maybe a NULL in there somewhere??  I could have checked but life is short.  There had to be a better way. SO I wrote my own… I wanted something that would search for a phrase, waiting a certain length of time – but also waiting after anything ELSE came through until the buffer was truly empty..

Serial1.println(“AT+RST”); // reset and test if module is ready
if (SerialFinder(Serial1,”ready”,3000,300)) Serial.println(“GOT IT!!”);

Spot on!  Now, that still does not account for why my WIFI module won’t work  properly – that may well need another module purchasing to compare with – but I hope that helps others who may well be struggling with this very issue. Here is the function below – just drop it in your code or in a library somewhere  – do what you will with it. It’s simple enough… feed it the string – it will return true or false whether it finds the string or not – but not until the timeout. You could add a parameter to kill the timeout once the string is found – but then – what about anything coming in after then and you can’t just flush the buffer – info may not have yet finished coming in. Seems to me the right option would be to just make the delay “sensible”.  You can of course change from Serial1 to Serial etc (multiple serial does not work if you’re using a humble UNO but the mega has either 2 or 2 UARTS and I DEFINITELY recommend having one for your project and one for monitoring/programming) anyway – here it is.

boolean SerialFinder(HardwareSerial &refSer, char *str,unsigned long howlong,unsigned long timeout)
{
   boolean gotit=false;
   unsigned long mytime;
   char *strtemp;
   char incoming;
   strtemp=str; mytime=millis()+howlong;
   while ((mytime>millis()) || refSer.available()) // if timer demands or there is something there
   {
    if (refSer.available())
      {
       mytime=millis()+timeout; incoming=refSer.read();
       Serial.print(incoming); // for debug
       if (incoming==*strtemp) { strtemp++; if (*strtemp==0) {strtemp=str; gotit=true; } } else strtemp=str;
      }
   }
  return gotit;
}

And so I start again from scratch but at least this time knowing my searches work… and so it begins..

Serial1.begin(115200);// talking to WIFI
Serial.begin(115200); // for monitoring
delay(1000);
Serial.println(“Initiating with AT+RST”);
Serial1.println(“AT+RST”); // restart module
if (SerialFinder(Serial1,”ready”,2500,200)) Serial.println(“Good”); else Serial.println(“Nope!”);

Advertisements

3 thoughts on “Investigating the ESP8266–Serial Killing

  1. Hi Scargill,

    Thanks for your ESP8266 material! Your posts have been, by far, the most informative i’ve found. I’ve tried your code above and I’m only able to get it to work reliably if I set howLong to 2000 and timeout to 1000. Just wondering why my timing is so much different. I’m using the most current firmware. Any thoughts?

    Thanks,
    John

    • My timings are based on milliseconds and should be the same on any board… if we ever get the boards to work reliably I’ll package everything I’ve done up and put the code out. I have an App working on my Android phone to turn stuff on and off but the number of times I have to reset the board makes it a pain to use.

  2. Awesome material, i have been battling with the exact same issue, and it´s good to know i´m not the only one.
    I´m gona test this as soon has i get home, keep up the good work :).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s