Adding LCD to Web Page Controlled LED (Arduino + ESP8266)

The Plan

In my previous post (LED’s Control Through ESP8266 + Arduino Web Page), I demonstrated how I used the ESP8266 and an Arduino Mega to create a web page that could control some LED lights from anyplace I could access the internet.  In my other previous post (Cheap $4.59 LCD with Arduino), I showed how I wired up a very cheap LCD to my Arduino and the demo software that showed how to draw various item and text on the screen.  I have not played around with the LCD a little and am now going to mash the 2 together and display a few key server statistics on the LCD screen.  Amazingly, it wasn’t as hard as I thought it would be.

In some of my previous posts, I already included details about how I have a counter for some key servers stats like number of web pages served, number or LED change request served, etc.  I am going to reuse those same counters and display to the screen.

The Arduino SW

First I draw the basic background of the screen by the following code.  I added comments to help make things easy to understand.

Note: I luckily guessed the LCD library was using the same color codes used for HTML pages.  I used this page to get the colors I wanted… http://www.w3schools.com/html/html_colors.asp

...
#define LCD_NETWORK_ROW 101
#define LCD_IPADDR_ROW 114
#define LCD_GRAY_ROW 101
#define LCD_SERVED_ROW 14
#define LCD_CHANGES_ROW 28
#define LCD_RESETS_ROW 42
...
void SetUpLCDBaseDisplay(){
 myGLCD.InitLCD();
 myGLCD.setFont(SmallFont);
 myGLCD.clrScr();

 //*** Create blue title bar with name ***
 myGLCD.setColor(0, 0, 255); // Blue for interior of rectangle coming up
 myGLCD.fillRect(0, 0, 159, 13); // Draw a solid rectangle from upper left = (0,0) to bottom right (159,13) 
 myGLCD.setBackColor(0, 0, 255); // Blue background for upcoming text
 myGLCD.setColor(255, 255, 255); // White lettering for upcoming text
 myGLCD.print("Pete's ESP8266 Hack", RIGHT, 1); // Write the text right justified at row 1
 
 //*** Create gray bar at bottom with status ***
 myGLCD.setColor(64, 64, 64); // Grey 
 myGLCD.fillRect(0, LCD_GRAY_ROW, 159, 127); // Gray box at bottom of screen
 myGLCD.setBackColor(64, 64, 64); // Gray background for upcoming text
 myGLCD.setColor(255, 255, 255); // White lettering for upcoming text
 myGLCD.print("Network:", LEFT, LCD_NETWORK_ROW); 
 myGLCD.print("...init",RIGHT, LCD_NETWORK_ROW);
 myGLCD.print("IP Add:", LEFT, LCD_IPADDR_ROW);
 myGLCD.print("...init",RIGHT, LCD_IPADDR_ROW);

 //** Create labels for key server stats 
 myGLCD.setBackColor(0, 66, 0); // Darkish Green ... note: lettering is set to white from last above still
 myGLCD.print("LED Changes: " + String(int(NumberLEDRequest)), RIGHT, LCD_CHANGES_ROW);
 myGLCD.print("Web Served: " + String(int(NumberServed)), RIGHT, LCD_SERVED_ROW);
 myGLCD.print("ESP8266 RSTS: " + String(int(NumberOfResets)), RIGHT, LCD_RESETS_ROW); 
}

This is what the screen looks like ..

20141224_233050

Whenever I increment any of my key server stats, I call this function…

void UpdateLCDStats(){
 myGLCD.setBackColor(0, 66, 0); // Darkish green background
 myGLCD.setColor(255, 255, 255); // White lettering
 myGLCD.print(String(int(NumberLEDRequest)), RIGHT, LCD_CHANGES_ROW);
 myGLCD.print(String(int(NumberServed)), RIGHT, LCD_SERVED_ROW);
 myGLCD.print(String(int(NumberOfResets)), RIGHT, LCD_RESETS_ROW);
}

This will update the LCD with the most recent counter values.  I was originally re-writing the entire line including the label, but found that I would sometime miss some of the incoming serial data.  The screen updating turns out to be pretty slow so writing all the characters must have been taking too long.  I minimized the amount of LCD update to just 3 digits to try to avoid this issue.

Here is the full Arduino sketch if you want it…

https://drive.google.com/file/d/0B1a0nPfCQQvKc2otRWY4Tkc4Tkk/view?usp=sharing

Save to your local drive and then you can open it in a text editor if you don’t have the Arduino IDE.

The Results

The testing went pretty well so here is a quick video of the system in action….

Advertisements

Cheap $4.59 LCD with Arduino

The Plan

Now that I have the ESP8266 reasonably stable and serving up a web page that can take inputs from a user to control 3 LED’s, I am going to move on and add more peripherals to learn more of the Arduino capabilities. The first peripheral is going to be an LCD.

Because I am really cheap, I decided to dive right in and buy the cheapest one I could find for $4.59 (shipping included) here:

http://www.banggood.com/1_8-Inch-Serial-SPI-TFT-LCD-Display-Module-With-Power-IC-SD-Socket-p-909802.html

I knew it was a risk since there is nearly no documentation for it and is not one of the compatible LCD’s listed at the arduino.cc web site.  I did make sure that the vendors page did at least have a link to some code examples at http://pan.baidu.com/s/1bnkWQT5… although the wording on the page of “Normally, the chip is Samsung S6D02A1″ didn’t really give me a lot of confidence.  Since I was only shelling out $4.59 I figured it was worth the risk.

The Zip File

I went to http://pan.baidu.com/s/1bnkWQT5 and was able to download a zip file.  Inside the zip file were a few .pdf files with some specifications.  One note was that the logic level was 2.8V which is a problem since the Arduino is 5V logic levels.  There was a comment on the product page…. “Using with Arduino, every IO port should be connected with resistance range 500 ~ 2KΩ.”.  I am assuming this is a cheap way to address the voltage difference.

The Wiring

First was to wire up LCD module.  The module has connection holes on 2 edges.  One came populated with a standard pin header and the other side just had the holes where a header could be installed.  There is a SD Card slot which has traces going to the holes that don’t have pins installed but NOT to the pre-populated header.  Looks like will need to solder if I want to use the SD Card slot.  Here is a picture….

LCDBackSide

Since I was mostly interested in just the LCD for now, I just plugged the pre-populated header into my bread board.  The pins were labeled…

1 – RST
2 – CS
3 – D/C
4 – DIN
5 – CLK
6 – VCC
7 – BL
8 – GND

There was a directory in the zip file, “1.8SPI Test Code for ArduinoUNO”.  I found an example Arduino sketch inside, QDtech_Demo_160x128_Serial_S6D02A1.ino.  At the start of the sketch, there was a section that listed what LCD pins should be connected to which Arduino digital IO….

//for QD_TFT180X SPI LCD Modle
//http://www.QDtech.net
//http://qdtech.taobao.com
//Param1:Value Can be:QD_TFT180A/QD_TFT180B/QD_TFT180C
//Param2 instructions:Connect to LCD_Pin SDA/SDI/MOSI(it means LCD_Model Pin_SDA/SDI/MOSI Connect to Arduino_UNO Pin11)
//Param3 instructions:Connect to LCD_Pin SCL/CLK/SCLK(it means LCD_Model Pin_SCL/CLK/SCLK Connect to Arduino_UNO Pin10)
//Param4 instructions:Connect to LCD_Pin CS/CE(it means LCD_Model Pin_CS/CE Connect to Arduino_UNO Pin9)
//Param5 instructions:Connect to LCD_Pin RST/RESET(it means LCD_Model Pin_RST/RESET Connect to Arduino_UNO Pin12)
//Param6 instructions:Connect to LCD_Pin RS/DC(it means LCD_Model Pin_RS/DC Connect to Arduino_UNO Pin8)
UTFT myGLCD(QD_TFT180C,11,10,9,12,8); // Remember to change the model parameter to suit your display module!

Most pins were easy to figure out.  The only questionable ones were DIN and BL.  I assumed that DIN meant Data In which would seems to match up with MOSI (Master Out Slave In) meaning.  I took a chance and just wired that up.  One of the included data sheets had VCC listed at typical 4.5V so I also took a chance and just directly hooked it up to the Arduino +5V output.  BL I assumed was for Back Light control.  Since I really don’t care about back light level, I just tied it to the +5V for full brightness.

The Software

I loaded up the “QDtech_Demo_160x128_Serial_S6D02A1.ino” into the Arduino IDE.  I couldn’t get it to compile at first then realized that I needed to import the UTFT library.  Luckily I found it in the same directory.  In the Arduino IDE go to Sketch -> Import Library -> Add Library… Browse to the UTFT directory which is in the same directory as the example sketch.  Once I did that, the code compiled.

The First Attempt

I loaded the example sketch to the Arduino with the LCD hooked up as described above … held my breath… and….. got a blank white screen.  😦

The Debug

After checking all my wiring, I remembered the “Using with Arduino, every IO port should be connected with resistance range 500 ~ 2KΩ.” comment on vendors product description page.  I thought that was “optional” to make it more stable if the screen was jittery or refreshed looked bad or something intermittent.  Since I didn’t have any other ideas, I went ahead and added a 1K resistor in series to every one of the control pins (not VCC or BL or GND).  I restarted the Arduino sketch and…. VOILA!  The LCD started to draw things and animate things.  Here is a video of what the example sketch did with the LCD….

Note: I tried on both the Arduino Uno and the Arduino Mega.  Both worked the same.

The Next

The example Arduino sketch in the zip file is pretty well document.  Going to start playing around with it to better understand the functions, capabilities and limitations.  After that, I want to add the LCD to my other project that remotely controls LED’s (posted here: LED’s Control Through ESP8266 + Arduino Web Page).  I can display some key server stats like the IP address, number of LED changes, up time, etc.   Maybe even something like a heartbeat animation for fun.

Update…. See my later post of how I added some basic text updates to my project “https://petestechprojects.wordpress.com/2014/12/25/adding-lcd-to-web-page-controlled-led-arduino-esp8266/

Adding LED States to Web Page (LED’s Control Through ESP8266 + Arduino Web Page)

The Plan

In my previous post demonstrated how I can remotely control some LEDs through a web page being served up by an Arduino hooked up to the ESP8266 (post here).  The web page was static and the check boxes always defaulted back to Off.  I am going to add code that will pre-populate the check box to show which state the LED’s are in when the web page is served up.  I also am going to add a new button that will request what is the latest state of the LED’s since multiple users could be controlling the LED’s.  This is what I want to see….HTMLFormSnap12_19

The HTML Implementation

To add 2 buttons that will return different strings to the server when clicked, I added this to my previous HTML…

 <fieldset>
 <legend>Actions</legend>
   <input type="submit" name="LEDFormAction" value="Set LED States"> &nbsp &nbsp &nbsp 
   <input type="submit" name="LEDFormAction" value="Get LED States">"
 </fieldset>

You can find the rest of the HTML in my last post referenced above.

With this, the POST message sent to the server will also include:

  • LEDFormAction=Get+LED+States
  • or
  • LEDFormAction=Set+LED+States

Here is an example one for the POST messages sent when someone clicks the “Set LED States”…

RedLEDState=RED_OFF&GreenLEDState=GREEN_ON&BlueLEDState=BLUE_OFF&LEDFormAction=Set+LED+States

Now all the web server code needs to do is look for a line with “LEDFormAction=Set+LED+State”  and then change the LED states based on the request found on the same line.  If it finds “LEDFormAction=Get+LED+State”, it will just formulate the HTML with latest LED states and send back without changing the LED states.  You can look at the code linked below to see the Arduino code implementation.

The Arduino Code Implementation

To pre-populate the buttons with the latest state, I just pre-formulate the HTML code for that section using an if statement like this…

 if (RED_State){
 RED_StateHTML = "<input type=\"radio\" name=\"RedLEDState\" value=\"RED_ON\" checked=\"checked\"> ON"
 "<input type=\"radio\" name=\"RedLEDState\" value=\"RED_OFF\"> OFF<br>";
 }else{
 RED_StateHTML = "<input type=\"radio\" name=\"RedLEDState\" value=\"RED_ON\"> ON"
 "<input type=\"radio\" name=\"RedLEDState\" value=\"RED_OFF\" checked=\"checked\"> OFF<br>";
 }
... repeat for each LED ...

Then I just concatenate the string into the full HTML code sent out and the requester will see the correct check box filled in.

To add the functions for the 2 buttons shown in the HTML above, I just look for the key words and do the appropriate calls as explained above.

 if (InLine.indexOf("LEDFormAction=Set+LED+States") != -1){
    ParseLEDControl(InLine);
    SetLEDStates();
    NumberLEDRequest++;
 }
 if (InLine.indexOf("LEDFormAction=Get+LED+States") != -1){
    //Do nothing sinc the "POST / " command already is sending HTML page with latest LED states
 }

The Arduino Code

If you want the full code…

https://drive.google.com/file/d/0B1a0nPfCQQvKTkQ4QXo1aWVWczg/view?usp=sharing

Save to your local drive and then you can open it in a text editor if you don’t have the Arduino IDE.

BTW – I added a little extra code to actually try to wait for key responses during CIPSEND commands instead of a blind timeout in this version.  Not sure if it really helps as I still see the ESP8266 randomly just reset itself quite often but this seems cleaner way to do communications.

LED’s Control Through ESP8266 + Arduino Web Page

The Plan

In my previous post, “LED’s Control through TTY“, I showed how I can control some LED’s though a TTY client connected to my Arduino and ESP8266 ($4 Wifi module).  I also posted how I made a reasonably stable web server utilizing a command que to respond to html requests here “Mini Server with Command Queue Memory Issue“.  I am going to mash them together by adding a form in my HTML code that will send requests to the server to change the LED states.

The Web Page Implementation

I will use a HTML form to send a POST request back to the server.  If you are like me and not familiar with how this works, I will explain what I know and how I will try to get it to work.

First I found out how to create a form with radio buttons and a submit button.  Here is what the page looks like…

HTMLFormSnap

I found www.w3schools.com/tags/tag_form.asp that helped me write the HTML code for the above like this…

<html>
<body>
<form action="" method="post">
 <fieldset>
 <legend>Red LED State</legend>
 <input type="radio" name="RedLEDState" value="RED_ON"> ON
 <input type="radio" name="RedLEDState" value="RED_OFF" checked="checked"> OFF<br>
 </fieldset>
 <fieldset>
 <legend>Green LED State</legend>
 <input type="radio" name="GreenLEDState" value="GREEN_ON"> ON
 <input type="radio" name="GreenLEDState" value="GREEN_OFF" checked="checked"> OFF<br>
 </fieldset>
 <fieldset>
 <legend>Blue LED State</legend>
 <input type="radio" name="BlueLEDState" value="BLUE_ON"> ON
 <input type="radio" name="BleuLEDState" value="BLUE_OFF" checked="checked"> OFF<br>
 </fieldset>
<input type="submit" value="Submit">
</form>
</body>
</html>

The Server Implementation

Disclaimer: I am no expert.  Just sharing what I found through googl’ing and trial and error.

When someone clicks the submit button in the form above, it will send a “POST” to the server.  This post will include the name / value pair as defined in the above.  Best to just show what my server sees when someone clicks the submit button above….

POST / HTTP/1.1
Host: 192.168.0.175
Connection: keep-alive
Content-Length: 64
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://192.168.0.175
User-Agent: Mozilla/5.0 (Linux; Android 4.1.2; SPH-L300 Build/JZO54K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.93 Mobile Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://192.168.0.175/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8

RedLEDState=RED_OFF&GreenLEDState=GREEN_ON&BlueLEDState=BLUE_OFF 

Note the last line highlighted in cyan.  In this example, the RED and GREEN LED ON button would have been checked and the BLUE LED OFF button was checked.  I plan on using this request line to control the LED states.  The one side effect is that the browser is now waiting for a HTML response.  My simple hack to address this is to just re-send the same web page again for now.  Eventually I will add code pre-populate the radio buttons with the current state of the LED’s instead of all OFF.

The Code

The really messy code is available here:

https://drive.google.com/file/d/0B1a0nPfCQQvKbThLeFM5MW44dFU/view?usp=sharing

Save to your local drive and then you can open it in a text editor if you don’t have the Arduino ID.

The coding is REALLY sloppy for now.  Will go back to clean up once I get everything I want working.

The Hardware Setup

If you missed it in my earlier post…

Update12_14_14

The Demo

Video demo of the system in action…

Mini Server with Command Queue Memory Issue

The Problem

Previously in my post, “Arduino + ESP8266 Mini Server with Command Que“, I showed how I overcame the problem of missing incoming messages from the ESP8266 by implementing a command queue system.  As with most engineering issues I have worked on… once you solve one problem you make another.

The command queue system worked great until I started stuffing the queue entries with a lot of data. I wanted a much more elaborate HTML page which ended up being + 800 characters long.  That pretty much got me into a bunch of memory problems that took me a long time to debug.

The Behavior

Everything was working great….. for a while.  Then I added a form to my HTML code.  The first time it served up the HTML, everything was great.  The next time, nothing would be sent back out.  Every time my program tried to send out the long HTML string saved in the corresponding queue entry, there was nothing coming out.  I thought I had broken my code someplace in the loop and spent a long time trying to back track.  Eventually I found out that if I cut my HTML size down, things were ok again.  The only difference was the length of the string.  I am not 100% sure, but that sounds like a classic memory corruption issue and I know using a lot of String objects in Arduino code is risky on memory.

The Plan

I spent a lot of time trying to figure out how to change from using an array of Strings to and array of  char arrays.  Ended up being a dead end.  Instead I stepped back and thought about how to actually address the real problem… wasting memory.

Instead of storing the entire command string in the queue, I am only going to store the type of command that needs to be sent  and any critical info (ie: the +IPD channel from the ESP8266).  When the queue pointer gets to the command entry, I will then formulate the string and send to the Serial1 port.  This should dramatically reduce the amount of memory I am wasting.

The Implementation

It took a lot of debugging and testing and revising.  Ran into an issue with multi-part command, but here is the relevant part.  I first have some #defines for the different types of commands to make the switch statement easier….

#define HTML_REQUEST 1
#define FAVICON_REQUEST 2

In the module to enter commands into the queue…

...
 if (InLine.indexOf("GET / ") != -1) {
 CommandQue[QueIn++]=HTML_REQUEST;
 NumberServed++;
 }
 if (InLine.indexOf("POST / ") != -1) {
 CommandQue[QueIn++]=HTML_REQUEST;
 NumberLEDRequest++;
 }
 if (InLine.indexOf("favicon.ico") != -1) { 
 CommandQue[QueIn++]=FAVICON_REQUEST;
 NumberIconReqs++;
...

Previously I will filling in an entire really long string when there was an HTML request that could be taking 100’s of bytes in memory multiplied by how many requests came in.  Now I am using only 1 byte in memory for each request.

Then in the module process the command…

 switch (CommandQue[QueOut]){
 case HTML_REQUEST:
 float CIPSendTime;
 //*** Build the HTML code ***
 //Note: Need this first since HTTP Header needs length of content
 HTMLCode = "<HTML>"
 "<HEAD><TITLE>Pete's Mini8266 Server</TITLE>"
 "<BODY><H1>Welcome to Pete's ESP8266 \"hacking\" project</H1>"
 "<form action=\"\" method=\"post\">"
 "<fieldset>"
 "<legend>Red LED State</legend>"
 "<input type=\"radio\" name=\"RedLEDState\" value=\"RED_ON\"> ON"
 "<input type=\"radio\" name=\"RedLEDState\" value=\"RED_OFF\" checked=\"checked\"> OFF<br>"
 "</fieldset>"
 "<fieldset>"
 "<legend>Green LED State</legend>"
...  Finish off the rest of the HTML code ...
Serial1.println("AT+CIPSEND=" + String(CommandQueIPD_CH[QueOut]) + ","+ String(HTTPHeader.length()+2));
...

Now there is only one long string and is sent and memory freed right away.

There is a lot more hacking to be able to match up the IPD channel with the string and continue queuing up request between multi-step commands but too long and detailed to explain.  The really messy code is available here:

https://drive.google.com/file/d/0B1a0nPfCQQvKbThLeFM5MW44dFU/view?usp=sharing

Save to your local drive and then you can open it in a text editor if you don’t have the Arduino ID.

The coding is REALLY sloppy for now.  Will go back to clean up once I get everything I want working.

The Testing

I have been hitting the mini-server from multiple clients with more than a 6 line web page and things seem to be working well.  I do get random ESP8266 resets but my recovery code has been able to re-init and get everything working again each time.

The Next Step

Going to move on and show how I am using an HTML form and the “post” mechanism to control LED’s on my board from a web page.

Arduino + ESP8266 Recovery Mechanisms

The Plan

I have spent a lot of time trying to make my Arduino + ESP8266 mini web server more stable.  I still run into some issues that I can’t avoid or recover from.  To address this, I am going to try to implement some auto-recovery mechanisms.

The Problems

  1. The ESP8266 seems to randomly just reset.  Could be power issues supplied from supplying the ESP8266 from the USB port or my bad web server code.  Not sure, but want to be able to recover from this situation.
  2. ESP8266 serial port gets stuck with “busy s…”.  I am not 100% sure, but it seems to consistently happen if I abort a HTML request from my browser (which closes the connection) right when my server code is trying to send the HTTP header and HTML code back.  After then I get the “busy s…” for anything I try to send to the ESP8266.

The Implementation

Random Reset: My serial port parser looks for the occurrence of “System Ready”.  This is sent by the ESP8266 any time it resets.  If the “System Ready” string is found, send out all the AT commands to start up the ESP8266 as a server.

...
if (InLine.indexOf("System Ready") != -1) {
 Serial.println("The ESP8266 Reset for some reason");
 InitWifiModule();
 }
...

...
void InitWifiModule(){
 int CommandStep = 1;
 BlinkLED(REDLED,CommandStep,50); 
 SendCommand("AT+RST", "Ready", true);
 BlinkLED(GREENLED,CommandStep,50);
 CommandStep++;

 BlinkLED(REDLED,CommandStep,50); 
 SendCommand("AT+GMR", "OK", true);
 BlinkLED(GREENLED,CommandStep,50);
 CommandStep++;

 delay(3000);

 BlinkLED(REDLED,CommandStep,50); 
 SendCommand("AT+CIFSR", "OK", true);
 BlinkLED(GREENLED,CommandStep,50);
 CommandStep++;


 BlinkLED(REDLED,CommandStep,50); 
 SendCommand("AT+CIPMUX=1","OK",true);
 BlinkLED(GREENLED,CommandStep,50);
 CommandStep++;

 BlinkLED(REDLED,CommandStep,50); 
 SendCommand("AT+CIPSERVER=1,80","OK",true);
 BlinkLED(GREENLED,CommandStep,50);

 digitalWrite(GREENLED,HIGH);
}

“busy s…” Lockup: Once I see this, I have never been able to recover the ESP8266.  Even sending the AT+RST command doesn’t help.  The only way I can find around this is to HW Reset the ESP8266.  Luckily there is a HW Reset pin on the ESP8266.  I wired digital IO 22 (randomly picked on my Arduino Mega board) to the ESP8266 through my NTE4050B “one way level shifter”.  Now when my parser sees “busy s…” it will toggle digital IO 22.  My random reset monitor (see above) will see the ESP8266 reset and will send the server init command.

... 
if (InLine.indexOf("busy s...") != -1) {
 Serial.println("dead with busy s... HW Reset");
 QueOut=QueIn; //Clear out the command que
 digitalWrite(ESP_RESET,LOW);
 delay(500);
 digitalWrite(ESP_RESET,HIGH); 
 // Note: Parser should see the reset and start the InitWifiModule routine
}
...

It has been a few posts since I posted a diagram.  Here is the latest with the Uno replaced by the Mega and the new ESP8266 reset signal in place….

Update12_14_14

The Testing

To simulate the random reset, I turned off/on the power to the ESP8266.  My new code resent all AT command to start up the server again and I can refresh my web browsers with no problems.

Testing the “busy s…” was also pretty easy.  I hit the browser refresh… waited 1 second… hit the “x” on the browser to about the request….. wait 1 second… tried to request the page again… The HW reset was toggled and the AT commands started the server.  I can then request the page again from the browser and everything looks ok.

With that, I think I can recover from most problems I have been seeing.

The code

Here is my code with all the additions so far.  Tired of copy pasting the entire code.  If you want it, save to your local drive from here: https://drive.google.com/file/d/0B1a0nPfCQQvKX3d2OUFpSkRtQW8/view?usp=sharing

You can open it in a text editor if you don’t have the Arduino IDE.

Arduino + ESP8266 Mini Server with Command Que

The Problem

Up to this point, my mini web server running on my Arduino + ESP8266 is ok if things move very slow.  Once I start hitting it with several page requests and aborts, the system just crashes.  After looking through the serial logs, it became clear that I was missing a lot of incoming characters.  This was because there were several places in my old code that was blocking incoming characters while sitting and waiting for the “OK” response.  While I was waiting for the “OK”, some other client would request something and I would totally miss the request.

The (Attempted) Solution:

So I spent a lot of time (…more than I should have….) entirely re-writing my serial port handling code.  The major re-write was to add a command que that would then write the command to the serial port after some delay (points A & B under step 4 below).  The high level concept is:

  1. For each line received from the ESP8266, look for a key word (ie: “GET / “) that I need to answer.
  2. Formulate an answer string when that key word is found on an incoming line.
  3. Stick the string in a fifo style command que to be sent later.
  4. When there are no characters coming in, send the oldest command in the que out (fifo style).
    1. I had to add a time stamp check to add a delay between 2 consecutive commands being sent.  I had to do this because the ESP8266 sometimes would respond with some sort of “busy” response if I tried to send 2 commands too quickly together.
    2. I also added a time stamp check to add a delay between when I received a request to when I sent out the next response.  I just wait a while and assume that my command was successful and move on.  I am not making a commercial grade server and spent too much time here and want to move on.
  5. If a character is received from the ESP8266, go to step 1.  If no characters came from the ESP8266, keep sending commands in the que until all gone.

Best I can do in words.  You can just read the attached code below for more details.

Disclaimer: There are likely many server experts out there cringing at what I am doing.  I am no expert here and really just wanted to play around and got carried away with trying to actually serve up a web page.  Should have stopped long ago and made a custom daemon and custom client to do what I wanted.  This ended up being a long distraction… although it was fun to learn more about how servers work.

Extra Fix

HTTP header: A very helpful visitor commented in my earlier post “Mini Server on Arduino + ESP8266” that I was not sending the HTTP header.  I found very nice and simple tutorial here: http://www.jmarshall.com/easy/http/.  I added a VERY simple HTTP header to my response for HTML page and don’t have to send the connection close command any more.  The client automatically closes the port now.  It took some tricky coding but the clients seem much happier.

The Code

Tired of copy pasting the entire code.  If you want it, go here: https://drive.google.com/file/d/0B1a0nPfCQQvKX3d2OUFpSkRtQW8/view?usp=sharing

You can open it in a text editor if you don’t have the Arduino IDE.