Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 4

/*****************************************************************************

* ej's o2 analyzer - v0.1


* http://ejlabs.net/diy-nitrox-analyzer
*
* License
* -------
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*****************************************************************************/

//#define _DEBUG

#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <RunningAverage.h>

#define RA_SIZE 20
RunningAverage RA(RA_SIZE);

Adafruit_ADS1115 ads(0x48);
LiquidCrystal_I2C lcd(0x3F,16,2); // your i2c address might differnt. if not
working try scanning i2c first.

const int buttonPin=2; // push button


//const int ledPin = 13; // led
double calibrationv;
float multiplier;

int programState = 0;
int buttonState;
long buttonMillis = 0;
const long intervalButton = 2000; // 2 sec button hold to calibration

/*
Calculate MOD (Maximum Operating Depth)
*/
float max_po1 = 1.40;
float max_po2 = 1.60;
float cal_mod (float percentage, float ppo2 = 1.4) {
return 10 * ( (ppo2/(percentage/100)) - 1 );
}

int read_sensor(int x=0) {


int16_t millivolts = 0;
if (x == 0) {
millivolts = ads.readADC_Differential_0_1();
RA.addValue(millivolts);
}
}

void setup(void) {

#ifdef _DEBUG
Serial.begin(9600);
#endif

pinMode(buttonPin,INPUT_PULLUP);

// The ADC input range (or gain) can be changed via the following
// functions, but be careful never to exceed VDD +0.3V max, or to
// exceed the upper and lower limits if you adjust the input range!
// Setting these values incorrectly may destroy your ADC!
// ADS1015
ADS1115
// -------
-------
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV
0.1875mV (default)
// ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV
0.125mV
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV
0.0625mV
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV
0.03125mV
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV
0.015625mV
// ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV
0.0078125mV

ads.setGain(GAIN_TWO);
multiplier = 0.0625F;
ads.begin(); // ads1115 start

lcd.init();
lcd.backlight();
lcd.clear();

RA.clear();
for(int cx=0; cx<= RA_SIZE; cx++) {
read_sensor(0);
}

calibrationv = EEPROMReadInt(0);
if (calibrationv < 100) calibrationv=calibrate(0);
}

void EEPROMWriteInt(int p_address, int p_value)


{
byte lowByte = ((p_value >> 0) & 0xFF);
byte highByte = ((p_value >> 8) & 0xFF);

EEPROM.write(p_address, lowByte);
EEPROM.write(p_address + 1, highByte);
}
unsigned int EEPROMReadInt(int p_address)
{
byte lowByte = EEPROM.read(p_address);
byte highByte = EEPROM.read(p_address + 1);

return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);


}

int calibrate(int x){


lcd.clear();
lcd.print("Calibrating");

double result;
for(int cx=0; cx<= RA_SIZE; cx++) {
read_sensor(0);
}
result = RA.getAverage();
result = abs(result);
EEPROMWriteInt(x, result); // write to eeprom
delay(1000);
lcd.clear();
return result;
}

void analysing(int x, int cal, String txt) {


double currentmv;
double result;
double mv = 0.0;

read_sensor(x);
currentmv = RA.getAverage();
currentmv = abs(currentmv);

result = (currentmv / cal) * 20.9;


if (result > 99.9) result = 99.9;
mv = currentmv * multiplier;

lcd.setCursor(0,0);
if (mv < 0.02) {
lcd.print("Sensor error! ");
} else {
lcd.print(txt);
lcd.print(result,1);
lcd.print("% ");
lcd.print(mv,1);
lcd.print("mv");
lcd.setCursor(0,1);
lcd.print("MOD ");
lcd.print(cal_mod(result,max_po1),1);
lcd.print("m ");
lcd.print(cal_mod(result,max_po2),1);
lcd.print("m ");
}
}

void loop(void) {

unsigned long currentMillis = millis();


buttonState = digitalRead(buttonPin);
if (buttonState == LOW && programState == 0) {
buttonMillis = currentMillis;
programState = 1;
} else if (programState == 1 && buttonState == HIGH) {
programState = 0;
}

if(currentMillis - buttonMillis > intervalButton && programState == 1) {


calibrationv=calibrate(0); // calibration
programState = 1;
}
analysing(0,calibrationv,"O2 ");
delay(500);

You might also like