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:
Thu Aug 02 14:55:08 2012 +0000
Revision:
1:9cff4feccbce
Parent:
0:52d05d950581
Child:
2:a1c26faa9103
barebones in place - max and min functions just added along wtih readsesnors display etc

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 1:9cff4feccbce 52 // variables for the eg cells and pressure sensor eg1calamd eg2cal ar reading when the sensor is in 0.21bar O2 and
pegcjs 1:9cff4feccbce 53 //dcal is the reading whe the pressure sensor is at the surface
pegcjs 1:9cff4feccbce 54 float eg1cal=0.09,eg2cal=0.09,pcal=0.1136;
pegcjs 1:9cff4feccbce 55 // NB these are updated from /local/cal.dat so values not so important.... eventually
pegcjs 1:9cff4feccbce 56
pegcjs 1:9cff4feccbce 57 float depth=0,ppo1=0,ppo2=0, Vb=0,pressure=0; // depth, 1st o2 sensor second o2 sensor battery voltage,,Pressure
pegcjs 1:9cff4feccbce 58 float fo1=0,fo2=0,mod=55; //%f values,mod
pegcjs 1:9cff4feccbce 59 //===== sub to get time from ds1307 and create the 'seconds' which is a version of timestamp....
pegcjs 1:9cff4feccbce 60 int getseconds() {
pegcjs 1:9cff4feccbce 61 my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year);
pegcjs 1:9cff4feccbce 62 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days.
pegcjs 1:9cff4feccbce 63 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 64 //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days....
pegcjs 1:9cff4feccbce 65 // ie wrong but simpler than the real thing
pegcjs 1:9cff4feccbce 66 return(seconds);
pegcjs 1:9cff4feccbce 67 }
pegcjs 1:9cff4feccbce 68
pegcjs 1:9cff4feccbce 69
pegcjs 1:9cff4feccbce 70 void set_custom_char() {
pegcjs 1:9cff4feccbce 71 char cgchar[64]={
pegcjs 1:9cff4feccbce 72 6,9,9,9,9,9,9,15, // battery empty symbol 0
pegcjs 1:9cff4feccbce 73 6,9,9,9,9,15,15,15, // battery 50% symbol 1
pegcjs 1:9cff4feccbce 74 6,9,9,15,15,15,15,15, // battery 75% symbol 2
pegcjs 1:9cff4feccbce 75 6,15,15,15,15,15,15,15, // battery 100% symbol 3
pegcjs 1:9cff4feccbce 76 31,19,21,21,21,21,19,31, // diving symbol 4 inverse D
pegcjs 1:9cff4feccbce 77 6,6,6,6,6,0,0,6, // warning symbol 5
pegcjs 1:9cff4feccbce 78 31,17,23,17,29,17,31,0, // surface symbol 6 inverse S
pegcjs 1:9cff4feccbce 79 0,0,9,9,0,17,14,0 // happy symbol 7
pegcjs 1:9cff4feccbce 80 };
pegcjs 1:9cff4feccbce 81 int i=0;
pegcjs 1:9cff4feccbce 82 // do stuff here to set cstom chars
pegcjs 1:9cff4feccbce 83 g_lcd.writeCommand(0x40); // set start address for CGRAM
pegcjs 1:9cff4feccbce 84 for (i=0; i<64; i++) {
pegcjs 1:9cff4feccbce 85 g_lcd.writeData(cgchar[i]);
pegcjs 1:9cff4feccbce 86 }
pegcjs 1:9cff4feccbce 87
pegcjs 1:9cff4feccbce 88 }
pegcjs 1:9cff4feccbce 89
pegcjs 1:9cff4feccbce 90
pegcjs 1:9cff4feccbce 91 // subroutine to calibreate o2 sesnors and store ca data in /local/CAL.dat
pegcjs 1:9cff4feccbce 92 void calibrate() {
pegcjs 1:9cff4feccbce 93 int count=1;
pegcjs 1:9cff4feccbce 94 float ppo1=0,ppo2=0,pres=0;
pegcjs 1:9cff4feccbce 95 // average 20 readings for noise reduction
pegcjs 1:9cff4feccbce 96 g_lcd.cls();
pegcjs 1:9cff4feccbce 97 for (count=20; count>0; count--) {
pegcjs 1:9cff4feccbce 98 g_lcd.locate(0,0);
pegcjs 1:9cff4feccbce 99 g_lcd.printf("Calibrating %.2d",count);
pegcjs 1:9cff4feccbce 100 ppo1=ppo1+EG1;
pegcjs 1:9cff4feccbce 101 ppo2=ppo2+EG2;
pegcjs 1:9cff4feccbce 102 pres=pres+PRESin;
pegcjs 1:9cff4feccbce 103 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 104 g_lcd.printf("%1.2f: %1.2f: %1.2f",ppo1/(20-count+1),ppo2/(20-count+1),pres/(20-count+1));
pegcjs 1:9cff4feccbce 105 wait(1);
pegcjs 1:9cff4feccbce 106 }
pegcjs 1:9cff4feccbce 107 //average
pegcjs 1:9cff4feccbce 108 ppo1=ppo1/20;
pegcjs 1:9cff4feccbce 109 ppo2=ppo2/20;
pegcjs 1:9cff4feccbce 110 // set calibration variables
pegcjs 1:9cff4feccbce 111 eg1cal=ppo1;
pegcjs 1:9cff4feccbce 112 eg2cal=ppo2;
pegcjs 1:9cff4feccbce 113 pcal=pres/20; // surface pressure....
pegcjs 1:9cff4feccbce 114 scrubtime=0; // reset the scrubber timer to zero.
pegcjs 1:9cff4feccbce 115 }
pegcjs 1:9cff4feccbce 116
pegcjs 1:9cff4feccbce 117 // subroutine to write the main display data
pegcjs 1:9cff4feccbce 118 //0123456789abcdef
pegcjs 1:9cff4feccbce 119
pegcjs 1:9cff4feccbce 120 //x.xx:xx D XX xx
pegcjs 1:9cff4feccbce 121 //x.xx:xx B XX xxx NB the warning, staus and battery icons are driven by separate subroutines.
pegcjs 1:9cff4feccbce 122 void display() {
pegcjs 1:9cff4feccbce 123 //1st line
pegcjs 1:9cff4feccbce 124 g_lcd.locate(0,0);
pegcjs 1:9cff4feccbce 125 g_lcd.printf("%1.2f:%.2d X %.2d %.2d",ppo1,(int)fo1,(int)depth,(int)mod);
pegcjs 1:9cff4feccbce 126 //2nd line
pegcjs 1:9cff4feccbce 127 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 128 g_lcd.printf("%1.2f:%.2d B %.2d %.2d",ppo2,(int)fo2,(int)depth,(int)mod);
pegcjs 1:9cff4feccbce 129 }
pegcjs 1:9cff4feccbce 130
pegcjs 1:9cff4feccbce 131 //read battery state and insert the battery symbol
pegcjs 1:9cff4feccbce 132 void battery() {
pegcjs 1:9cff4feccbce 133 int batsym=0;
pegcjs 1:9cff4feccbce 134 Vb=Vbatt; // read adc connected to battery via a 1/3 potential divider
pegcjs 1:9cff4feccbce 135 if (Vb>0.606) batsym=1;
pegcjs 1:9cff4feccbce 136 if (Vb>0.707) batsym=2;
pegcjs 1:9cff4feccbce 137 if (Vb>0.808) batsym=3;
pegcjs 1:9cff4feccbce 138 g_lcd.character(8,1,batsym);
pegcjs 1:9cff4feccbce 139 }
pegcjs 1:9cff4feccbce 140
pegcjs 1:9cff4feccbce 141 // pick maximum of two values
pegcjs 1:9cff4feccbce 142 float maximum(float a,float b) {
pegcjs 1:9cff4feccbce 143 float maximum;
pegcjs 1:9cff4feccbce 144 if (a>b) maximum=a;
pegcjs 1:9cff4feccbce 145 else maximum=b;
pegcjs 1:9cff4feccbce 146 return(maximum);
pegcjs 1:9cff4feccbce 147 }
pegcjs 1:9cff4feccbce 148
pegcjs 1:9cff4feccbce 149 // pick minimum of two values
pegcjs 1:9cff4feccbce 150 float minimum(float a,float b) {
pegcjs 1:9cff4feccbce 151 float minim;
pegcjs 1:9cff4feccbce 152 if (a<b) minim=a;
pegcjs 1:9cff4feccbce 153 else minim=b;
pegcjs 1:9cff4feccbce 154 return(minim);
pegcjs 1:9cff4feccbce 155 }
pegcjs 1:9cff4feccbce 156
pegcjs 1:9cff4feccbce 157
pegcjs 1:9cff4feccbce 158
pegcjs 1:9cff4feccbce 159 // read sensors and generate calibrated outputs
pegcjs 1:9cff4feccbce 160 void readsensors() {
pegcjs 1:9cff4feccbce 161 float barometric=0,mod1,mod2;
pegcjs 1:9cff4feccbce 162 ppo1=EG1*0.21/eg1cal; // eg1cal is 0.21bar ppO2
pegcjs 1:9cff4feccbce 163 ppo2=EG2*0.21/eg2cal; // second oxygen cell ppO2
pegcjs 1:9cff4feccbce 164 pressure=(PRESin*3.3-0.024)/(0.0038574); // pressure in kPa assuming standard cal for mpx5700 sensor
pegcjs 1:9cff4feccbce 165 barometric=(pcal*3.3-0.024)/(0.0038574); // sealevel in kPa assuming standard cal for mpx5700 sensor
pegcjs 1:9cff4feccbce 166 depth=(pressure-barometric)*0.1; //100kPa=10m 1kPa=0.1m - this gives depth in m for freshwater.
pegcjs 1:9cff4feccbce 167 //with two sensors will calculate mod from the largest ppo2 reading
pegcjs 1:9cff4feccbce 168 mod1=1.4/ppo1;
pegcjs 1:9cff4feccbce 169 mod2=1.4/ppo2;
pegcjs 1:9cff4feccbce 170 mod=minimum(mod1,mod2); // pick the
pegcjs 1:9cff4feccbce 171 }
pegcjs 1:9cff4feccbce 172
pegcjs 1:9cff4feccbce 173 int main() {
pegcjs 1:9cff4feccbce 174 // get time to log a startup time
pegcjs 1:9cff4feccbce 175 //my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year);
pegcjs 1:9cff4feccbce 176 //int startuptime=year*365*24*60*60+month*30*24*60*60+day*24*60*60+hours*60*60+min*60+sec; //simple timestamp = # seconds since midnight jan 1st 2000 if all months were 30 days.
pegcjs 1:9cff4feccbce 177
pegcjs 1:9cff4feccbce 178 int startuptime=getseconds();
pegcjs 1:9cff4feccbce 179 int startdive=0;
pegcjs 1:9cff4feccbce 180
pegcjs 1:9cff4feccbce 181 int seconds=0;; // this will be the divetiem variable eventually.
pegcjs 1:9cff4feccbce 182 int i=0,j=0; // general loop counting variables
pegcjs 1:9cff4feccbce 183
pegcjs 1:9cff4feccbce 184
pegcjs 1:9cff4feccbce 185 set_custom_char(); // does what it says on the tin really
pegcjs 1:9cff4feccbce 186 g_lcd.cls();
pegcjs 1:9cff4feccbce 187 g_lcd.locate(0, 0);
pegcjs 1:9cff4feccbce 188 g_lcd.printf( "RebMon");
pegcjs 1:9cff4feccbce 189 g_lcd.locate(0,1);
pegcjs 1:9cff4feccbce 190 g_lcd.printf("CAL?");
pegcjs 1:9cff4feccbce 191 battery();
pegcjs 1:9cff4feccbce 192
pegcjs 1:9cff4feccbce 193 // hang about waiting for the cal switch to be pressed in ccase it is
pegcjs 1:9cff4feccbce 194 while (seconds-startuptime<20) {
pegcjs 1:9cff4feccbce 195 seconds=getseconds();
pegcjs 1:9cff4feccbce 196 g_lcd.locate(5,1);
pegcjs 1:9cff4feccbce 197 g_lcd.printf("%.2d",21-(seconds-startuptime));
pegcjs 1:9cff4feccbce 198 battery(); // bung in battery symbol.
pegcjs 1:9cff4feccbce 199 g_lcd.locate(7,0);
pegcjs 1:9cff4feccbce 200 g_lcd.printf( "%.2d:%.2d:%.2d", hours,min,sec);
pegcjs 1:9cff4feccbce 201 if (CAL==0) {
pegcjs 1:9cff4feccbce 202 calibrate();
pegcjs 1:9cff4feccbce 203
pegcjs 1:9cff4feccbce 204 }
pegcjs 1:9cff4feccbce 205 wait(1);
pegcjs 1:9cff4feccbce 206 }
pegcjs 1:9cff4feccbce 207 g_lcd.cls();
pegcjs 1:9cff4feccbce 208 backlight=1; // backlight on - this driven by bc182l and 50ohm resistor off the 5V supply to send ~ 20mA
pegcjs 1:9cff4feccbce 209
pegcjs 1:9cff4feccbce 210 // ok there are three states in this system
pegcjs 1:9cff4feccbce 211 //MAIN LOOP ONCE STARTUP PROTOCOLS ARE COMPLETED
pegcjs 1:9cff4feccbce 212 while (1) {
pegcjs 1:9cff4feccbce 213
pegcjs 1:9cff4feccbce 214 readsensors();
pegcjs 1:9cff4feccbce 215
pegcjs 1:9cff4feccbce 216
pegcjs 1:9cff4feccbce 217 getseconds();
pegcjs 1:9cff4feccbce 218 battery();
pegcjs 1:9cff4feccbce 219 g_lcd.locate(0,0);
pegcjs 1:9cff4feccbce 220 g_lcd.printf( "%.2d:%.2d:%.2d", hours,min,sec);
pegcjs 1:9cff4feccbce 221 led1=1;
pegcjs 1:9cff4feccbce 222 wait(0.5);
pegcjs 1:9cff4feccbce 223 g_lcd.character(i,1,i);
pegcjs 1:9cff4feccbce 224 g_lcd.character(12,1,j);
pegcjs 1:9cff4feccbce 225 i=(i+1) % 8;
pegcjs 1:9cff4feccbce 226 j=(j+1) % 4;
pegcjs 1:9cff4feccbce 227 // setup local file to store data in
pegcjs 1:9cff4feccbce 228 // FILE *fp = fopen("/local/out.txt", "a"); // Open "out.txt" on the local file system for writing
pegcjs 1:9cff4feccbce 229 // fclose(fp);
pegcjs 1:9cff4feccbce 230 led1=0;
pegcjs 1:9cff4feccbce 231 wait(0.5);
pegcjs 1:9cff4feccbce 232 } // end while
pegcjs 1:9cff4feccbce 233 } //end main
pegcjs 1:9cff4feccbce 234
pegcjs 1:9cff4feccbce 235
pegcjs 1:9cff4feccbce 236
pegcjs 1:9cff4feccbce 237