Skip to content

Instantly share code, notes, and snippets.

@soemarko
Created October 28, 2018 17:42
Show Gist options
  • Select an option

  • Save soemarko/7af13d2d31edb54bd3f6ca529cf79fca to your computer and use it in GitHub Desktop.

Select an option

Save soemarko/7af13d2d31edb54bd3f6ca529cf79fca to your computer and use it in GitHub Desktop.

Revisions

  1. soemarko created this gist Oct 28, 2018.
    287 changes: 287 additions & 0 deletions o2-analizer.ino
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,287 @@

    #include <SPI.h>
    #include <Wire.h>
    #include <Piccolino_OLED.h>
    #include <Piccolino_RAM.h>
    #include <EEPROM.h>
    #include <Adafruit_ADS1015.h>
    #include <RunningAverage.h>

    const int buttonPin=3; // push button

    #define RA_SIZE 20
    RunningAverage RA(RA_SIZE);

    Adafruit_ADS1115 ads(0x48);

    PROGMEM const unsigned char logo [] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x09, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x9d, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x01, 0xdf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x60, 0x00, 0x00, 0x13, 0xff, 0x17, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x78, 0x10, 0x00, 0x93, 0xf8, 0x97, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x7c, 0x12, 0x00, 0xb7, 0xe3, 0x97, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x7e, 0x36, 0xa1, 0xbf, 0xcf, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x7e, 0x37, 0xed, 0xfe, 0xdf, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x7e, 0x3f, 0xff, 0xf8, 0xdf, 0xb7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x3e, 0x3f, 0xff, 0xe6, 0x1e, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x0e, 0x3f, 0xff, 0x9e, 0xd8, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x7e, 0xc7, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xfe, 0x7e, 0xdf, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xfe, 0x7c, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xfe, 0x71, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0x47, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0x1f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xfe, 0x0e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xf8, 0x71, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xc0, 0x66, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1f, 0x00, 0xd8, 0x0d, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x03, 0xde, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x01, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x03, 0x00, 0x00, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0x03, 0x00, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0x02, 0x01, 0x1f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x87, 0x02, 0x07, 0x1f, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xe7, 0x02, 0x07, 0x27, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x02, 0x0f, 0x39, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x03, 0xff, 0x3e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff};

    Piccolino_OLED display;
    Piccolino_RAM ram;

    int calibrationv;
    float multiplier;

    const int EEPROM_addr = 0;
    const int cal_holdTime = 1; // 2 sec button hold to calibration
    long secs_held; // How long the button was held (seconds)
    byte previous = HIGH;
    unsigned long firstTime; // how long since the button was first pressed
    int active = 0;
    double result_max = 0;

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

    void drawBitmap(int16_t x, int16_t y,
    const unsigned char * bitmap, int16_t w, int16_t h) {
    int16_t i, j, byteWidth = (w + 7) / 8;

    display.clear();

    for (j = 0; j < h; j++) {
    for (i = 0; i < w; i++) {
    if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
    display.drawPixel(x + i, y + j, WHITE);
    }
    }
    }

    display.update();

    }

    void read_sensor() {
    int16_t millivolts = 0;
    millivolts = ads.readADC_Differential_0_1();
    // Serial.println(millivolts);
    RA.addValue(millivolts);
    }

    void calibrate() {
    display.clear();
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.setTextSize(1);
    display.print(F("Calibrating..."));
    display.update();

    active = 0;
    result_max = 0.0;

    double avg = RA.getAverage();
    calibrationv = abs(avg);

    EEPROMWriteInt(EEPROM_addr, calibrationv); // write to eeprom

    // Serial.print(">>>>>> ");
    // Serial.println(calibrationv);

    delay(1000);
    }

    void analyzing() {
    double currentmv = 0;
    double result;
    double mv = 0.0;

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

    // Serial.print(">> ");
    // Serial.println(currentmv);

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

    display.clear();
    display.setTextColor(WHITE);
    display.setCursor(0, 0);

    if (mv < 0.02 || result <= 0) {
    display.setTextSize(2);
    display.println(F("Sensor"));
    display.print(F("Error!"));
    } else {
    display.setTextSize(4);
    display.print(result, 1);
    display.println(F("%"));

    if (result >= result_max) {
    result_max = result;
    }

    display.setTextSize(1);
    display.setCursor(0, 31);
    display.setTextColor(BLACK, WHITE);
    display.print(F("Max "));
    display.print(result_max, 1);
    display.print(F("% "));
    display.print(mv, 2);
    display.print(F("mv"));

    if (active % 4) {
    display.setCursor(115, 29);
    display.setTextColor(WHITE);
    display.print(F("."));
    }

    display.setTextColor(WHITE);
    display.setCursor(0, 40);
    display.print(F("pO2 "));
    display.print(max_po1, 1);
    display.print(F("/"));
    display.print(max_po2, 1);
    display.print(F(" MOD"));

    display.setTextSize(2);
    display.setCursor(0, 50);
    display.print(cal_mod(result, max_po1), 1);
    display.print(F("/"));
    display.print(cal_mod(result, max_po2), 1);
    display.print(F("m "));

    }
    display.update();
    }

    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);
    }


    void setup() {
    // put your setup code here, to run once:
    display.begin();
    ram.begin();

    // Serial.begin(9600);

    drawBitmap(0, 0, logo, 128, 64);
    pinMode(buttonPin, INPUT_PULLUP);

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

    //calibrate
    for (int cx = 0; cx < RA_SIZE; cx++) {
    read_sensor();
    delay(50);
    }

    calibrationv = EEPROMReadInt(EEPROM_addr);
    if (calibrationv < 100) {
    calibrate();
    }

    // delay(1000);
    }

    void loop() {
    // put your main code here, to run repeatedly:

    int current = digitalRead(buttonPin);

    if (current == LOW && previous == HIGH && (millis() - firstTime) > 200) {
    firstTime = millis();
    active = 17;
    }

    secs_held = (millis() - firstTime) / 1000;
    if (secs_held > 0 && current == LOW && previous == LOW) {
    if (secs_held >= cal_holdTime) {
    calibrate();
    }
    }

    previous = current;

    analyzing();
    delay(200);

    active++;
    }