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
Diff: Rebmon_main.cpp
- Revision:
- 9:71b8ac65b73a
- Parent:
- 8:f45e654b47d0
--- a/Rebmon_main.cpp Mon Jan 14 12:55:05 2013 +0000 +++ b/Rebmon_main.cpp Fri Apr 12 10:16:53 2013 +0000 @@ -5,8 +5,6 @@ #include "mbed.h" #include "TextOLED.h" -//TODO - MAKE A VERSION THAT DRIVES THE HUD, CHECKS THE 5V SUPPLY AND COMPENSATES THE READINGS IF ITS VARYING (LINEARLY) -// AND PREVENT A HANG IF THE DS1307 FAILS TO RESPOND. #define DRATIO 0.6420066 // ratio of voltage at pin20 to voltage actually generated by the sensor @@ -17,6 +15,7 @@ DigitalOut btest(p6); // pin to drive lastblue led // offsets for lm324 amp in terms of reading values on adc +// these are calibrated fromthe actual amplifier circuit but effectively include the ADC offsets for the mbed #define coff1 -0.013375 #define coff2 -0.00936 #define coff3 -0.0212136 @@ -232,12 +231,13 @@ // average 20 readings for noise reduction g_lcd.cls(); for (count=20; count>0; count--) { - g_lcd.locate(0,0); - g_lcd.printf("Calibrate 21%% %.2d",count); s1=s1+EG1; s2=s2+EG2; s3=s3+EG3; pres=pres+PRESin; + g_lcd.locate(0,0); + g_lcd.printf("CAL 21%% %.2d %1.2f",count,pres/(20-count+1)); + g_lcd.locate(0,1); g_lcd.printf("%1.2f: %1.2f: %1.2f",s1/(20-count+1),s2/(20-count+1),s3/(20-count+1)); wait(1); @@ -354,6 +354,7 @@ //read battery state and insert the battery symbol +//RE-WRITE THIS TO USE THE 5 EMPTY PIXELS INSIDE THE BATTERY OUTLINE TO REPRESENT 50Mv INCREMENTS ON 3.5V void battery() { char cgchar[32]={ 6,9,9,9,9,9,9,15, // battery empty symbol @@ -363,35 +364,54 @@ }; - int batsym=0,i=0; // battery < 3.85V + int batsym=0,i=0,bstate=0,row=0; // bstate =(Vbattery-3.5V)/0.05; // idea to build in 6 levels of battery indicator by on the fly reprogramming character 2 as required. Vb=0; - for (i=0; i<4; i++) { + for (i=0; i<20; i++) { Vb=Vb+Vbatt; // read adc connected to battery via a 1/3 potential divider wait(0.05); } - Vb=Vb/4; // average 4 readings to reduce noise + Vb=Vb*3.3/20/0.337; // average 4 readings to reduce noise and rescale to ADC limit and convert to volts and account for potential divider on pcb. + bstate=floor((Vb-3.5)/0.05); + if(bstate > 9) bstate=9; + if(bstate <0) bstate=0; + + // fill up batery symbol according to bstate + for(i=0;i<10;i++) + { + // find row to enter + row=6-floor((float)i/2); + if(bstate >=i) + { + if(iseven(i)==1) cgchar[row]=cgchar[row]+4; + else cgchar[row]=cgchar[row]+2; + } + + } + +/* if (Vb>0.388) batsym=8; //3.85-3.92V if (Vb>0.395) batsym=16; // battery 3.92-4V if (Vb>0.404) batsym=24; // battery . >4V + */ // write the appropriate battery symbol into the first custom character g_lcd.writeCommand(0x40); // set start address for CGRAM for (i=0; i<8; i++) { - g_lcd.writeData(cgchar[i+batsym]); + g_lcd.writeData(cgchar[i]); } g_lcd.character(11,1,0); // battery symbol - if (batsym ==0 && flash==0) g_lcd.character(11,1,32); // bung in space if flashing + if (bstate <2 && flash==0) g_lcd.character(11,1,32); // bung in space if flashing } -// sub to make the nice stop or no stop message work in locations 9,0 and 9,1 +// sub to make the nice status message work in locations 9,0 and 9,1 void vmessage() { int i,d,cpos=0; // "INITSURFDIVE" in vertical chas - 1 custom char per two symbols @@ -525,14 +545,14 @@ s1=s1+EG1; // read o2 sensors s2=s2+EG2; s3=s3+EG3; - MPXref=MPXref+V5V; // read 5V + MPXref=MPXref+V5V; // read 5V reference wait_ms(10); // slows stuff down a bit but not a big problem } Vdepth=Vdepth/20; // now have the average s1=s1/20-coff1; s2=s2/20-coff2; s3=s3/20-coff3; - MPXref=MPXref/20*3.3*2; // should be 5V + MPXref=MPXref/20*3.3*2; // should be 5V but may not be..... // compute ppO2s @@ -553,6 +573,8 @@ if (depth<0) depth=0; // deals wtih noise that may lead to small variation in values + + // THESE SHOULD BE JUST 100*ppox/(pressure/100); fo1=100*ppo1/((pressure-barometric)/100+1); // pressure in bar = pressure /100 and want a % so multiply by 100 as well fo2=100*ppo2/((pressure-barometric)/100+1); @@ -647,30 +669,41 @@ for(i=0;i<n;i++) { HUD_clr(); - wait(0.2); + wait(0.3); HUD_white(); - wait(0.05); + wait(0.3); + } + HUD_display(); } - +// sub to decide if the setpoint should change - in this variant it always changes at 9.5-10.5m +// this might become annoyiong later so might want to make this function totally manual and use SW1 to control it. int setswitch() { if(setpoint==0 && depth >(switchdepth+0.5)) { setpoint=1; // handle switch from low to high - HUD_flash(4); + HUD_flash(4); // 4 flashes says going to high setpoint // flash the hud here } if(setpoint==1 && depth < (switchdepth -0.5)) { setpoint=0; // swtich to low setpoint - HUD_flash(2); + HUD_flash(2); // two flashes says going to low setpoint // flash the HUD here } } int main() { + +// start the clock in case it stopped for some reason +//this happens when the power drops due to battery getting too low. +// system still runs as a monitor but wont log. +// might be useful later to build a sub that checks the clock is reading and starts it if its stopped + + my1307.start_clock(); + // first some local variables int startuptime=getseconds(); int startdive=0,endclock=0; // value of seconds when dive starts and counter to decide if dive complete... @@ -682,10 +715,19 @@ bool mdir=0; +// code to deal with clock problem +if(startuptime==0){ // clock buggered and needs reseting +j=my1307.settime( 0, 0, 1, 1, 1, 1, 13); // set time to 1am on 1st jan 2013 +g_lcd.locate(0,0); +g_lcd.printf( "Clockreset %d",j); + wait(3); +} set_custom_char(); // does what it says on the tin really g_lcd.cls(); g_lcd.locate(0, 0); - g_lcd.printf( "RebMon"); + g_lcd.printf( "CCRMon SP%1.1f:%1.1f",lowsetpoint,highsetpoint); + wait(3); + g_lcd.cls(); // clear display to look nice g_lcd.locate(0,1); g_lcd.printf("CAL?"); battery(); @@ -696,6 +738,7 @@ recall(); // display the correct scrubber time scrubtime=scrubold; + // hang about waiting for the cal switch to be pressed in ccase it is while (scount<30) { seconds=getseconds(); // NB if this hangs then nothing works :( - usually means 5V is dodgy @@ -738,6 +781,7 @@ seconds=getseconds(); minutes=(int)(((float)seconds-(float)startuptime)/60); led1=seconds % 2; // flash the onboard led to make it clear stuff is running + led2=!(seconds %2); if (j>1) flash=1; else flash=0; @@ -765,12 +809,12 @@ divetime=(seconds-startdive); // divetime no recorded in seconds since start of dive // do deco calcs here when implemented - if (divetime %15 ==0) store_log(); // this saves the dive profile and sensor optputs in a file called divelog.dat every 15s + if (divetime %15 ==0) store_log(); // this saves the dive profile data every 15s and sensor optputs in a file called divelog.dat if (depth<=0.5) { endclock=endclock+1; if (endclock>150) { - state=1; // 30s at shallower than 0.3m and we return to surface mode. */ + state=1; // 30s at shallower than 0.5m and we return to surface mode. */ FILE *fp=fopen("/local/CAL.dat","w"); fprintf(fp,"%e\n%e\n%e\n%d",eg1cal,eg2cal,pcal,scrubtime); fclose(fp); //NB file system locked on write so must make sure we close files in case want to reprogram etc...