ejrob

Arduino: HTML to LCD v1.1

May 19th, 2011
7,417
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* ***********************************************************************************************
  2.  * HTML to LCD Server v1.1
  3.  * Everett Robinson
  4.  *
  5.  * This project uses the Arduino ethernet shield and a sparkfun 16x2 character LCD to produce a
  6.  * webpage which shows what the LCD is currently displaying, and where a user can change what's
  7.  * displayed by entering something into a couple text fields (one for each row of the lcd). The Arduino
  8.  * then parses the Html Header using some code adapted from Kevin Haw's RoboSapien Server project:
  9.  * (http://www.arduino.cc/playground/Main/RoboSapienServer).
  10.  * The result of this parsing is the extraction and updating of the LCD with the strings the user
  11.  * entered, which are also converted back to something readable at the same time.
  12.  *
  13.  * Bug fixes:
  14.  * A problem in which any zero's were removed from the input has been fixed
  15.  *
  16.  * Remaining Bugs:
  17.  * - Some minor memory leaks may still remain, since strings are nasty like that
  18.  *
  19.  *************************************************************************************************
  20.  * LCD pin to Arduino Digital pin Connection Map (for Sparkfun 16x2 LCD)
  21.  *
  22.  *  // LCD pin 1  to GND
  23.  *  // LCD pin 2  to +5V
  24.  *  // LCD pin 3  to Resistor(2.2K) to GND
  25.  *  // LCD pin 4  (RS) to Arduino pin 2
  26.  *  // LCD pin 5  (RW) to Arduino pin 3
  27.  *  // LCD pin 6  (enable) to Arduino pin 5
  28.  *  // LCD pin 7
  29.  *  // LCD pin 8
  30.  *  // LCD pin 9
  31.  *  // LCD pin 10
  32.  *  // LCD pin 11 (Data 4) to Arduino pin 6
  33.  *  // LCD pin 12 (Data 5) to Arduino pin 7
  34.  *  // LCD pin 13 (Data 6) to Arduino pin 8
  35.  *  // LCD pin 14 (Data 7) to Arduino pin 9
  36.  *  // LCD pin 15 to +5V
  37.  *  // LCD pin 16 to GND
  38.  ************************************************************************************************/
  39.  
  40. //////////////////////////////////////////////////////////////////
  41. //Include all necessary libraries
  42. //////////////////////////////////////////////////////////////////
  43. #include <SPI.h>
  44. #include <Ethernet.h>
  45. #include <string.h>
  46. #include <LiquidCrystal.h>
  47. #include <avr/pgmspace.h>
  48. //#include <MemoryFree.h>  // Used to try and track down mem leaks, requires http://www.arduino.cc/playground/Code/AvailableMemory
  49.                            // Use the code from the forums half way down the page
  50.  
  51.  
  52. //////////////////////////////////////////////////////////////////
  53. //Start initializing webserver, lcd and other miscellaneous stuff
  54. //////////////////////////////////////////////////////////////////
  55.  
  56. byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x4C, 0x64 };
  57. byte ip[] = { 192,168,1, 99 };
  58. byte gateway[] = { 192,168,1, 1 };
  59. byte subnet[] = { 255, 255, 0, 0 };
  60.  
  61. // Server for web requests
  62. Server server(80);
  63.  
  64. // Initialize lcd pins according to previous mapping
  65. LiquidCrystal lcd(2, 3, 5, 6, 7, 8, 9);
  66.  
  67. // String variables fo each line on the LCD declared globally because I'm lazy, but also
  68. // because it needs to survive loop(), without being cleared from the stack (also to hell with good practice)
  69. String line1 = "                ";
  70. String line2 = "                ";
  71.  
  72. /////////////////////////////////////////////////////////////////////////
  73. // Constant strings for rendering the Webpage are stored in flash
  74. // memory to ration it for other non constant variables
  75. /////////////////////////////////////////////////////////////////////////
  76.  
  77. // Strings stored in flash mem for the Html Header
  78. prog_char Header_0[] PROGMEM = "HTTP/1.1 200 OK";            //
  79. prog_char Header_1[] PROGMEM = "Content-Type: text/html";    //
  80. prog_char Header_2[] PROGMEM = "";                           //
  81. prog_char Header_3[] PROGMEM = "<HTML>\n<HEAD>";             // The header lines
  82. prog_char Header_4[] PROGMEM = "<TITLE>HTML to LCD</TITLE>"; //
  83. prog_char Header_5[] PROGMEM = "</HEAD><BODY>";              //
  84.  
  85. // A table of pointers to the flash memory strings for the header
  86. PROGMEM const char *Header_table[] =
  87. {  
  88.   Header_0,
  89.   Header_1,
  90.   Header_2,
  91.   Header_3,
  92.   Header_4,
  93.   Header_5};
  94.  
  95. // Strings stored in flash mem for the body of the webpage, including the input forms
  96. // Only the longer lines, not involving variables are stored here
  97. prog_char Body_0[] PROGMEM = "<H2>Currently Displayed:</H2>";            
  98. prog_char Body_1[] PROGMEM = "<H2>Change it to something else!</H2>";    
  99. prog_char Body_2[] PROGMEM = "<form action=\"/?\" method=get>";                          
  100. prog_char Body_3[] PROGMEM = "<b>Line 1: </b><input type=\"text\" name=\"L1\" maxlength=\"16\" size=\"16\" /><br />";            
  101. prog_char Body_4[] PROGMEM = "<b>Line 2: </b><input type=\"text\" name=\"L2\" maxlength=\"16\" size=\"16\" /><br />";
  102. prog_char Body_5[] PROGMEM = "<input type=\"submit\" value=\"Submit\" /></form>";              
  103.  
  104. // A table of pointers to the flash memory strings for the body
  105. PROGMEM const char *Body_table[] =
  106. {  
  107.   Body_0,
  108.   Body_1,
  109.   Body_2,
  110.   Body_3,
  111.   Body_4,
  112.   Body_5};
  113.  
  114.  
  115.  
  116. //////////////////////////////////////////////////////////////////
  117. // Begin Webserver Specific Code
  118. //////////////////////////////////////////////////////////////////
  119.  
  120. // Print out MIME and HTML header at top of webpage using the
  121. // strings previously stored in flash memory
  122. void HtmlHeader(Client client) {
  123.  
  124.     char buffer[30]; //A character array to hold the strings from the flash mem
  125.    
  126.     for (int i = 0; i < 6; i++) {
  127.       strcpy_P(buffer, (char*)pgm_read_word(&(Header_table[i]))); // Necessary casts and dereferencing, just copy.
  128.       client.println( buffer );
  129.     }
  130. }
  131.  
  132. // Print the footer at the bottom of the webpage
  133. void HtmlFooter(Client client) {
  134.     client.println("</BODY></HTML>");
  135. }
  136.  
  137.  
  138. // Parse an HTTP request header one character at a time, seeking string variables (modified from Kevin Haw's code)
  139. void ParseHttpHeader(Client &client) {
  140.     char c;
  141.     int i = 0;    //An integer use to limit the size of rawUrlText (prevents crashing due to running out of memory)
  142.     String rawUrlText = "";
  143.  
  144.     // Skip through until we hit a question mark (first one)
  145.     while((c = client.read()) != '?' && client.available()) {
  146.       // Debug - print data
  147.       Serial.print(c);
  148.     }
  149.    
  150.     // Are we here for a question mark or did we run out of data?
  151.     if(client.available() > 2) {
  152.  
  153.       // Read the data and add it to our unmodified string rawURLText!
  154.       // the incrementer limits the input to about 1 line of plain text and 1/2 line of symbols, more causes line2 to truncate
  155.       while((c = client.read()) != ' ' && client.available() && i < 55) {
  156.           rawUrlText = rawUrlText + c;
  157.           Serial.print(c);
  158.           i++;
  159.       }
  160.      
  161.       htmlToHuman(rawUrlText);            // Make it readable
  162.       line1.setCharAt(line1.lastIndexOf('0'), ' '); // the lcd prints the 0's in the null terminator, so we remove them
  163.       line2.setCharAt(line2.lastIndexOf('0'), ' '); //This has been revised to prevent remove of legit 0's
  164.       lcd.clear();
  165.       lcd.setCursor(0,0);                 // set cursor to column 0, row 0 (the first row), and print
  166.       lcd.print(line1);
  167.       lcd.setCursor(0,1);                 // set cursor to column 0, row 1 (the second row), and print
  168.       lcd.print(line2);
  169.     }  
  170.   return;
  171. }
  172.  
  173. // A function that takes the html formatted string and makes it readable again
  174. void htmlToHuman(String URLstring) {
  175.  
  176.     int indexOfDelim = 0;  //This variable stores the location of our delimiter so we can find where line1 ends and line2 begins
  177.    
  178.     // The following array stores a list of ugly html codes, and the special charaters they represent (for changing them back)
  179.     const String CHAR_CONVERSIONS[29][2] = {{"+"," "},{"%40","@"},{"%23","#"},{"%24","$"},{"%2B","+"},{"%21","!"},{"%7E","~"},
  180.                                             {"%3A",":"},{"%3B",";"},{"%2C",","},{"%3F","?"},{"%2F","/"},{"%7C","|"},{"%5E","^"},
  181.                                             {"%5C","\\"},{"%7B","{"},{"%7D","}"},{"%5B","["},{"%5D","]"},{"%3C","<"},{"%3E",">"},
  182.                                             {"%28","("},{"%29",")"},{"%27","'"},{"%22","\""},{"%3F","?"},{"%26","&"},{"%3D","="},
  183.                                             {"%25","%"}};
  184.    
  185.     URLstring = URLstring.replace("L1=","");     // remove the unecessary field variable names
  186.     URLstring = URLstring.replace("&L2=","`");   // and turn this one into our delimiter character ` (The one on the ~ key)
  187.    
  188.     //A for loop that replaces all the html codes with the right symbols
  189.     for (int i=0 ; i < 29; i++) {
  190.       URLstring = URLstring.replace(CHAR_CONVERSIONS[i][0],CHAR_CONVERSIONS[i][1]);
  191.     }
  192.    
  193.     indexOfDelim = URLstring.indexOf("`");       // find the index of that delimiter
  194.    
  195.     line1 = URLstring.substring(0,indexOfDelim); // set line1 and line 2 using that knowlege
  196.     line1 += NULL;                               // but add a null terminator to each to avoid some odd bugs
  197.     line2 = URLstring.substring(indexOfDelim+1,URLstring.length());
  198.     line2 += NULL;
  199.    
  200.     return;
  201. }
  202.  
  203. // Set up webserver functionality (from Kevin Haw)
  204. void WebServerSetup() {
  205.   Ethernet.begin(mac, ip);
  206.   server.begin();
  207. }
  208.  
  209. // Web server loop (modified from Kevin Haw's code)
  210. void WebServerLoop() {  
  211.   Client client = server.available();
  212.   boolean bPendingHttpResponse = false; // True when we've received a whole HTTP request and need to output the webpage
  213.   boolean bPreventSecondParse = false;  //Stops a second successive run of parseHttpHeader(), this prevents some nasty bugs.
  214.   char c;  // For reading in HTTP request one character at a time
  215.  
  216.   if (client) {
  217.     // Loop as long as there's a connection
  218.     while (client.connected()) {
  219.       // Do we have pending data (an HTTP request) and is this the first parse?    
  220.       if (client.available() && !bPreventSecondParse) {
  221.  
  222.         // Indicate we need to respond to the HTTP request as soon as we're done processing it
  223.         bPendingHttpResponse = true;
  224.         bPreventSecondParse = true;
  225.        
  226.         ParseHttpHeader(client);  
  227.       }
  228.       else {
  229.         // There's no data waiting to be read in on the client socket.  Do we have a pending HTTP request?
  230.         if(bPendingHttpResponse) {
  231.           // Yes, we have a pending request.  Clear the flag and then send the webpage to the client
  232.           bPendingHttpResponse = false;
  233.           bPreventSecondParse = false;
  234.  
  235.           // send a standard http response header and HTML header
  236.           HtmlHeader(client);
  237.  
  238.           // The following code Sends the relevant Html to the connected connected client to render the web page
  239.           /* For readability, the Html sent to the client is as follows (the second and third lines are not stored in flash memory)
  240.            *"<H2>Currently Displayed:</H2>"
  241.            *"<b>Line 1:</b> " + line1 + "<br />"        
  242.            *"<b>Line 2:</b> " + line2 + "<br /><br />"
  243.            *"<H2>Change it to something else!</H2>"
  244.            *"<form action=\"/?\" method=get>"
  245.            *"<b>Line 1: </b><input type=\"text\" name=\"L1\" maxlength=\"16\" size=\"16\" /><br />"
  246.            *"<b>Line 2: </b><input type=\"text\" name=\"L2\" maxlength=\"16\" size=\"16\" /><br />"
  247.            *"<input type=\"submit\" value=\"Submit\" /></form>"
  248.            */
  249.            
  250.           char buffer[90]; //A character array to hold the strings from the flash mem
  251.          
  252.           strcpy_P(buffer, (char*)pgm_read_word(&(Body_table[0])));        // gets and prints the first line
  253.           client.println( buffer );
  254.           client.println("<b>Line 1:</b> " + line1 + "<br />");            // manually print the lines involving variables
  255.           client.println("<b>Line 2:</b> " + line2 + "<br /><br />");
  256.           for(int i = 1; i < 6; i++) {                                     // Use a for loop to print the remaining lines
  257.             strcpy_P(buffer, (char*)pgm_read_word(&(Body_table[i])));
  258.             client.println( buffer );
  259.           }
  260.          
  261.           // send HTML footer
  262.           HtmlFooter(client);
  263.  
  264.           // give the web browser time to receive the data
  265.           delay(1);
  266.           client.stop();
  267.         }
  268.       }
  269.     }  // End while(connected)
  270.   }
  271. }
  272.  
  273.  
  274. void setup(){
  275.   // open the serial port at 9600 bps:
  276.   Serial.begin(9600);
  277.   lcd.begin(16,2);                    // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  278.   lcd.clear();                        // start with a blank screen
  279.   WebServerSetup();
  280. }
  281.  
  282.  
  283. void loop(){
  284.   WebServerLoop();
  285. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×