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:
Fri Aug 03 11:29:30 2012 +0000
Revision:
3:0d94a277aa8c
Parent:
2:a1c26faa9103
Child:
4:74df6d31ee0a
just leds to go

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 1:9cff4feccbce 4 #include "TextLCD.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 1:9cff4feccbce 24 // switches and buttons - these are pulled up by resistors so are active low
pegcjs 1:9cff4feccbce 25 DigitalIn CAL(p36);
pegcjs 1:9cff4feccbce 26 DigitalIn SW1(p35);
pegcjs 1:9cff4feccbce 27
pegcjs 1:9cff4feccbce 28 // log data storage
pegcjs 1:9cff4feccbce 29 LocalFileSystem local("local");
pegcjs 1:9cff4feccbce 30
pegcjs 1:9cff4feccbce 31 // adc inputs for sensors
pegcjs 1:9cff4feccbce 32 AnalogIn PRESin(p20);
pegcjs 1:9cff4feccbce 33 AnalogIn EG1(p19);
pegcjs 1:9cff4feccbce 34 AnalogIn EG2(p18);
pegcjs 1:9cff4feccbce 35 AnalogIn Vbatt(p17);
pegcjs 1:9cff4feccbce 36
pegcjs 1:9cff4feccbce 37 // realtime clock
pegcjs 1:9cff4feccbce 38 DS1307 my1307(p28,p27); // start DS1307 class and give it pins for connections of the DS1307 device
pegcjs 1:9cff4feccbce 39
pegcjs 1:9cff4feccbce 40 // variables for realtime clock
pegcjs 1:9cff4feccbce 41 int sec = 0;
pegcjs 1:9cff4feccbce 42 int min = 0;
pegcjs 1:9cff4feccbce 43 int hours = 0;
pegcjs 1:9cff4feccbce 44 int day = 0;
pegcjs 1:9cff4feccbce 45 int date = 0;
pegcjs 1:9cff4feccbce 46 int month = 0;
pegcjs 1:9cff4feccbce 47 int year = 0;
pegcjs 1:9cff4feccbce 48
pegcjs 1:9cff4feccbce 49 int scrubtime=0; // these are expressed in minutes
pegcjs 1:9cff4feccbce 50 int divetime=0;
pegcjs 1:9cff4feccbce 51
pegcjs 3:0d94a277aa8c 52 int flash=0; // variable used top control flashing icons
pegcjs 2:a1c26faa9103 53 int state=0; // IMPORTANT - VARIABLE THAT DRIVES HNTE STATE MACHINE STATE=0 = STARTUP, STATE=1=SURFACE STATE=2= DIVING
pegcjs 2:a1c26faa9103 54
pegcjs 1:9cff4feccbce 55 // variables for the eg cells and pressure sensor eg1calamd eg2cal ar reading when the sensor is in 0.21bar O2 and
pegcjs 1:9cff4feccbce 56 //dcal is the reading whe the pressure sensor is at the surface
pegcjs 1:9cff4feccbce 57 float eg1cal=0.09,eg2cal=0.09,pcal=0.1136;
pegcjs 1:9cff4feccbce 58 // NB these are updated from /local/cal.dat so values not so important.... eventually
pegcjs 1:9cff4feccbce 59
pegcjs 1:9cff4feccbce 60 float depth=0,ppo1=0,ppo2=0, Vb=0,pressure=0; // depth, 1st o2 sensor second o2 sensor battery voltage,,Pressure
pegcjs 1:9cff4feccbce 61 float fo1=0,fo2=0,mod=55; //%f values,mod
pegcjs 3:0d94a277aa8c 62
pegcjs 1:9cff4feccbce 63 //===== sub to get time from ds1307 and create the 'seconds' which is a version of timestamp....
pegcjs 1:9cff4feccbce 64 int getseconds() {
pegcjs 1:9cff4feccbce 65 my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year);
pegcjs 1:9cff4feccbce 66 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days.
pegcjs 1:9cff4feccbce 67 int seconds=year*365*24*60*60+month*30*24*60*60+day*24*60*60+hours*60*60+min*60+sec;
pegcjs 1:9cff4feccbce 68 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days....
pegcjs 1:9cff4feccbce 69 // ie wrong but simpler than the real thing
pegcjs 1:9cff4feccbce 70 return(seconds);
pegcjs 1:9cff4feccbce 71 }
pegcjs 1:9cff4feccbce 72
pegcjs 1:9cff4feccbce 73
pegcjs 1:9cff4feccbce 74 void set_custom_char() {
pegcjs 1:9cff4feccbce 75 char cgchar[64]={
pegcjs 1:9cff4feccbce 76 6,9,9,9,9,9,9,15, // battery empty symbol 0
pegcjs 1:9cff4feccbce 77 6,9,9,9,9,15,15,15, // battery 50% symbol 1
pegcjs 1:9cff4feccbce 78 6,9,9,15,15,15,15,15, // battery 75% symbol 2
pegcjs 1:9cff4feccbce 79 6,15,15,15,15,15,15,15, // battery 100% symbol 3
pegcjs 1:9cff4feccbce 80 31,19,21,21,21,21,19,31, // diving symbol 4 inverse D
pegcjs 1:9cff4feccbce 81 6,6,6,6,6,0,0,6, // warning symbol 5
pegcjs 1:9cff4feccbce 82 31,17,23,17,29,17,31,0, // surface symbol 6 inverse S
pegcjs 2:a1c26faa9103 83 0,0,17,17,0,17,14,0 // happy symbol 7
pegcjs 1:9cff4feccbce 84 };
pegcjs 1:9cff4feccbce 85 int i=0;
pegcjs 1:9cff4feccbce 86 // do stuff here to set cstom chars
pegcjs 1:9cff4feccbce 87 g_lcd.writeCommand(0x40); // set start address for CGRAM
pegcjs 1:9cff4feccbce 88 for (i=0; i<64; i++) {
pegcjs 1:9cff4feccbce 89 g_lcd.writeData(cgchar[i]);
pegcjs 1:9cff4feccbce 90 }
pegcjs 1:9cff4feccbce 91
pegcjs 1:9cff4feccbce 92 }
pegcjs 1:9cff4feccbce 93
pegcjs 1:9cff4feccbce 94
pegcjs 1:9cff4feccbce 95 // subroutine to calibreate o2 sesnors and store ca data in /local/CAL.dat
pegcjs 1:9cff4feccbce 96 void calibrate() {
pegcjs 1:9cff4feccbce 97 int count=1;
pegcjs 1:9cff4feccbce 98 float ppo1=0,ppo2=0,pres=0;
pegcjs 1:9cff4feccbce 99 // average 20 readings for noise reduction
pegcjs 1:9cff4feccbce 100 g_lcd.cls();
pegcjs 1:9cff4feccbce 101 for (count=20; count>0; count--) {
pegcjs 1:9cff4feccbce 102 g_lcd.locate(0,0);
pegcjs 1:9cff4feccbce 103 g_lcd.printf("Calibrating %.2d",count);
pegcjs 1:9cff4feccbce 104 ppo1=ppo1+EG1;
pegcjs 1:9cff4feccbce 105 ppo2=ppo2+EG2;
pegcjs 1:9cff4feccbce 106 pres=pres+PRESin;
pegcjs 1:9cff4feccbce 107 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 108 g_lcd.printf("%1.2f: %1.2f: %1.2f",ppo1/(20-count+1),ppo2/(20-count+1),pres/(20-count+1));
pegcjs 1:9cff4feccbce 109 wait(1);
pegcjs 1:9cff4feccbce 110 }
pegcjs 1:9cff4feccbce 111 //average
pegcjs 1:9cff4feccbce 112 ppo1=ppo1/20;
pegcjs 1:9cff4feccbce 113 ppo2=ppo2/20;
pegcjs 1:9cff4feccbce 114 // set calibration variables
pegcjs 1:9cff4feccbce 115 eg1cal=ppo1;
pegcjs 1:9cff4feccbce 116 eg2cal=ppo2;
pegcjs 1:9cff4feccbce 117 pcal=pres/20; // surface pressure....
pegcjs 1:9cff4feccbce 118 scrubtime=0; // reset the scrubber timer to zero.
pegcjs 2:a1c26faa9103 119 // write cal data NB overwites previous
pegcjs 2:a1c26faa9103 120 FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 2:a1c26faa9103 121 fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime);
pegcjs 2:a1c26faa9103 122 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 1:9cff4feccbce 123 }
pegcjs 1:9cff4feccbce 124
pegcjs 1:9cff4feccbce 125
pegcjs 2:a1c26faa9103 126 void status() {
pegcjs 3:0d94a277aa8c 127 if (state==0) {
pegcjs 3:0d94a277aa8c 128 g_lcd.character(9,0,5); // warning icon until 1 min up
pegcjs 3:0d94a277aa8c 129 g_lcd.character(8,0,6); // surface icon
pegcjs 3:0d94a277aa8c 130 }
pegcjs 2:a1c26faa9103 131 if (state==1) g_lcd.character(8,0,6); // surface icon
pegcjs 3:0d94a277aa8c 132 if (state==2 && flash==1) g_lcd.character(8,0,4); // diving icon
pegcjs 3:0d94a277aa8c 133 if (state==2 && flash==0) g_lcd.character(8,0,68); // diving icon
pegcjs 3:0d94a277aa8c 134 }
pegcjs 3:0d94a277aa8c 135
pegcjs 3:0d94a277aa8c 136 // warning and LED conditions
pegcjs 2:a1c26faa9103 137
pegcjs 2:a1c26faa9103 138 void warning() {
pegcjs 3:0d94a277aa8c 139 if (depth>=mod && flash==1) g_lcd.character(13,0,5);
pegcjs 2:a1c26faa9103 140
pegcjs 2:a1c26faa9103 141 }
pegcjs 2:a1c26faa9103 142
pegcjs 2:a1c26faa9103 143 void leds() {
pegcjs 1:9cff4feccbce 144 }
pegcjs 1:9cff4feccbce 145
pegcjs 1:9cff4feccbce 146 //read battery state and insert the battery symbol
pegcjs 1:9cff4feccbce 147 void battery() {
pegcjs 1:9cff4feccbce 148 int batsym=0;
pegcjs 1:9cff4feccbce 149 Vb=Vbatt; // read adc connected to battery via a 1/3 potential divider
pegcjs 1:9cff4feccbce 150 if (Vb>0.606) batsym=1;
pegcjs 1:9cff4feccbce 151 if (Vb>0.707) batsym=2;
pegcjs 1:9cff4feccbce 152 if (Vb>0.808) batsym=3;
pegcjs 3:0d94a277aa8c 153 if (batsym >0) g_lcd.character(8,1,batsym);
pegcjs 3:0d94a277aa8c 154 if (batsym ==0 && flash==1) g_lcd.character(8,1,batsym);
pegcjs 3:0d94a277aa8c 155 if (batsym ==0 && flash==0) g_lcd.character(8,1,32);
pegcjs 1:9cff4feccbce 156 }
pegcjs 1:9cff4feccbce 157
pegcjs 2:a1c26faa9103 158 // subroutine to write the main display data
pegcjs 2:a1c26faa9103 159 //0123456789abcdef
pegcjs 2:a1c26faa9103 160
pegcjs 2:a1c26faa9103 161 //x.xx:xx D XX xx
pegcjs 2:a1c26faa9103 162 //x.xx:xx B XX xxx NB the warning, staus and battery icons are driven by separate subroutines.
pegcjs 2:a1c26faa9103 163 void display() {
pegcjs 2:a1c26faa9103 164 //1st line
pegcjs 2:a1c26faa9103 165 g_lcd.locate(0,0);
pegcjs 2:a1c26faa9103 166 g_lcd.printf("%1.2f:%.2d %.2d %.2d",ppo1,(int)fo1,(int)depth,(int)mod);
pegcjs 2:a1c26faa9103 167 //2nd line
pegcjs 2:a1c26faa9103 168 g_lcd.locate(0,1);
pegcjs 3:0d94a277aa8c 169 g_lcd.printf("%1.2f:%.2d %.2d %.3d",ppo2,(int)fo2,divetime,scrubtime);
pegcjs 2:a1c26faa9103 170 // bung in battery icon
pegcjs 2:a1c26faa9103 171 battery();
pegcjs 2:a1c26faa9103 172 status(); // this will set the diviong / suface mode icon
pegcjs 2:a1c26faa9103 173 warning(); // this will set the warning icon assuming that max ppo2 is exceeded
pegcjs 2:a1c26faa9103 174
pegcjs 2:a1c26faa9103 175 leds(); // this sets the leds according to the various warning conditions
pegcjs 2:a1c26faa9103 176
pegcjs 2:a1c26faa9103 177 }
pegcjs 2:a1c26faa9103 178
pegcjs 2:a1c26faa9103 179
pegcjs 1:9cff4feccbce 180 // pick maximum of two values
pegcjs 1:9cff4feccbce 181 float maximum(float a,float b) {
pegcjs 1:9cff4feccbce 182 float maximum;
pegcjs 1:9cff4feccbce 183 if (a>b) maximum=a;
pegcjs 1:9cff4feccbce 184 else maximum=b;
pegcjs 1:9cff4feccbce 185 return(maximum);
pegcjs 2:a1c26faa9103 186 }
pegcjs 2:a1c26faa9103 187
pegcjs 1:9cff4feccbce 188 // pick minimum of two values
pegcjs 1:9cff4feccbce 189 float minimum(float a,float b) {
pegcjs 1:9cff4feccbce 190 float minim;
pegcjs 1:9cff4feccbce 191 if (a<b) minim=a;
pegcjs 1:9cff4feccbce 192 else minim=b;
pegcjs 1:9cff4feccbce 193 return(minim);
pegcjs 2:a1c26faa9103 194 }
pegcjs 2:a1c26faa9103 195
pegcjs 1:9cff4feccbce 196
pegcjs 2:a1c26faa9103 197
pegcjs 2:a1c26faa9103 198 // read sensors and generate calibrated outputs NB battery is read elsewhere
pegcjs 1:9cff4feccbce 199 void readsensors() {
pegcjs 1:9cff4feccbce 200 float barometric=0,mod1,mod2;
pegcjs 1:9cff4feccbce 201 ppo1=EG1*0.21/eg1cal; // eg1cal is 0.21bar ppO2
pegcjs 1:9cff4feccbce 202 ppo2=EG2*0.21/eg2cal; // second oxygen cell ppO2
pegcjs 2:a1c26faa9103 203 pressure=(PRESin*3.3-0.024)/(0.0038574); // pressure in kPa assuming standard cal for mpx5700 sensor SUSPECT
pegcjs 3:0d94a277aa8c 204 // barometric=(pcal*3.3-0.024)/(0.0038574); // sealevel in kPa assuming standard cal for mpx5700 sensor
pegcjs 2:a1c26faa9103 205 depth=(pressure-101.325)*0.1; //100kPa=10m 1kPa=0.1m - this gives depth in m for freshwater.
pegcjs 1:9cff4feccbce 206 //with two sensors will calculate mod from the largest ppo2 reading
pegcjs 2:a1c26faa9103 207
pegcjs 2:a1c26faa9103 208 fo1=100*ppo1/(pressure/100); // pressure in bar = pressure /100 and want a % so multiply by 100 as well
pegcjs 2:a1c26faa9103 209 fo2=100*ppo2/(pressure/100);
pegcjs 3:0d94a277aa8c 210
pegcjs 2:a1c26faa9103 211
pegcjs 2:a1c26faa9103 212 mod1=(1.4/(fo1/100)-1)*10;
pegcjs 2:a1c26faa9103 213 mod2=(1.4/(fo2/100)-1)*10;
pegcjs 3:0d94a277aa8c 214
pegcjs 2:a1c26faa9103 215 mod=minimum(mod1,mod2); // pick the least value
pegcjs 2:a1c26faa9103 216 //DEBUG
pegcjs 3:0d94a277aa8c 217
pegcjs 1:9cff4feccbce 218 }
pegcjs 3:0d94a277aa8c 219 // sub to test if a variable is an even number
pegcjs 3:0d94a277aa8c 220 /*int iseven(int g) {
pegcjs 3:0d94a277aa8c 221 int test=0;
pegcjs 3:0d94a277aa8c 222 if ((float)g/2==(int)((float)g/2)) test=1;
pegcjs 3:0d94a277aa8c 223 return(test);
pegcjs 3:0d94a277aa8c 224 }*/
pegcjs 1:9cff4feccbce 225
pegcjs 1:9cff4feccbce 226 int main() {
pegcjs 2:a1c26faa9103 227 // first some local variables
pegcjs 2:a1c26faa9103 228 int startuptime=getseconds();
pegcjs 3:0d94a277aa8c 229 int startdive=0,endclock=0;; // value of seconds when dive starts and counter to decide if dive complete...
pegcjs 1:9cff4feccbce 230
pegcjs 3:0d94a277aa8c 231 int seconds=0,minutes=0,dt=0;; // minutes is elapsed minutes since start of prog
pegcjs 1:9cff4feccbce 232 int i=0,j=0; // general loop counting variables
pegcjs 1:9cff4feccbce 233
pegcjs 1:9cff4feccbce 234
pegcjs 1:9cff4feccbce 235 set_custom_char(); // does what it says on the tin really
pegcjs 1:9cff4feccbce 236 g_lcd.cls();
pegcjs 1:9cff4feccbce 237 g_lcd.locate(0, 0);
pegcjs 1:9cff4feccbce 238 g_lcd.printf( "RebMon");
pegcjs 1:9cff4feccbce 239 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 240 g_lcd.printf("CAL?");
pegcjs 1:9cff4feccbce 241 battery();
pegcjs 3:0d94a277aa8c 242 j=0;
pegcjs 1:9cff4feccbce 243 // hang about waiting for the cal switch to be pressed in ccase it is
pegcjs 1:9cff4feccbce 244 while (seconds-startuptime<20) {
pegcjs 1:9cff4feccbce 245 seconds=getseconds();
pegcjs 1:9cff4feccbce 246 g_lcd.locate(5,1);
pegcjs 1:9cff4feccbce 247 g_lcd.printf("%.2d",21-(seconds-startuptime));
pegcjs 3:0d94a277aa8c 248 if(j>1) flash=1;
pegcjs 3:0d94a277aa8c 249 else flash=0;
pegcjs 1:9cff4feccbce 250 battery(); // bung in battery symbol.
pegcjs 1:9cff4feccbce 251 g_lcd.locate(7,0);
pegcjs 1:9cff4feccbce 252 g_lcd.printf( "%.2d:%.2d:%.2d", hours,min,sec);
pegcjs 1:9cff4feccbce 253 if (CAL==0) {
pegcjs 1:9cff4feccbce 254 calibrate();
pegcjs 1:9cff4feccbce 255
pegcjs 1:9cff4feccbce 256 }
pegcjs 3:0d94a277aa8c 257 wait(0.2);
pegcjs 3:0d94a277aa8c 258 j=(j+1) % 4;
pegcjs 1:9cff4feccbce 259 }
pegcjs 1:9cff4feccbce 260 g_lcd.cls();
pegcjs 1:9cff4feccbce 261 backlight=1; // backlight on - this driven by bc182l and 50ohm resistor off the 5V supply to send ~ 20mA
pegcjs 1:9cff4feccbce 262
pegcjs 1:9cff4feccbce 263 // ok there are three states in this system
pegcjs 1:9cff4feccbce 264 //MAIN LOOP ONCE STARTUP PROTOCOLS ARE COMPLETED
pegcjs 3:0d94a277aa8c 265 j=0;
pegcjs 1:9cff4feccbce 266 while (1) {
pegcjs 2:a1c26faa9103 267 wait(0.2); //stop screen flicker
pegcjs 1:9cff4feccbce 268 readsensors();
pegcjs 2:a1c26faa9103 269 seconds=getseconds();
pegcjs 2:a1c26faa9103 270 minutes=(int)((float)seconds-(float)startuptime)/60;
pegcjs 3:0d94a277aa8c 271 dt=seconds-startuptime; // elapsed seconds
pegcjs 3:0d94a277aa8c 272
pegcjs 3:0d94a277aa8c 273 if (j>1) flash=1;
pegcjs 3:0d94a277aa8c 274 else flash=0;
pegcjs 3:0d94a277aa8c 275
pegcjs 3:0d94a277aa8c 276 display(); // write the display
pegcjs 3:0d94a277aa8c 277
pegcjs 3:0d94a277aa8c 278 // setup state variable
pegcjs 3:0d94a277aa8c 279 if (minutes<1) state=0; // startup mode - do nothing just wait to allow sensor readings to settle.
pegcjs 3:0d94a277aa8c 280 if (minutes>=1) state=1; // surface mode - ok to go for a dive now
pegcjs 3:0d94a277aa8c 281 if (minutes>1 && depth>0.5 && state==1) {
pegcjs 3:0d94a277aa8c 282 state=2; // enter dive mode
pegcjs 3:0d94a277aa8c 283 startdive=seconds; // set start of divetime.
pegcjs 3:0d94a277aa8c 284 endclock=0; // reset end of dive clock
pegcjs 3:0d94a277aa8c 285 }
pegcjs 3:0d94a277aa8c 286 if (state==2) {
pegcjs 3:0d94a277aa8c 287 divetime=(int)((float)seconds-(float)startdive)/60; // time since start of dive in minutes.
pegcjs 3:0d94a277aa8c 288 // do deco calcs here when implemented
pegcjs 3:0d94a277aa8c 289 if (depth<0.3) {
pegcjs 3:0d94a277aa8c 290 endclock++;
pegcjs 3:0d94a277aa8c 291 if (endclock==150) state=1; // 30s at shallower than 0.3m and we return to surface mode.
pegcjs 3:0d94a277aa8c 292 }
pegcjs 3:0d94a277aa8c 293 }
pegcjs 1:9cff4feccbce 294
pegcjs 1:9cff4feccbce 295
pegcjs 3:0d94a277aa8c 296 j=(j+1) %4; // flash control variable = used to make the warnings flash for 0.4s duty cycle
pegcjs 1:9cff4feccbce 297 } // end while
pegcjs 1:9cff4feccbce 298 } //end main
pegcjs 1:9cff4feccbce 299
pegcjs 1:9cff4feccbce 300
pegcjs 1:9cff4feccbce 301
pegcjs 1:9cff4feccbce 302