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:
Mon Jan 14 12:52:45 2013 +0000
Revision:
7:f93b7eaab5f6
Parent:
6:ab2d7d0a9b07
Child:
8:f45e654b47d0
Fixed bug in setswitch prevennting switch back to lowsetpoint on ascent; added hud flashes 4 flashes = going to high sp , 2 flashes = going to low sp.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pegcjs 1:9cff4feccbce 1 //lpc1124lcddemo
pegcjs 7:f93b7eaab5f6 2 // driver for mbed based ppo2 monitoring system for closed circuit rebreather
pegcjs 7:f93b7eaab5f6 3 // reading 3 electrogalvanic oxygen sensors and one pressure sensor
pegcjs 1:9cff4feccbce 4 #include "ds1307.h"
pegcjs 1:9cff4feccbce 5 #include "mbed.h"
pegcjs 5:35417986539a 6 #include "TextOLED.h"
pegcjs 1:9cff4feccbce 7
pegcjs 7:f93b7eaab5f6 8 //TODO - MAKE A VERSION THAT DRIVES THE HUD, CHECKS THE 5V SUPPLY AND COMPENSATES THE READINGS IF ITS VARYING (LINEARLY)
pegcjs 7:f93b7eaab5f6 9 // AND PREVENT A HANG IF THE DS1307 FAILS TO RESPOND.
pegcjs 1:9cff4feccbce 10
pegcjs 7:f93b7eaab5f6 11 #define DRATIO 0.6420066 // ratio of voltage at pin20 to voltage actually generated by the sensor
pegcjs 7:f93b7eaab5f6 12
pegcjs 7:f93b7eaab5f6 13 //hud LINES
pegcjs 7:f93b7eaab5f6 14 DigitalOut AB(p7); //pins AB for data bits
pegcjs 7:f93b7eaab5f6 15 DigitalOut CP(p5); // clock to shift reg
pegcjs 7:f93b7eaab5f6 16 //DigitalOut MR(p8); // reset to shift reg (low for clear)#
pegcjs 7:f93b7eaab5f6 17 DigitalOut btest(p6); // pin to drive lastblue led
pegcjs 7:f93b7eaab5f6 18
pegcjs 7:f93b7eaab5f6 19 // offsets for lm324 amp in terms of reading values on adc
pegcjs 7:f93b7eaab5f6 20 #define coff1 -0.013375
pegcjs 7:f93b7eaab5f6 21 #define coff2 -0.00936
pegcjs 7:f93b7eaab5f6 22 #define coff3 -0.0212136
pegcjs 7:f93b7eaab5f6 23
pegcjs 7:f93b7eaab5f6 24
pegcjs 7:f93b7eaab5f6 25
pegcjs 7:f93b7eaab5f6 26 Serial pc(USBTX, USBRX); // tx, rx for debug and usb pc comunications
pegcjs 7:f93b7eaab5f6 27
pegcjs 1:9cff4feccbce 28
pegcjs 1:9cff4feccbce 29 //pin assignments and declarations
pegcjs 1:9cff4feccbce 30 // LCD display
pegcjs 1:9cff4feccbce 31 TextLCD g_lcd(p26, p25, p24, p23, p22, p21); // RS, E, DB4, DB5, DB6, DB7
pegcjs 1:9cff4feccbce 32 //backlight
pegcjs 1:9cff4feccbce 33 DigitalOut backlight(p29);
pegcjs 1:9cff4feccbce 34
pegcjs 1:9cff4feccbce 35 //onboard leds
pegcjs 1:9cff4feccbce 36 DigitalOut led1(LED1);
pegcjs 1:9cff4feccbce 37 DigitalOut led2(LED2);
pegcjs 1:9cff4feccbce 38
pegcjs 1:9cff4feccbce 39 // warning leds
pegcjs 1:9cff4feccbce 40 DigitalOut red(p34);
pegcjs 1:9cff4feccbce 41 DigitalOut green(p33);
pegcjs 1:9cff4feccbce 42 DigitalOut blue(p30);
pegcjs 1:9cff4feccbce 43
pegcjs 6:ab2d7d0a9b07 44
pegcjs 1:9cff4feccbce 45 // switches and buttons - these are pulled up by resistors so are active low
pegcjs 1:9cff4feccbce 46 DigitalIn CAL(p36);
pegcjs 5:35417986539a 47 DigitalIn SW1(p35); // reed switch in display unit
pegcjs 7:f93b7eaab5f6 48 DigitalIn SW2(p10); // reed switch in dispaly unit - NONE FUNCIONAL IN CURRENT HEAD - SWITCH FAILED DURING POTTING
pegcjs 7:f93b7eaab5f6 49 //DigitalIn MODE(p11);// a switchn on the mbed pcb to select between SCR and CCR modes for the LEDs NOT USED ANYMORE
pegcjs 1:9cff4feccbce 50
pegcjs 1:9cff4feccbce 51 // log data storage
pegcjs 1:9cff4feccbce 52 LocalFileSystem local("local");
pegcjs 1:9cff4feccbce 53
pegcjs 1:9cff4feccbce 54 // adc inputs for sensors
pegcjs 1:9cff4feccbce 55 AnalogIn PRESin(p20);
pegcjs 1:9cff4feccbce 56 AnalogIn EG1(p19);
pegcjs 1:9cff4feccbce 57 AnalogIn EG2(p18);
pegcjs 7:f93b7eaab5f6 58 AnalogIn EG3(p16);
pegcjs 7:f93b7eaab5f6 59 AnalogIn Vbatt(p17); // battery voltage divided down by 3
pegcjs 7:f93b7eaab5f6 60 AnalogIn V5V(p15); // sense the '5V' output from the max1724 unit - divided down by 2. Nominally 2.5V===0.757575757' in 3.3V ADC
pegcjs 7:f93b7eaab5f6 61
pegcjs 7:f93b7eaab5f6 62
pegcjs 1:9cff4feccbce 63
pegcjs 1:9cff4feccbce 64 // realtime clock
pegcjs 1:9cff4feccbce 65 DS1307 my1307(p28,p27); // start DS1307 class and give it pins for connections of the DS1307 device
pegcjs 1:9cff4feccbce 66
pegcjs 1:9cff4feccbce 67 // variables for realtime clock
pegcjs 1:9cff4feccbce 68 int sec = 0;
pegcjs 1:9cff4feccbce 69 int min = 0;
pegcjs 1:9cff4feccbce 70 int hours = 0;
pegcjs 1:9cff4feccbce 71 int day = 0;
pegcjs 1:9cff4feccbce 72 int date = 0;
pegcjs 1:9cff4feccbce 73 int month = 0;
pegcjs 1:9cff4feccbce 74 int year = 0;
pegcjs 4:74df6d31ee0a 75 int seconds=0; // general number of seconds since 2000 etc timestamp variable
pegcjs 1:9cff4feccbce 76
pegcjs 7:f93b7eaab5f6 77 int scrubtime=0,scrubold=0; // these are expressed in minutes
pegcjs 1:9cff4feccbce 78 int divetime=0;
pegcjs 1:9cff4feccbce 79
pegcjs 3:0d94a277aa8c 80 int flash=0; // variable used top control flashing icons
pegcjs 2:a1c26faa9103 81 int state=0; // IMPORTANT - VARIABLE THAT DRIVES HNTE STATE MACHINE STATE=0 = STARTUP, STATE=1=SURFACE STATE=2= DIVING
pegcjs 7:f93b7eaab5f6 82 float lowsetpoint=0.7,highsetpoint=1.2,switchdepth=10; // variables to determine HUD led states
pegcjs 7:f93b7eaab5f6 83 //switchdepth is centre of switch region 1m deep if switchdepth=10 then will go to high as descebnd
pegcjs 7:f93b7eaab5f6 84 //through 10.5 and go back to low when ascending through 9.5
pegcjs 7:f93b7eaab5f6 85 int setpoint=0; // 0=low 1 = high
pegcjs 2:a1c26faa9103 86
pegcjs 1:9cff4feccbce 87 // variables for the eg cells and pressure sensor eg1calamd eg2cal ar reading when the sensor is in 0.21bar O2 and
pegcjs 1:9cff4feccbce 88 //dcal is the reading whe the pressure sensor is at the surface
pegcjs 7:f93b7eaab5f6 89 float eg1cal=0.09,eg2cal=0.09,eg3cal=0.09,pcal=0.1136;
pegcjs 1:9cff4feccbce 90 // NB these are updated from /local/cal.dat so values not so important.... eventually
pegcjs 1:9cff4feccbce 91
pegcjs 7:f93b7eaab5f6 92 float depth=0,ppo1=0,ppo2=0,ppo3=0 ,Vb=0,pressure=0; // depth, 1st o2 sensor second o2 sensor battery voltage,,Pressure
pegcjs 7:f93b7eaab5f6 93 float fo1=0,fo2=0,fo3=0,mod=55; //%f values,mod
pegcjs 3:0d94a277aa8c 94
pegcjs 6:ab2d7d0a9b07 95 FILE *lp; // file pointer for log file
pegcjs 6:ab2d7d0a9b07 96
pegcjs 7:f93b7eaab5f6 97 bool nostop=1, deco=0; // variables to define state for deco
pegcjs 7:f93b7eaab5f6 98
pegcjs 7:f93b7eaab5f6 99
pegcjs 7:f93b7eaab5f6 100
pegcjs 7:f93b7eaab5f6 101 //HUD codes
pegcjs 7:f93b7eaab5f6 102 // make a HUD clock pulse
pegcjs 7:f93b7eaab5f6 103 int clk()
pegcjs 7:f93b7eaab5f6 104 {
pegcjs 7:f93b7eaab5f6 105 wait_us(1);
pegcjs 7:f93b7eaab5f6 106 CP=0;
pegcjs 7:f93b7eaab5f6 107 wait_us(1);
pegcjs 7:f93b7eaab5f6 108 CP=1;
pegcjs 7:f93b7eaab5f6 109 return(0);
pegcjs 7:f93b7eaab5f6 110 }
pegcjs 7:f93b7eaab5f6 111
pegcjs 7:f93b7eaab5f6 112 // write 8 bits to the HUD shift register
pegcjs 7:f93b7eaab5f6 113 int HUD_write(char d)
pegcjs 7:f93b7eaab5f6 114 {
pegcjs 7:f93b7eaab5f6 115 int i=0;
pegcjs 7:f93b7eaab5f6 116 for(i=7; i>=0; i--) {
pegcjs 7:f93b7eaab5f6 117 AB=d & (1 << i);
pegcjs 7:f93b7eaab5f6 118 AB=!AB;
pegcjs 7:f93b7eaab5f6 119 clk();
pegcjs 7:f93b7eaab5f6 120 }
pegcjs 7:f93b7eaab5f6 121 return(0);
pegcjs 7:f93b7eaab5f6 122 }
pegcjs 7:f93b7eaab5f6 123
pegcjs 7:f93b7eaab5f6 124 // make all HUD leds white - useful for warnings etc
pegcjs 7:f93b7eaab5f6 125 int HUD_white()
pegcjs 7:f93b7eaab5f6 126 {
pegcjs 7:f93b7eaab5f6 127 // set all white;
pegcjs 7:f93b7eaab5f6 128 HUD_write(255);
pegcjs 7:f93b7eaab5f6 129 btest=0;
pegcjs 7:f93b7eaab5f6 130
pegcjs 7:f93b7eaab5f6 131 return(0);
pegcjs 7:f93b7eaab5f6 132 }
pegcjs 7:f93b7eaab5f6 133 // clear the HUD - make al black
pegcjs 7:f93b7eaab5f6 134 int HUD_clr()
pegcjs 7:f93b7eaab5f6 135 {
pegcjs 7:f93b7eaab5f6 136 HUD_write(0);
pegcjs 7:f93b7eaab5f6 137 btest=1;
pegcjs 7:f93b7eaab5f6 138 return(0);
pegcjs 7:f93b7eaab5f6 139 }
pegcjs 7:f93b7eaab5f6 140
pegcjs 7:f93b7eaab5f6 141
pegcjs 7:f93b7eaab5f6 142
pegcjs 7:f93b7eaab5f6 143 // code to detect leap years
pegcjs 7:f93b7eaab5f6 144 int LeapYear(int year) {
pegcjs 7:f93b7eaab5f6 145 int leap=0;
pegcjs 7:f93b7eaab5f6 146
pegcjs 7:f93b7eaab5f6 147 if (year % 400==0) leap=1;
pegcjs 7:f93b7eaab5f6 148 else if (year %100 ==0) leap=0;
pegcjs 7:f93b7eaab5f6 149 else if (year % 4 ==0) leap=1;
pegcjs 7:f93b7eaab5f6 150 else leap=0;
pegcjs 7:f93b7eaab5f6 151 return(leap);
pegcjs 7:f93b7eaab5f6 152 }
pegcjs 7:f93b7eaab5f6 153
pegcjs 7:f93b7eaab5f6 154
pegcjs 1:9cff4feccbce 155 //===== sub to get time from ds1307 and create the 'seconds' which is a version of timestamp....
pegcjs 1:9cff4feccbce 156 int getseconds() {
pegcjs 7:f93b7eaab5f6 157 int leap=0,dayofyear=0,timestamp=0;
pegcjs 7:f93b7eaab5f6 158 int y=0,byear=0;
pegcjs 7:f93b7eaab5f6 159 int days[12]={0,31,59,90,120,151,181,212,243,273,304,334};
pegcjs 1:9cff4feccbce 160 my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year);
pegcjs 1:9cff4feccbce 161 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days.
pegcjs 7:f93b7eaab5f6 162 //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 163 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days....
pegcjs 1:9cff4feccbce 164 // ie wrong but simpler than the real thing
pegcjs 7:f93b7eaab5f6 165
pegcjs 7:f93b7eaab5f6 166
pegcjs 7:f93b7eaab5f6 167 // sort out ds1307 definiteion of year
pegcjs 7:f93b7eaab5f6 168 year=year+2000;
pegcjs 7:f93b7eaab5f6 169 leap=LeapYear(year);
pegcjs 7:f93b7eaab5f6 170
pegcjs 7:f93b7eaab5f6 171 // now decide dayofyear
pegcjs 7:f93b7eaab5f6 172 dayofyear=days[month-1]+date-1;
pegcjs 7:f93b7eaab5f6 173 if (leap==1 && month >2) dayofyear++; // deal with extra february day in leap year
pegcjs 7:f93b7eaab5f6 174
pegcjs 7:f93b7eaab5f6 175 // now find number of days since 1970
pegcjs 7:f93b7eaab5f6 176 for (y=1970; y<year; y++) {
pegcjs 7:f93b7eaab5f6 177 if (LeapYear(y) == 1) {
pegcjs 7:f93b7eaab5f6 178 byear += 366*24*60*60;
pegcjs 7:f93b7eaab5f6 179 } else {
pegcjs 7:f93b7eaab5f6 180 byear += 365*24*60*60;
pegcjs 7:f93b7eaab5f6 181 }
pegcjs 7:f93b7eaab5f6 182 }
pegcjs 7:f93b7eaab5f6 183
pegcjs 7:f93b7eaab5f6 184 // finally get the seconds right and construct timestamp in seconds since beginning of 1970
pegcjs 7:f93b7eaab5f6 185 timestamp=(byear)+dayofyear*24*3600+hours*3600+min*60+sec;
pegcjs 7:f93b7eaab5f6 186
pegcjs 7:f93b7eaab5f6 187 //DEBUG====================================
pegcjs 7:f93b7eaab5f6 188 // printf("secondst = %d\t timestamp = %d\t%.2d : %.2d : %d - %.2d:%.2d:%.2d\r",secondst,timestamp,date,month,year,hours,min,sec);
pegcjs 7:f93b7eaab5f6 189
pegcjs 7:f93b7eaab5f6 190 return(timestamp);
pegcjs 7:f93b7eaab5f6 191
pegcjs 1:9cff4feccbce 192 }
pegcjs 1:9cff4feccbce 193
pegcjs 1:9cff4feccbce 194
pegcjs 1:9cff4feccbce 195 void set_custom_char() {
pegcjs 1:9cff4feccbce 196 char cgchar[64]={
pegcjs 7:f93b7eaab5f6 197 6,9,9,9,9,9,9,15, // battery symbol 0 address 64 = 0x40
pegcjs 7:f93b7eaab5f6 198 28,20,20,20,20,20,29,0, // 0. symbol for ppo2 1 address 72 = 0x48
pegcjs 7:f93b7eaab5f6 199 8,24,8,8,8,8,29,0, // 1. symbol for ppo2 2 address 80 =0x50
pegcjs 7:f93b7eaab5f6 200 6,15,15,15,15,15,15,15, // unused 3 address 88 = 0x58
pegcjs 7:f93b7eaab5f6 201 31,19,21,21,21,21,19,31, // unused 4 address 96 = 0x60
pegcjs 7:f93b7eaab5f6 202 6,6,6,6,6,0,0,6, // top char Vmessg 5 address 104 =0x68 - used for Vmessage
pegcjs 7:f93b7eaab5f6 203 31,17,23,17,29,17,31,0, // bottom char Vmessg 6 address 112 =0x70 -used for Vmessg
pegcjs 7:f93b7eaab5f6 204 2,6,2,2,2,2,23 // for dec point in depth 7 address 120 =0x78
pegcjs 1:9cff4feccbce 205 };
pegcjs 1:9cff4feccbce 206 int i=0;
pegcjs 1:9cff4feccbce 207 // do stuff here to set cstom chars
pegcjs 1:9cff4feccbce 208 g_lcd.writeCommand(0x40); // set start address for CGRAM
pegcjs 1:9cff4feccbce 209 for (i=0; i<64; i++) {
pegcjs 1:9cff4feccbce 210 g_lcd.writeData(cgchar[i]);
pegcjs 1:9cff4feccbce 211 }
pegcjs 1:9cff4feccbce 212
pegcjs 1:9cff4feccbce 213 }
pegcjs 1:9cff4feccbce 214
pegcjs 6:ab2d7d0a9b07 215 // stash cal values on local drive
pegcjs 6:ab2d7d0a9b07 216 void store() {
pegcjs 7:f93b7eaab5f6 217 int timestamp=0;
pegcjs 7:f93b7eaab5f6 218 timestamp=getseconds();
pegcjs 7:f93b7eaab5f6 219 wait(0.1);
pegcjs 6:ab2d7d0a9b07 220 FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 7:f93b7eaab5f6 221 fprintf(fp,"%e\n%e\n%e\n%e\n%d\n%d\n",eg1cal,eg2cal,eg3cal,pcal,scrubtime,timestamp);
pegcjs 7:f93b7eaab5f6 222
pegcjs 6:ab2d7d0a9b07 223 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 7:f93b7eaab5f6 224 wait(0.1);
pegcjs 6:ab2d7d0a9b07 225 }
pegcjs 6:ab2d7d0a9b07 226
pegcjs 1:9cff4feccbce 227
pegcjs 1:9cff4feccbce 228 // subroutine to calibreate o2 sesnors and store ca data in /local/CAL.dat
pegcjs 1:9cff4feccbce 229 void calibrate() {
pegcjs 1:9cff4feccbce 230 int count=1;
pegcjs 7:f93b7eaab5f6 231 float s1=0,s2=0,s3=0,pres=0;
pegcjs 1:9cff4feccbce 232 // average 20 readings for noise reduction
pegcjs 1:9cff4feccbce 233 g_lcd.cls();
pegcjs 1:9cff4feccbce 234 for (count=20; count>0; count--) {
pegcjs 1:9cff4feccbce 235 g_lcd.locate(0,0);
pegcjs 4:74df6d31ee0a 236 g_lcd.printf("Calibrate 21%% %.2d",count);
pegcjs 7:f93b7eaab5f6 237 s1=s1+EG1;
pegcjs 7:f93b7eaab5f6 238 s2=s2+EG2;
pegcjs 7:f93b7eaab5f6 239 s3=s3+EG3;
pegcjs 1:9cff4feccbce 240 pres=pres+PRESin;
pegcjs 1:9cff4feccbce 241 g_lcd.locate(0,1);
pegcjs 7:f93b7eaab5f6 242 g_lcd.printf("%1.2f: %1.2f: %1.2f",s1/(20-count+1),s2/(20-count+1),s3/(20-count+1));
pegcjs 1:9cff4feccbce 243 wait(1);
pegcjs 1:9cff4feccbce 244 }
pegcjs 1:9cff4feccbce 245 //average
pegcjs 7:f93b7eaab5f6 246 s1=s1/20-coff1;
pegcjs 7:f93b7eaab5f6 247 s2=s2/20-coff2;
pegcjs 7:f93b7eaab5f6 248 s3=s3/20-coff3;
pegcjs 1:9cff4feccbce 249 // set calibration variables
pegcjs 7:f93b7eaab5f6 250 eg1cal=s1;
pegcjs 7:f93b7eaab5f6 251 eg2cal=s2;
pegcjs 7:f93b7eaab5f6 252 eg3cal=s3;
pegcjs 7:f93b7eaab5f6 253 pcal=pres/20/DRATIO; // surface pressure output voltage from sensor
pegcjs 1:9cff4feccbce 254 scrubtime=0; // reset the scrubber timer to zero.
pegcjs 7:f93b7eaab5f6 255 scrubold=0; // set stored scrub time to zero too.
pegcjs 2:a1c26faa9103 256 // write cal data NB overwites previous
pegcjs 6:ab2d7d0a9b07 257 /* FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 6:ab2d7d0a9b07 258 fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime);
pegcjs 6:ab2d7d0a9b07 259 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...*/
pegcjs 6:ab2d7d0a9b07 260 store();
pegcjs 1:9cff4feccbce 261 }
pegcjs 1:9cff4feccbce 262
pegcjs 4:74df6d31ee0a 263 // sub to test if a variable is an even number
pegcjs 4:74df6d31ee0a 264 int iseven(int g) {
pegcjs 4:74df6d31ee0a 265 int test=0;
pegcjs 5:35417986539a 266 if (g%2 ==0) test=1;
pegcjs 4:74df6d31ee0a 267 return(test);
pegcjs 4:74df6d31ee0a 268 }
pegcjs 4:74df6d31ee0a 269
pegcjs 1:9cff4feccbce 270
pegcjs 2:a1c26faa9103 271 void status() {
pegcjs 7:f93b7eaab5f6 272 /* if (state==0) {
pegcjs 7:f93b7eaab5f6 273 g_lcd.character(7,0,33); // warning icon until 1 min up
pegcjs 7:f93b7eaab5f6 274 g_lcd.character(8,0,83); // surface icon - letter S
pegcjs 5:35417986539a 275 } else {
pegcjs 7:f93b7eaab5f6 276 g_lcd.character(7,0,32);
pegcjs 3:0d94a277aa8c 277 }
pegcjs 7:f93b7eaab5f6 278 if (state==1) g_lcd.character(8,0,83); // surface icon
pegcjs 7:f93b7eaab5f6 279 if (state==2 && iseven(seconds)==1) g_lcd.character(8,0,4); // diving icon - inverse D
pegcjs 7:f93b7eaab5f6 280 if (state==2 && iseven(seconds)==0) g_lcd.character(8,0,68); // diving icon - normal D
pegcjs 7:f93b7eaab5f6 281 */
pegcjs 7:f93b7eaab5f6 282 // yes - this does nothing as all this is now done by vmessage
pegcjs 4:74df6d31ee0a 283 }
pegcjs 3:0d94a277aa8c 284
pegcjs 3:0d94a277aa8c 285 // warning and LED conditions
pegcjs 2:a1c26faa9103 286
pegcjs 2:a1c26faa9103 287 void warning() {
pegcjs 7:f93b7eaab5f6 288 if (depth>=mod && flash==1) g_lcd.character(11,0,33);
pegcjs 7:f93b7eaab5f6 289 else g_lcd.character(11,0,32); // blank sapce
pegcjs 2:a1c26faa9103 290
pegcjs 2:a1c26faa9103 291 }
pegcjs 2:a1c26faa9103 292
pegcjs 4:74df6d31ee0a 293 // pick maximum of two values
pegcjs 7:f93b7eaab5f6 294 float maximum(float a,float b,float c) {
pegcjs 4:74df6d31ee0a 295 float maximum;
pegcjs 7:f93b7eaab5f6 296 if(a>b && a>c) maximum=a;
pegcjs 7:f93b7eaab5f6 297 if(b>a && b>c) maximum=b;
pegcjs 7:f93b7eaab5f6 298 if(c>a && c>b) maximum=c;
pegcjs 4:74df6d31ee0a 299 return(maximum);
pegcjs 4:74df6d31ee0a 300 }
pegcjs 4:74df6d31ee0a 301
pegcjs 7:f93b7eaab5f6 302 // pick minimum of three values
pegcjs 7:f93b7eaab5f6 303 float minimum(float a,float b,float c) {
pegcjs 4:74df6d31ee0a 304 float minim;
pegcjs 7:f93b7eaab5f6 305 if (a<b && a < c) minim=a;
pegcjs 7:f93b7eaab5f6 306 if(b<a && b<c) minim=b;
pegcjs 7:f93b7eaab5f6 307 if(c<a && c <b) minim=c;
pegcjs 7:f93b7eaab5f6 308
pegcjs 4:74df6d31ee0a 309 return(minim);
pegcjs 4:74df6d31ee0a 310 }
pegcjs 4:74df6d31ee0a 311
pegcjs 4:74df6d31ee0a 312
pegcjs 7:f93b7eaab5f6 313 // handset led control
pegcjs 2:a1c26faa9103 314 void leds() {
pegcjs 4:74df6d31ee0a 315 // first turn everything off
pegcjs 5:35417986539a 316 red=0;
pegcjs 5:35417986539a 317 green=0;
pegcjs 5:35417986539a 318 blue=0;
pegcjs 7:f93b7eaab5f6 319 float ppox,ppom,sp;
pegcjs 5:35417986539a 320 int mo=0;
pegcjs 7:f93b7eaab5f6 321 //mo=MODE;
pegcjs 7:f93b7eaab5f6 322 if(setpoint==0) sp=lowsetpoint;
pegcjs 7:f93b7eaab5f6 323 else sp=highsetpoint;
pegcjs 7:f93b7eaab5f6 324 ppox=maximum(ppo1,ppo2,ppo3); // use max value to compute leds...
pegcjs 7:f93b7eaab5f6 325 ppom=minimum(ppo1,ppo2,ppo3); // unless we want minimum
pegcjs 5:35417986539a 326 if (mo==0) { // CCR mode
pegcjs 7:f93b7eaab5f6 327 if (ppom<0.2 && flash==1) {red=1;} // flashing red means very bad things - getting very --low on oxygen!!!
pegcjs 7:f93b7eaab5f6 328 if (ppom>0.2 && ppox < (sp-0.15)) red=1; // non-flashing red
pegcjs 7:f93b7eaab5f6 329 if (ppox>=(sp-0.15) && ppox <(sp-0.5)) {
pegcjs 5:35417986539a 330 red=1; // red-green
pegcjs 5:35417986539a 331 green=1;
pegcjs 5:35417986539a 332 }
pegcjs 7:f93b7eaab5f6 333 if (ppox<(sp+0.05) && ppox >=(sp-0.05)) green=1; // green - optimal range in ccr mode
pegcjs 7:f93b7eaab5f6 334 if (ppox<(sp+0.15) && ppox >=(sp+0.05)) {
pegcjs 5:35417986539a 335 green=1; // green-blue - high ppo2 be careful of spiking
pegcjs 5:35417986539a 336 blue=1;
pegcjs 5:35417986539a 337 }
pegcjs 7:f93b7eaab5f6 338 if (ppox<1.6 && ppox>=(sp+0.15)) blue=1; // DANGER blue high ppo2
pegcjs 7:f93b7eaab5f6 339 if (ppox>=1.6 && flash==1) blue=1;
pegcjs 5:35417986539a 340 }
pegcjs 7:f93b7eaab5f6 341 /*if (mo==1) { // SCR mode
pegcjs 7:f93b7eaab5f6 342 if (ppom<0.2 && flash==1) red=1;
pegcjs 7:f93b7eaab5f6 343 if (ppom>=0.2 && ppox <0.26) red=1; // will give green red for low but not lethal ppo2s
pegcjs 7:f93b7eaab5f6 344 if (depth < 0.8*mod && ppom>0.2) green=1;
pegcjs 5:35417986539a 345 if (depth< mod && depth >=0.8*mod) {
pegcjs 5:35417986539a 346 green=1;
pegcjs 5:35417986539a 347 blue=1;
pegcjs 5:35417986539a 348 }
pegcjs 5:35417986539a 349 if (depth >=mod && flash==1) blue=1;
pegcjs 7:f93b7eaab5f6 350 }*/
pegcjs 6:ab2d7d0a9b07 351
pegcjs 1:9cff4feccbce 352 }
pegcjs 1:9cff4feccbce 353
pegcjs 4:74df6d31ee0a 354
pegcjs 4:74df6d31ee0a 355
pegcjs 1:9cff4feccbce 356 //read battery state and insert the battery symbol
pegcjs 1:9cff4feccbce 357 void battery() {
pegcjs 7:f93b7eaab5f6 358 char cgchar[32]={
pegcjs 7:f93b7eaab5f6 359 6,9,9,9,9,9,9,15, // battery empty symbol
pegcjs 7:f93b7eaab5f6 360 6,9,9,9,9,15,15,15, // battery 50% symbol
pegcjs 7:f93b7eaab5f6 361 6,9,9,15,15,15,15,15, // battery 75% symbol
pegcjs 7:f93b7eaab5f6 362 6,15,15,15,15,15,15,15, // battery 100% symbol
pegcjs 7:f93b7eaab5f6 363 };
pegcjs 7:f93b7eaab5f6 364
pegcjs 7:f93b7eaab5f6 365
pegcjs 7:f93b7eaab5f6 366 int batsym=0,i=0; // battery < 3.85V
pegcjs 7:f93b7eaab5f6 367
pegcjs 7:f93b7eaab5f6 368
pegcjs 7:f93b7eaab5f6 369 // idea to build in 6 levels of battery indicator by on the fly reprogramming character 2 as required.
pegcjs 7:f93b7eaab5f6 370 Vb=0;
pegcjs 7:f93b7eaab5f6 371 for (i=0; i<4; i++) {
pegcjs 7:f93b7eaab5f6 372 Vb=Vb+Vbatt; // read adc connected to battery via a 1/3 potential divider
pegcjs 7:f93b7eaab5f6 373 wait(0.05);
pegcjs 7:f93b7eaab5f6 374 }
pegcjs 7:f93b7eaab5f6 375 Vb=Vb/4; // average 4 readings to reduce noise
pegcjs 7:f93b7eaab5f6 376
pegcjs 7:f93b7eaab5f6 377 if (Vb>0.388) batsym=8; //3.85-3.92V
pegcjs 7:f93b7eaab5f6 378 if (Vb>0.395) batsym=16; // battery 3.92-4V
pegcjs 7:f93b7eaab5f6 379 if (Vb>0.404) batsym=24; // battery . >4V
pegcjs 7:f93b7eaab5f6 380
pegcjs 7:f93b7eaab5f6 381
pegcjs 7:f93b7eaab5f6 382 // write the appropriate battery symbol into the first custom character
pegcjs 7:f93b7eaab5f6 383 g_lcd.writeCommand(0x40); // set start address for CGRAM
pegcjs 7:f93b7eaab5f6 384 for (i=0; i<8; i++) {
pegcjs 7:f93b7eaab5f6 385 g_lcd.writeData(cgchar[i+batsym]);
pegcjs 7:f93b7eaab5f6 386 }
pegcjs 7:f93b7eaab5f6 387
pegcjs 7:f93b7eaab5f6 388 g_lcd.character(11,1,0); // battery symbol
pegcjs 7:f93b7eaab5f6 389 if (batsym ==0 && flash==0) g_lcd.character(11,1,32); // bung in space if flashing
pegcjs 7:f93b7eaab5f6 390
pegcjs 7:f93b7eaab5f6 391
pegcjs 1:9cff4feccbce 392 }
pegcjs 1:9cff4feccbce 393
pegcjs 7:f93b7eaab5f6 394 // sub to make the nice stop or no stop message work in locations 9,0 and 9,1
pegcjs 7:f93b7eaab5f6 395 void vmessage() {
pegcjs 7:f93b7eaab5f6 396 int i,d,cpos=0;
pegcjs 7:f93b7eaab5f6 397 // "INITSURFDIVE" in vertical chas - 1 custom char per two symbols
pegcjs 7:f93b7eaab5f6 398 char mesg[48]={ 17,31,17,0,31,6,12,31, 0,17,31,17,0,1,31,1, 19,21,25,0,31,16,31,0, 31,13,23,0,31,5,1,0, 31,17,14,0,17,31,17,0, 15,16,15,0,31,21,17,0};
pegcjs 7:f93b7eaab5f6 399
pegcjs 7:f93b7eaab5f6 400
pegcjs 7:f93b7eaab5f6 401
pegcjs 7:f93b7eaab5f6 402 g_lcd.writeCommand(104); // set start address for CGRAM characrter #6 out of 8
pegcjs 7:f93b7eaab5f6 403
pegcjs 7:f93b7eaab5f6 404 for (i=0; i<16; i++) { // write 2 chars worth into this segment NO DECO
pegcjs 7:f93b7eaab5f6 405
pegcjs 7:f93b7eaab5f6 406
pegcjs 7:f93b7eaab5f6 407 g_lcd.writeData(mesg[i+state*16]);
pegcjs 7:f93b7eaab5f6 408 } // endfor
pegcjs 7:f93b7eaab5f6 409
pegcjs 7:f93b7eaab5f6 410
pegcjs 7:f93b7eaab5f6 411
pegcjs 7:f93b7eaab5f6 412 g_lcd.character(12,0,5); // custom char 5
pegcjs 7:f93b7eaab5f6 413
pegcjs 7:f93b7eaab5f6 414 g_lcd.character(12,1,6); // custom char 6
pegcjs 7:f93b7eaab5f6 415
pegcjs 7:f93b7eaab5f6 416 }
pegcjs 7:f93b7eaab5f6 417
pegcjs 7:f93b7eaab5f6 418
pegcjs 2:a1c26faa9103 419 // subroutine to write the main display data
pegcjs 2:a1c26faa9103 420 //0123456789abcdef
pegcjs 2:a1c26faa9103 421
pegcjs 2:a1c26faa9103 422 //x.xx:xx D XX xx
pegcjs 2:a1c26faa9103 423 //x.xx:xx B XX xxx NB the warning, staus and battery icons are driven by separate subroutines.
pegcjs 2:a1c26faa9103 424 void display() {
pegcjs 7:f93b7eaab5f6 425 int mo=0,tmp=0;
pegcjs 7:f93b7eaab5f6 426 //mo=MODE;
pegcjs 7:f93b7eaab5f6 427 g_lcd.character(3,1,32);
pegcjs 2:a1c26faa9103 428 //1st line
pegcjs 7:f93b7eaab5f6 429
pegcjs 7:f93b7eaab5f6 430 //ppo1
pegcjs 7:f93b7eaab5f6 431 if(ppo1<1) tmp=(int)(ppo1*100); else tmp=(int)(ppo1*100-100);
pegcjs 7:f93b7eaab5f6 432 g_lcd.locate(1,0);
pegcjs 7:f93b7eaab5f6 433 g_lcd.printf("%02d ",tmp);
pegcjs 7:f93b7eaab5f6 434 if(ppo1>=1) g_lcd.character(0,0,2);
pegcjs 7:f93b7eaab5f6 435 if(ppo1<1) g_lcd.character(0,0,1);
pegcjs 7:f93b7eaab5f6 436
pegcjs 7:f93b7eaab5f6 437 if(ppo2<1) tmp=(int)(ppo2*100); else tmp=(int)(ppo2*100-100);
pegcjs 7:f93b7eaab5f6 438 g_lcd.locate(5,0);
pegcjs 7:f93b7eaab5f6 439 g_lcd.printf("%02d ",tmp);
pegcjs 7:f93b7eaab5f6 440 if(ppo2>=1) g_lcd.character(4,0,2);
pegcjs 7:f93b7eaab5f6 441 if(ppo2<1) g_lcd.character(4,0,1);
pegcjs 7:f93b7eaab5f6 442
pegcjs 7:f93b7eaab5f6 443 if(ppo3<1) tmp=(int)(ppo3*100); else tmp=(int)(ppo3*100-100);
pegcjs 7:f93b7eaab5f6 444 g_lcd.locate(9,0);
pegcjs 7:f93b7eaab5f6 445 g_lcd.printf("%02d ",tmp);
pegcjs 7:f93b7eaab5f6 446 if(ppo3>=1) g_lcd.character(8,0,2);
pegcjs 7:f93b7eaab5f6 447 if(ppo3<1) g_lcd.character(8,0,1);
pegcjs 7:f93b7eaab5f6 448
pegcjs 7:f93b7eaab5f6 449 g_lcd.locate(13,0);
pegcjs 7:f93b7eaab5f6 450 g_lcd.printf("%.2d",(int)depth); // depth
pegcjs 7:f93b7eaab5f6 451 g_lcd.locate(4,1);
pegcjs 7:f93b7eaab5f6 452 g_lcd.printf("%2dm",(int)mod); // mod
pegcjs 2:a1c26faa9103 453 //2nd line
pegcjs 2:a1c26faa9103 454 g_lcd.locate(0,1);
pegcjs 7:f93b7eaab5f6 455 tmp=minimum((float)fo1,(float)fo2,(float)fo3); // get min fraction of oxygen to display lowest for deco use
pegcjs 7:f93b7eaab5f6 456 g_lcd.printf("%2d%%",tmp);
pegcjs 7:f93b7eaab5f6 457 g_lcd.locate(13,1);
pegcjs 7:f93b7eaab5f6 458 g_lcd.printf("%03d",scrubtime % 1000); // modulo to avoid digits conflict - means divetime is always less than 100
pegcjs 7:f93b7eaab5f6 459 g_lcd.locate(8,1);
pegcjs 7:f93b7eaab5f6 460 g_lcd.printf("%2d",(int)(divetime/60) % 100 ); // rolls back to zero if go over 99
pegcjs 2:a1c26faa9103 461 // bung in battery icon
pegcjs 2:a1c26faa9103 462 battery();
pegcjs 5:35417986539a 463 status(); // this will set the diving / suface mode icon
pegcjs 7:f93b7eaab5f6 464 // warning(); // this will set the warning ic on assuming that max ppo2 is exceeded
pegcjs 7:f93b7eaab5f6 465 g_lcd.character(7,1,32); // space to cover any write error on top line
pegcjs 2:a1c26faa9103 466 leds(); // this sets the leds according to the various warning conditions
pegcjs 7:f93b7eaab5f6 467 /* if (mo==0) {
pegcjs 5:35417986539a 468 g_lcd.character(7,1,99); //'c' = ccr
pegcjs 5:35417986539a 469 } else {
pegcjs 5:35417986539a 470 g_lcd.character(7,1,115); //'s' = scr
pegcjs 7:f93b7eaab5f6 471 }*/
pegcjs 5:35417986539a 472 // custom character setting to sort out dp in depths
pegcjs 6:ab2d7d0a9b07 473
pegcjs 6:ab2d7d0a9b07 474
pegcjs 5:35417986539a 475 char cgchar[80]={
pegcjs 5:35417986539a 476 7,5,5,5,23,0,0,0, // .0
pegcjs 5:35417986539a 477 2,2,2,2,18,0,0,0, // .1
pegcjs 7:f93b7eaab5f6 478 7,1,7,4,23,0,0,0, // .2
pegcjs 7:f93b7eaab5f6 479 7,1,3,1,23,0,0,0, // .3
pegcjs 7:f93b7eaab5f6 480 5,5,7,1,17,0,0,0, //.4
pegcjs 7:f93b7eaab5f6 481 7,4,7,1,23,0,0,0, //.5
pegcjs 7:f93b7eaab5f6 482 7,4,7,5,23,0,0,0, //.6
pegcjs 5:35417986539a 483 7,1,2,2,18,0,0,0, //.7
pegcjs 5:35417986539a 484 7,5,7,5,23,0,0,0, //.8
pegcjs 5:35417986539a 485 7,5,7,1,17,0,0,0 //.9
pegcjs 5:35417986539a 486
pegcjs 5:35417986539a 487 };
pegcjs 7:f93b7eaab5f6 488 // special dp digit for depth
pegcjs 5:35417986539a 489 int i=0,d=0;
pegcjs 5:35417986539a 490 d=(int)((depth-(int)depth)*10); // should be size of the 1st decimal place
pegcjs 5:35417986539a 491 // do stuff here to set cstom chars
pegcjs 5:35417986539a 492 g_lcd.writeCommand(120); // set start address for CGRAM
pegcjs 5:35417986539a 493 for (i=0; i<8; i++) {
pegcjs 5:35417986539a 494 g_lcd.writeData(cgchar[i+d*8]);
pegcjs 5:35417986539a 495 }
pegcjs 5:35417986539a 496
pegcjs 7:f93b7eaab5f6 497 g_lcd.character(15,0,7); // put in appropriate custom character
pegcjs 7:f93b7eaab5f6 498
pegcjs 7:f93b7eaab5f6 499 // display the current setpoint information
pegcjs 7:f93b7eaab5f6 500 if(setpoint==0) g_lcd.character(7,1,218); // letter down arrow for low setpoint
pegcjs 7:f93b7eaab5f6 501 if(setpoint==1) g_lcd.character(7,1,217); // Letter 'H'
pegcjs 7:f93b7eaab5f6 502 if(flash==1) g_lcd.character(7,1,115); // Letter ':'
pegcjs 2:a1c26faa9103 503
pegcjs 2:a1c26faa9103 504 }
pegcjs 2:a1c26faa9103 505
pegcjs 2:a1c26faa9103 506
pegcjs 2:a1c26faa9103 507
pegcjs 1:9cff4feccbce 508
pegcjs 7:f93b7eaab5f6 509 // read sensors and generate calibrated outputs NB battery is read elsewhere
pegcjs 2:a1c26faa9103 510
pegcjs 1:9cff4feccbce 511 void readsensors() {
pegcjs 7:f93b7eaab5f6 512 float barometric=0,mod1,mod2,mod3,temp,Vdepth=0,s1,s2,s3,MPXref=0;
pegcjs 7:f93b7eaab5f6 513 int tc=0;
pegcjs 7:f93b7eaab5f6 514 // ppo1=EG1*0.21/eg1cal; // eg1cal is 0.21bar ppO2
pegcjs 7:f93b7eaab5f6 515 // ppo2=EG2*0.21/eg2cal; // second oxygen cell ppO2
pegcjs 7:f93b7eaab5f6 516 // ppo3=EG3*0.21/eg3cal;
pegcjs 7:f93b7eaab5f6 517
pegcjs 7:f93b7eaab5f6 518 s1=0;
pegcjs 7:f93b7eaab5f6 519 s2=0;
pegcjs 7:f93b7eaab5f6 520 s3=0;
pegcjs 7:f93b7eaab5f6 521 for(tc=0;tc<20;tc++) // noise on Vdepth so average readings to compensate
pegcjs 7:f93b7eaab5f6 522 {
pegcjs 7:f93b7eaab5f6 523 Vdepth=Vdepth+(PRESin/DRATIO); // read the depth sensor and calculate the real value rather using the dividing ratio
pegcjs 7:f93b7eaab5f6 524 wait_ms(10); // slows stuff down a bit but not a big problem
pegcjs 7:f93b7eaab5f6 525 s1=s1+EG1; // read o2 sensors
pegcjs 7:f93b7eaab5f6 526 s2=s2+EG2;
pegcjs 7:f93b7eaab5f6 527 s3=s3+EG3;
pegcjs 7:f93b7eaab5f6 528 MPXref=MPXref+V5V; // read 5V
pegcjs 7:f93b7eaab5f6 529 wait_ms(10); // slows stuff down a bit but not a big problem
pegcjs 7:f93b7eaab5f6 530 }
pegcjs 7:f93b7eaab5f6 531 Vdepth=Vdepth/20; // now have the average
pegcjs 7:f93b7eaab5f6 532 s1=s1/20-coff1;
pegcjs 7:f93b7eaab5f6 533 s2=s2/20-coff2;
pegcjs 7:f93b7eaab5f6 534 s3=s3/20-coff3;
pegcjs 7:f93b7eaab5f6 535 MPXref=MPXref/20*3.3*2; // should be 5V
pegcjs 6:ab2d7d0a9b07 536
pegcjs 7:f93b7eaab5f6 537
pegcjs 7:f93b7eaab5f6 538 // compute ppO2s
pegcjs 7:f93b7eaab5f6 539 ppo1=s1*0.21/eg1cal;
pegcjs 7:f93b7eaab5f6 540 ppo2=s2*0.21/eg2cal;
pegcjs 7:f93b7eaab5f6 541 ppo3=s3*0.21/eg3cal;
pegcjs 7:f93b7eaab5f6 542
pegcjs 7:f93b7eaab5f6 543 pc.printf("EG1=%f\tEG2=%f\tEG3=%f \tMPXref=%f \r",s1,s2,s3,MPXref);
pegcjs 7:f93b7eaab5f6 544 pressure=(Vdepth*3.3/MPXref-0.04)/0.0012858; // pressure in kpa NB - assums that the 5V is correct
pegcjs 7:f93b7eaab5f6 545 //pressure=(PRESin*3.3/0.65006-0.04)/(0.0012858); // pressure in kPa assuming standard cal for mpx5700 sensor SUSPECT
pegcjs 7:f93b7eaab5f6 546 // NB the mpx5700 runs off 5v so would be better to divide its output down by 3/5 to get full range measurement
pegcjs 7:f93b7eaab5f6 547 //outputs. with no division the max mbed adc of 3.3V coresponds to 480kpa or about 38m depth.....
pegcjs 7:f93b7eaab5f6 548 // standard spec on mpx5700 should be 5V*(P*0.0012858+0.04)
pegcjs 7:f93b7eaab5f6 549 // new sensor has 3/5 divider built into sensor wiring.
pegcjs 7:f93b7eaab5f6 550 //barometric=(pcal*3.3/0.65006-0.004)/(0.0012858); // sealevel in kPa assuming standard cal for mpx5700 sensor
pegcjs 7:f93b7eaab5f6 551 barometric=(pcal*3.3/MPXref-0.04)/0.0012858; // barometric pressure (kpa) evaluated from calibration which we assume is baseline
pegcjs 5:35417986539a 552 depth=(pressure-barometric)*0.1; //100kPa=10m 1kPa=0.1m - this gives depth in m for freshwater.
pegcjs 7:f93b7eaab5f6 553
pegcjs 7:f93b7eaab5f6 554 if (depth<0) depth=0; // deals wtih noise that may lead to small variation in values
pegcjs 2:a1c26faa9103 555
pegcjs 7:f93b7eaab5f6 556 // THESE SHOULD BE JUST 100*ppox/(pressure/100);
pegcjs 5:35417986539a 557 fo1=100*ppo1/((pressure-barometric)/100+1); // pressure in bar = pressure /100 and want a % so multiply by 100 as well
pegcjs 5:35417986539a 558 fo2=100*ppo2/((pressure-barometric)/100+1);
pegcjs 7:f93b7eaab5f6 559 fo3=100*ppo3/((pressure-barometric)/100+1); // maybe these should be ppox/(depth/10+1)*100....?
pegcjs 6:ab2d7d0a9b07 560
pegcjs 7:f93b7eaab5f6 561 /*if (fo1<0) fo2=0;
pegcjs 6:ab2d7d0a9b07 562 if (fo2<0) fo1=0;
pegcjs 7:f93b7eaab5f6 563 */
pegcjs 7:f93b7eaab5f6 564 //with three sensors will calculate mod from the largest ppo2 reading
pegcjs 2:a1c26faa9103 565 mod1=(1.4/(fo1/100)-1)*10;
pegcjs 2:a1c26faa9103 566 mod2=(1.4/(fo2/100)-1)*10;
pegcjs 7:f93b7eaab5f6 567 mod3=(1.4/(fo3/100)-1)*10;
pegcjs 3:0d94a277aa8c 568
pegcjs 7:f93b7eaab5f6 569 mod=minimum(mod1,mod2,mod3); // pick the least value
pegcjs 7:f93b7eaab5f6 570
pegcjs 7:f93b7eaab5f6 571 // output for debugging to pc via usb line.
pegcjs 7:f93b7eaab5f6 572 // pc.printf("VDepth %f\tPressure %f\tbarometric %f\tdepth %f\t \n\r",Vdepth,pressure,barometric,depth);
pegcjs 7:f93b7eaab5f6 573 //NB - problem - we really need to monitor the 5V power line to ensure that it's driving the depth sensor ok.
pegcjs 7:f93b7eaab5f6 574 // it may need thicker cables as it currently only manages 4.8V on the board when everything is running.
pegcjs 3:0d94a277aa8c 575
pegcjs 1:9cff4feccbce 576 }
pegcjs 6:ab2d7d0a9b07 577 // get values back from cal file on local drive
pegcjs 6:ab2d7d0a9b07 578 void recall() {
pegcjs 6:ab2d7d0a9b07 579 FILE *fp=fopen("/local/CAL.dat","r");
pegcjs 7:f93b7eaab5f6 580 fscanf(fp,"%e\n%e\n%e\n%e\n%d",&eg1cal,&eg2cal,&eg3cal,&pcal,&scrubold);
pegcjs 6:ab2d7d0a9b07 581 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 6:ab2d7d0a9b07 582 }
pegcjs 6:ab2d7d0a9b07 583
pegcjs 6:ab2d7d0a9b07 584 // write the logfile opened and closed by start and end of dive
pegcjs 6:ab2d7d0a9b07 585 void store_log() {
pegcjs 7:f93b7eaab5f6 586
pegcjs 6:ab2d7d0a9b07 587 //FILE *fp=fopen("/local/divelog.dat","a");
pegcjs 7:f93b7eaab5f6 588 float v5=0;
pegcjs 7:f93b7eaab5f6 589 v5=V5V;
pegcjs 7:f93b7eaab5f6 590 fprintf(lp,"%d\t%e\t%e\t%e\t%e\t%e\t%e\t%d\n",seconds,depth,ppo1,ppo2,ppo3,Vb,v5,scrubtime);
pegcjs 7:f93b7eaab5f6 591
pegcjs 7:f93b7eaab5f6 592 if (divetime % 60==0) fflush(lp);
pegcjs 7:f93b7eaab5f6 593 // fclose(fp);
pegcjs 7:f93b7eaab5f6 594 }
pegcjs 7:f93b7eaab5f6 595
pegcjs 7:f93b7eaab5f6 596 // read switches and report state
pegcjs 7:f93b7eaab5f6 597 int switches() {
pegcjs 7:f93b7eaab5f6 598 int ss=0;
pegcjs 7:f93b7eaab5f6 599 if (SW1==1 && SW2==1) ss=3;
pegcjs 7:f93b7eaab5f6 600 if (SW2==1 && SW1==0) ss=2;
pegcjs 7:f93b7eaab5f6 601 if (SW1==1 && SW2==0) ss=1;
pegcjs 7:f93b7eaab5f6 602 return(ss);
pegcjs 6:ab2d7d0a9b07 603 }
pegcjs 4:74df6d31ee0a 604
pegcjs 7:f93b7eaab5f6 605 // interpret the ppo2 data into a simple set of hud codes.
pegcjs 7:f93b7eaab5f6 606 int HUD_display()
pegcjs 7:f93b7eaab5f6 607 {
pegcjs 7:f93b7eaab5f6 608 int i,j3,h1,h2,h3;
pegcjs 7:f93b7eaab5f6 609 float cset=0;
pegcjs 7:f93b7eaab5f6 610 char gcode[6]={0,1,3,2,6,4}; // grey code for HUD reading 'red,amber,green,cyan,blue'
pegcjs 7:f93b7eaab5f6 611
pegcjs 7:f93b7eaab5f6 612 HUD_clr(); // clear the HUID ready for write
pegcjs 7:f93b7eaab5f6 613
pegcjs 7:f93b7eaab5f6 614
pegcjs 7:f93b7eaab5f6 615 if(setpoint==0) // low setpoint
pegcjs 7:f93b7eaab5f6 616 {
pegcjs 7:f93b7eaab5f6 617 cset=lowsetpoint;
pegcjs 7:f93b7eaab5f6 618 }
pegcjs 7:f93b7eaab5f6 619
pegcjs 7:f93b7eaab5f6 620 if(setpoint==1) // hgh setpoint
pegcjs 7:f93b7eaab5f6 621 {
pegcjs 7:f93b7eaab5f6 622 cset=highsetpoint;
pegcjs 7:f93b7eaab5f6 623 }
pegcjs 7:f93b7eaab5f6 624
pegcjs 7:f93b7eaab5f6 625 h1=(int)((ppo1-cset)/0.1+3.5);
pegcjs 7:f93b7eaab5f6 626 if(h1<1) h1=1;
pegcjs 7:f93b7eaab5f6 627 if(h1>5) h1=5;
pegcjs 7:f93b7eaab5f6 628 h2=(int)((ppo2-cset)/0.1+3.5);
pegcjs 7:f93b7eaab5f6 629 if(h2<1) h2=1;
pegcjs 7:f93b7eaab5f6 630 if(h2>5) h2=5;
pegcjs 7:f93b7eaab5f6 631 h3=(int)((ppo3-cset)/0.1+3.5);
pegcjs 7:f93b7eaab5f6 632 if(h3<1) h3=1;
pegcjs 7:f93b7eaab5f6 633 if(h3>5) h3=5;
pegcjs 7:f93b7eaab5f6 634
pegcjs 7:f93b7eaab5f6 635 if(h3>3) btest=0; // handle extra blue connected to btest setting btest low lights blue led
pegcjs 7:f93b7eaab5f6 636
pegcjs 7:f93b7eaab5f6 637
pegcjs 7:f93b7eaab5f6 638 i=gcode[h1]+8*gcode[h2]+64*gcode[h3]; // this is possible bigger than a char so have to typeconvert
pegcjs 7:f93b7eaab5f6 639 HUD_write(i);
pegcjs 7:f93b7eaab5f6 640
pegcjs 7:f93b7eaab5f6 641 }
pegcjs 7:f93b7eaab5f6 642
pegcjs 7:f93b7eaab5f6 643 // sub to flash HUD n times as a warning of setpoint shift
pegcjs 7:f93b7eaab5f6 644 int HUD_flash(int n)
pegcjs 7:f93b7eaab5f6 645 {
pegcjs 7:f93b7eaab5f6 646 int i;
pegcjs 7:f93b7eaab5f6 647 for(i=0;i<n;i++)
pegcjs 7:f93b7eaab5f6 648 {
pegcjs 7:f93b7eaab5f6 649 HUD_clr();
pegcjs 7:f93b7eaab5f6 650 wait(0.2);
pegcjs 7:f93b7eaab5f6 651 HUD_white();
pegcjs 7:f93b7eaab5f6 652 wait(0.05);
pegcjs 7:f93b7eaab5f6 653 }
pegcjs 7:f93b7eaab5f6 654 }
pegcjs 7:f93b7eaab5f6 655
pegcjs 7:f93b7eaab5f6 656 int setswitch()
pegcjs 7:f93b7eaab5f6 657 {
pegcjs 7:f93b7eaab5f6 658 if(setpoint==0 && depth >(switchdepth+0.5))
pegcjs 7:f93b7eaab5f6 659 {
pegcjs 7:f93b7eaab5f6 660 setpoint=1; // handle switch from low to high
pegcjs 7:f93b7eaab5f6 661 HUD_flash(4);
pegcjs 7:f93b7eaab5f6 662 // flash the hud here
pegcjs 7:f93b7eaab5f6 663 }
pegcjs 7:f93b7eaab5f6 664
pegcjs 7:f93b7eaab5f6 665 if(setpoint==1 && depth < (switchdepth -0.5))
pegcjs 7:f93b7eaab5f6 666 {
pegcjs 7:f93b7eaab5f6 667 setpoint=0; // swtich to low setpoint
pegcjs 7:f93b7eaab5f6 668 HUD_flash(2);
pegcjs 7:f93b7eaab5f6 669 // flash the HUD here
pegcjs 7:f93b7eaab5f6 670 }
pegcjs 7:f93b7eaab5f6 671 }
pegcjs 1:9cff4feccbce 672
pegcjs 1:9cff4feccbce 673 int main() {
pegcjs 2:a1c26faa9103 674 // first some local variables
pegcjs 2:a1c26faa9103 675 int startuptime=getseconds();
pegcjs 4:74df6d31ee0a 676 int startdive=0,endclock=0; // value of seconds when dive starts and counter to decide if dive complete...
pegcjs 1:9cff4feccbce 677
pegcjs 6:ab2d7d0a9b07 678 int minutes=0; // minutes is elapsed minutes since start of prog
pegcjs 7:f93b7eaab5f6 679 int j=0,scount=1;; // general loop counting variable
pegcjs 7:f93b7eaab5f6 680 int sw=0; // status of the switches in the handset
pegcjs 7:f93b7eaab5f6 681 char schars[4]={32,0xd9,0xda,0xfb}; // up arrow, down arrow and both arrows;
pegcjs 6:ab2d7d0a9b07 682
pegcjs 7:f93b7eaab5f6 683 bool mdir=0;
pegcjs 1:9cff4feccbce 684
pegcjs 1:9cff4feccbce 685 set_custom_char(); // does what it says on the tin really
pegcjs 1:9cff4feccbce 686 g_lcd.cls();
pegcjs 1:9cff4feccbce 687 g_lcd.locate(0, 0);
pegcjs 1:9cff4feccbce 688 g_lcd.printf( "RebMon");
pegcjs 1:9cff4feccbce 689 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 690 g_lcd.printf("CAL?");
pegcjs 1:9cff4feccbce 691 battery();
pegcjs 4:74df6d31ee0a 692 j=0;
pegcjs 7:f93b7eaab5f6 693 wait(0.2);
pegcjs 7:f93b7eaab5f6 694
pegcjs 6:ab2d7d0a9b07 695 // get cal values last used from local drive
pegcjs 6:ab2d7d0a9b07 696 recall();
pegcjs 6:ab2d7d0a9b07 697 // display the correct scrubber time
pegcjs 7:f93b7eaab5f6 698 scrubtime=scrubold;
pegcjs 1:9cff4feccbce 699 // hang about waiting for the cal switch to be pressed in ccase it is
pegcjs 7:f93b7eaab5f6 700 while (scount<30) {
pegcjs 7:f93b7eaab5f6 701 seconds=getseconds(); // NB if this hangs then nothing works :( - usually means 5V is dodgy
pegcjs 7:f93b7eaab5f6 702 red=1;
pegcjs 7:f93b7eaab5f6 703 green=1;
pegcjs 7:f93b7eaab5f6 704 blue=1; // light all leds
pegcjs 7:f93b7eaab5f6 705
pegcjs 1:9cff4feccbce 706 g_lcd.locate(5,1);
pegcjs 7:f93b7eaab5f6 707 g_lcd.printf("%.2d ",30-scount);
pegcjs 4:74df6d31ee0a 708 if (j>1) flash=1;
pegcjs 3:0d94a277aa8c 709 else flash=0;
pegcjs 1:9cff4feccbce 710 battery(); // bung in battery symbol.
pegcjs 1:9cff4feccbce 711 g_lcd.locate(7,0);
pegcjs 1:9cff4feccbce 712 g_lcd.printf( "%.2d:%.2d:%.2d", hours,min,sec);
pegcjs 7:f93b7eaab5f6 713 // if (CAL==0) {
pegcjs 7:f93b7eaab5f6 714 if(SW1==0) {
pegcjs 1:9cff4feccbce 715 calibrate();
pegcjs 7:f93b7eaab5f6 716 scount=31; // make sure it goes to next frame ok
pegcjs 1:9cff4feccbce 717 }
pegcjs 7:f93b7eaab5f6 718 wait(0.05);
pegcjs 7:f93b7eaab5f6 719
pegcjs 7:f93b7eaab5f6 720
pegcjs 3:0d94a277aa8c 721 j=(j+1) % 4;
pegcjs 7:f93b7eaab5f6 722 if(flash==0) HUD_white();
pegcjs 7:f93b7eaab5f6 723 else HUD_clr();
pegcjs 7:f93b7eaab5f6 724 scount++;
pegcjs 7:f93b7eaab5f6 725 }
pegcjs 1:9cff4feccbce 726 g_lcd.cls();
pegcjs 5:35417986539a 727
pegcjs 1:9cff4feccbce 728
pegcjs 1:9cff4feccbce 729 // ok there are three states in this system
pegcjs 1:9cff4feccbce 730 //MAIN LOOP ONCE STARTUP PROTOCOLS ARE COMPLETED
pegcjs 3:0d94a277aa8c 731 j=0;
pegcjs 7:f93b7eaab5f6 732 g_lcd.cls();
pegcjs 1:9cff4feccbce 733 while (1) {
pegcjs 7:f93b7eaab5f6 734 wait(0.1); //stop screen flicker
pegcjs 1:9cff4feccbce 735 readsensors();
pegcjs 7:f93b7eaab5f6 736 setswitch(); // check the setpoint and adjust if crossing the swtich depth
pegcjs 7:f93b7eaab5f6 737 HUD_display(); // write the HUD codes
pegcjs 2:a1c26faa9103 738 seconds=getseconds();
pegcjs 4:74df6d31ee0a 739 minutes=(int)(((float)seconds-(float)startuptime)/60);
pegcjs 7:f93b7eaab5f6 740 led1=seconds % 2; // flash the onboard led to make it clear stuff is running
pegcjs 3:0d94a277aa8c 741
pegcjs 3:0d94a277aa8c 742 if (j>1) flash=1;
pegcjs 3:0d94a277aa8c 743 else flash=0;
pegcjs 3:0d94a277aa8c 744
pegcjs 3:0d94a277aa8c 745 display(); // write the display
pegcjs 7:f93b7eaab5f6 746 HUD_display(); // write the HUD
pegcjs 7:f93b7eaab5f6 747 // sw=switches(); // read the switches and report their state
pegcjs 7:f93b7eaab5f6 748 // if(SW1==0) g_lcd.character(11,0,0xEF); else g_lcd.character(11,0,32); // NB here is possible alternate display underwater switching point
pegcjs 7:f93b7eaab5f6 749 // HERE do deco calcs - update tissues and compute desat , nostop or ascent times as required.
pegcjs 3:0d94a277aa8c 750
pegcjs 3:0d94a277aa8c 751 // setup state variable
pegcjs 7:f93b7eaab5f6 752 if (minutes<1) state=0; // startup mode - do nothing just wait to allow sensor readings to settle.
pegcjs 4:74df6d31ee0a 753 if (minutes>=1 && state==0) state=1; // surface mode - ok to go for a dive now
pegcjs 6:ab2d7d0a9b07 754 if (minutes>=1 && depth>0.8 && state==1) {
pegcjs 3:0d94a277aa8c 755 state=2; // enter dive mode
pegcjs 6:ab2d7d0a9b07 756 lp=fopen("/local/divelog.dat","a");
pegcjs 7:f93b7eaab5f6 757 fprintf(lp,"#startdive = %d\n#seconds\tdepth\tppo1\tppo2\tppo3\tVb\t\tV5V\tscrubtime\n",seconds); // bung in a header here in case one needs it
pegcjs 4:74df6d31ee0a 758 if (startdive==0) startdive=seconds; // set start of divetime. don't do this twice
pegcjs 3:0d94a277aa8c 759 endclock=0; // reset end of dive clock
pegcjs 3:0d94a277aa8c 760 }
pegcjs 7:f93b7eaab5f6 761 // in dive mode - things to do, 1 update divetime and scrubber time, 2 write log data 3 check for end of dive...
pegcjs 7:f93b7eaab5f6 762 if (state==2) {
pegcjs 7:f93b7eaab5f6 763 // divetime=(int)(((float)seconds-(float)startdive)/60.0); // time since start of dive in minutes.
pegcjs 7:f93b7eaab5f6 764 divetime=(seconds-startdive); // divetime no recorded in seconds since start of dive
pegcjs 7:f93b7eaab5f6 765
pegcjs 3:0d94a277aa8c 766 // do deco calcs here when implemented
pegcjs 7:f93b7eaab5f6 767 if (divetime %15 ==0) store_log(); // this saves the dive profile and sensor optputs in a file called divelog.dat every 15s
pegcjs 7:f93b7eaab5f6 768 if (depth<=0.5) {
pegcjs 4:74df6d31ee0a 769 endclock=endclock+1;
pegcjs 4:74df6d31ee0a 770
pegcjs 6:ab2d7d0a9b07 771 if (endclock>150) {
pegcjs 7:f93b7eaab5f6 772 state=1; // 30s at shallower than 0.3m and we return to surface mode. */
pegcjs 6:ab2d7d0a9b07 773 FILE *fp=fopen("/local/CAL.dat","w");
pegcjs 6:ab2d7d0a9b07 774 fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime);
pegcjs 6:ab2d7d0a9b07 775 fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...
pegcjs 7:f93b7eaab5f6 776
pegcjs 7:f93b7eaab5f6 777 store();
pegcjs 6:ab2d7d0a9b07 778 fclose(lp);
pegcjs 7:f93b7eaab5f6 779 } // endif endclock
pegcjs 7:f93b7eaab5f6 780
pegcjs 7:f93b7eaab5f6 781 } // end if depth
pegcjs 7:f93b7eaab5f6 782 scrubtime=scrubold+(divetime/60); //
pegcjs 7:f93b7eaab5f6 783 } // end state 2
pegcjs 1:9cff4feccbce 784
pegcjs 1:9cff4feccbce 785
pegcjs 3:0d94a277aa8c 786 j=(j+1) %4; // flash control variable = used to make the warnings flash for 0.4s duty cycle
pegcjs 7:f93b7eaab5f6 787
pegcjs 7:f93b7eaab5f6 788
pegcjs 7:f93b7eaab5f6 789 vmessage(); // call to generate status message in vertical segment
pegcjs 1:9cff4feccbce 790 } // end while
pegcjs 1:9cff4feccbce 791 } //end main
pegcjs 1:9cff4feccbce 792
pegcjs 1:9cff4feccbce 793
pegcjs 1:9cff4feccbce 794
pegcjs 1:9cff4feccbce 795