Advertisement
ejrob

Arduino: HTML to LCD v1.2

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