Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Thread_Communication_V4_fortest by
main.cpp
- Committer:
- benparkes
- Date:
- 2018-01-06
- Revision:
- 17:aa585f901750
- Parent:
- 16:f30928e622a2
- Child:
- 18:728fddea6d9c
File content as of revision 17:aa585f901750:
#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 ()
{
while (1) {
dataLock.lock(); // Entering Critial Section
// Store Data in global Variables
LDR = LDR_In.read();
TEMP = Sensor.getTemperature();
PRES = Sensor.getPressure();
memset((char *)TIME, NULL, 21);
time(&raw_time);
sample_epoch = localtime(&raw_time);
strftime((char *)TIME, 21,"%d/%m/%Y, %X", sample_epoch);
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;
sprintf(X_str,"%s, \n\rTemperature: %2.2f, \n\rPressure: %4.2f, \n\rLight: %.4f", mail->Time_Date, 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");
}
