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
Rebmon_main.cpp@1:9cff4feccbce, 2012-08-02 (annotated)
- 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?
User | Revision | Line number | New 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 |