practical / Mbed 2 deprecated updatedPatient2

Dependencies:   mbed

Committer:
tatsuyanah
Date:
Sat Apr 13 23:14:31 2019 +0000
Revision:
0:c837d6abadc5
Child:
1:417090fd8386
wholeCode

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tatsuyanah 0:c837d6abadc5 1 // ESP8266 Static page WEB server to control Mbed
tatsuyanah 0:c837d6abadc5 2
tatsuyanah 0:c837d6abadc5 3 #include "mbed.h"
tatsuyanah 0:c837d6abadc5 4 #include "algorithm.h"
tatsuyanah 0:c837d6abadc5 5 #include "MAX30102.h"
tatsuyanah 0:c837d6abadc5 6
tatsuyanah 0:c837d6abadc5 7 #define MAX_BRIGHTNESS 255
tatsuyanah 0:c837d6abadc5 8 Serial pc(USBTX, USBRX);
tatsuyanah 0:c837d6abadc5 9 Serial esp(p9, p10);
tatsuyanah 0:c837d6abadc5 10 //Serial esp(p28, p27); // tx, rx
tatsuyanah 0:c837d6abadc5 11
tatsuyanah 0:c837d6abadc5 12
tatsuyanah 0:c837d6abadc5 13 // Standard Mbed LED definitions
tatsuyanah 0:c837d6abadc5 14 DigitalOut led1(LED1);
tatsuyanah 0:c837d6abadc5 15 DigitalOut led2(LED2);
tatsuyanah 0:c837d6abadc5 16 DigitalOut led3(LED3);
tatsuyanah 0:c837d6abadc5 17 DigitalOut led4(LED4);
tatsuyanah 0:c837d6abadc5 18
tatsuyanah 0:c837d6abadc5 19 // some test values to show on web page
tatsuyanah 0:c837d6abadc5 20 AnalogIn Ain1(p18);
tatsuyanah 0:c837d6abadc5 21 AnalogIn Ain2(p19);
tatsuyanah 0:c837d6abadc5 22 AnalogIn LM35(p20);
tatsuyanah 0:c837d6abadc5 23 DigitalIn INT(p8);
tatsuyanah 0:c837d6abadc5 24 /*
tatsuyanah 0:c837d6abadc5 25 char ssid[32] = "hsd"; // enter WiFi router ssid inside the quotes
tatsuyanah 0:c837d6abadc5 26 char pwd [32] = "austin123"; // enter WiFi router password inside the quotes
tatsuyanah 0:c837d6abadc5 27 */
tatsuyanah 0:c837d6abadc5 28
tatsuyanah 0:c837d6abadc5 29 uint32_t aun_ir_buffer[500]; //IR LED sensor data
tatsuyanah 0:c837d6abadc5 30 int32_t n_ir_buffer_length; //data length
tatsuyanah 0:c837d6abadc5 31 uint32_t aun_red_buffer[500]; //Red LED sensor data
tatsuyanah 0:c837d6abadc5 32 int32_t n_sp02; //SPO2 value
tatsuyanah 0:c837d6abadc5 33 int8_t ch_spo2_valid; //indicator to show if the SP02 calculation is valid
tatsuyanah 0:c837d6abadc5 34 int32_t n_heart_rate; //heart rate value
tatsuyanah 0:c837d6abadc5 35 int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
tatsuyanah 0:c837d6abadc5 36 uint8_t uch_dummy;
tatsuyanah 0:c837d6abadc5 37 char uploadTimeOut=1;
tatsuyanah 0:c837d6abadc5 38 Timer timer1second;
tatsuyanah 0:c837d6abadc5 39
tatsuyanah 0:c837d6abadc5 40 float temperature, AdcIn, Ht;
tatsuyanah 0:c837d6abadc5 41 float R1=100000, R2=10000; // resistor values to give a 10:1 reduction of measured AnalogIn voltage
tatsuyanah 0:c837d6abadc5 42 char Vcc[10];
tatsuyanah 0:c837d6abadc5 43 char Temp[10];
tatsuyanah 0:c837d6abadc5 44 char Null[10];
tatsuyanah 0:c837d6abadc5 45
tatsuyanah 0:c837d6abadc5 46 // things for sending/receiving data over serial
tatsuyanah 0:c837d6abadc5 47 volatile int tx_in=0;
tatsuyanah 0:c837d6abadc5 48 volatile int tx_out=0;
tatsuyanah 0:c837d6abadc5 49 volatile int rx_in=0;
tatsuyanah 0:c837d6abadc5 50 volatile int rx_out=0;
tatsuyanah 0:c837d6abadc5 51 const int buffer_size = 4095;
tatsuyanah 0:c837d6abadc5 52 char tx_buffer[buffer_size+1];
tatsuyanah 0:c837d6abadc5 53 char rx_buffer[buffer_size+1];
tatsuyanah 0:c837d6abadc5 54 void Tx_interrupt();
tatsuyanah 0:c837d6abadc5 55 void Rx_interrupt();
tatsuyanah 0:c837d6abadc5 56 void send_line();
tatsuyanah 0:c837d6abadc5 57 void read_line();
tatsuyanah 0:c837d6abadc5 58
tatsuyanah 0:c837d6abadc5 59 int DataRX;
tatsuyanah 0:c837d6abadc5 60 int update;
tatsuyanah 0:c837d6abadc5 61 int count;
tatsuyanah 0:c837d6abadc5 62 char cmdbuff[1024];
tatsuyanah 0:c837d6abadc5 63 char replybuff[4096];
tatsuyanah 0:c837d6abadc5 64 char webdata[4096]; // This may need to be bigger depending on WEB browser used
tatsuyanah 0:c837d6abadc5 65 char webbuff[4096]; // Currently using 1986 characters, Increase this if more web page data added
tatsuyanah 0:c837d6abadc5 66 char timebuf[30];
tatsuyanah 0:c837d6abadc5 67 void SendCMD(),getreply(),ReadWebData(),startserver();
tatsuyanah 0:c837d6abadc5 68 void gettime(),setRTC(),gettemp(),getbattery();
tatsuyanah 0:c837d6abadc5 69 char rx_line[1024];
tatsuyanah 0:c837d6abadc5 70 int port =80; // set server port
tatsuyanah 0:c837d6abadc5 71 int SERVtimeout =5; // set server timeout in seconds in case link breaks.
tatsuyanah 0:c837d6abadc5 72 struct tm t;
tatsuyanah 0:c837d6abadc5 73 // manual set RTC values
tatsuyanah 0:c837d6abadc5 74 int minute =20; // 0-59
tatsuyanah 0:c837d6abadc5 75 int hour =11; // 2-23
tatsuyanah 0:c837d6abadc5 76 int dayofmonth =13; // 1-31
tatsuyanah 0:c837d6abadc5 77 int month =4; // 1-12
tatsuyanah 0:c837d6abadc5 78 int year =19; // last 2 digits
tatsuyanah 0:c837d6abadc5 79
tatsuyanah 0:c837d6abadc5 80 int main()
tatsuyanah 0:c837d6abadc5 81 {
tatsuyanah 0:c837d6abadc5 82 float f_temp;
tatsuyanah 0:c837d6abadc5 83 uint32_t un_min, un_max, un_prev_data; //variables to calculate the on-board LED brightness that reflects the heartbeats
tatsuyanah 0:c837d6abadc5 84 int i;
tatsuyanah 0:c837d6abadc5 85 int32_t n_brightness;
tatsuyanah 0:c837d6abadc5 86
tatsuyanah 0:c837d6abadc5 87 pc.baud(115200);
tatsuyanah 0:c837d6abadc5 88 esp.baud(9600);
tatsuyanah 0:c837d6abadc5 89 led1=1,led2=0,led3=0, led4=0;
tatsuyanah 0:c837d6abadc5 90 // Setup a serial interrupt function to receive data
tatsuyanah 0:c837d6abadc5 91 esp.attach(&Rx_interrupt, Serial::RxIrq);
tatsuyanah 0:c837d6abadc5 92 // Setup a serial interrupt function to transmit data
tatsuyanah 0:c837d6abadc5 93 esp.attach(&Tx_interrupt, Serial::TxIrq);
tatsuyanah 0:c837d6abadc5 94 if (time(NULL) < 1420070400) {
tatsuyanah 0:c837d6abadc5 95 setRTC();
tatsuyanah 0:c837d6abadc5 96 }
tatsuyanah 0:c837d6abadc5 97 startserver();
tatsuyanah 0:c837d6abadc5 98 DataRX=0;
tatsuyanah 0:c837d6abadc5 99 count=0;
tatsuyanah 0:c837d6abadc5 100
tatsuyanah 0:c837d6abadc5 101
tatsuyanah 0:c837d6abadc5 102 maxim_max30102_reset(); //resets the MAX30102
tatsuyanah 0:c837d6abadc5 103 wait(1);
tatsuyanah 0:c837d6abadc5 104 //read and clear status register
tatsuyanah 0:c837d6abadc5 105 maxim_max30102_read_reg(0,&uch_dummy);
tatsuyanah 0:c837d6abadc5 106
tatsuyanah 0:c837d6abadc5 107 //while(pc.readable()==0)
tatsuyanah 0:c837d6abadc5 108 {
tatsuyanah 0:c837d6abadc5 109 // pc.printf("\x1B[2J"); //clear terminal program screen
tatsuyanah 0:c837d6abadc5 110 pc.printf("Press any key to start conversion\n\r");
tatsuyanah 0:c837d6abadc5 111 wait(1);
tatsuyanah 0:c837d6abadc5 112 }
tatsuyanah 0:c837d6abadc5 113 uch_dummy=getchar();
tatsuyanah 0:c837d6abadc5 114
tatsuyanah 0:c837d6abadc5 115 maxim_max30102_init(); //initializes the MAX30102
tatsuyanah 0:c837d6abadc5 116
tatsuyanah 0:c837d6abadc5 117 n_brightness=0;
tatsuyanah 0:c837d6abadc5 118 un_min=0x3FFFF;
tatsuyanah 0:c837d6abadc5 119 un_max=0;
tatsuyanah 0:c837d6abadc5 120
tatsuyanah 0:c837d6abadc5 121 n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
tatsuyanah 0:c837d6abadc5 122
tatsuyanah 0:c837d6abadc5 123 //read the first 500 samples, and determine the signal range
tatsuyanah 0:c837d6abadc5 124 for(i=0;i<n_ir_buffer_length;i++)
tatsuyanah 0:c837d6abadc5 125 {
tatsuyanah 0:c837d6abadc5 126 //while(INT.read()==1); //wait until the interrupt pin asserts
tatsuyanah 0:c837d6abadc5 127
tatsuyanah 0:c837d6abadc5 128 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
tatsuyanah 0:c837d6abadc5 129
tatsuyanah 0:c837d6abadc5 130 if(un_min>aun_red_buffer[i])
tatsuyanah 0:c837d6abadc5 131 un_min=aun_red_buffer[i]; //update signal min
tatsuyanah 0:c837d6abadc5 132 if(un_max<aun_red_buffer[i])
tatsuyanah 0:c837d6abadc5 133 un_max=aun_red_buffer[i]; //update signal max
tatsuyanah 0:c837d6abadc5 134 pc.printf("red=");
tatsuyanah 0:c837d6abadc5 135 pc.printf("%i", aun_red_buffer[i]);
tatsuyanah 0:c837d6abadc5 136 pc.printf(", ir=");
tatsuyanah 0:c837d6abadc5 137 pc.printf("%i\n\r", aun_ir_buffer[i]);
tatsuyanah 0:c837d6abadc5 138 }
tatsuyanah 0:c837d6abadc5 139 un_prev_data=aun_red_buffer[i];
tatsuyanah 0:c837d6abadc5 140
tatsuyanah 0:c837d6abadc5 141 //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
tatsuyanah 0:c837d6abadc5 142 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
tatsuyanah 0:c837d6abadc5 143
tatsuyanah 0:c837d6abadc5 144 timer1second.start();
tatsuyanah 0:c837d6abadc5 145 while(1) {
tatsuyanah 0:c837d6abadc5 146 if(DataRX==1) {
tatsuyanah 0:c837d6abadc5 147 ReadWebData();
tatsuyanah 0:c837d6abadc5 148 esp.attach(&Rx_interrupt, Serial::RxIrq);
tatsuyanah 0:c837d6abadc5 149 }
tatsuyanah 0:c837d6abadc5 150 if(n_heart_rate <=10)
tatsuyanah 0:c837d6abadc5 151 {
tatsuyanah 0:c837d6abadc5 152 maxim_max30102_init(); //initializes the MAX30102
tatsuyanah 0:c837d6abadc5 153
tatsuyanah 0:c837d6abadc5 154 n_brightness=0;
tatsuyanah 0:c837d6abadc5 155 un_min=0x3FFFF;
tatsuyanah 0:c837d6abadc5 156 un_max=0;
tatsuyanah 0:c837d6abadc5 157
tatsuyanah 0:c837d6abadc5 158 // n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
tatsuyanah 0:c837d6abadc5 159
tatsuyanah 0:c837d6abadc5 160 //read the first 500 samples, and determine the signal range
tatsuyanah 0:c837d6abadc5 161 for(i=0;i<n_ir_buffer_length;i++)
tatsuyanah 0:c837d6abadc5 162 {
tatsuyanah 0:c837d6abadc5 163 //while(INT.read()==1); //wait until the interrupt pin asserts
tatsuyanah 0:c837d6abadc5 164
tatsuyanah 0:c837d6abadc5 165 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
tatsuyanah 0:c837d6abadc5 166
tatsuyanah 0:c837d6abadc5 167 if(un_min>aun_red_buffer[i])
tatsuyanah 0:c837d6abadc5 168 un_min=aun_red_buffer[i]; //update signal min
tatsuyanah 0:c837d6abadc5 169 if(un_max<aun_red_buffer[i])
tatsuyanah 0:c837d6abadc5 170 un_max=aun_red_buffer[i]; //update signal max
tatsuyanah 0:c837d6abadc5 171 pc.printf("red=");
tatsuyanah 0:c837d6abadc5 172 pc.printf("%i", aun_red_buffer[i]);
tatsuyanah 0:c837d6abadc5 173 pc.printf(", ir=");
tatsuyanah 0:c837d6abadc5 174 pc.printf("%i\n\r", aun_ir_buffer[i]);
tatsuyanah 0:c837d6abadc5 175 }
tatsuyanah 0:c837d6abadc5 176 un_prev_data=aun_red_buffer[i];
tatsuyanah 0:c837d6abadc5 177
tatsuyanah 0:c837d6abadc5 178 //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
tatsuyanah 0:c837d6abadc5 179 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
tatsuyanah 0:c837d6abadc5 180
tatsuyanah 0:c837d6abadc5 181 }
tatsuyanah 0:c837d6abadc5 182 i=0;
tatsuyanah 0:c837d6abadc5 183 un_min=0x3FFFF;
tatsuyanah 0:c837d6abadc5 184 un_max=0;
tatsuyanah 0:c837d6abadc5 185
tatsuyanah 0:c837d6abadc5 186 //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
tatsuyanah 0:c837d6abadc5 187 for(i=100;i<500;i++)
tatsuyanah 0:c837d6abadc5 188 {
tatsuyanah 0:c837d6abadc5 189 aun_red_buffer[i-100]=aun_red_buffer[i];
tatsuyanah 0:c837d6abadc5 190 aun_ir_buffer[i-100]=aun_ir_buffer[i];
tatsuyanah 0:c837d6abadc5 191
tatsuyanah 0:c837d6abadc5 192 //update the signal min and max
tatsuyanah 0:c837d6abadc5 193 if(un_min>aun_red_buffer[i])
tatsuyanah 0:c837d6abadc5 194 un_min=aun_red_buffer[i];
tatsuyanah 0:c837d6abadc5 195 if(un_max<aun_red_buffer[i])
tatsuyanah 0:c837d6abadc5 196 un_max=aun_red_buffer[i];
tatsuyanah 0:c837d6abadc5 197 }
tatsuyanah 0:c837d6abadc5 198
tatsuyanah 0:c837d6abadc5 199 //take 100 sets of samples before calculating the heart rate.
tatsuyanah 0:c837d6abadc5 200 for(i=400;i<500;i++)
tatsuyanah 0:c837d6abadc5 201 {
tatsuyanah 0:c837d6abadc5 202 un_prev_data=aun_red_buffer[i-1];
tatsuyanah 0:c837d6abadc5 203 while(INT.read()==1);
tatsuyanah 0:c837d6abadc5 204 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
tatsuyanah 0:c837d6abadc5 205
tatsuyanah 0:c837d6abadc5 206 if(aun_red_buffer[i]>un_prev_data)
tatsuyanah 0:c837d6abadc5 207 {
tatsuyanah 0:c837d6abadc5 208 f_temp=aun_red_buffer[i]-un_prev_data;
tatsuyanah 0:c837d6abadc5 209 f_temp/=(un_max-un_min);
tatsuyanah 0:c837d6abadc5 210 f_temp*=MAX_BRIGHTNESS;
tatsuyanah 0:c837d6abadc5 211 n_brightness-=(int)f_temp;
tatsuyanah 0:c837d6abadc5 212 if(n_brightness<0)
tatsuyanah 0:c837d6abadc5 213 n_brightness=0;
tatsuyanah 0:c837d6abadc5 214 }
tatsuyanah 0:c837d6abadc5 215 else
tatsuyanah 0:c837d6abadc5 216 {
tatsuyanah 0:c837d6abadc5 217 f_temp=un_prev_data-aun_red_buffer[i];
tatsuyanah 0:c837d6abadc5 218 f_temp/=(un_max-un_min);
tatsuyanah 0:c837d6abadc5 219 f_temp*=MAX_BRIGHTNESS;
tatsuyanah 0:c837d6abadc5 220 n_brightness+=(int)f_temp;
tatsuyanah 0:c837d6abadc5 221 if(n_brightness>MAX_BRIGHTNESS)
tatsuyanah 0:c837d6abadc5 222 n_brightness=MAX_BRIGHTNESS;
tatsuyanah 0:c837d6abadc5 223 }
tatsuyanah 0:c837d6abadc5 224 //pc.printf("red=%i, ir=%i, HR=%i,HRvalid=%i,SpO2=%i,SPO2Valid=%i\n\r",aun_red_buffer[i],aun_ir_buffer[i],n_heart_rate, ch_hr_valid, n_sp02, ch_spo2_valid);
tatsuyanah 0:c837d6abadc5 225
tatsuyanah 0:c837d6abadc5 226 }
tatsuyanah 0:c837d6abadc5 227 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
tatsuyanah 0:c837d6abadc5 228 //eo while
tatsuyanah 0:c837d6abadc5 229 sprintf(Vcc,"%i",n_heart_rate);
tatsuyanah 0:c837d6abadc5 230 //
tatsuyanah 0:c837d6abadc5 231
tatsuyanah 0:c837d6abadc5 232 if(timer1second.read()>2)
tatsuyanah 0:c837d6abadc5 233 {
tatsuyanah 0:c837d6abadc5 234 timer1second.reset();
tatsuyanah 0:c837d6abadc5 235 // get new values
tatsuyanah 0:c837d6abadc5 236 gettime();
tatsuyanah 0:c837d6abadc5 237 gettemp();
tatsuyanah 0:c837d6abadc5 238 // getbattery();
tatsuyanah 0:c837d6abadc5 239
tatsuyanah 0:c837d6abadc5 240 // send new values
tatsuyanah 0:c837d6abadc5 241 /* if(n_heart_rate>=499 || n_heart_rate <=30)
tatsuyanah 0:c837d6abadc5 242 {
tatsuyanah 0:c837d6abadc5 243 sprintf(Null,"%s","Null");
tatsuyanah 0:c837d6abadc5 244 sprintf(cmdbuff, "count,time,analog1,analog2=%d,\"%s\",\"%s\",\"%s\"\r\n",count,timebuf,Temp,Null);
tatsuyanah 0:c837d6abadc5 245 }
tatsuyanah 0:c837d6abadc5 246 else*/
tatsuyanah 0:c837d6abadc5 247 {
tatsuyanah 0:c837d6abadc5 248 count++;
tatsuyanah 0:c837d6abadc5 249 sprintf(cmdbuff, "count,time,analog1,analog2=%d,\"%s\",\"%s\",\"%s\"\r\n",count,timebuf,Temp,Vcc);
tatsuyanah 0:c837d6abadc5 250 }
tatsuyanah 0:c837d6abadc5 251 SendCMD();
tatsuyanah 0:c837d6abadc5 252 getreply();
tatsuyanah 0:c837d6abadc5 253
tatsuyanah 0:c837d6abadc5 254 update=0;
tatsuyanah 0:c837d6abadc5 255
tatsuyanah 0:c837d6abadc5 256 }
tatsuyanah 0:c837d6abadc5 257 }
tatsuyanah 0:c837d6abadc5 258 }
tatsuyanah 0:c837d6abadc5 259
tatsuyanah 0:c837d6abadc5 260 // Reads and processes GET and POST web data
tatsuyanah 0:c837d6abadc5 261 void ReadWebData()
tatsuyanah 0:c837d6abadc5 262 {
tatsuyanah 0:c837d6abadc5 263 wait_ms(200);
tatsuyanah 0:c837d6abadc5 264 esp.attach(NULL,Serial::RxIrq);
tatsuyanah 0:c837d6abadc5 265 DataRX=0;
tatsuyanah 0:c837d6abadc5 266 memset(webdata, '\0', sizeof(webdata));
tatsuyanah 0:c837d6abadc5 267 strcpy(webdata, rx_buffer);
tatsuyanah 0:c837d6abadc5 268 memset(rx_buffer, '\0', sizeof(rx_buffer));
tatsuyanah 0:c837d6abadc5 269 rx_in = 0;
tatsuyanah 0:c837d6abadc5 270 rx_out = 0;
tatsuyanah 0:c837d6abadc5 271 // check web data for form information
tatsuyanah 0:c837d6abadc5 272 if( strstr(webdata, "check=led1v") != NULL ) {
tatsuyanah 0:c837d6abadc5 273 led1=!led1;
tatsuyanah 0:c837d6abadc5 274 }
tatsuyanah 0:c837d6abadc5 275 if( strstr(webdata, "check=led2v") != NULL ) {
tatsuyanah 0:c837d6abadc5 276 led2=!led2;
tatsuyanah 0:c837d6abadc5 277 }
tatsuyanah 0:c837d6abadc5 278 if( strstr(webdata, "check=led3v") != NULL ) {
tatsuyanah 0:c837d6abadc5 279 led3=!led3;
tatsuyanah 0:c837d6abadc5 280 }
tatsuyanah 0:c837d6abadc5 281 if( strstr(webdata, "check=led4v") != NULL ) {
tatsuyanah 0:c837d6abadc5 282 led4=!led4;
tatsuyanah 0:c837d6abadc5 283 }
tatsuyanah 0:c837d6abadc5 284 if( strstr(webdata, "POST") != NULL ) { // set update flag if POST request
tatsuyanah 0:c837d6abadc5 285 update=1;
tatsuyanah 0:c837d6abadc5 286 }
tatsuyanah 0:c837d6abadc5 287 if( strstr(webdata, "GET") != NULL && strstr(webdata, "favicon") == NULL ) { // set update flag for GET request but do not want to update for favicon requests
tatsuyanah 0:c837d6abadc5 288 update=1;
tatsuyanah 0:c837d6abadc5 289 }
tatsuyanah 0:c837d6abadc5 290 }
tatsuyanah 0:c837d6abadc5 291 // Starts webserver
tatsuyanah 0:c837d6abadc5 292 void startserver()
tatsuyanah 0:c837d6abadc5 293 {
tatsuyanah 0:c837d6abadc5 294 gettime();
tatsuyanah 0:c837d6abadc5 295 gettemp();
tatsuyanah 0:c837d6abadc5 296 getbattery();
tatsuyanah 0:c837d6abadc5 297 pc.printf("++++++++++ Resetting ESP ++++++++++\r\n");
tatsuyanah 0:c837d6abadc5 298 strcpy(cmdbuff,"node.restart()\r\n");
tatsuyanah 0:c837d6abadc5 299 SendCMD();
tatsuyanah 0:c837d6abadc5 300 wait(2);
tatsuyanah 0:c837d6abadc5 301 getreply();
tatsuyanah 0:c837d6abadc5 302
tatsuyanah 0:c837d6abadc5 303 pc.printf("\n++++++++++ Starting Server ++++++++++\r\n> ");
tatsuyanah 0:c837d6abadc5 304
tatsuyanah 0:c837d6abadc5 305 // initial values
tatsuyanah 0:c837d6abadc5 306 sprintf(cmdbuff, "count,time,analog1,analog2=0,\"%s\",\"%s\",\"%s\"\r\n",timebuf,Temp,Vcc);
tatsuyanah 0:c837d6abadc5 307 SendCMD();
tatsuyanah 0:c837d6abadc5 308 getreply();
tatsuyanah 0:c837d6abadc5 309 wait(0.5);
tatsuyanah 0:c837d6abadc5 310
tatsuyanah 0:c837d6abadc5 311 //create server
tatsuyanah 0:c837d6abadc5 312 sprintf(cmdbuff, "srv=net.createServer(net.TCP,%d)\r\n",SERVtimeout);
tatsuyanah 0:c837d6abadc5 313 SendCMD();
tatsuyanah 0:c837d6abadc5 314 getreply();
tatsuyanah 0:c837d6abadc5 315 wait(0.5);
tatsuyanah 0:c837d6abadc5 316 strcpy(cmdbuff,"srv:listen(80,function(conn)\r\n");
tatsuyanah 0:c837d6abadc5 317 SendCMD();
tatsuyanah 0:c837d6abadc5 318 getreply();
tatsuyanah 0:c837d6abadc5 319 wait(0.3);
tatsuyanah 0:c837d6abadc5 320 strcpy(cmdbuff,"conn:on(\"receive\",function(conn,payload) \r\n");
tatsuyanah 0:c837d6abadc5 321 SendCMD();
tatsuyanah 0:c837d6abadc5 322 getreply();
tatsuyanah 0:c837d6abadc5 323 wait(0.3);
tatsuyanah 0:c837d6abadc5 324
tatsuyanah 0:c837d6abadc5 325 //print data to mbed
tatsuyanah 0:c837d6abadc5 326 strcpy(cmdbuff,"print(payload)\r\n");
tatsuyanah 0:c837d6abadc5 327 SendCMD();
tatsuyanah 0:c837d6abadc5 328 getreply();
tatsuyanah 0:c837d6abadc5 329 wait(0.2);
tatsuyanah 0:c837d6abadc5 330
tatsuyanah 0:c837d6abadc5 331 //web page data
tatsuyanah 0:c837d6abadc5 332 strcpy(cmdbuff,"conn:send('<!DOCTYPE html><html><meta http-equiv=\"refresh\" content=\"2\"><body><h1>Meditek Web Monitor</h1>')\r\n");
tatsuyanah 0:c837d6abadc5 333 SendCMD();
tatsuyanah 0:c837d6abadc5 334 getreply();
tatsuyanah 0:c837d6abadc5 335 wait(0.4);
tatsuyanah 0:c837d6abadc5 336 strcpy(cmdbuff,"conn:send('Hit count: '..count..'')\r\n");
tatsuyanah 0:c837d6abadc5 337 SendCMD();
tatsuyanah 0:c837d6abadc5 338 getreply();
tatsuyanah 0:c837d6abadc5 339 wait(0.2);
tatsuyanah 0:c837d6abadc5 340 strcpy(cmdbuff,"conn:send('<br>Last hit (based on mbed RTC time): '..time..'<br><hr>')\r\n");
tatsuyanah 0:c837d6abadc5 341 SendCMD();
tatsuyanah 0:c837d6abadc5 342 getreply();
tatsuyanah 0:c837d6abadc5 343 wait(0.4);
tatsuyanah 0:c837d6abadc5 344
tatsuyanah 0:c837d6abadc5 345 strcpy(cmdbuff,"conn:send('Current Temp is : '..analog1..' C<br>Current HeartRate is : '..analog2..' count/min<br><hr>')\r\n");
tatsuyanah 0:c837d6abadc5 346 SendCMD();
tatsuyanah 0:c837d6abadc5 347 getreply();
tatsuyanah 0:c837d6abadc5 348 wait(0.3);
tatsuyanah 0:c837d6abadc5 349 strcpy(cmdbuff,"conn:send('<form method=\"POST\"')\r\n");
tatsuyanah 0:c837d6abadc5 350 SendCMD();
tatsuyanah 0:c837d6abadc5 351 getreply();
tatsuyanah 0:c837d6abadc5 352 wait(0.3);
tatsuyanah 0:c837d6abadc5 353 strcpy(cmdbuff, "conn:send('<p><input type=\"checkbox\" name=\"check\" value=\"led1v\"> flip LED1')\r\n");
tatsuyanah 0:c837d6abadc5 354 SendCMD();
tatsuyanah 0:c837d6abadc5 355 getreply();
tatsuyanah 0:c837d6abadc5 356 wait(0.3);
tatsuyanah 0:c837d6abadc5 357 strcpy(cmdbuff, "conn:send('<p><input type=\"checkbox\" name=\"check\" value=\"led2v\"> flip LED2')\r\n");
tatsuyanah 0:c837d6abadc5 358 SendCMD();
tatsuyanah 0:c837d6abadc5 359 getreply();
tatsuyanah 0:c837d6abadc5 360 wait(0.3);
tatsuyanah 0:c837d6abadc5 361 strcpy(cmdbuff, "conn:send('<p><input type=\"checkbox\" name=\"check\" value=\"led3v\"> flip LED3')\r\n");
tatsuyanah 0:c837d6abadc5 362 SendCMD();
tatsuyanah 0:c837d6abadc5 363 getreply();
tatsuyanah 0:c837d6abadc5 364 wait(0.3);
tatsuyanah 0:c837d6abadc5 365 strcpy(cmdbuff, "conn:send('<p><input type=\"checkbox\" name=\"check\" value=\"led4v\"> flip LED4')\r\n");
tatsuyanah 0:c837d6abadc5 366 SendCMD();
tatsuyanah 0:c837d6abadc5 367 getreply();
tatsuyanah 0:c837d6abadc5 368 wait(0.3);
tatsuyanah 0:c837d6abadc5 369 strcpy(cmdbuff,"conn:send('<p><input type=\"submit\" value=\"send-refresh\"></form>')\r\n");
tatsuyanah 0:c837d6abadc5 370 SendCMD();
tatsuyanah 0:c837d6abadc5 371 getreply();
tatsuyanah 0:c837d6abadc5 372 wait(0.3);
tatsuyanah 0:c837d6abadc5 373 strcpy(cmdbuff, "conn:send('<p><h2>How to use:</h2><ul><li>Select a checkbox to flip on/off</li><li>Click Send-Refresh to send data and refresh values</li></ul></body></html>')\r\n");
tatsuyanah 0:c837d6abadc5 374 SendCMD();
tatsuyanah 0:c837d6abadc5 375 getreply();
tatsuyanah 0:c837d6abadc5 376 wait(0.5);
tatsuyanah 0:c837d6abadc5 377 // end web page data
tatsuyanah 0:c837d6abadc5 378 strcpy(cmdbuff, "conn:on(\"sent\",function(conn) conn:close() end)\r\n"); // close current connection
tatsuyanah 0:c837d6abadc5 379 SendCMD();
tatsuyanah 0:c837d6abadc5 380 getreply();
tatsuyanah 0:c837d6abadc5 381 wait(0.3);
tatsuyanah 0:c837d6abadc5 382 strcpy(cmdbuff, "end)\r\n");
tatsuyanah 0:c837d6abadc5 383 SendCMD();
tatsuyanah 0:c837d6abadc5 384 getreply();
tatsuyanah 0:c837d6abadc5 385 wait(0.2);
tatsuyanah 0:c837d6abadc5 386 strcpy(cmdbuff, "end)\r\n");
tatsuyanah 0:c837d6abadc5 387 SendCMD();
tatsuyanah 0:c837d6abadc5 388 getreply();
tatsuyanah 0:c837d6abadc5 389 wait(0.2);
tatsuyanah 0:c837d6abadc5 390
tatsuyanah 0:c837d6abadc5 391 strcpy(cmdbuff, "tmr.alarm(0, 1000, 1, function()\r\n");
tatsuyanah 0:c837d6abadc5 392 SendCMD();
tatsuyanah 0:c837d6abadc5 393 getreply();
tatsuyanah 0:c837d6abadc5 394 wait(0.2);
tatsuyanah 0:c837d6abadc5 395 strcpy(cmdbuff, "if wifi.sta.getip() == nil then\r\n");
tatsuyanah 0:c837d6abadc5 396 SendCMD();
tatsuyanah 0:c837d6abadc5 397 getreply();
tatsuyanah 0:c837d6abadc5 398 wait(0.2);
tatsuyanah 0:c837d6abadc5 399 strcpy(cmdbuff, "print(\"Connecting to AP...\\n\")\r\n");
tatsuyanah 0:c837d6abadc5 400 SendCMD();
tatsuyanah 0:c837d6abadc5 401 getreply();
tatsuyanah 0:c837d6abadc5 402 wait(0.2);
tatsuyanah 0:c837d6abadc5 403 strcpy(cmdbuff, "else\r\n");
tatsuyanah 0:c837d6abadc5 404 SendCMD();
tatsuyanah 0:c837d6abadc5 405 getreply();
tatsuyanah 0:c837d6abadc5 406 wait(0.2);
tatsuyanah 0:c837d6abadc5 407 strcpy(cmdbuff, "ip, nm, gw=wifi.sta.getip()\r\n");
tatsuyanah 0:c837d6abadc5 408 SendCMD();
tatsuyanah 0:c837d6abadc5 409 getreply();
tatsuyanah 0:c837d6abadc5 410 wait(0.2);
tatsuyanah 0:c837d6abadc5 411 strcpy(cmdbuff,"print(\"IP Address: \",ip)\r\n");
tatsuyanah 0:c837d6abadc5 412 SendCMD();
tatsuyanah 0:c837d6abadc5 413 getreply();
tatsuyanah 0:c837d6abadc5 414 wait(0.2);
tatsuyanah 0:c837d6abadc5 415 strcpy(cmdbuff,"tmr.stop(0)\r\n");
tatsuyanah 0:c837d6abadc5 416 SendCMD();
tatsuyanah 0:c837d6abadc5 417 getreply();
tatsuyanah 0:c837d6abadc5 418 wait(0.2);
tatsuyanah 0:c837d6abadc5 419 strcpy(cmdbuff,"end\r\n");
tatsuyanah 0:c837d6abadc5 420 SendCMD();
tatsuyanah 0:c837d6abadc5 421 getreply();
tatsuyanah 0:c837d6abadc5 422 wait(0.2);
tatsuyanah 0:c837d6abadc5 423 strcpy(cmdbuff,"end)\r\n");
tatsuyanah 0:c837d6abadc5 424 SendCMD();
tatsuyanah 0:c837d6abadc5 425 getreply();
tatsuyanah 0:c837d6abadc5 426 wait(0.2);
tatsuyanah 0:c837d6abadc5 427
tatsuyanah 0:c837d6abadc5 428 pc.printf("\n\n++++++++++ Ready ++++++++++\r\n\n");
tatsuyanah 0:c837d6abadc5 429 }
tatsuyanah 0:c837d6abadc5 430
tatsuyanah 0:c837d6abadc5 431
tatsuyanah 0:c837d6abadc5 432 // ESP Command data send
tatsuyanah 0:c837d6abadc5 433 void SendCMD()
tatsuyanah 0:c837d6abadc5 434 {
tatsuyanah 0:c837d6abadc5 435 int i;
tatsuyanah 0:c837d6abadc5 436 char temp_char;
tatsuyanah 0:c837d6abadc5 437 bool empty;
tatsuyanah 0:c837d6abadc5 438 i = 0;
tatsuyanah 0:c837d6abadc5 439 // Start Critical Section - don't interrupt while changing global buffer variables
tatsuyanah 0:c837d6abadc5 440 NVIC_DisableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 441 empty = (tx_in == tx_out);
tatsuyanah 0:c837d6abadc5 442 while ((i==0) || (cmdbuff[i-1] != '\n')) {
tatsuyanah 0:c837d6abadc5 443 // Wait if buffer full
tatsuyanah 0:c837d6abadc5 444 if (((tx_in + 1) % buffer_size) == tx_out) {
tatsuyanah 0:c837d6abadc5 445 // End Critical Section - need to let interrupt routine empty buffer by sending
tatsuyanah 0:c837d6abadc5 446 NVIC_EnableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 447 while (((tx_in + 1) % buffer_size) == tx_out) {
tatsuyanah 0:c837d6abadc5 448 }
tatsuyanah 0:c837d6abadc5 449 // Start Critical Section - don't interrupt while changing global buffer variables
tatsuyanah 0:c837d6abadc5 450 NVIC_DisableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 451 }
tatsuyanah 0:c837d6abadc5 452 tx_buffer[tx_in] = cmdbuff[i];
tatsuyanah 0:c837d6abadc5 453 i++;
tatsuyanah 0:c837d6abadc5 454 tx_in = (tx_in + 1) % buffer_size;
tatsuyanah 0:c837d6abadc5 455 }
tatsuyanah 0:c837d6abadc5 456 if (esp.writeable() && (empty)) {
tatsuyanah 0:c837d6abadc5 457 temp_char = tx_buffer[tx_out];
tatsuyanah 0:c837d6abadc5 458 tx_out = (tx_out + 1) % buffer_size;
tatsuyanah 0:c837d6abadc5 459 // Send first character to start tx interrupts, if stopped
tatsuyanah 0:c837d6abadc5 460 esp.putc(temp_char);
tatsuyanah 0:c837d6abadc5 461 }
tatsuyanah 0:c837d6abadc5 462 // End Critical Section
tatsuyanah 0:c837d6abadc5 463 NVIC_EnableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 464 return;
tatsuyanah 0:c837d6abadc5 465 }
tatsuyanah 0:c837d6abadc5 466
tatsuyanah 0:c837d6abadc5 467 // Get Command and ESP status replies
tatsuyanah 0:c837d6abadc5 468 void getreply()
tatsuyanah 0:c837d6abadc5 469 {
tatsuyanah 0:c837d6abadc5 470 read_line();
tatsuyanah 0:c837d6abadc5 471 sscanf(rx_line,replybuff);
tatsuyanah 0:c837d6abadc5 472 }
tatsuyanah 0:c837d6abadc5 473
tatsuyanah 0:c837d6abadc5 474 // Read a line from the large rx buffer from rx interrupt routine
tatsuyanah 0:c837d6abadc5 475 void read_line() {
tatsuyanah 0:c837d6abadc5 476 int i;
tatsuyanah 0:c837d6abadc5 477 i = 0;
tatsuyanah 0:c837d6abadc5 478 // Start Critical Section - don't interrupt while changing global buffer variables
tatsuyanah 0:c837d6abadc5 479 NVIC_DisableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 480 // Loop reading rx buffer characters until end of line character
tatsuyanah 0:c837d6abadc5 481 while ((i==0) || (rx_line[i-1] != '\r')) {
tatsuyanah 0:c837d6abadc5 482 // Wait if buffer empty
tatsuyanah 0:c837d6abadc5 483 if (rx_in == rx_out) {
tatsuyanah 0:c837d6abadc5 484 // End Critical Section - need to allow rx interrupt to get new characters for buffer
tatsuyanah 0:c837d6abadc5 485 NVIC_EnableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 486 while (rx_in == rx_out) {
tatsuyanah 0:c837d6abadc5 487 }
tatsuyanah 0:c837d6abadc5 488 // Start Critical Section - don't interrupt while changing global buffer variables
tatsuyanah 0:c837d6abadc5 489 NVIC_DisableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 490 }
tatsuyanah 0:c837d6abadc5 491 rx_line[i] = rx_buffer[rx_out];
tatsuyanah 0:c837d6abadc5 492 i++;
tatsuyanah 0:c837d6abadc5 493 rx_out = (rx_out + 1) % buffer_size;
tatsuyanah 0:c837d6abadc5 494 }
tatsuyanah 0:c837d6abadc5 495 // End Critical Section
tatsuyanah 0:c837d6abadc5 496 NVIC_EnableIRQ(UART1_IRQn);
tatsuyanah 0:c837d6abadc5 497 rx_line[i-1] = 0;
tatsuyanah 0:c837d6abadc5 498 return;
tatsuyanah 0:c837d6abadc5 499 }
tatsuyanah 0:c837d6abadc5 500
tatsuyanah 0:c837d6abadc5 501
tatsuyanah 0:c837d6abadc5 502 // Interupt Routine to read in data from serial port
tatsuyanah 0:c837d6abadc5 503 void Rx_interrupt() {
tatsuyanah 0:c837d6abadc5 504 DataRX=1;
tatsuyanah 0:c837d6abadc5 505 //led3=1;
tatsuyanah 0:c837d6abadc5 506 // Loop just in case more than one character is in UART's receive FIFO buffer
tatsuyanah 0:c837d6abadc5 507 // Stop if buffer full
tatsuyanah 0:c837d6abadc5 508 while ((esp.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) {
tatsuyanah 0:c837d6abadc5 509 rx_buffer[rx_in] = esp.getc();
tatsuyanah 0:c837d6abadc5 510 // Uncomment to Echo to USB serial to watch data flow
tatsuyanah 0:c837d6abadc5 511 pc.putc(rx_buffer[rx_in]);
tatsuyanah 0:c837d6abadc5 512 rx_in = (rx_in + 1) % buffer_size;
tatsuyanah 0:c837d6abadc5 513 }
tatsuyanah 0:c837d6abadc5 514 //led3=0;
tatsuyanah 0:c837d6abadc5 515 return;
tatsuyanah 0:c837d6abadc5 516 }
tatsuyanah 0:c837d6abadc5 517
tatsuyanah 0:c837d6abadc5 518
tatsuyanah 0:c837d6abadc5 519 // Interupt Routine to write out data to serial port
tatsuyanah 0:c837d6abadc5 520 void Tx_interrupt() {
tatsuyanah 0:c837d6abadc5 521 //led2=1;
tatsuyanah 0:c837d6abadc5 522 // Loop to fill more than one character in UART's transmit FIFO buffer
tatsuyanah 0:c837d6abadc5 523 // Stop if buffer empty
tatsuyanah 0:c837d6abadc5 524 while ((esp.writeable()) && (tx_in != tx_out)) {
tatsuyanah 0:c837d6abadc5 525 esp.putc(tx_buffer[tx_out]);
tatsuyanah 0:c837d6abadc5 526 tx_out = (tx_out + 1) % buffer_size;
tatsuyanah 0:c837d6abadc5 527 }
tatsuyanah 0:c837d6abadc5 528 //led2=0;
tatsuyanah 0:c837d6abadc5 529 return;
tatsuyanah 0:c837d6abadc5 530 }
tatsuyanah 0:c837d6abadc5 531
tatsuyanah 0:c837d6abadc5 532 void gettime()
tatsuyanah 0:c837d6abadc5 533 {
tatsuyanah 0:c837d6abadc5 534 time_t seconds = time(NULL);
tatsuyanah 0:c837d6abadc5 535 strftime(timebuf,50,"%H:%M:%S %a %d %b %y", localtime(&seconds));
tatsuyanah 0:c837d6abadc5 536 }
tatsuyanah 0:c837d6abadc5 537
tatsuyanah 0:c837d6abadc5 538 void setRTC()
tatsuyanah 0:c837d6abadc5 539 {
tatsuyanah 0:c837d6abadc5 540 t.tm_sec = (0); // 0-59
tatsuyanah 0:c837d6abadc5 541 t.tm_min = (minute); // 0-59
tatsuyanah 0:c837d6abadc5 542 t.tm_hour = (hour); // 0-23
tatsuyanah 0:c837d6abadc5 543 t.tm_mday = (dayofmonth); // 1-31
tatsuyanah 0:c837d6abadc5 544 t.tm_mon = (month-1); // 0-11 "0" = Jan, -1 added for Mbed RCT clock format
tatsuyanah 0:c837d6abadc5 545 t.tm_year = ((year)+100); // year since 1900, current DCF year + 100 + 1900 = correct year
tatsuyanah 0:c837d6abadc5 546 set_time(mktime(&t)); // set RTC clock
tatsuyanah 0:c837d6abadc5 547 }
tatsuyanah 0:c837d6abadc5 548 // Analog in example
tatsuyanah 0:c837d6abadc5 549 void getbattery()
tatsuyanah 0:c837d6abadc5 550 {
tatsuyanah 0:c837d6abadc5 551 AdcIn=Ain1.read();
tatsuyanah 0:c837d6abadc5 552 Ht = (AdcIn*3.3); // set the numeric to the exact MCU analog reference voltage for greater accuracy
tatsuyanah 0:c837d6abadc5 553 // sprintf(Vcc,"%2.3f",Ht);
tatsuyanah 0:c837d6abadc5 554
tatsuyanah 0:c837d6abadc5 555 //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second
tatsuyanah 0:c837d6abadc5 556
tatsuyanah 0:c837d6abadc5 557 //timer1second.start();
tatsuyanah 0:c837d6abadc5 558 //timer20ms.start();
tatsuyanah 0:c837d6abadc5 559
tatsuyanah 0:c837d6abadc5 560
tatsuyanah 0:c837d6abadc5 561
tatsuyanah 0:c837d6abadc5 562 }
tatsuyanah 0:c837d6abadc5 563 // Temperature example
tatsuyanah 0:c837d6abadc5 564 void gettemp()
tatsuyanah 0:c837d6abadc5 565 {
tatsuyanah 0:c837d6abadc5 566
tatsuyanah 0:c837d6abadc5 567 //float f_temp;
tatsuyanah 0:c837d6abadc5 568 float temp_C , temp_F, average[10], averageTemp;
tatsuyanah 0:c837d6abadc5 569 int index;
tatsuyanah 0:c837d6abadc5 570 AdcIn=Ain2.read();
tatsuyanah 0:c837d6abadc5 571 //Ht = (AdcIn*3.3); // set the numeric to the exact MCU analog reference voltage for greater accuracy
tatsuyanah 0:c837d6abadc5 572
tatsuyanah 0:c837d6abadc5 573
tatsuyanah 0:c837d6abadc5 574 averageTemp=0;
tatsuyanah 0:c837d6abadc5 575 for(index=0; index<10; index++)
tatsuyanah 0:c837d6abadc5 576 {
tatsuyanah 0:c837d6abadc5 577 average[index]=LM35.read();
tatsuyanah 0:c837d6abadc5 578 //wait(0.02);
tatsuyanah 0:c837d6abadc5 579 }
tatsuyanah 0:c837d6abadc5 580 for(index=0; index<10; index++)
tatsuyanah 0:c837d6abadc5 581 {
tatsuyanah 0:c837d6abadc5 582 averageTemp = (averageTemp +(average[index]/10));
tatsuyanah 0:c837d6abadc5 583 }
tatsuyanah 0:c837d6abadc5 584 temp_C=(averageTemp*3.685*100);
tatsuyanah 0:c837d6abadc5 585 temp_F=(((9.0*temp_C)/5.0) + 32.0);
tatsuyanah 0:c837d6abadc5 586 sprintf(Temp,"%2.3f",temp_C);
tatsuyanah 0:c837d6abadc5 587
tatsuyanah 0:c837d6abadc5 588 pc.printf("Temperature is %.2f C, %.2f F \n\r ", temp_C,temp_F);
tatsuyanah 0:c837d6abadc5 589
tatsuyanah 0:c837d6abadc5 590 }