GroupZ - 05012018 1511

Revision:
1:84581acd1333
Parent:
0:1c898341428b
--- a/main.cpp	Fri Jan 05 15:10:50 2018 +0000
+++ b/main.cpp	Tue Jan 09 14:53:07 2018 +0000
@@ -1,6 +1,8 @@
 #include "mbed.h"
-#include "TextLCD.h"
+#include "lcdClass.h"
 #include "math.h"
+#include "SDBlockDevice.h"
+#include "FATFileSystem.h"
 #include "EthernetInterface.h"
 #include "TCPServer.h"
 #include "TCPSocket.h"
@@ -17,98 +19,309 @@
 #define IP        "10.0.0.10"
 #define NETMASK   "255.0.0.0"
 #define GATEWAY   "10.0.0.1"
-
-
-BMP280 BMP(D14, D15);
-Serial myserial(USBTX,USBRX);
-TextLCD mylcd(D9,D8,D7,D6,D5,D4);
-BusOut leds(D11,D12);
-DigitalIn toggle(D2);
-bool pressed = false;
-int counter = 0;
-AnalogIn ldrin(A0);
-Thread thread;
-Thread thread2;
-Semaphore mysem(10);
-char buffer[10];
-char buffer2[10];
-char buffer3[10];
-void enet(void const *name);
+//********************Variables and Initialisations****************************************//
+Serial myserial(USBTX,USBRX); lcdClass mylcd(D9,D8,D7,D6,D5,D4); DigitalOut leds(D11);
+InterruptIn SWi1(D1); InterruptIn SWi2(D0); InterruptIn SWi3(D2); AnalogIn ldrin(A0); 
+int SW1 = 0; int SW2 = 0; int SW3 = 0; int record = 0; int serialmode = 0; int pcinput = 0;
+int lcdmode = 2; int datemode = 1; int y = 2015; int mon = 1; int d = 1; int h = 0; int minu = 0;
+Thread thread1, thread2, thread3, thread4, thread5, thread6; int serialcheck = 0; int samplerate = 1000; 
+Semaphore mysem(10);  char ldrString[10]; char tempString[10]; char presString[10]; BMP280 BMP(D14, D15);
+string database[5][120]; bool togPress = false; bool debugmode = false; bool data120 = false; bool switchactive = false;
+struct tm T; bool mainset = false; int SetDateTime(int year, int month, int day, int hour, int min);
+bool Pressed, Pressed1, yearPress, monPress, dayPress, hourPress, minPress = false; InterruptIn  onBoardSwitch(USER_BUTTON);
+bool EditTimeParam = false; int TimeParam = 0; char Row1[32]; char Row2[32]; 
+SDBlockDevice sd(PB_5, D12, D13, D10); FATFileSystem fs("sd", &sd); //set up SD
+void serialmenu(); void ratelimiter(); void clockz(); void showrecord();  
+//******************Variables and Initialisations*****************************************//
 
-int main(){
-    myserial.baud(115200);
-    mylcd.cls();
-    thread.start(callback(enet, (void *) "Thread\r\n")); 
-    while(true) {
+void sensors(void const *name) {
+      //This function is used to sample the sensors, control the serial menu and update the 2D array
+      while(true) {
         mysem.wait();
-        leds = 1; 
-        float ldr = floor(ldrin*30000)/100;
-        float temp = BMP.getTemperature();
-        float pressure = BMP.getPressure() ;
-        //if (counter > 7) {counter = 0;}
-        //leds = counter;
-        //if (toggle == false) {if (pressed == false) {counter++; pressed = true;} } else {pressed = false;}
-        //int x = floor(ldr*8);
-        //leds = counter;
-        sprintf(buffer , "%2.2f", ldr);
-        sprintf(buffer2, "%2.2f", temp);
-        sprintf(buffer3, "%3.2f", pressure);
-        mylcd.locate(9,1); mylcd.printf("L:%s ", buffer );
-        mylcd.locate(0,1); mylcd.printf("T:%s ", buffer2);
-        mylcd.locate(4,0); mylcd.printf("P:%s ", buffer3);
-        myserial.printf("ldr=%s temp=%s pres=%s \r\n", buffer, buffer2, buffer3);
+        Thread::wait(samplerate); //Set thread wait to the samplerate (default 1000ms)
+        if (debugmode) {leds = 1;} //Turn on white LED
+        time_t timer = time(NULL); //Set time to 0
+        strftime(Row1, 32, "%H:%M:%S", localtime(&timer));//Format Time as string
+        strftime(Row2, 32, "%d/%m/%Y", localtime(&timer));  //Format Date as string
+        float ldr = floor(ldrin*30000)/100;  //Set ldr to ldr value to 2 decimal points
+        float temp = BMP.getTemperature();   //Set temp to the BMP temperature
+        float presh = BMP.getPressure() ;    //Set presh to the BMP pressure
+        sprintf(ldrString , "%2.2f", ldr);   //Format ldr as string
+        sprintf(tempString, "%2.2f", temp);  //Format temp as string
+        sprintf(presString, "%3.2f", presh); //Format pressure as string
         
-        Thread::wait(1000);
-        leds = 0;
-        mysem.release();
+        //Case statment for mode set by serial
+        //0: Main, 1: live data, 2: show data, 3: delete data, 4: set samplerate, 5: set Time/date, 6: toggle debug, 7: show IP
+        if (serialmode == 0 && mainset == false) {serialmenu(); mainset = true;}
+        if (serialmode == 1 && mainset == false) {mainset = true; myserial.printf("ldr=%s temp=%s pres=%s \r\n", ldrString, tempString, presString); }
+        if (serialmode == 2 && mainset == false) {showrecord(); mainset = true; }
+        if (serialmode == 3 && mainset == false) {mainset = true; myserial.printf("Deleted all temp sensor data \r\n"); memset(database,0,sizeof(database));}
+        if (serialmode == 4 && mainset == false) {ratelimiter(); mainset = true;}
+        if (serialmode == 5 && mainset == false) {mainset = true; myserial.printf("Set Time/Date \r\n");}
+        if (serialmode == 6 && mainset == false) {mainset = true; debugmode = !debugmode; if (debugmode) {myserial.printf("Debug on \r\n");} else {myserial.printf("Debug off \r\n");} }
+        if (serialmode == 7 && mainset == false) {mainset = true; myserial.printf("IP: %s \r\n", IP);}
+        
+        //Update 2D array with data
+        database[0][record] = ldrString;   //Column 1: ldr data
+        database[1][record] = tempString;  //Column 2: temp data
+        database[2][record] = presString; //Column 3: pressure data
+        database[3][record] = Row1;
+        database[4][record] = Row2;
+        if (debugmode) {leds = 0;} //Turn off white led
+        if (record > 119) {record = 0; data120 = true; } else { record += 1;} //Increment record counter
+        mysem.release(); //Release thread.
     }
 }
 
+void showrecord(){
+    //This function is used to display the last 120 data entries on serial
+    
+    //Don't display the data until there is 120 data entries. 
+    if (data120 == false) {myserial.printf("Not enough records. Please wait %d seconds. \r\n", 120-record); serialmode = 0; mainset = false;}
+    else {     
+        for(int i=record; i < 120; i++) {  //Displays all the recent values from current record to 120 (FIFO buffer)
+            string response;
+            response  = "Time:" ; response += database[3][i]; //Add time
+            response += " Date:"; response += database[4][i]; //Add date
+            response += " LDR:" ; response += database[0][i]; //Add LDR value
+            response += " Temp:"; response += database[1][i]; //Add Temp value
+            response += " Pres:"; response += database[2][i]; //Add pressure value
+            response += "\r\n"; //Line return
+            myserial.printf(response.c_str()); //Display Time, LDR, Temp, Press
+        }
+        for(int i = 0; i < record; i++){ //displays all the recent values from 0 to record (FIFO buffer)
+            string response;
+            response  = "Time:" ; response += database[3][i]; //Add time
+            response += " Date:"; response += database[4][i]; //Add date
+            response += " LDR:" ; response += database[0][i]; //Add LDR value
+            response += " Temp:"; response += database[1][i]; //Add Temp value
+            response += " Pres:"; response += database[2][i]; //Add pressure value
+            response += "\r\n"; //Line return
+            myserial.printf(response.c_str()); //Display Time, LDR, Temp, Press }
+        }
+    }
+}
+void LCDupdate (void const *name){
+    //The purpose of this function is to update the LCD screen
+    while (true) {
+        mysem.wait();
+        Thread::wait(50); //Wait 50ms
+        if (SW3 == 1) { if (togPress == false) { if (lcdmode == 2) {lcdmode = 1;} else {lcdmode += 1;} togPress = true; mylcd.cls(); }
+            } else { togPress = false;} //Toggle mode
+        if (lcdmode == 1) { clockz(); } //Display time
+        if (lcdmode == 2) {             //Display live sensor data
+            mylcd.locate(9,1); mylcd.printf("L:%s ", ldrString);  //Display LDR value
+            mylcd.locate(0,1); mylcd.printf("T:%s ", tempString); //Display temp value
+            mylcd.locate(4,0); mylcd.printf("P:%s ", presString); //Display pressure value
+        }
+        mysem.release(); //Release thread
+    }
+}
+    
 
 void enet(void const *name)
+//The purpose of this function is to set up and transmit data via ethernet
 {
-    //Configure an ethernet connection
-    EthernetInterface eth;
-    eth.set_network(IP, NETMASK, GATEWAY);
-    eth.connect();
-    printf("The target IP address is '%s'\n", eth.get_ip_address());
-    
-    //Now setup a web server
-    TCPServer srv;           //TCP/IP Server
-    //TCPSocket clt_sock;      //Socket for communication
-    SocketAddress clt_addr;  //Address of incoming connection
-    
-    /* Open the server on ethernet stack */
-    srv.open(&eth);
-    
-    /* Bind the HTTP port (TCP 80) to the server */
-    srv.bind(eth.get_ip_address(), 80);
-    
-    /* Can handle 5 simultaneous connections */
-    srv.listen(5);
-    
+    EthernetInterface eth; //Configure an ethernet connection
+    eth.set_network(IP, NETMASK, GATEWAY); //Configure network
+    eth.connect(); //Connect ethernet
+    TCPServer srv; //Socket for communication
+    SocketAddress clt_addr; //Address of incoming connection
+    srv.open(&eth); // Open the server on ethernet stack
+    srv.bind(eth.get_ip_address(), 80); // Bind the HTTP port (TCP 80) to the server 
+    srv.listen(5);  // Can handle 5 simultaneous connections 
     while (true) {
         mysem.wait();
         using namespace std;
         TCPSocket clt_sock;
         srv.accept(&clt_sock, &clt_addr);
+        
+        //This code sends the HTML website to the computer.
         string response;
         response =  "<html> \r\n ";
         response += "<meta http-equiv=\"refresh\" content=\"1; url=http://10.0.0.10\">";
-        response += "\r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:11%; left:37%;\"> ";
-        response += "16:34";
+        response += "\r\n <h1 style=\"color:black; font-size: 200%; position: fixed; top:17.5%; left:38%;\"> ";
+        response += Row1;
         response += "</h1> \r\n <h1 style=\"color:black; font-size: 200%; position: fixed; top:17.5%; left:55.5%;\">";
-        response += "31/12/2017";
+        response += Row2;
         response += "</h1> \r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:30%; left:46%;\">";
-        response += buffer;
+        response += tempString;
         response += "</h1> \r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:51%; left:46%;\">";
-        response += buffer2;
+        response += ldrString;
         response += "</h1> \r\n <h1 style=\"color:black; font-size: 400%; position: fixed; top:72%; left:46%;\">";
-        response += buffer3;
+        response += presString;
         response += "</h1> \r\n <body style=\"background-image:url(https://image.ibb.co/nyTj9w/pic2.png); background-size: 100% 100%;\"></body> ";
         response += "\r\n </html>";
         clt_sock.send(response.c_str(), response.size()+1);
-        Thread::wait(10);
+        Thread::wait(samplerate); //Thread wait 10ms
+        mysem.release();  //Release thread
+    }
+}
+void serialin(void const *name){
+    //The purpose of this function is to handle the serial communication
+    
+    while (true) {
+        mysem.wait();
+        Thread::wait(1000); //Thread wait 1000ms
+        myserial.scanf("%d", &serialcheck); //Wait for command from serial
+        if (serialmode != 5 && serialcheck == 9) {serialmode = 0; mainset = false;} //if command is 9 return to main menu
+        else if (serialmode == 0) {serialmode = serialcheck; mainset = false; myserial.printf("press 9 to return to main menu\r\n");}
+        else if (serialmode == 4) { //if the mode is set samplerate:
+            if (serialcheck == 1) {samplerate = 100; }  //Set samplerate to 0.1s
+            if (serialcheck == 2) {samplerate = 1000;}  //Set samplerate to 1s
+            if (serialcheck == 3) {samplerate = 5000;}  //Set samplerate to 5s
+            if (serialcheck == 4) {samplerate = 10000;} //Set samplerate to 10s
+            if (serialcheck == 5) {samplerate = 15000;} //Set samplerate to 15s
+            if (serialcheck == 6) {samplerate = 30000;} //Set samplerate to 30s
+            if (serialcheck == 7) {samplerate = 60000;} //Set samplerate to 60s
+            if (serialcheck < 8 && serialcheck > 0) {myserial.printf("Sample rate set to %dms \r\n", samplerate); serialmode = 0; mainset = false;}
+        }
+        if (serialmode == 5) { //if the mode is set date/time
+                 if (mainset == false) {datemode = 1; mainset = true; } 
+                 if (datemode == 1) { myserial.printf(" Set year: "); datemode++;} //set year
+            else if (datemode == 2) { myserial.printf("%d \r\n Set month: ",serialcheck); y = serialcheck; datemode++;} //set month
+            else if (datemode == 3) { myserial.printf("%d \r\n Set day: ",serialcheck); mon = serialcheck; datemode++;} //set day
+            else if (datemode == 4) { myserial.printf("%d \r\n Set hour: ",serialcheck); d = serialcheck; datemode++;} //set hour
+            else if (datemode == 5) { myserial.printf("%d \r\n Set minute: ", serialcheck); h = serialcheck; datemode++;} //set minute
+            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;}
+        }
+        mysem.release();
+    }
+}
+    
+void interrupts(void const *name){
+    //The purpose of this function is to wait for Interrupt-In's
+    while (true) {
+        mysem.wait(); 
+        Thread::wait(40); //Thread wait 40ms
+        SW1 = SWi1;  //Set SW1
+        SW2 = SWi2;  //Set SW2
+        SW3 = SWi3;  //Set SW3
+        mysem.release(); //Release thread
+    }
+}
+void SDcard(void const *name){
+    while (true) {
+        mysem.wait();
+        Thread::wait(samplerate);
+        FILE* fp = fopen("/sd/test.txt","a");   //edit test.txt file
+        string response;
+        response = Row1; response += ",";           //Add time
+        response += Row2; response += ",";          //Add date
+        response += ldrString; response += ",";     //Add ldr value
+        response += tempString; response += ",";    //Add temp value
+        response += presString; response += "\r\n"; //Add pressure value
+        fprintf(fp, response.c_str());              //Print response
+        if (onBoardSwitch == 1) {     //if switch is pressed start eject
+            switchactive = true;
+        }
+        if (switchactive == true) {
+            sd.deinit();    //eject SD
+        }
+        fclose(fp); //Close test.txt
         mysem.release();
     }
+}
+int SetDateTime(int year, int month, int day, int hour, int min)
+{  //The purpose of this function is to set the date and time
+    T.tm_year = year - 1900; //Set year
+    T.tm_mon = month - 1;    //Set month
+    T.tm_mday = day;         //Set day
+    T.tm_hour = hour;        //Set hour
+    T.tm_min = minu;         //Set minute
+    T.tm_sec = 0;            //Set second
+    return (mktime(&T));
+}
+
+void clockz() {
+        //The purpose of this function is to set the time on the LCD
+        if ((SW1 == 1) && (SW2 == 1)) { //If both buttons pressed
+            if (Pressed == false) { //if first time:
+                EditTimeParam = not EditTimeParam; //Toggle mode
+                if (EditTimeParam == false) { set_time(SetDateTime(y, mon, d, h, minu)); } //Set Datetime
+                mylcd.cls(); //Clear LCD screen
+                Pressed = true;
+            }
+        }
+        else{ Pressed = false; }
+        if (EditTimeParam == true) {
+            if (SW1 == 1) { //if switch is pressed
+                if (Pressed1 == false) {
+                    TimeParam++; //increment TimeParam for switch case
+                    mylcd.cls(); //Clear LCD screen
+                    Pressed1 = true;
+                    if (TimeParam > 4) {TimeParam = 0;}
+                }
+            }
+            else {
+                Pressed1 = false;
+            }
+            switch (TimeParam) {
+                case 0: //Year
+                    if (SW2 == 1) { if (yearPress == false) { y++; yearPress = true; } } else { yearPress = false; } //Increment year
+                    if (y > 2030) { y = 2015; mylcd.cls(); } //If upper limit hit, reset to lower limit
+                    mylcd.locate(0, 0); mylcd.printf("Year: %d\n", y); //Display year
+                    break;
+                case 1: //Month
+                    if (SW2 == 1) { if (monPress == false) { mon++; monPress = true; } } else { monPress = false; } //Increment month
+                    if (mon > 12) { mon = 1; mylcd.cls(); } //if upper limit hit, reset to lower limit
+                    mylcd.locate(0, 0); mylcd.printf("Month: %d\n", mon); //Display month
+                    break;
+                case 2: //Day
+                    if (SW2 == 1) { if (dayPress == false) { d++; dayPress = true; } } else { dayPress = false; } //Increment day
+                    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(); }
+                    mylcd.locate(0, 0); mylcd.printf("Day: %d\n", d); //Display day
+                    break;
+                case 3: //Hour
+                    if (SW2 == 1) { if (hourPress == false) { h++; hourPress = true; } } else { hourPress = false; } //Increment hour
+                    if (h > 23) { h = 0; mylcd.cls(); } //if upper limit hit, reset to lower limit
+                    mylcd.locate(0, 0); mylcd.printf("Hour: %d\n", h); //Display hour
+                    break;
+                case 4: //Minute
+                    if (SW2 == 1) { if (minPress == false) { minu++; minPress = true; } } else { minPress = false; } //Increment minute
+                    if (minu > 59) { minu = 0; mylcd.cls(); } //if upper limit hit, reset to lower limit
+                    mylcd.locate(0, 0); mylcd.printf("Minute: %d\n", minu); //Display minute
+                    break;
+            }
+        }
+        else {
+            mylcd.locate(0, 0); mylcd.printf("%s", Row1); //Print Time on LCD, row 1
+            mylcd.locate(0, 1); mylcd.printf("%s", Row2); //Print Date on LCD, row 2
+        }
+}
+
+void serialmenu() {            
+    //The purpose of this function is to print the serial menu
+    myserial.printf("Welcome to Group Z ELEC351 Coursework. Press 9 to start. \r\n");
+    myserial.printf("Please select (type in the number) an option: \r\n");
+    myserial.printf("1. Show live sensor data \r\n");
+    myserial.printf("2. Show old sensor data \r\n");
+    myserial.printf("3. delete all sensor data \r\n");
+    myserial.printf("4. Select sampling rate \r\n");
+    myserial.printf("5. Set time/date \r\n");
+    myserial.printf("6. Toggle debug \r\n");
+    myserial.printf("7. Show IP address \r\n");
+}
+void ratelimiter() {       
+    //The purpose of this function is to print the samplerate options to the serial     
+    myserial.printf("Please select (type in the number) a sample rate: \r\n");
+    myserial.printf("1. 0.1s \r\n");
+    myserial.printf("2. 1s \r\n");
+    myserial.printf("3. 5s \r\n");
+    myserial.printf("4. 10s \r\n");
+    myserial.printf("5. 15s \r\n");
+    myserial.printf("6. 30s \r\n");
+    myserial.printf("7. 60s \r\n");
+}
+int main(){
+    //The purpose of this function is to be the main code to run the threads.
+    myserial.baud(115200); //Set serial speed to 115200
+    mylcd.cls();           //Clear LCD
+    thread1.start(callback(enet,    (void *)   "Thread1\r\n"));   // Start Ethernet thread
+    thread2.start(callback(sensors, (void *)   "Thread2\r\n"));   // Start sensors thread
+    thread3.start(callback(serialin,(void *)   "Thread3\r\n"));   // Start Serialin thread
+    thread4.start(callback(interrupts,(void *) "Thread4\r\n"));   // Start interrupts thread
+    thread5.start(callback(LCDupdate,(void *)  "Thread5\r\n"));   // Start LCDupdate thread
+    thread6.start(callback(SDcard,(void *)     "Thread6\r\n"));   // Start SDcard thread
+    set_time(SetDateTime(y, mon, d, h, minu));  //Set DateTime
 }
\ No newline at end of file