A code to drive a 3sensor reading unit for monitoring the operation opf a closed circuit rebreather (CCR) with 3 electrogalvanic sensors. Also uses a DS1307 for realtime clock and an MPX5700 to read the depth (mounted inside the breathing loop to keep it 'dry'). circuit diagrams available on rebreather world.

Dependencies:   DS1307 TextOLED mbed

Committer:
pegcjs
Date:
Tue Aug 07 16:25:18 2012 +0000
Revision:
6:ab2d7d0a9b07
Parent:
5:35417986539a
Child:
7:f93b7eaab5f6
finalised version - ready to build permanent hardware

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pegcjs 1:9cff4feccbce 1 //lpc1124lcddemo
pegcjs 1:9cff4feccbce 2 #include "ds1307.h"
pegcjs 1:9cff4feccbce 3 #include "mbed.h"
pegcjs 5:35417986539a 4 #include "TextOLED.h"
pegcjs 1:9cff4feccbce 5
pegcjs 1:9cff4feccbce 6
pegcjs 1:9cff4feccbce 7 #define METRE 0.02 // change in DEPin for 1m depth
pegcjs 1:9cff4feccbce 8
pegcjs 1:9cff4feccbce 9 //pin assignments and declarations
pegcjs 1:9cff4feccbce 10 // LCD display
pegcjs 1:9cff4feccbce 11 TextLCD g_lcd(p26, p25, p24, p23, p22, p21); // RS, E, DB4, DB5, DB6, DB7
pegcjs 1:9cff4feccbce 12 //backlight
pegcjs 1:9cff4feccbce 13 DigitalOut backlight(p29);
pegcjs 1:9cff4feccbce 14
pegcjs 1:9cff4feccbce 15 //onboard leds
pegcjs 1:9cff4feccbce 16 DigitalOut led1(LED1);
pegcjs 1:9cff4feccbce 17 DigitalOut led2(LED2);
pegcjs 1:9cff4feccbce 18
pegcjs 1:9cff4feccbce 19 // warning leds
pegcjs 1:9cff4feccbce 20 DigitalOut red(p34);
pegcjs 1:9cff4feccbce 21 DigitalOut green(p33);
pegcjs 1:9cff4feccbce 22 DigitalOut blue(p30);
pegcjs 1:9cff4feccbce 23
pegcjs 6:ab2d7d0a9b07 24
pegcjs 1:9cff4feccbce 25 // switches and buttons - these are pulled up by resistors so are active low
pegcjs 1:9cff4feccbce 26 DigitalIn CAL(p36);
pegcjs 5:35417986539a 27 DigitalIn SW1(p35); // reed switch in display unit
pegcjs 5:35417986539a 28 DigitalIn SW2(p10); // reed switch in dispaly unit
pegcjs 5:35417986539a 29 DigitalIn MODE(p11);// a switchn on the mbed pcb to select between SCR and CCR modes for the LEDs
pegcjs 1:9cff4feccbce 30
pegcjs 1:9cff4feccbce 31 // log data storage
pegcjs 1:9cff4feccbce 32 LocalFileSystem local("local");
pegcjs 1:9cff4feccbce 33
pegcjs 1:9cff4feccbce 34 // adc inputs for sensors
pegcjs 1:9cff4feccbce 35 AnalogIn PRESin(p20);
pegcjs 1:9cff4feccbce 36 AnalogIn EG1(p19);
pegcjs 1:9cff4feccbce 37 AnalogIn EG2(p18);
pegcjs 1:9cff4feccbce 38 AnalogIn Vbatt(p17);
pegcjs 1:9cff4feccbce 39
pegcjs 1:9cff4feccbce 40 // realtime clock
pegcjs 1:9cff4feccbce 41 DS1307 my1307(p28,p27); // start DS1307 class and give it pins for connections of the DS1307 device
pegcjs 1:9cff4feccbce 42
pegcjs 1:9cff4feccbce 43 // variables for realtime clock
pegcjs 1:9cff4feccbce 44 int sec = 0;
pegcjs 1:9cff4feccbce 45 int min = 0;
pegcjs 1:9cff4feccbce 46 int hours = 0;
pegcjs 1:9cff4feccbce 47 int day = 0;
pegcjs 1:9cff4feccbce 48 int date = 0;
pegcjs 1:9cff4feccbce 49 int month = 0;
pegcjs 1:9cff4feccbce 50 int year = 0;
pegcjs 4:74df6d31ee0a 51 int seconds=0; // general number of seconds since 2000 etc timestamp variable
pegcjs 1:9cff4feccbce 52
pegcjs 6:ab2d7d0a9b07 53 int scrubtime=0,scrubold=0;; // these are expressed in minutes
pegcjs 1:9cff4feccbce 54 int divetime=0;
pegcjs 1:9cff4feccbce 55
pegcjs 3:0d94a277aa8c 56 int flash=0; // variable used top control flashing icons
pegcjs 2:a1c26faa9103 57 int state=0; // IMPORTANT - VARIABLE THAT DRIVES HNTE STATE MACHINE STATE=0 = STARTUP, STATE=1=SURFACE STATE=2= DIVING
pegcjs 2:a1c26faa9103 58
pegcjs 1:9cff4feccbce 59 // variables for the eg cells and pressure sensor eg1calamd eg2cal ar reading when the sensor is in 0.21bar O2 and
pegcjs 1:9cff4feccbce 60 //dcal is the reading whe the pressure sensor is at the surface
pegcjs 1:9cff4feccbce 61 float eg1cal=0.09,eg2cal=0.09,pcal=0.1136;
pegcjs 1:9cff4feccbce 62 // NB these are updated from /local/cal.dat so values not so important.... eventually
pegcjs 1:9cff4feccbce 63
pegcjs 1:9cff4feccbce 64 float depth=0,ppo1=0,ppo2=0, Vb=0,pressure=0; // depth, 1st o2 sensor second o2 sensor battery voltage,,Pressure
pegcjs 1:9cff4feccbce 65 float fo1=0,fo2=0,mod=55; //%f values,mod
pegcjs 3:0d94a277aa8c 66
pegcjs 6:ab2d7d0a9b07 67 FILE *lp; // file pointer for log file
pegcjs 6:ab2d7d0a9b07 68
pegcjs 1:9cff4feccbce 69 //===== sub to get time from ds1307 and create the 'seconds' which is a version of timestamp....
pegcjs 1:9cff4feccbce 70 int getseconds() {
pegcjs 1:9cff4feccbce 71 my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year);
pegcjs 1:9cff4feccbce 72 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days.
pegcjs 4:74df6d31ee0a 73 int secondst=year*365*24*60*60+month*30*24*60*60+day*24*60*60+hours*60*60+min*60+sec;
pegcjs 1:9cff4feccbce 74 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days....
pegcjs 1:9cff4feccbce 75 // ie wrong but simpler than the real thing
pegcjs 4:74df6d31ee0a 76 return(secondst);
pegcjs 1:9cff4feccbce 77 }
pegcjs 1:9cff4feccbce 78
pegcjs 1:9cff4feccbce 79
pegcjs 1:9cff4feccbce 80 void set_custom_char() {
pegcjs 1:9cff4feccbce 81 char cgchar[64]={
pegcjs 1:9cff4feccbce 82 6,9,9,9,9,9,9,15, // battery empty symbol 0
pegcjs 1:9cff4feccbce 83 6,9,9,9,9,15,15,15, // battery 50% symbol 1
pegcjs 1:9cff4feccbce 84 6,9,9,15,15,15,15,15, // battery 75% symbol 2
pegcjs 1:9cff4feccbce 85 6,15,15,15,15,15,15,15, // battery 100% symbol 3
pegcjs 1:9cff4feccbce 86 31,19,21,21,21,21,19,31, // diving symbol 4 inverse D
pegcjs 1:9cff4feccbce 87 6,6,6,6,6,0,0,6, // warning symbol 5
pegcjs 1:9cff4feccbce 88 31,17,23,17,29,17,31,0, // surface symbol 6 inverse S
pegcjs 5:35417986539a 89 2,6,2,2,2,2,23 // defined to handle dec point in depth 7
pegcjs 1:9cff4feccbce 90 };
pegcjs 1:9cff4feccbce 91 int i=0;
pegcjs 1:9cff4feccbce 92 // do stuff here to set cstom chars
pegcjs 1:9cff4feccbce 93 g_lcd.writeCommand(0x40); // set start address for CGRAM
pegcjs 1:9cff4feccbce 94 for (i=0; i<64; i++) {
pegcjs 1:9cff4feccbce 95 g_lcd.writeData(cgchar[i]);
pegcjs 1:9cff4feccbce 96 }
pegcjs 1:9cff4feccbce 97
pegcjs 1:9cff4feccbce 98 }
pegcjs 1:9cff4feccbce 99
pegcjs 6:ab2d7d0a9b07 100 // stash cal values on local drive
pegcjs 6:ab2d7d0a9b07 101 void store() {
pegcjs 6:ab2d7d0a9b07 102 FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 6:ab2d7d0a9b07 103 fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime);
pegcjs 6:ab2d7d0a9b07 104 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 6:ab2d7d0a9b07 105 }
pegcjs 6:ab2d7d0a9b07 106
pegcjs 1:9cff4feccbce 107
pegcjs 1:9cff4feccbce 108 // subroutine to calibreate o2 sesnors and store ca data in /local/CAL.dat
pegcjs 1:9cff4feccbce 109 void calibrate() {
pegcjs 1:9cff4feccbce 110 int count=1;
pegcjs 1:9cff4feccbce 111 float ppo1=0,ppo2=0,pres=0;
pegcjs 1:9cff4feccbce 112 // average 20 readings for noise reduction
pegcjs 1:9cff4feccbce 113 g_lcd.cls();
pegcjs 1:9cff4feccbce 114 for (count=20; count>0; count--) {
pegcjs 1:9cff4feccbce 115 g_lcd.locate(0,0);
pegcjs 4:74df6d31ee0a 116 g_lcd.printf("Calibrate 21%% %.2d",count);
pegcjs 1:9cff4feccbce 117 ppo1=ppo1+EG1;
pegcjs 1:9cff4feccbce 118 ppo2=ppo2+EG2;
pegcjs 1:9cff4feccbce 119 pres=pres+PRESin;
pegcjs 1:9cff4feccbce 120 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 121 g_lcd.printf("%1.2f: %1.2f: %1.2f",ppo1/(20-count+1),ppo2/(20-count+1),pres/(20-count+1));
pegcjs 1:9cff4feccbce 122 wait(1);
pegcjs 1:9cff4feccbce 123 }
pegcjs 1:9cff4feccbce 124 //average
pegcjs 1:9cff4feccbce 125 ppo1=ppo1/20;
pegcjs 1:9cff4feccbce 126 ppo2=ppo2/20;
pegcjs 1:9cff4feccbce 127 // set calibration variables
pegcjs 1:9cff4feccbce 128 eg1cal=ppo1;
pegcjs 1:9cff4feccbce 129 eg2cal=ppo2;
pegcjs 1:9cff4feccbce 130 pcal=pres/20; // surface pressure....
pegcjs 1:9cff4feccbce 131 scrubtime=0; // reset the scrubber timer to zero.
pegcjs 2:a1c26faa9103 132 // write cal data NB overwites previous
pegcjs 6:ab2d7d0a9b07 133 /* FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 6:ab2d7d0a9b07 134 fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime);
pegcjs 6:ab2d7d0a9b07 135 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...*/
pegcjs 6:ab2d7d0a9b07 136 store();
pegcjs 1:9cff4feccbce 137 }
pegcjs 1:9cff4feccbce 138
pegcjs 4:74df6d31ee0a 139 // sub to test if a variable is an even number
pegcjs 4:74df6d31ee0a 140 int iseven(int g) {
pegcjs 4:74df6d31ee0a 141 int test=0;
pegcjs 5:35417986539a 142 if (g%2 ==0) test=1;
pegcjs 4:74df6d31ee0a 143 return(test);
pegcjs 4:74df6d31ee0a 144 }
pegcjs 4:74df6d31ee0a 145
pegcjs 1:9cff4feccbce 146
pegcjs 2:a1c26faa9103 147 void status() {
pegcjs 3:0d94a277aa8c 148 if (state==0) {
pegcjs 3:0d94a277aa8c 149 g_lcd.character(9,0,5); // warning icon until 1 min up
pegcjs 3:0d94a277aa8c 150 g_lcd.character(8,0,6); // surface icon
pegcjs 5:35417986539a 151 } else {
pegcjs 5:35417986539a 152 g_lcd.character(9,0,32);
pegcjs 3:0d94a277aa8c 153 }
pegcjs 2:a1c26faa9103 154 if (state==1) g_lcd.character(8,0,6); // surface icon
pegcjs 4:74df6d31ee0a 155 if (state==2 && iseven(seconds)==1) g_lcd.character(8,0,4); // diving icon
pegcjs 4:74df6d31ee0a 156 if (state==2 && iseven(seconds)==0) g_lcd.character(8,0,68); // diving icon
pegcjs 4:74df6d31ee0a 157
pegcjs 4:74df6d31ee0a 158 }
pegcjs 3:0d94a277aa8c 159
pegcjs 3:0d94a277aa8c 160 // warning and LED conditions
pegcjs 2:a1c26faa9103 161
pegcjs 2:a1c26faa9103 162 void warning() {
pegcjs 3:0d94a277aa8c 163 if (depth>=mod && flash==1) g_lcd.character(13,0,5);
pegcjs 6:ab2d7d0a9b07 164 else g_lcd.character(13,0,32); // blank sapce
pegcjs 2:a1c26faa9103 165
pegcjs 2:a1c26faa9103 166 }
pegcjs 2:a1c26faa9103 167
pegcjs 4:74df6d31ee0a 168 // pick maximum of two values
pegcjs 4:74df6d31ee0a 169 float maximum(float a,float b) {
pegcjs 4:74df6d31ee0a 170 float maximum;
pegcjs 4:74df6d31ee0a 171 if (a>b) maximum=a;
pegcjs 4:74df6d31ee0a 172 else maximum=b;
pegcjs 4:74df6d31ee0a 173 return(maximum);
pegcjs 4:74df6d31ee0a 174 }
pegcjs 4:74df6d31ee0a 175
pegcjs 4:74df6d31ee0a 176 // pick minimum of two values
pegcjs 4:74df6d31ee0a 177 float minimum(float a,float b) {
pegcjs 4:74df6d31ee0a 178 float minim;
pegcjs 4:74df6d31ee0a 179 if (a<b) minim=a;
pegcjs 4:74df6d31ee0a 180 else minim=b;
pegcjs 4:74df6d31ee0a 181 return(minim);
pegcjs 4:74df6d31ee0a 182 }
pegcjs 4:74df6d31ee0a 183
pegcjs 4:74df6d31ee0a 184
pegcjs 4:74df6d31ee0a 185
pegcjs 2:a1c26faa9103 186 void leds() {
pegcjs 4:74df6d31ee0a 187 // first turn everything off
pegcjs 5:35417986539a 188 red=0;
pegcjs 5:35417986539a 189 green=0;
pegcjs 5:35417986539a 190 blue=0;
pegcjs 5:35417986539a 191 float ppo;
pegcjs 5:35417986539a 192 int mo=0;
pegcjs 5:35417986539a 193 mo=MODE;
pegcjs 5:35417986539a 194 ppo=maximum(ppo1,ppo2); // use max value to compute leds...
pegcjs 5:35417986539a 195 if (mo==0) { // CCR mode
pegcjs 5:35417986539a 196 if (ppo<0.2 && flash==1) red=1; // flashing red means very bad things - getting low on oxygen!!!
pegcjs 5:35417986539a 197 if (ppo>0.2 && ppo < 1) red=1; // non-flashing red
pegcjs 5:35417986539a 198 if (ppo>=1.0 && ppo <1.2) {
pegcjs 5:35417986539a 199 red=1; // red-green
pegcjs 5:35417986539a 200 green=1;
pegcjs 5:35417986539a 201 }
pegcjs 5:35417986539a 202 if (ppo<1.3 && ppo >=1.2) green=1; // green - optimal range in ccr mode
pegcjs 5:35417986539a 203 if (ppo<1.4 && ppo >=1.3) {
pegcjs 5:35417986539a 204 green=1; // green-blue - high ppo2 be careful of spiking
pegcjs 5:35417986539a 205 blue=1;
pegcjs 5:35417986539a 206 }
pegcjs 5:35417986539a 207 if (ppo2<1.6 && ppo2>=1.4) blue=1; // DANGE ble high ppo2
pegcjs 5:35417986539a 208 if (ppo2>=1.6 && flash==1) blue=1;
pegcjs 5:35417986539a 209 }
pegcjs 5:35417986539a 210 if (mo==1) { // SCR mode
pegcjs 5:35417986539a 211 if (ppo<0.2 && flash==1) red=1;
pegcjs 6:ab2d7d0a9b07 212 if(ppo2>=0.2 && ppo2 <0.26) red=1; // will give green red for low but not lethal ppo2s
pegcjs 5:35417986539a 213 if (depth < 0.8*mod && ppo>0.2) green=1;
pegcjs 5:35417986539a 214 if (depth< mod && depth >=0.8*mod) {
pegcjs 5:35417986539a 215 green=1;
pegcjs 5:35417986539a 216 blue=1;
pegcjs 5:35417986539a 217 }
pegcjs 5:35417986539a 218 if (depth >=mod && flash==1) blue=1;
pegcjs 5:35417986539a 219 }
pegcjs 6:ab2d7d0a9b07 220
pegcjs 1:9cff4feccbce 221 }
pegcjs 1:9cff4feccbce 222
pegcjs 4:74df6d31ee0a 223
pegcjs 4:74df6d31ee0a 224
pegcjs 1:9cff4feccbce 225 //read battery state and insert the battery symbol
pegcjs 1:9cff4feccbce 226 void battery() {
pegcjs 1:9cff4feccbce 227 int batsym=0;
pegcjs 1:9cff4feccbce 228 Vb=Vbatt; // read adc connected to battery via a 1/3 potential divider
pegcjs 1:9cff4feccbce 229 if (Vb>0.606) batsym=1;
pegcjs 1:9cff4feccbce 230 if (Vb>0.707) batsym=2;
pegcjs 1:9cff4feccbce 231 if (Vb>0.808) batsym=3;
pegcjs 3:0d94a277aa8c 232 if (batsym >0) g_lcd.character(8,1,batsym);
pegcjs 3:0d94a277aa8c 233 if (batsym ==0 && flash==1) g_lcd.character(8,1,batsym);
pegcjs 3:0d94a277aa8c 234 if (batsym ==0 && flash==0) g_lcd.character(8,1,32);
pegcjs 1:9cff4feccbce 235 }
pegcjs 1:9cff4feccbce 236
pegcjs 2:a1c26faa9103 237 // subroutine to write the main display data
pegcjs 2:a1c26faa9103 238 //0123456789abcdef
pegcjs 2:a1c26faa9103 239
pegcjs 2:a1c26faa9103 240 //x.xx:xx D XX xx
pegcjs 2:a1c26faa9103 241 //x.xx:xx B XX xxx NB the warning, staus and battery icons are driven by separate subroutines.
pegcjs 2:a1c26faa9103 242 void display() {
pegcjs 5:35417986539a 243 int mo=0;
pegcjs 5:35417986539a 244 mo=MODE;
pegcjs 2:a1c26faa9103 245 //1st line
pegcjs 2:a1c26faa9103 246 g_lcd.locate(0,0);
pegcjs 5:35417986539a 247 g_lcd.printf("%1.2f:%.2d",ppo1,(int)fo1);
pegcjs 5:35417986539a 248 g_lcd.locate(10,0);
pegcjs 6:ab2d7d0a9b07 249 g_lcd.printf("%.2d",(int)depth);
pegcjs 6:ab2d7d0a9b07 250 g_lcd.locate(14,0);
pegcjs 6:ab2d7d0a9b07 251 g_lcd.printf("%.2d",(int)mod);
pegcjs 2:a1c26faa9103 252 //2nd line
pegcjs 2:a1c26faa9103 253 g_lcd.locate(0,1);
pegcjs 5:35417986539a 254 g_lcd.printf("%1.2f:%.2d",ppo2,(int)fo2);
pegcjs 5:35417986539a 255 g_lcd.locate(10,1);
pegcjs 5:35417986539a 256 g_lcd.printf("%.2d %.3d",divetime % 100 ,scrubtime % 1000); // modulo to avoid digits conflict - means divetime is always less than 100
pegcjs 2:a1c26faa9103 257 // bung in battery icon
pegcjs 2:a1c26faa9103 258 battery();
pegcjs 5:35417986539a 259 status(); // this will set the diving / suface mode icon
pegcjs 2:a1c26faa9103 260 warning(); // this will set the warning icon assuming that max ppo2 is exceeded
pegcjs 2:a1c26faa9103 261
pegcjs 2:a1c26faa9103 262 leds(); // this sets the leds according to the various warning conditions
pegcjs 5:35417986539a 263 if (mo==0) {
pegcjs 5:35417986539a 264 g_lcd.character(7,1,99); //'c' = ccr
pegcjs 5:35417986539a 265 } else {
pegcjs 5:35417986539a 266 g_lcd.character(7,1,115); //'s' = scr
pegcjs 5:35417986539a 267 }
pegcjs 5:35417986539a 268 // custom character setting to sort out dp in depths
pegcjs 6:ab2d7d0a9b07 269
pegcjs 6:ab2d7d0a9b07 270
pegcjs 5:35417986539a 271 char cgchar[80]={
pegcjs 5:35417986539a 272 7,5,5,5,23,0,0,0, // .0
pegcjs 5:35417986539a 273 2,2,2,2,18,0,0,0, // .1
pegcjs 5:35417986539a 274 7,1,7,4,23,0,0,0, // 0.2
pegcjs 5:35417986539a 275 7,1,3,1,23,0,0,0, // 0.3
pegcjs 5:35417986539a 276 5,5,7,1,17,0,0,0, //0.4
pegcjs 5:35417986539a 277 7,4,7,1,23,0,0,0, //0.5
pegcjs 5:35417986539a 278 7,4,7,5,23,0,0,0, //0.6
pegcjs 5:35417986539a 279 7,1,2,2,18,0,0,0, //.7
pegcjs 5:35417986539a 280 7,5,7,5,23,0,0,0, //.8
pegcjs 5:35417986539a 281 7,5,7,1,17,0,0,0 //.9
pegcjs 5:35417986539a 282
pegcjs 5:35417986539a 283 };
pegcjs 5:35417986539a 284
pegcjs 5:35417986539a 285 int i=0,d=0;
pegcjs 5:35417986539a 286 d=(int)((depth-(int)depth)*10); // should be size of the 1st decimal place
pegcjs 5:35417986539a 287 // do stuff here to set cstom chars
pegcjs 5:35417986539a 288 g_lcd.writeCommand(120); // set start address for CGRAM
pegcjs 5:35417986539a 289 for (i=0; i<8; i++) {
pegcjs 5:35417986539a 290 g_lcd.writeData(cgchar[i+d*8]);
pegcjs 5:35417986539a 291 }
pegcjs 5:35417986539a 292
pegcjs 5:35417986539a 293 g_lcd.character(12,0,7); // put in appropriate custom character
pegcjs 2:a1c26faa9103 294
pegcjs 2:a1c26faa9103 295 }
pegcjs 2:a1c26faa9103 296
pegcjs 2:a1c26faa9103 297
pegcjs 2:a1c26faa9103 298
pegcjs 1:9cff4feccbce 299
pegcjs 2:a1c26faa9103 300
pegcjs 2:a1c26faa9103 301 // read sensors and generate calibrated outputs NB battery is read elsewhere
pegcjs 1:9cff4feccbce 302 void readsensors() {
pegcjs 1:9cff4feccbce 303 float barometric=0,mod1,mod2;
pegcjs 1:9cff4feccbce 304 ppo1=EG1*0.21/eg1cal; // eg1cal is 0.21bar ppO2
pegcjs 1:9cff4feccbce 305 ppo2=EG2*0.21/eg2cal; // second oxygen cell ppO2
pegcjs 5:35417986539a 306 // NB this assumes that the calibration is done at exactly 1 bar.... - not always the case but ok for sea level diving
pegcjs 2:a1c26faa9103 307 pressure=(PRESin*3.3-0.024)/(0.0038574); // pressure in kPa assuming standard cal for mpx5700 sensor SUSPECT
pegcjs 5:35417986539a 308 barometric=(pcal*3.3-0.024)/(0.0038574); // sealevel in kPa assuming standard cal for mpx5700 sensor
pegcjs 6:ab2d7d0a9b07 309
pegcjs 5:35417986539a 310 depth=(pressure-barometric)*0.1; //100kPa=10m 1kPa=0.1m - this gives depth in m for freshwater.
pegcjs 6:ab2d7d0a9b07 311 if (depth<0) depth=0;
pegcjs 2:a1c26faa9103 312
pegcjs 5:35417986539a 313 fo1=100*ppo1/((pressure-barometric)/100+1); // pressure in bar = pressure /100 and want a % so multiply by 100 as well
pegcjs 5:35417986539a 314 fo2=100*ppo2/((pressure-barometric)/100+1);
pegcjs 6:ab2d7d0a9b07 315
pegcjs 6:ab2d7d0a9b07 316 if (fo1<0) fo2=0;
pegcjs 6:ab2d7d0a9b07 317 if (fo2<0) fo1=0;
pegcjs 3:0d94a277aa8c 318
pegcjs 5:35417986539a 319 //with two sensors will calculate mod from the largest ppo2 reading
pegcjs 2:a1c26faa9103 320 mod1=(1.4/(fo1/100)-1)*10;
pegcjs 2:a1c26faa9103 321 mod2=(1.4/(fo2/100)-1)*10;
pegcjs 3:0d94a277aa8c 322
pegcjs 2:a1c26faa9103 323 mod=minimum(mod1,mod2); // pick the least value
pegcjs 3:0d94a277aa8c 324
pegcjs 1:9cff4feccbce 325 }
pegcjs 6:ab2d7d0a9b07 326 // get values back from cal file on local drive
pegcjs 6:ab2d7d0a9b07 327 void recall() {
pegcjs 6:ab2d7d0a9b07 328 FILE *fp=fopen("/local/CAL.dat","r");
pegcjs 6:ab2d7d0a9b07 329 fscanf(fp,"%e\n%e\n%e\n%d",&eg1cal,&eg2cal,&pcal,&scrubold);
pegcjs 6:ab2d7d0a9b07 330 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 6:ab2d7d0a9b07 331 }
pegcjs 6:ab2d7d0a9b07 332
pegcjs 6:ab2d7d0a9b07 333 // write the logfile opened and closed by start and end of dive
pegcjs 6:ab2d7d0a9b07 334 void store_log() {
pegcjs 6:ab2d7d0a9b07 335 Vb=Vbatt;
pegcjs 6:ab2d7d0a9b07 336 //FILE *fp=fopen("/local/divelog.dat","a");
pegcjs 6:ab2d7d0a9b07 337 fprintf(lp,"%d\t%e\t%e\t%e\t%e\t%d\n",seconds,depth,ppo1,ppo2,Vb,scrubtime);
pegcjs 6:ab2d7d0a9b07 338 // fclose(fp);
pegcjs 6:ab2d7d0a9b07 339 }
pegcjs 4:74df6d31ee0a 340
pegcjs 1:9cff4feccbce 341
pegcjs 1:9cff4feccbce 342 int main() {
pegcjs 2:a1c26faa9103 343 // first some local variables
pegcjs 2:a1c26faa9103 344 int startuptime=getseconds();
pegcjs 4:74df6d31ee0a 345 int startdive=0,endclock=0; // value of seconds when dive starts and counter to decide if dive complete...
pegcjs 1:9cff4feccbce 346
pegcjs 6:ab2d7d0a9b07 347 int minutes=0; // minutes is elapsed minutes since start of prog
pegcjs 6:ab2d7d0a9b07 348 int j=0; // general loop counting variable
pegcjs 6:ab2d7d0a9b07 349
pegcjs 1:9cff4feccbce 350
pegcjs 1:9cff4feccbce 351
pegcjs 1:9cff4feccbce 352 set_custom_char(); // does what it says on the tin really
pegcjs 1:9cff4feccbce 353 g_lcd.cls();
pegcjs 1:9cff4feccbce 354 g_lcd.locate(0, 0);
pegcjs 1:9cff4feccbce 355 g_lcd.printf( "RebMon");
pegcjs 1:9cff4feccbce 356 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 357 g_lcd.printf("CAL?");
pegcjs 1:9cff4feccbce 358 battery();
pegcjs 4:74df6d31ee0a 359 j=0;
pegcjs 6:ab2d7d0a9b07 360 // get cal values last used from local drive
pegcjs 6:ab2d7d0a9b07 361 recall();
pegcjs 6:ab2d7d0a9b07 362 // display the correct scrubber time
pegcjs 6:ab2d7d0a9b07 363 scrubtime=scrubtime+scrubold;
pegcjs 1:9cff4feccbce 364 // hang about waiting for the cal switch to be pressed in ccase it is
pegcjs 1:9cff4feccbce 365 while (seconds-startuptime<20) {
pegcjs 1:9cff4feccbce 366 seconds=getseconds();
pegcjs 1:9cff4feccbce 367 g_lcd.locate(5,1);
pegcjs 1:9cff4feccbce 368 g_lcd.printf("%.2d",21-(seconds-startuptime));
pegcjs 4:74df6d31ee0a 369 if (j>1) flash=1;
pegcjs 3:0d94a277aa8c 370 else flash=0;
pegcjs 1:9cff4feccbce 371 battery(); // bung in battery symbol.
pegcjs 1:9cff4feccbce 372 g_lcd.locate(7,0);
pegcjs 1:9cff4feccbce 373 g_lcd.printf( "%.2d:%.2d:%.2d", hours,min,sec);
pegcjs 1:9cff4feccbce 374 if (CAL==0) {
pegcjs 1:9cff4feccbce 375 calibrate();
pegcjs 1:9cff4feccbce 376
pegcjs 1:9cff4feccbce 377 }
pegcjs 3:0d94a277aa8c 378 wait(0.2);
pegcjs 3:0d94a277aa8c 379 j=(j+1) % 4;
pegcjs 1:9cff4feccbce 380 }
pegcjs 1:9cff4feccbce 381 g_lcd.cls();
pegcjs 5:35417986539a 382
pegcjs 1:9cff4feccbce 383
pegcjs 1:9cff4feccbce 384 // ok there are three states in this system
pegcjs 1:9cff4feccbce 385 //MAIN LOOP ONCE STARTUP PROTOCOLS ARE COMPLETED
pegcjs 3:0d94a277aa8c 386 j=0;
pegcjs 1:9cff4feccbce 387 while (1) {
pegcjs 2:a1c26faa9103 388 wait(0.2); //stop screen flicker
pegcjs 1:9cff4feccbce 389 readsensors();
pegcjs 2:a1c26faa9103 390 seconds=getseconds();
pegcjs 4:74df6d31ee0a 391 minutes=(int)(((float)seconds-(float)startuptime)/60);
pegcjs 6:ab2d7d0a9b07 392
pegcjs 3:0d94a277aa8c 393
pegcjs 3:0d94a277aa8c 394 if (j>1) flash=1;
pegcjs 3:0d94a277aa8c 395 else flash=0;
pegcjs 3:0d94a277aa8c 396
pegcjs 3:0d94a277aa8c 397 display(); // write the display
pegcjs 3:0d94a277aa8c 398
pegcjs 3:0d94a277aa8c 399 // setup state variable
pegcjs 3:0d94a277aa8c 400 if (minutes<1) state=0; // startup mode - do nothing just wait to allow sensor readings to settle.
pegcjs 4:74df6d31ee0a 401 if (minutes>=1 && state==0) state=1; // surface mode - ok to go for a dive now
pegcjs 6:ab2d7d0a9b07 402 if (minutes>=1 && depth>0.8 && state==1) {
pegcjs 3:0d94a277aa8c 403 state=2; // enter dive mode
pegcjs 6:ab2d7d0a9b07 404 lp=fopen("/local/divelog.dat","a");
pegcjs 4:74df6d31ee0a 405 if (startdive==0) startdive=seconds; // set start of divetime. don't do this twice
pegcjs 3:0d94a277aa8c 406 endclock=0; // reset end of dive clock
pegcjs 3:0d94a277aa8c 407 }
pegcjs 3:0d94a277aa8c 408 if (state==2) {
pegcjs 4:74df6d31ee0a 409 divetime=(int)(((float)seconds-(float)startdive)/60); // time since start of dive in minutes.
pegcjs 3:0d94a277aa8c 410 // do deco calcs here when implemented
pegcjs 6:ab2d7d0a9b07 411 if ((seconds-startdive) %15 ==0) store_log(); // this saves the dive profile and sensor optputs in a file called divelog.dat every 15s
pegcjs 6:ab2d7d0a9b07 412 if (depth<=0.3) {
pegcjs 4:74df6d31ee0a 413 endclock=endclock+1;
pegcjs 4:74df6d31ee0a 414
pegcjs 6:ab2d7d0a9b07 415 if (endclock>150) {
pegcjs 6:ab2d7d0a9b07 416 state=1; // 30s at shallower than 0.3m and we return to surface mode.
pegcjs 6:ab2d7d0a9b07 417 FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 6:ab2d7d0a9b07 418 fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime);
pegcjs 6:ab2d7d0a9b07 419 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 6:ab2d7d0a9b07 420 fclose(lp);
pegcjs 6:ab2d7d0a9b07 421 }
pegcjs 3:0d94a277aa8c 422 }
pegcjs 6:ab2d7d0a9b07 423 scrubtime=scrubold+divetime; //
pegcjs 3:0d94a277aa8c 424 }
pegcjs 1:9cff4feccbce 425
pegcjs 1:9cff4feccbce 426
pegcjs 3:0d94a277aa8c 427 j=(j+1) %4; // flash control variable = used to make the warnings flash for 0.4s duty cycle
pegcjs 1:9cff4feccbce 428 } // end while
pegcjs 1:9cff4feccbce 429 } //end main
pegcjs 1:9cff4feccbce 430
pegcjs 1:9cff4feccbce 431
pegcjs 1:9cff4feccbce 432
pegcjs 1:9cff4feccbce 433