Having a problem with ESP8266 01. Potentially it could be with the Serial??

Hi,

The board is an Arduino MEGA 2560.

I writing a program to control a garden watering system and part of this will rely on communication over WiFi.

I have connected an ESP8266 and although I had a few initial problems, fixed via firmware updates, I am now having code issues.

Initially I wrote, thanks for help from the net, a small program that will allow me to connect to my local WiFi. With this working, I sought to embed the code into the main program.

The problem is that I get different responses from the ESP8266 between the two programs.

I am not sure if the issue is with my code, the ESP8266, or the way I am using the serial connection.

Have attached the main code file from both programs:

Serial Output from WifiTest program:

Resetting module
AT+RST


OK
WIFI DISCONNECT

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

load 0x40100000, len 27728, room 16 
tail 0
chksum 0x2a
load 0x3ffe8000, len 2124, room 8 
tail 4
chksum 0x07
load 0x3ffe8850, len 9276, room 4 
tail 8
chksum 0xba
csum 0xba
Œãr“lŒlŒìl`Œâr“lìlŒl`Œâs’lŽŸ
ready

Serial output for AutoWater program:

Resetting WIFI module
AT+RST


OK
WIFI DISCONNECT

 ets Jan  8 2013,rst cause:2,
Wifi module has no response.

WifiTest.ino (2.29 KB)

AutoWater.ino (11.4 KB)

in your code you set a timeout to read from Serial at 1 second

     ESP8266.setTimeout(1000);

then later in the code, after sending a command and waiting for 1 second, you read the content back from the ESP8266 and try to find the word "ready"

  if (ESP8266.find("ready"))

if you do then you are all happy and if not you print "Module have no response."

it is possible that if your ESP module takes more than 2 seconds to answer that the "ready" keyword you are waiting for does not arrive in time and thus your read times out and you print your error message.

try with this at the begining

     ESP8266.setTimeout(5000);

that will set the timeout to read from your Serial to 5 seconds, will give you a chance to wait a bit longer for the ESP to answer

actually looking at your second code - the one for your watering system, your code is a bit different as you do

	Serial.println(ESP8266.readString());
		if (ESP8266.find("ready"))

the first line of this code will empty the ESP8266 serial buffer (whatever is in there up to the timeout) so when you execute the second line, you try to read again from the ESP8266 serial buffer until the timeout waiting for the keyword "ready", but because your previous statement emptied the buffer, you will never see the "ready" string if it was already sent and if it was not sent in the first read, but still does not arrive within the timeout of 1s, then you are wrongly assuming things don't work.

so if you increase the timeout to 5 seconds, then you have better chances of capturing the ready, but then be aware that your first line of code above will get it thus you will fail.

suggestion:

Don't use readString or find. readString will build up a string just for you to print and that will put an extra toll on your memory and either you need to set long timeouts which slows down all your operations, or deal with timing issues. if you stick to "find", then you deal with the long timeout if "ready" arrives before the 5 seconds as the function will return but you can't print the ESP communication for debug purpose.

What you can do for error checking is wait for the characters coming back from your ESP8266 using

while (ESP8266.available() > 0) {
      incomingByte = ESP8266l.read();

within a while loop for a timeout

and build up a 5 characters rolling buffer of whatever you are receiving (i.e. each time you receive a character you add it into the buffer and if your buffer is full then you switch all the characters by 1 position and add the new character at the end) and check if your buffer matches "ready". (and you can print characters as they come in as well to get a sense of what you get back from the ESP8266)

this way you only keep in memory 5 bytes (possibly 6 if you want to use strcmp - then you need a trailing zero to the buffer)

for a first code update, I would probably suggest you bump the timeout to 5 seconds and don't print out debug code and use ESP8266.find("ready")

Thanks for the feedback.

I had updated the second code so that it would write the ESP8266 response to the debug console, so that I could see what was happening.

I didn't understand the purpose of the SetTimeout, so thanks for that. I changed it to 5 seconds as suggested, and this gave me the result I was expecting. However the code will need to call a lot of AT commands, and waiting 5 seconds for each one isn't ideal. I think that is the idea of the delays.

No that said, with it working I then started playing around with the timeout, and believe it or not but i was able to set it back to 1 second and it still worked. Wouldn't believe how long I have been trying to sort this out.

Thanks for the tips on improving the code. I have a fair bit to learn in that area, and its been 20 years since I last did c++.

Ideally I want to create log entries that then get uploaded to a server. You would have seen a bit of commented code where I got a bit lost with linked lists and pointers. Next challenge.

thanks again.

Good to hear that's already making a difference.

The bug in your code was really that you were emptying the incoming buffer to print the debugging so when waiting for "ready" you had no chance. Going back to 1 second can work - actually will work most of the time - but you are just making a bet that your ESP8266 returns quickly - and while it's often the case (1 second is a long time for a microprocessor) it might not always be the case and thus you should not make this assumption.

So my recommendation - especially if you use ESP8266.find("ready") is to set it to 5 seconds. if you find the ready keyword, you won't wait for the timeout, it will return as soon as it found "ready" within a 5 second window. if it did not receive this in 5 seconds, then it will abort and you know you have an error (or delay).

To your comment

Serial.setTimeout() sets the maximum milliseconds to wait for serial data when using Serial.readBytesUntil(), Serial.readBytes(), Serial.parseInt() or Serial.parseFloat() (and it defaults to 1000 milliseconds).

So the SetTimeout is really when only when you want to read back from the Serial line using high level functions ==> sending your AT commands will not be slowed down, they will go straight to the ESP.

Unless you want to micro-manage your code and know at every single point if things are fine, I would suggest not checking at every single command if the answer on the serial line in OK. That's a lot of sync points that are probably not necessary for general case. A good enough rule of thumb would be to check if the global transaction went fine.

If you try push data to a web server, what I suggest is that you send all the AT commands to the ESP8266 up to your POST/GET command to your server

At that point you send a ESP8266.flush(); to ensure all those AT commands have reached the ESP.

On the web server side, have your web server program return a response with content you can easily analyze such as "SERVER OK".

So after you sent the GET/POST command, that's where you would read the serial buffer until you find your "SERVER OK" substring.

You will have lots of incoming data on the serial line - all the info that has been pushed back from the ESP and possibly even buffer overflow, but that's OK because the only thing you care about is getting within a reasonable delay the "SERVER OK" string which is at the very end

How to send GET and POST commands to ESP8266 to send the data to the server? I have tried these commands:
AT+CIPSTART=0,"TCP","www.thingspeak.com",80
AT+CIPSEND=0,200,
<
GET https://api.thingspeak.com/update?api_key=31K1OK5WV8XO4CVQ&field1=0HTTP/1.1\r\n Host: www.thingspeak.com\r\n\r\n

but i did't received any data on my dashboard in thingspeak?
Can anyone help me to figureout the issue here?

you can't send \r\n\r\n from the console...instead make sure the console is set to send both and type twice return but don't send those characters

also before sending from the console, try sending that string for a telnet client, manually. once you get the text right in telnet, this is what you need to generate for your arduino