Software to drive a monitor unit for a closed circuit rebreather using 3 electrogalvanic oxygen sensor cells run through an amplifier (lm324) . Uses a separate ds1307 clock IC to get timestamp values for logged data.

Dependencies:   DS1307 TextOLED_custom mbed

The main electornics is housed in another pod mounted on the back of the unit. I'm using an mbed lpc11u24 to drive everything which comes with a flash drive for data logging built in. It has an external ds1307 clock chip added and a very cheapo lm324 quad op-amp to amplify the o2 sensor signals from the 10s of mV range by 30x so that ppo2=0.21 corresponds to about 0.3V. I still have to do some ADC averaging with this amplifier and do have to calibrate out the individual offsets of the chip but this works ok now that I've worked out which amp is on which adc...

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