Martin Slade / GroupUproject

Fork of 352 by Elec351 MMB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

Go to the documentation of this file.
00001 #include "mbed.h"
00002 #include "lcdClass.h"
00003 #include "math.h"
00004 #include "SDBlockDevice.h"
00005 #include "FATFileSystem.h"
00006 #include "EthernetInterface.h"
00007 #include "TCPServer.h"
00008 #include "TCPSocket.h"
00009 #include "BMP280.h"
00010 #include <string>
00011 #include <iostream>
00012 #define HTTP_STATUS_LINE "HTTP/1.0 200 OK"
00013 #define HTTP_HEADER_FIELDS "Content-Type: text/html; charset=utf-8"
00014 #define HTTP_RESPONSE HTTP_STATUS_LINE "\r\n"   \
00015                       HTTP_HEADER_FIELDS "\r\n" \
00016                       "\r\n"                    \
00017                       HTTP_MESSAGE_BODY "\r\n"
00018 
00019 #define IP        "10.0.0.10"
00020 #define NETMASK   "255.0.0.0"
00021 #define GATEWAY   "10.0.0.1"
00022 //********************Variables and Initialisations****************************************//
00023 Serial myserial(USBTX,USBRX); lcdClass mylcd(D9,D8,D7,D6,D5,D4); DigitalOut leds(D11);
00024 InterruptIn SWi1(D1); InterruptIn SWi2(D0); InterruptIn SWi3(D2); AnalogIn ldrin(A0); 
00025 int SW1 = 0; int SW2 = 0; int SW3 = 0; int record = 0; int serialmode = 0; int pcinput = 0;
00026 int lcdmode = 2; int datemode = 1; int y = 2015; int mon = 1; int d = 1; int h = 0; int minu = 0;
00027 Thread thread1, thread2, thread3, thread4, thread5, thread6; int serialcheck = 0; int samplerate = 1000; 
00028 Semaphore mysem(10);  char ldrString[10]; char tempString[10]; char presString[10]; BMP280 BMP(D14, D15);
00029 string database[5][120]; bool togPress = false; bool debugmode = false; bool data120 = false; bool switchactive = false;
00030 struct tm T; bool mainset = false; int SetDateTime(int year, int month, int day, int hour, int min);
00031 bool Pressed, Pressed1, yearPress, monPress, dayPress, hourPress, minPress = false; InterruptIn  onBoardSwitch(USER_BUTTON);
00032 bool EditTimeParam = false; int TimeParam = 0; char Row1[32]; char Row2[32]; 
00033 SDBlockDevice sd(PB_5, D12, D13, D10); FATFileSystem fs("sd", &sd); //set up SD
00034 void serialmenu(); void ratelimiter(); void clockz(); void showrecord();  
00035 //******************Variables and Initialisations*****************************************//
00036  
00037 void sensors(void const *name) {
00038       //This function is used to sample the sensors, control the serial menu and update the 2D array
00039       while(true) {
00040         mysem.wait();
00041         Thread::wait(samplerate); //Set thread wait to the samplerate (default 1000ms)
00042         if (debugmode) {leds = 1;} //Turn on white LED
00043         time_t timer = time(NULL); //Set time to 0
00044         strftime(Row1, 32, "%H:%M:%S", localtime(&timer));//Format Time as string
00045         strftime(Row2, 32, "%d/%m/%Y", localtime(&timer));  //Format Date as string
00046         float ldr = floor(ldrin*30000)/100;  //Set ldr to ldr value to 2 decimal points
00047         float temp = BMP.getTemperature();   //Set temp to the BMP temperature
00048         float presh = BMP.getPressure() ;    //Set presh to the BMP pressure
00049         sprintf(ldrString , "%2.2f", ldr);   //Format ldr as string
00050         sprintf(tempString, "%2.2f", temp);  //Format temp as string
00051         sprintf(presString, "%3.2f", presh); //Format pressure as string
00052         
00053         //Case statment for mode set by serial
00054         //0: Main, 1: live data, 2: show data, 3: delete data, 4: set samplerate, 5: set Time/date, 6: toggle debug, 7: show IP
00055         if (serialmode == 0 && mainset == false) {serialmenu(); mainset = true;}
00056         if (serialmode == 1 && mainset == false) {mainset = true; myserial.printf("ldr=%s temp=%s pres=%s \r\n", ldrString, tempString, presString); }
00057         if (serialmode == 2 && mainset == false) {showrecord(); mainset = true; }
00058         if (serialmode == 3 && mainset == false) {mainset = true; myserial.printf("Deleted all temp sensor data \r\n"); memset(database,0,sizeof(database));}
00059         if (serialmode == 4 && mainset == false) {ratelimiter(); mainset = true;}
00060         if (serialmode == 5 && mainset == false) {mainset = true; myserial.printf("Set Time/Date \r\n");}
00061         if (serialmode == 6 && mainset == false) {mainset = true; debugmode = !debugmode; if (debugmode) {myserial.printf("Debug on \r\n");} else {myserial.printf("Debug off \r\n");} }
00062         if (serialmode == 7 && mainset == false) {mainset = true; myserial.printf("IP: %s \r\n", IP);}
00063         
00064         //Update 2D array with data
00065         database[0][record] = ldrString;   //Column 1: ldr data
00066         database[1][record] = tempString;  //Column 2: temp data
00067         database[2][record] = presString; //Column 3: pressure data
00068         database[3][record] = Row1;
00069         database[4][record] = Row2;
00070         if (debugmode) {leds = 0;} //Turn off white led
00071         if (record > 119) {record = 0; data120 = true; } else { record += 1;} //Increment record counter
00072         mysem.release(); //Release thread.
00073     }
00074 }
00075 
00076 void showrecord(){
00077     //This function is used to display the last 120 data entries on serial
00078     
00079     //Don't display the data until there is 120 data entries. 
00080     if (data120 == false) {myserial.printf("Not enough records. Please wait %d seconds. \r\n", 120-record); serialmode = 0; mainset = false;}
00081     else {     
00082         for(int i=record; i < 120; i++) {  //Displays all the recent values from current record to 120 (FIFO buffer)
00083             string response;
00084             response  = "Time:" ; response += database[3][i]; //Add time
00085             response += " Date:"; response += database[4][i]; //Add date
00086             response += " LDR:" ; response += database[0][i]; //Add LDR value
00087             response += " Temp:"; response += database[1][i]; //Add Temp value
00088             response += " Pres:"; response += database[2][i]; //Add pressure value
00089             response += "\r\n"; //Line return
00090             myserial.printf(response.c_str()); //Display Time, LDR, Temp, Press
00091         }
00092         for(int i = 0; i < record; i++){ //displays all the recent values from 0 to record (FIFO buffer)
00093             string response;
00094             response  = "Time:" ; response += database[3][i]; //Add time
00095             response += " Date:"; response += database[4][i]; //Add date
00096             response += " LDR:" ; response += database[0][i]; //Add LDR value
00097             response += " Temp:"; response += database[1][i]; //Add Temp value
00098             response += " Pres:"; response += database[2][i]; //Add pressure value
00099             response += "\r\n"; //Line return
00100             myserial.printf(response.c_str()); //Display Time, LDR, Temp, Press }
00101         }
00102     }
00103 }
00104 void LCDupdate (void const *name){
00105     //The purpose of this function is to update the LCD screen
00106     while (true) {
00107         mysem.wait();
00108         Thread::wait(50); //Wait 50ms
00109         if (SW3 == 1) { if (togPress == false) { if (lcdmode == 2) {lcdmode = 1;} else {lcdmode += 1;} togPress = true; mylcd.cls(); }
00110             } else { togPress = false;} //Toggle mode
00111         if (lcdmode == 1) { clockz(); } //Display time
00112         if (lcdmode == 2) {             //Display live sensor data
00113             mylcd.locate(9,1); mylcd.printf("L:%s ", ldrString);  //Display LDR value
00114             mylcd.locate(0,1); mylcd.printf("T:%s ", tempString); //Display temp value
00115             mylcd.locate(4,0); mylcd.printf("P:%s ", presString); //Display pressure value
00116         }
00117         mysem.release(); //Release thread
00118     }
00119 }
00120     
00121 
00122 void enet(void const *name)
00123 //The purpose of this function is to set up and transmit data via ethernet
00124 {
00125     EthernetInterface eth; //Configure an ethernet connection
00126     eth.set_network(IP, NETMASK, GATEWAY); //Configure network
00127     eth.connect(); //Connect ethernet
00128     TCPServer srv; //Socket for communication
00129     SocketAddress clt_addr; //Address of incoming connection
00130     srv.open(&eth); // Open the server on ethernet stack
00131     srv.bind(eth.get_ip_address(), 80); // Bind the HTTP port (TCP 80) to the server 
00132     srv.listen(5);  // Can handle 5 simultaneous connections 
00133     while (true) {
00134         mysem.wait();
00135         using namespace std;
00136         TCPSocket clt_sock;
00137         srv.accept(&clt_sock, &clt_addr);
00138         
00139         //This code sends the HTML website to the computer.
00140         string response;
00141         response =  "<html> \r\n ";
00142         response += "<meta http-equiv=\"refresh\" content=\"1; url=http://10.0.0.10\">";
00143         response += "\r\n <h1 style=\"color:black; font-size: 200%; position: fixed; top:17.5%; left:38%;\"> ";
00144         response += Row1;
00145         response += "</h1> \r\n <h1 style=\"color:black; font-size: 200%; position: fixed; top:17.5%; left:55.5%;\">";
00146         response += Row2;
00147         response += "</h1> \r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:30%; left:46%;\">";
00148         response += tempString;
00149         response += "</h1> \r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:51%; left:46%;\">";
00150         response += ldrString;
00151         response += "</h1> \r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:72%; left:46%;\">";
00152         response += presString;
00153         response += "</h1> \r\n <body style=\"background-image:url(https://image.ibb.co/nyTj9w/pic2.png); background-size: 100% 100%;\"></body> ";
00154         response += "\r\n </html>";
00155         clt_sock.send(response.c_str(), response.size()+1);
00156         Thread::wait(samplerate); //Thread wait 10ms
00157         mysem.release();  //Release thread
00158     }
00159 }
00160 void serialin(void const *name){
00161     //The purpose of this function is to handle the serial communication
00162     
00163     while (true) {
00164         mysem.wait();
00165         Thread::wait(1000); //Thread wait 1000ms
00166         myserial.scanf("%d", &serialcheck); //Wait for command from serial
00167         if (serialmode != 5 && serialcheck == 9) {serialmode = 0; mainset = false;} //if command is 9 return to main menu
00168         else if (serialmode == 0) {serialmode = serialcheck; mainset = false; myserial.printf("press 9 to return to main menu\r\n");}
00169         else if (serialmode == 4) { //if the mode is set samplerate:
00170             if (serialcheck == 1) {samplerate = 100; }  //Set samplerate to 0.1s
00171             if (serialcheck == 2) {samplerate = 1000;}  //Set samplerate to 1s
00172             if (serialcheck == 3) {samplerate = 5000;}  //Set samplerate to 5s
00173             if (serialcheck == 4) {samplerate = 10000;} //Set samplerate to 10s
00174             if (serialcheck == 5) {samplerate = 15000;} //Set samplerate to 15s
00175             if (serialcheck == 6) {samplerate = 30000;} //Set samplerate to 30s
00176             if (serialcheck == 7) {samplerate = 60000;} //Set samplerate to 60s
00177             if (serialcheck < 8 && serialcheck > 0) {myserial.printf("Sample rate set to %dms \r\n", samplerate); serialmode = 0; mainset = false;}
00178         }
00179         if (serialmode == 5) { //if the mode is set date/time
00180                  if (mainset == false) {datemode = 1; mainset = true; } 
00181                  if (datemode == 1) { myserial.printf(" Set year: "); datemode++;} //set year
00182             else if (datemode == 2) { myserial.printf("%d \r\n Set month: ",serialcheck); y = serialcheck; datemode++;} //set month
00183             else if (datemode == 3) { myserial.printf("%d \r\n Set day: ",serialcheck); mon = serialcheck; datemode++;} //set day
00184             else if (datemode == 4) { myserial.printf("%d \r\n Set hour: ",serialcheck); d = serialcheck; datemode++;} //set hour
00185             else if (datemode == 5) { myserial.printf("%d \r\n Set minute: ", serialcheck); h = serialcheck; datemode++;} //set minute
00186             else {myserial.printf("%d \r\nDate set to: %d/%d/%d %d:%d \r\n", serialcheck,d, mon, y, h, serialcheck); minu = serialcheck; serialmode = 0;set_time(SetDateTime(y, mon, d, h, minu)); mainset = false;}
00187         }
00188         mysem.release();
00189     }
00190 }
00191     
00192 void interrupts(void const *name){
00193     //The purpose of this function is to wait for Interrupt-In's
00194     while (true) {
00195         mysem.wait(); 
00196         Thread::wait(40); //Thread wait 40ms
00197         SW1 = SWi1;  //Set SW1
00198         SW2 = SWi2;  //Set SW2
00199         SW3 = SWi3;  //Set SW3
00200         mysem.release(); //Release thread
00201     }
00202 }
00203 void SDcard(void const *name){
00204     while (true) {
00205         mysem.wait();
00206         Thread::wait(samplerate);
00207         FILE* fp = fopen("/sd/test.txt","a");   //edit test.txt file
00208         string response;
00209         response = Row1; response += ",";           //Add time
00210         response += Row2; response += ",";          //Add date
00211         response += ldrString; response += ",";     //Add ldr value
00212         response += tempString; response += ",";    //Add temp value
00213         response += presString; response += "\r\n"; //Add pressure value
00214         fprintf(fp, response.c_str());              //Print response
00215         if (onBoardSwitch == 1) {     //if switch is pressed start eject
00216             switchactive = true;
00217         }
00218         if (switchactive == true) {
00219             sd.deinit();    //eject SD
00220         }
00221         fclose(fp); //Close test.txt
00222         mysem.release();
00223     }
00224 }
00225 int SetDateTime(int year, int month, int day, int hour, int min)
00226 {  //The purpose of this function is to set the date and time
00227     T.tm_year = year - 1900; //Set year
00228     T.tm_mon = month - 1;    //Set month
00229     T.tm_mday = day;         //Set day
00230     T.tm_hour = hour;        //Set hour
00231     T.tm_min = minu;         //Set minute
00232     T.tm_sec = 0;            //Set second
00233     return (mktime(&T));
00234 }
00235 
00236 void clockz() {
00237         //The purpose of this function is to set the time on the LCD
00238         if ((SW1 == 1) && (SW2 == 1)) { //If both buttons pressed
00239             if (Pressed == false) { //if first time:
00240                 EditTimeParam = not EditTimeParam; //Toggle mode
00241                 if (EditTimeParam == false) { set_time(SetDateTime(y, mon, d, h, minu)); } //Set Datetime
00242                 mylcd.cls(); //Clear LCD screen
00243                 Pressed = true;
00244             }
00245         }
00246         else{ Pressed = false; }
00247         if (EditTimeParam == true) {
00248             if (SW1 == 1) { //if switch is pressed
00249                 if (Pressed1 == false) {
00250                     TimeParam++; //increment TimeParam for switch case
00251                     mylcd.cls(); //Clear LCD screen
00252                     Pressed1 = true;
00253                     if (TimeParam > 4) {TimeParam = 0;}
00254                 }
00255             }
00256             else {
00257                 Pressed1 = false;
00258             }
00259             switch (TimeParam) {
00260                 case 0: //Year
00261                     if (SW2 == 1) { if (yearPress == false) { y++; yearPress = true; } } else { yearPress = false; } //Increment year
00262                     if (y > 2030) { y = 2015; mylcd.cls(); } //If upper limit hit, reset to lower limit
00263                     mylcd.locate(0, 0); mylcd.printf("Year: %d\n", y); //Display year
00264                     break;
00265                 case 1: //Month
00266                     if (SW2 == 1) { if (monPress == false) { mon++; monPress = true; } } else { monPress = false; } //Increment month
00267                     if (mon > 12) { mon = 1; mylcd.cls(); } //if upper limit hit, reset to lower limit
00268                     mylcd.locate(0, 0); mylcd.printf("Month: %d\n", mon); //Display month
00269                     break;
00270                 case 2: //Day
00271                     if (SW2 == 1) { if (dayPress == false) { d++; dayPress = true; } } else { dayPress = false; } //Increment day
00272                     if ((mon == (4 || 6 || 9 || 11)) && (d > 30)) { d = 1; mylcd.cls(); } else if ((mon == 2) && (d > 28)) { d = 0; mylcd.cls(); } else if (d > 31) { d = 0; mylcd.cls(); }
00273                     mylcd.locate(0, 0); mylcd.printf("Day: %d\n", d); //Display day
00274                     break;
00275                 case 3: //Hour
00276                     if (SW2 == 1) { if (hourPress == false) { h++; hourPress = true; } } else { hourPress = false; } //Increment hour
00277                     if (h > 23) { h = 0; mylcd.cls(); } //if upper limit hit, reset to lower limit
00278                     mylcd.locate(0, 0); mylcd.printf("Hour: %d\n", h); //Display hour
00279                     break;
00280                 case 4: //Minute
00281                     if (SW2 == 1) { if (minPress == false) { minu++; minPress = true; } } else { minPress = false; } //Increment minute
00282                     if (minu > 59) { minu = 0; mylcd.cls(); } //if upper limit hit, reset to lower limit
00283                     mylcd.locate(0, 0); mylcd.printf("Minute: %d\n", minu); //Display minute
00284                     break;
00285             }
00286         }
00287         else {
00288             mylcd.locate(0, 0); mylcd.printf("%s", Row1); //Print Time on LCD, row 1
00289             mylcd.locate(0, 1); mylcd.printf("%s", Row2); //Print Date on LCD, row 2
00290         }
00291 }
00292 
00293 void serialmenu() {            
00294     //The purpose of this function is to print the serial menu
00295     myserial.printf("Welcome to Group Z ELEC351 Coursework. Press 9 to start. \r\n");
00296     myserial.printf("Please select (type in the number) an option: \r\n");
00297     myserial.printf("1. Show live sensor data \r\n");
00298     myserial.printf("2. Show old sensor data \r\n");
00299     myserial.printf("3. delete all sensor data \r\n");
00300     myserial.printf("4. Select sampling rate \r\n");
00301     myserial.printf("5. Set time/date \r\n");
00302     myserial.printf("6. Toggle debug \r\n");
00303     myserial.printf("7. Show IP address \r\n");
00304 }
00305 void ratelimiter() {       
00306     //The purpose of this function is to print the samplerate options to the serial     
00307     myserial.printf("Please select (type in the number) a sample rate: \r\n");
00308     myserial.printf("1. 0.1s \r\n");
00309     myserial.printf("2. 1s \r\n");
00310     myserial.printf("3. 5s \r\n");
00311     myserial.printf("4. 10s \r\n");
00312     myserial.printf("5. 15s \r\n");
00313     myserial.printf("6. 30s \r\n");
00314     myserial.printf("7. 60s \r\n");
00315 }
00316 int main(){
00317     //The purpose of this function is to be the main code to run the threads.
00318     myserial.baud(115200); //Set serial speed to 115200
00319     mylcd.cls();           //Clear LCD
00320     thread1.start(callback(enet,    (void *)   "Thread1\r\n"));   // Start Ethernet thread
00321     thread2.start(callback(sensors, (void *)   "Thread2\r\n"));   // Start sensors thread
00322     thread3.start(callback(serialin,(void *)   "Thread3\r\n"));   // Start Serialin thread
00323     thread4.start(callback(interrupts,(void *) "Thread4\r\n"));   // Start interrupts thread
00324     thread5.start(callback(LCDupdate,(void *)  "Thread5\r\n"));   // Start LCDupdate thread
00325     thread6.start(callback(SDcard,(void *)     "Thread6\r\n"));   // Start SDcard thread
00326     set_time(SetDateTime(y, mon, d, h, minu));  //Set DateTime
00327 }