Curtis Cooper / Mbed 2 deprecated HUZZAHESP8266-web-control-LPC1768_4180

Dependencies:   mbed LSM9DS1_Library_cal_new

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // ESP8266 Static page WEB server to control Mbed
00002 
00003 #include "mbed.h"
00004 #include "LSM9DS1.h"
00005 #define PI 3.14159
00006 // Earth's magnetic field varies by location. Add or subtract
00007 // a declination to get a more accurate heading. Calculate
00008 // your's here:
00009 // http://www.ngdc.noaa.gov/geomag-web/#declination
00010 #define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA.
00011 
00012 Serial pc(USBTX, USBRX);
00013 // Calculate pitch, roll, and heading.
00014 // Pitch/roll calculations taken from this app note:
00015 // http://cache.freescale.com/files/sensors/doc/app_note/AN3461.pdf?fpsp=1
00016 // Heading calculations taken from this app note:
00017 // http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/Magnetic__Literature_Application_notes-documents/AN203_Compass_Heading_Using_Magnetometers.pdf
00018 
00019 Serial esp(p28, p27); // tx, rx
00020 
00021 
00022 // Standard Mbed LED definitions
00023 DigitalOut  led1(LED1);
00024 DigitalOut  led2(LED2);
00025 DigitalOut  led3(LED3);
00026 DigitalOut  led4(LED4);
00027 
00028 
00029 /*
00030 char ssid[32] = "PBNet";     // enter WiFi router ssid inside the quotes
00031 char pwd [32] = "password"; // enter WiFi router password inside the quotes
00032 */
00033 
00034 
00035 float heading;
00036 float R1=100000, R2=10000; // resistor values to give a 10:1 reduction of measured AnalogIn voltage
00037 char Heading[10];
00038 
00039 
00040 // things for sending/receiving data over serial
00041 volatile int tx_in=0;
00042 volatile int tx_out=0;
00043 volatile int rx_in=0;
00044 volatile int rx_out=0;
00045 const int buffer_size = 4095;
00046 char tx_buffer[buffer_size+1];
00047 char rx_buffer[buffer_size+1];
00048 void Tx_interrupt();
00049 void Rx_interrupt();
00050 void send_line();
00051 void read_line();
00052 
00053 int DataRX;
00054 int update;
00055 int count;
00056 char cmdbuff[1024];
00057 char replybuff[4096];
00058 char webdata[4096]; // This may need to be bigger depending on WEB browser used
00059 char webbuff[4096];     // Currently using 1986 characters, Increase this if more web page data added
00060 char timebuf[30];
00061 void SendCMD(),getreply(),ReadWebData(),startserver();
00062 void gettime(),setRTC(),getbattery();
00063 void getheading(float mx, float my, float mz);
00064 char rx_line[1024];
00065 int port        =80;  // set server port
00066 int SERVtimeout =5;    // set server timeout in seconds in case link breaks.
00067 struct tm t;
00068 // manual set RTC values
00069 int minute      =00;    // 0-59
00070 int hour        =12;    // 2-23
00071 int dayofmonth  =26;    // 1-31
00072 int month       =8;     // 1-12
00073 int year        =15;    // last 2 digits
00074 
00075 int main()
00076 {
00077     //////////////////////////////heading///////////////////////////////////
00078     LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
00079     IMU.begin();
00080     IMU.calibrateMag(0);
00081     ///////////////////////////////////////////////////////////////////////
00082     
00083     pc.baud(9600);
00084     esp.baud(9600);
00085     led1=1,led2=0,led3=0, led4=0;
00086     // Setup a serial interrupt function to receive data
00087     esp.attach(&Rx_interrupt, Serial::RxIrq);
00088     // Setup a serial interrupt function to transmit data
00089     esp.attach(&Tx_interrupt, Serial::TxIrq);
00090     if (time(NULL) < 1420070400) {
00091         setRTC();
00092     }
00093     startserver();
00094     DataRX=0;
00095     count=0;
00096     while(1) {
00097         
00098         while(!IMU.magAvailable(X_AXIS));//wait until IMU is available
00099         IMU.readMag();
00100         if(DataRX==1) {
00101             ReadWebData();
00102             esp.attach(&Rx_interrupt, Serial::RxIrq);
00103         }
00104         if(update==1) // update time, hit count, and analog levels in the HUZZAH chip
00105         {
00106             // get new values
00107             gettime();
00108             getheading(IMU.calcMag(IMU.mx),IMU.calcMag(IMU.my), IMU.calcMag(IMU.mz));
00109             count++;
00110             // send new values
00111             sprintf(cmdbuff, "time,heading,analog2=%d,\"%s\"\r\n",timebuf,Heading);
00112             SendCMD();
00113             getreply();
00114             update=0;   
00115         }
00116     }
00117 }
00118 
00119 // Reads and processes GET and POST web data
00120 void ReadWebData()
00121 {
00122     wait_ms(200);
00123     esp.attach(NULL,Serial::RxIrq);
00124     DataRX=0;
00125     memset(webdata, '\0', sizeof(webdata));
00126     strcpy(webdata, rx_buffer);
00127     memset(rx_buffer, '\0', sizeof(rx_buffer));
00128     rx_in = 0;
00129     rx_out = 0;
00130     // check web data for form information
00131     if( strstr(webdata, "POST") != NULL ) { // set update flag if POST request
00132         update=1;
00133     }
00134     if( strstr(webdata, "GET") != NULL && strstr(webdata, "favicon") == NULL ) { // set update flag for GET request but do not want to update for favicon requests
00135         update=1;
00136     }
00137 }
00138 // Starts webserver
00139 void startserver()
00140 {
00141     gettime();
00142     pc.printf("++++++++++ Resetting ESP ++++++++++\r\n");
00143     strcpy(cmdbuff,"node.restart()\r\n");
00144     SendCMD();
00145     wait(2);
00146     getreply();
00147     
00148     pc.printf("\n++++++++++ Starting Server ++++++++++\r\n> ");
00149 
00150     // initial values
00151     sprintf(cmdbuff, "time,heading=\"%s\",\"%s\"\r\n",timebuf,Heading);
00152     SendCMD();
00153     getreply();
00154     wait(0.5);
00155 
00156     //create server
00157     sprintf(cmdbuff, "srv=net.createServer(net.TCP,%d)\r\n",SERVtimeout);
00158     SendCMD();
00159     getreply();
00160     wait(0.5);
00161     
00162     strcpy(cmdbuff,"srv:listen(80,function(conn)\r\n");
00163     SendCMD();
00164     getreply();
00165     wait(0.3);
00166     
00167     strcpy(cmdbuff,"conn:on(\"receive\",function(conn,payload) \r\n");
00168     SendCMD();
00169     getreply();
00170     wait(0.3);
00171 
00172     //print data to mbed
00173     strcpy(cmdbuff,"print(payload)\r\n");
00174     SendCMD();
00175     getreply();
00176     wait(0.2);
00177 
00178     //web page data
00179     strcpy(cmdbuff,"conn:send('<!DOCTYPE html><html><body><h1>ESP8266 Mbed IoT Web Controller</h1>')\r\n");
00180     SendCMD();
00181     getreply();
00182     wait(0.4);
00183 
00184     strcpy(cmdbuff,"conn:send('Heading: '..heading..' degrees<br><hr></div>')\r\n");
00185     SendCMD();
00186     getreply();
00187     wait(0.3);
00188     
00189     strcpy(cmdbuff,"conn:send('<form method=\"POST\" id =\"formid\"')\r\n");
00190     SendCMD();
00191     getreply();
00192     wait(0.3);
00193 
00194 
00195     strcpy(cmdbuff,"conn:send('<p><input type=\"submit\" value=\"press\"></form></body></html>')\r\n");
00196     SendCMD();
00197     getreply();
00198     wait(0.3);
00199 
00200     // end web page data
00201     strcpy(cmdbuff, "conn:on(\"sent\",function(conn) conn:close() end)\r\n"); // close current connection
00202     SendCMD();
00203     getreply();
00204     wait(0.3);
00205     
00206     strcpy(cmdbuff, "end)\r\n");
00207     SendCMD();
00208     getreply();
00209     wait(0.2);
00210 
00211     strcpy(cmdbuff, "end)\r\n");
00212     SendCMD();
00213     getreply();
00214     wait(0.2);
00215 
00216     strcpy(cmdbuff, "tmr.alarm(0, 1000, 1, function()\r\n");
00217     SendCMD();
00218     getreply();
00219     wait(0.2);
00220     
00221     strcpy(cmdbuff, "if wifi.sta.getip() == nil then\r\n");
00222     SendCMD();
00223     getreply();
00224     wait(0.2);
00225     
00226     strcpy(cmdbuff, "print(\"Connecting to AP...\\n\")\r\n");
00227     SendCMD();
00228     getreply();
00229     wait(0.2);
00230     
00231     strcpy(cmdbuff, "else\r\n");
00232     SendCMD();
00233     getreply();
00234     wait(0.2);
00235     
00236     strcpy(cmdbuff, "ip, nm, gw=wifi.sta.getip()\r\n");
00237     SendCMD();
00238     getreply();
00239     wait(0.2);
00240     
00241     strcpy(cmdbuff,"print(\"IP Address: \",ip)\r\n");
00242     SendCMD();
00243     getreply();
00244     wait(0.2);
00245     
00246     strcpy(cmdbuff,"tmr.stop(0)\r\n");
00247     SendCMD();
00248     getreply();
00249     wait(0.2);
00250     
00251     strcpy(cmdbuff,"end\r\n");
00252     SendCMD();
00253     getreply();
00254     wait(0.2);
00255     
00256     strcpy(cmdbuff,"end)\r\n");
00257     SendCMD();
00258     getreply();
00259     wait(0.2);
00260     
00261     pc.printf("\n\n++++++++++ Ready ++++++++++\r\n\n");
00262 }
00263 
00264 
00265 // ESP Command data send
00266 void SendCMD()
00267 {
00268     int i;
00269     char temp_char;
00270     bool empty;
00271     i = 0;
00272 // Start Critical Section - don't interrupt while changing global buffer variables
00273     NVIC_DisableIRQ(UART1_IRQn);
00274     empty = (tx_in == tx_out);
00275     while ((i==0) || (cmdbuff[i-1] != '\n')) {
00276 // Wait if buffer full
00277         if (((tx_in + 1) % buffer_size) == tx_out) {
00278 // End Critical Section - need to let interrupt routine empty buffer by sending
00279             NVIC_EnableIRQ(UART1_IRQn);
00280             while (((tx_in + 1) % buffer_size) == tx_out) {
00281             }
00282 // Start Critical Section - don't interrupt while changing global buffer variables
00283             NVIC_DisableIRQ(UART1_IRQn);
00284         }
00285         tx_buffer[tx_in] = cmdbuff[i];
00286         i++;
00287         tx_in = (tx_in + 1) % buffer_size;
00288     }
00289     if (esp.writeable() && (empty)) {
00290         temp_char = tx_buffer[tx_out];
00291         tx_out = (tx_out + 1) % buffer_size;
00292 // Send first character to start tx interrupts, if stopped
00293         esp.putc(temp_char);
00294     }
00295 // End Critical Section
00296     NVIC_EnableIRQ(UART1_IRQn);
00297     return;
00298 }
00299 
00300 // Get Command and ESP status replies
00301 void getreply()
00302 {
00303     read_line();
00304     sscanf(rx_line,replybuff);
00305 }
00306  
00307 // Read a line from the large rx buffer from rx interrupt routine
00308 void read_line() {
00309     int i;
00310     i = 0;
00311 // Start Critical Section - don't interrupt while changing global buffer variables
00312     NVIC_DisableIRQ(UART1_IRQn);
00313 // Loop reading rx buffer characters until end of line character
00314     while ((i==0) || (rx_line[i-1] != '\r')) {
00315 // Wait if buffer empty
00316         if (rx_in == rx_out) {
00317 // End Critical Section - need to allow rx interrupt to get new characters for buffer
00318             NVIC_EnableIRQ(UART1_IRQn);
00319             while (rx_in == rx_out) {
00320             }
00321 // Start Critical Section - don't interrupt while changing global buffer variables
00322             NVIC_DisableIRQ(UART1_IRQn);
00323         }
00324         rx_line[i] = rx_buffer[rx_out];
00325         i++;
00326         rx_out = (rx_out + 1) % buffer_size;
00327     }
00328 // End Critical Section
00329     NVIC_EnableIRQ(UART1_IRQn);
00330     rx_line[i-1] = 0;
00331     return;
00332 }
00333  
00334  
00335 // Interupt Routine to read in data from serial port
00336 void Rx_interrupt() {
00337     DataRX=1;
00338     //led3=1;
00339 // Loop just in case more than one character is in UART's receive FIFO buffer
00340 // Stop if buffer full
00341     while ((esp.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
00342         rx_buffer[rx_in] = esp.getc();
00343 // Uncomment to Echo to USB serial to watch data flow
00344         pc.putc(rx_buffer[rx_in]);
00345         rx_in = (rx_in + 1) % buffer_size;
00346     }
00347     //led3=0;
00348     return;
00349 }
00350  
00351  
00352 // Interupt Routine to write out data to serial port
00353 void Tx_interrupt() {
00354     //led2=1;
00355 // Loop to fill more than one character in UART's transmit FIFO buffer
00356 // Stop if buffer empty
00357     while ((esp.writeable()) && (tx_in != tx_out)) {
00358         esp.putc(tx_buffer[tx_out]);
00359         tx_out = (tx_out + 1) % buffer_size;
00360     }
00361     //led2=0;
00362     return;
00363 }
00364 
00365 void gettime()
00366 {
00367     time_t seconds = time(NULL);
00368     strftime(timebuf,50,"%H:%M:%S %a %d %b %y", localtime(&seconds));
00369 }
00370 
00371 void setRTC()
00372 {
00373     t.tm_sec = (0);             // 0-59
00374     t.tm_min = (minute);        // 0-59
00375     t.tm_hour = (hour);         // 0-23
00376     t.tm_mday = (dayofmonth);   // 1-31
00377     t.tm_mon = (month-1);       // 0-11  "0" = Jan, -1 added for Mbed RCT clock format
00378     t.tm_year = ((year)+100);   // year since 1900,  current DCF year + 100 + 1900 = correct year
00379     set_time(mktime(&t));       // set RTC clock
00380 }
00381 
00382 // Heading calculation
00383 void getheading(float mx, float my, float mz)
00384 {
00385 // touchy trig stuff to use arctan to get compass heading (scale is 0..360)
00386     mx = -mx;
00387     if (my == 0.0)
00388         heading = (mx < 0.0) ? 180.0 : 0.0;
00389     else
00390         heading = atan2(mx, my)*360.0/(2.0*PI);
00391     //pc.printf("heading atan=%f \n\r",heading);
00392     heading -= DECLINATION; //correct for geo location
00393     if(heading>180.0) heading = heading - 360.0;
00394     else if(heading<-180.0) heading = 360.0 + heading;
00395     else if(heading<0.0) heading = 360.0  + heading;
00396     sprintf(Heading, "%3.3f", heading);
00397 
00398 }