Ben Parkes
/
Thread_Communication_V5
V4
Fork of Thread_Communication_V4_fortest by
main.cpp
- Committer:
- benparkes
- Date:
- 2018-01-06
- Revision:
- 18:728fddea6d9c
- Parent:
- 17:aa585f901750
File content as of revision 18:728fddea6d9c:
#include "mbed.h" #include "main.h" #include "stdio.h" #define FallingEdge 0 #define RisingEdge 1 #define USER_BUTTON_PRESSED 1 LCD lcd(PD_15, PF_12, PF_13, PE_9, PF_14, PF_15); BMP280 Sensor(D14, D15); //Define Functions void PrintLCD (); void Rx_interrupt(); void serialCMD(); void sensorRead(); void readISR(); void circBuff(); void writeRemove_SD(); void Network1(); void LCD_timerISR(); // USER_BUTTON ISRs (Debounce) void userButtonRise(); void userButtonFall(); void userButtonTimeoutHandler(); // Tickers & Timeouts Timeout userButtonTimeout; // FOR debouncing User Switch Ticker read; // ***Sets sampling period!*** (ISR Signals sampling Thread) Ticker refresh; /* LOCKS */ Mutex DataBuffer; Mutex dataLock; /* THREADS */ Thread _PrintLCD, _serialCMD, _circBuff; Thread _sensorRead (osPriorityRealtime); //dataLock Thread Thread _writeRemove_SD; Thread _Network1; /* GLOBAL DATA */ volatile float LDR = 0; volatile double PRES = 0; volatile double TEMP = 0; volatile char TIME[21]; volatile double sampleTime = 15.0; //int LCD_refresh = 1; // int to hold current switch state int userButtonState = FallingEdge; /* DEBOUNCER INTERRUPTS */ InterruptIn userButton(USER_BUTTON); void userButtonRise () { userButton.rise(NULL); userButtonState = RisingEdge; userButtonTimeout.attach(&userButtonTimeoutHandler, 0.1); } void userButtonFall () { userButton.fall(NULL); _writeRemove_SD.signal_set(USER_BUTTON_PRESSED); userButtonState = FallingEdge; userButtonTimeout.attach(&userButtonTimeoutHandler, 0.1); } void userButtonTimeoutHandler() { userButtonTimeout.detach(); switch (userButtonState) { case RisingEdge: userButton.fall(&userButtonFall); break; case FallingEdge: userButton.rise(userButtonRise); break; }// End Switch } //End ISR /*--------------------------------MAIN--------------------------------*/ int main() { pc.baud(57600); pc.attach(&Rx_interrupt, Serial::RxIrq); POST(); pc.printf("\n\n\nType HELP for list of available Commands\n\n\n\r"); _serialCMD.start(serialCMD); _sensorRead.start(sensorRead); _PrintLCD.start(PrintLCD); _circBuff.start(circBuff); _writeRemove_SD.start(writeRemove_SD); _Network1.start(Network1); userButton.rise(&userButtonRise); read.attach(&readISR, sampleTime); refresh.attach(&LCD_timerISR, LCD_REFRESH); while (1) { Yellow_ext = ON; Thread::wait (200); Yellow_ext = OFF; Thread::wait(200); }// End While } // End Main /*--------------------------------------------------------------------*/ /*-----------------Circular Buffer------------------------------------*/ void circBuff () { while(1) { Thread::signal_wait(DATA_READY); // wait for signal from sensorRead //Lock data buffer DataBuffer.lock(); //Format samples, send to FIFO buffer head memset(data_buffer[sample_h],NULL,64); osEvent evt = mail_FIFO.get(); if (evt.status == osEventMail) { mail_t *mail = (mail_t*)evt.value.p; char sample_time[21]; int rTime = mail->Time_Date; time((time_t*)rTime); sample_epoch = localtime((time_t*)rTime); strftime(sample_time, 21,"%d/%m/%Y, %X", sample_epoch); sprintf(data_buffer[sample_h],"%s, %2.2f, %4.2f, %.4f\n\r", sample_time, mail->temp_Value, mail->press_Value, mail->LDR_Value); mail_FIFO.free(mail); } //Set seperate FIFO head and tail for printing data data_h = sample_h; data_t = sample_t; //Move sample FIFO buffer head to next row in buffer sample_h++; //Check sample FIFO buffer head if(sample_h >= MAX_SAMPLES) { sample_h = 0; } //Check sample FIFO buffer tail if(sample_t == sample_h) { sample_t++; if(sample_t >= (MAX_SAMPLES)) { sample_t = 0; } } //Unlock data buffer DataBuffer.unlock(); }// End While }// End Circular buffer /*-------------------------------------------------------------*/ /*---------------------Read Sensors ---------------------------*/ void readISR () // Ticker interrupt defined in main { _sensorRead.signal_set(SENSOR_UPDATE); } // Keep short void sensorRead () { volatile float LDR = 0; volatile double PRES = 0; volatile double TEMP = 0; while (1) { dataLock.lock(); // Entering Critial Section // Store Data in global Variables LDR = LDR_In.read(); TEMP = Sensor.getTemperature(); PRES = Sensor.getPressure(); dataLock.unlock(); // Exiting Critical Section Green_int = !Green_int; // debugging //Read sensors, send to mail-queue mail_t *mail = mail_LCD.alloc(); mail->LDR_Value = LDR; mail->temp_Value = TEMP; mail->press_Value = PRES; mail_LCD.put(mail); mail_t *mail1 = mail_FIFO.alloc(); mail1->Time_Date = raw_time; mail1->LDR_Value = LDR; mail1->temp_Value = TEMP; mail1->press_Value = PRES; mail_FIFO.put(mail); mail_t *mail2 = mail_Network.alloc(); mail1->Time_Date = raw_time; mail2->LDR_Value = LDR; mail2->temp_Value = TEMP; mail2->press_Value = PRES; mail_Network.put(mail); _circBuff.signal_set(DATA_READY); // Set signal to buffer to store updated values Thread::signal_wait(SENSOR_UPDATE); // Wait for the Timer interrupt } } /*--------------------------------------------------------------------*/ /*--------------------------------LCD---------------------------------*/ void LCD_timerISR () { _PrintLCD.signal_set(LCD_READY); } void PrintLCD () { int i = 0; int j = 4; char lightString[16]; char tempString[16]; char pressString[16]; char lcd_TIME[21]; while(1) { lcd.RowSelect(3); if (j == 4) { lcd.Clear(); lcd.RowSelect(0); switch (i) { case 0: { osEvent evt = mail_LCD.get(); if (evt.status == osEventMail) { mail_t *mail = (mail_t*)evt.value.p; sprintf(lightString,"%.4f", mail->LDR_Value); sprintf(tempString,"%2.2f", mail->temp_Value); sprintf(pressString,"%4.2f", mail->press_Value); mail_LCD.free(mail); } lcd.Write("Light:"); lcd.RowSelect(1); lcd.Write(lightString); i++; j = 0; break; } case 1: lcd.Write("Temperature(C):"); lcd.RowSelect(1); lcd.Write(tempString); i++; j = 0; break; case 2: lcd.Write("Pressure(mBar):"); lcd.RowSelect(1); lcd.Write(pressString); i =0; j = 0; break; default: i = 0; j = 0; break; }//end switch }// end if else { j++; } lcd.RowSelect(3); dataLock.lock(); memset(lcd_TIME, NULL, 21); time(&raw_time); sample_epoch = localtime(&raw_time); strftime( lcd_TIME,21,"%d/%m/%Y %X", sample_epoch); dataLock.unlock(); lcd.Write(lcd_TIME); Thread::signal_wait(LCD_READY); Red_int = !Red_int; }//end while }// end thread /*--------------------------------------------------------------------*/ /*------------------------------SERIAL_CMD----------------------------*/ //Interrupt when recieving from serial port void Rx_interrupt() { //Wait for serial input while (pc.readable()) { //Return input to serial rx_buffer[rx_in] = pc.getc(); pc.putc(rx_buffer[rx_in]); //If enter key is pressed, set serial thread signal if(rx_buffer[rx_in] == 0xD) { _serialCMD.signal_set(ENTER_KEY); } //Increment buffer head else { if(rx_in>=32) { puts("\n\rERROR - Stop typing so much!\n\r"); rx_in = 0; memset(rx_buffer, NULL, 32); } else { rx_in = (rx_in + 1); } } } } //Check what command what recieved and execute void serialCMD() { bool xx = 1; // State for CMD STATE while(1) { //Wait for thread signal Thread::signal_wait(ENTER_KEY); //Detach serial interrupt pc.attach(NULL, Serial::RxIrq); struct tm * s_time; char tm_n[4]; /*----CARRAGE RETURN-------------*/ if(rx_buffer[0] == 0xD) { pc.puts("\n\r"); } /*----READ ALL----------------------------------*/ else if(strstr(rx_buffer, "READ ALL")) { pc.puts("\n\r Reading all samples...\n\r"); //Lock data buffer DataBuffer.lock(); //Print all samples to serial for(int n=data_t; n<=MAX_SAMPLES; n++) { pc.puts(data_buffer[n]); } if(data_t>data_h) { for(int n=0; n<=(data_t-1); n++) { pc.puts(data_buffer[n]); } } //Lock data buffer DataBuffer.unlock(); pc.puts(" All Samples read!\n\r"); } /*----DELETE ALL----------------------------------*/ else if(strstr(rx_buffer, "DELETE ALL")) { pc.puts("\n\r Deleting all samples...\n\r"); //Lock data buffer DataBuffer.lock(); //Delete all sampled data for(int n=0; n<=MAX_SAMPLES; n++) { memset(data_buffer[n], NULL, 64); } data_h = data_t; sample_h = sample_t; //Unlock data buffer DataBuffer.unlock(); pc.puts(" All previous samples deleted!\n\r"); } /*----READ----------------------------------*/ else if(strstr(rx_buffer, "READ")) { pc.puts("\n\r Reading N samples...\n\r"); int N = atoi(strncpy(tm_n,&rx_buffer[5],4)); int S = 0; //Lock data buffer DataBuffer.lock(); //Check if N is greater than buffer size if(N >= MAX_SAMPLES) { N = MAX_SAMPLES; } //Read N samples from FIFO buffer if(N <= 0) { pc.puts("ERROR - N must be greater than 0\n\r"); N = 0; } else { for(int n=data_h; n>=0; n--) { if(S>=N) {} else { pc.puts(data_buffer[n]); S++; } } for(int n=MAX_SAMPLES-1; n<=data_t; n--) { if(S>=N) {} else { pc.puts(data_buffer[n]); S++; } } } pc.printf(" Read %d samples\n\r",N); //Unlock data buffer DataBuffer.unlock(); } /*----DELETE----------------------------------*/ else if(strstr(rx_buffer, "DELETE")) { pc.puts("\n\r Deleting N samples...\n\r"); int N = atoi(strncpy(tm_n,&rx_buffer[6],4)); int S = 0; //Lock data buffer DataBuffer.lock(); //Check if N is greater than buffer size if(N >= MAX_SAMPLES) { N = MAX_SAMPLES; } //Read N samples from FIFO buffer if(N <= 0) { pc.puts("ERROR - N must be greater than 0\n\r"); N = 0; } else { for(int n=data_t; n<=MAX_SAMPLES; n++) { if(S>=N) {} else { memset(data_buffer[n], NULL, 64); S++; data_t = n; sample_t = n; } } for(int n=MAX_SAMPLES-1; n<=data_t; n--) { if(S>=N) {} else { memset(data_buffer[n], NULL, 64); S++; data_t = n; sample_t = n; } } } pc.printf(" Deleted %d samples\n\r",N); //Unlock data buffer DataBuffer.unlock(); } /*----SETDATE----------------------------------*/ else if(strstr(rx_buffer, "SETDATE")) { time(&raw_time); s_time = localtime(&raw_time); //Update day in time structure int dd = atoi(strncpy(tm_n,&rx_buffer[8],2)); s_time->tm_mday = dd; memset(tm_n, NULL, 4); //Update month in time structure int mm = atoi(strncpy(tm_n,&rx_buffer[11],2)); s_time->tm_mon = mm-1; memset(tm_n, NULL, 4); //Update year in time structure int yyyy = atoi(strncpy(tm_n,&rx_buffer[14],4)); s_time->tm_year = yyyy-1900; memset(tm_n, NULL, 4); //Set date from updated time structure set_time(mktime(s_time)); strftime(serial_buffer, 80, "\n\r Date updated to: %d/%m/%Y\n\r", s_time); pc.puts(serial_buffer); } /*----SETTIME---------------------------------*/ else if(strstr(rx_buffer, "SETTIME")) { time(&raw_time); s_time = localtime(&raw_time); //Update seconds in time structure int ss = atoi(strncpy(tm_n,&rx_buffer[14],2)); s_time->tm_sec = ss; memset(tm_n, NULL, 4); //Update minutes in time structure int mm = atoi(strncpy(tm_n,&rx_buffer[11],2)); s_time->tm_min = mm; memset(tm_n, NULL, 4); //Update hour in time structure int hh = atoi(strncpy(tm_n,&rx_buffer[8],2)); s_time->tm_hour = hh; memset(tm_n, NULL, 4); //Set time from updated time structure set_time(mktime(s_time)); strftime(serial_buffer, 80, "\n\r Time updated to: %X\n\r", s_time); pc.puts(serial_buffer); } /*----SETT----------------------------------*/ else if(strstr(rx_buffer, "SETT")) { read.detach(); double AA = atof(strncpy(tm_n,&rx_buffer[5],4)); if (AA < 0.1 || AA > 60) { AA = 15; pc.puts("ERROR - Sample Time out of range (0.1<=T<=60)\n\r"); } sampleTime = AA; pc.printf("\n\r Sample Time updated to: %2.1f seconds\n\r", sampleTime); read.attach(readISR, sampleTime); memset(tm_n, NULL, 4); } /*----STATE----------------------------------*/ else if(strstr(rx_buffer, "STATE")) { strncpy(tm_n,&rx_buffer[6],3); if (strstr(tm_n, "ON")) { if (xx == 1) { pc.puts("\n\r Already Sampling\n\r"); } else { read.attach(&readISR, sampleTime); pc.puts("\n\r Sampling ON\n\r"); xx = 1; } } else if (strstr(tm_n, "OFF")) { if ( xx == 0 ) { pc.puts("\n\r Already not Sampling\n\r"); } else { read.detach(); pc.puts("\n\r Sampling OFF\n\r"); xx = 0; } } else { pc.puts("Error - STATE can only be ON or OFF\n\r"); } //pc.puts(" STATE\n\r"); } /*----LOGGING----------------------------------*/ else if(strstr(rx_buffer, "LOGGING")) { pc.puts(" LOGGING\n\r"); } /*----HELP--------------------------------------*/ else if (strstr(rx_buffer, "HELP")) { pc.puts("\n\n\r Currently Available Commands:\n\r"); pc.puts("\tREAD n - Read n previous samples\n\r"); pc.puts("\tREAD ALL - Read All previous samples held in memory\n\r"); pc.puts("\tSETTIME hh:mm::ss - Set time in 24hr format\n\r"); pc.puts("\tSETDATE dd/mm/yyyy - Set time in specified format\n\r"); pc.puts("\tDELETE ALL - Delete all sampled held in internal memory\n\r"); pc.puts("\tSETT - Set sample period. must be an integer in range 0 < T < 61\n\r"); } else if (strstr(rx_buffer,"tell me a joke")) { pc.puts("\n\r Why do programmers always get Halloween and Christmas mixed up...?\n\r"); Thread::wait(5000); pc.puts(" Because Oct 31 == Dec 25! LOL"); } /*----ERROR---*/ else { pc.puts("Error - Command not recognised. Type HELP for a list of available commands\n\r"); } /*----------------------------------------------*/ //Clear serial buffers memset(serial_buffer, NULL, 80); memset(rx_buffer, NULL, 32); rx_in = 0; //Attach serial interrupt pc.attach(&Rx_interrupt, Serial::RxIrq); } } /*------------------------------------------------*/ /*---------------SD THread------------------------*/ void writeRemove_SD() { while(1) { Thread::signal_wait(USER_BUTTON_PRESSED); //wait for debounce signal int sd_state = sdIn; switch (sd_state) { case 1: pc.printf("SD Card not inserted!\n\r"); pc.printf("Insert SD Card and press User button again\n\r"); break; default: pc.printf("This should never happen\n\r"); break; case 0: pc.printf("Initalising SD Card\n\r"); //check init if (sd.init() != 0) { pc.printf(" ERROR - SD card failed to initialise.\n\rRestart board\n\r PROBABLY wires come out\n\r"); } else { // Create Filing system for SD Card FATFileSystem fs("sd", &sd); //OpenFiles to write/append to pc.printf("Writing to SDC\n\r"); FILE* fp = fopen("/sd/TheChamberOfSecrets.txt", "a"); //"w" to overwrite file ftb // Check for error in opening file if (fp == NULL) { pc.printf("*****ERROR - Could not open file for write*****\n\r"); } //HERE IS WHERE TO PRINT DATA TO SD CARD FROM BUFFER (REMEMBER TO EMPTY BUFFER???) //Lock data buffer DataBuffer.lock(); dataLock.lock(); //Print all samples to SD for(int n=data_t; n<=MAX_SAMPLES; n++) { fputs(data_buffer[n], fp); fprintf(fp, "\n\r"); } if(data_t>data_h) { for(int n=0; n<=(data_t-1); n++) { fputs(data_buffer[n], fp); } } //Lock data buffer DataBuffer.unlock(); dataLock.unlock(); //fprintf(fp, "dd/mm/yy hh:mm:ss, TEMPERATURE, PRESSURE, LIGHT\n\r"); fclose(fp); pc.printf("Write Sucessful!\n\r"); sd.deinit(); pc.printf("SD Card Ready to Remove\n\r"); Green_ext = 1; Thread::wait(500); Green_ext = 0; Thread::wait(500); Green_ext = 1; Thread::wait(500); Green_ext = 0; Thread::wait(500); Green_ext = 1; Thread::wait(500); Green_ext = 0; Thread::wait(500); Green_ext = 1; Thread::wait(500); Green_ext = 0; Thread::wait(500); }// end if }//End Switch }// End While }// End Thread /*--------------------------------------------------------------------------*/ /*---------------------------Networking Thread------------------------------*/ void Network1 () { printf("Setting up server\n\r"); //Configure an ethernet connection EthernetInterface eth; eth.set_network(IP, NETMASK, GATEWAY); eth.connect(); if (eth.get_ip_address() == NULL) { pc.printf("Error - Can't get IP. Network not setup\n\r"); pc.printf("Reset Required. Make sure network cables are plugged in\n\r"); } else { printf("The target IP address is '%s'\n\r", eth.get_ip_address()); //Now setup a web server TCPServer srv; //TCP/IP Server SocketAddress clt_addr; //Address of incoming connection /* Open the server on ethernet stack */ srv.open(ð); /* Bind the HTTP port (TCP 80) to the server */ srv.bind(eth.get_ip_address(), 80); /* Can handle 5 simultaneous connections */ srv.listen(5); TCPSocket clt_sock; //Socket for communication pc.printf("\rServer Ready\n\r"); while (true) { using namespace std; //Block and wait on an incoming connection srv.accept(&clt_sock, &clt_addr); //printf("accept %s:%d\n\r", clt_addr.get_ip_address(), clt_addr.get_port()); //Uses a C++ string to make it easier to concatinate string response; string strL = "LDR:"; string strP = ", Pressure(mBar): "; string strT = ", Temp(C): "; string strDT ="Date/Time: ,"; //This is a C string char X_str[128]; /*//Read the LDR value dataLock.lock(); // add watchdog? float L = LDR ; float T = TEMP; float P = PRES; char DT[21]; strcpy((char*)TIME,DT); dataLock.unlock(); //Convert to a C String //sprintf(l_str, "%1.3f", L ); // try \n\r?? //sprintf(t_str, "%2.2f", T); //sprintf(p_str, "%4.2f", P);*/ osEvent evt = mail_Network.get(); if (evt.status == osEventMail) { mail_t *mail = (mail_t*)evt.value.p; char sample_time[21]; int rTime = mail->Time_Date; time((time_t*)rTime); sample_epoch = localtime((time_t*)rTime); strftime(sample_time, 21,"%d/%m/%Y, %X", sample_epoch); sprintf(X_str,"%s, \n\rTemperature: %2.2f, \n\rPressure: %4.2f, \n\rLight: %.4f", sample_time, mail->temp_Value, mail->press_Value, mail->LDR_Value); mail_Network.free(mail); } //Build the C++ string response response = HTTP_MESSAGE_BODY1; response += X_str; /* response += strL; response += strDT; response += strL; response += l_str; response += strT; response += t_str; response += strP; response += p_str;*/ response += HTTP_MESSAGE_BODY2; //Send static HTML response (as a C string) clt_sock.send(response.c_str(), response.size()+6); }// end While }//end if }// end thread /*---------------------------POST--------------------------------------------*/ void POST () { pc.printf(" Basic POST\n\r"); pc.printf(" ALL Leds should be flashing\n\r"); for(unsigned int n = 0; n<10; n++) { Green_int = ON; Blue_int = ON; Red_int = ON; Green_ext = ON; Yellow_ext = ON; Red_ext = ON; wait (0.2); Green_int = OFF; Blue_int = OFF; Red_int = OFF; Green_ext = OFF; Yellow_ext = OFF; Red_ext = OFF; wait (0.2); } pc.printf("Switch states:\n\r"); pc.printf("\tSW_L: %d\n\r\tSW_R %d\n\r", SW_L.read(), SW_R.read()); float Temp = Sensor.getTemperature(); float Pres = Sensor.getPressure(); float ldrs = LDR_In.read(); pc.printf("Sensor test:\n\r"); pc.printf("T: %f\tP: %f\tL: %f\n\r",Temp,Pres,ldrs); pc.printf("LCD Test\n\r"); lcd.Clear(); lcd.RowSelect(0); lcd.Write("1******LCD*********1"); lcd.RowSelect(1); lcd.Write("2******TEST********2"); lcd.RowSelect(2); lcd.Write("3******LCD*********3"); lcd.RowSelect(3); lcd.Write("4******TEST********4"); wait(1); lcd.Clear(); pc.printf("Basic POST end\n\r"); }