Programación para que un ADC1115 funcione en modo single ended

Hola a toda la comunidad.
Primero feliz año a tod@s.
Quería realizar una consulta a ver si alguien me puede echar una mano.
Realicé un proyecto hace poco de un oxímetro que mide el porcentaje de oxígeno presente en el aire mediante una célula medidora de oxígeno, un arduino nano, un convertidor analógico-digital ADC1115 y una pantalla OLED. Funciona a la perfección.
Ahora estoy llevando a cabo un proyecto más ambicioso donde comparo la señal proveniente de la célula con otra de referencia para, a la vez que se mide la presencia de oxígeno en el oxímetro, abrir o cerrar una electroválvula en función del porcentaje de oxígeno presente en la mezcla.
Debo inyectar entonces la misma señal de la célula en dos circuitos, el oxímetro y el comparador (un Amplificador operacional).
Aquí viene el problema. el ADC1115 está programado en modo diferencial. Uso los pines A0 y A1 para medir la tensión que viene de la célula y tener el porcentaje. Es misma señal la inyecto en en el Amp Op, esta vez al pin de entrada no inversora y tierra. Gran fallo, ya que estoy cortocircuitando A1 del ADC1115 a tierra y esto me desestabiliza la medida.
Creo que una solución es hacer trabajar al ADC1115 en modo single ended, de forma que la señal de la célula la inyectaría entre A0 y tierra.
AQUÍ VIENE MI CONSULTA
Cómo cambiar la programación del Arduino para que el ADC1115 funcione en modo single ended en lugar del modo diferencial.
Aquí dejo el código en el que el ADC1115 funciona en modo diferencial por si alguien se anima y me puede indicar las modificaciones para que funcione en modo single ended.
Muchas gracias

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_ADS1X15.h>
#include <EEPROM.h>
#include <RunningAverage.h>

#define RA_SIZE 20
RunningAverage RA(RA_SIZE);

Adafruit_ADS1115 ads;

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

const int buttonPin=2; // push button
const int buzzer = 9; // buzzer
const int ledPin = 13; // led

double calibrationv;
float multiplier;

const int cal_holdTime = 2; // 2 sec button hold to calibration
const int mod_holdTime = 4; // 4 sec hold to po2 mod change
const int max_holdtime = 6; // 6 sec hold to reset max o2 result

long millis_held;    // How long the button was held (milliseconds)
long secs_held;      // How long the button was held (seconds)
long prev_secs_held; // How long the button was held in the previous check
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)
*/
float max_po1 = 1.30;
const float max_po2 = 1.60;
float cal_mod (float percentage, float ppo2 = 1.4) {
  return 10 * ( (ppo2/(percentage/100)) - 1 );
}

void beep(int x=1) { // make beep for x time
  //digitalWrite(ledPin, HIGH); // led blink disable for battery save
  for(int i=0; i<x; i++) {    
      tone(buzzer, 2800, 7000);
      delay(200);    
  }
  //digitalWrite(ledPin, LOW);
  noTone(buzzer);
}



void read_sensor(int adc=0) {  
  int16_t millivolts = 0;
 millivolts = ads.readADC_Differential_0_1();
  RA.addValue(millivolts);
}

void setup(void) {  

  //Serial.begin(9600);

  /* power saving stuff for battery power */
  // Disable ADC
  // ADCSRA = 0;
  // Disable the analog comparator by setting the ACD bit
  // (bit 7) of the ACSR register to one.
  // ACSR = B10000000;
  // Disable digital input buffers on all analog input pins
  // DIDR0 = DIDR0 | B00111111;

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  ads.setGain(GAIN_TWO);
  multiplier = 0,0625F;
  ads.begin(); // ads1115 start

  pinMode(buttonPin,INPUT_PULLUP);  

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

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

  beep(1);
}

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) {

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(0,0);  
  display.setTextSize(2);
  display.print(F("Calibrando"));
  display.display();

  //RA.clear();
  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

  beep(1);
  delay(1000);
  active = 0;
  return result;
}

void analysing(int x, int cal) {
  double currentmv=0;
  double result;
  double mv = 0.0;

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

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

  display.clearDisplay();
  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(2);
    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.setCursor(75,31);
    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 "));

    // menu
    if (secs_held < 5 && active > 16) {
      display.setTextSize(2);
      display.setCursor(0,31);
      display.setTextColor(BLACK, WHITE);      
      if (secs_held >= cal_holdTime && secs_held < mod_holdTime) {
        display.print(F("   CAL    "));
      }
      if (secs_held >= mod_holdTime && secs_held < max_holdtime) {
        display.print(F("   PO2    "));
      }
      if (secs_held >= max_holdtime && secs_held < 10) {
        display.print(F("   MAX    "));
      }     
    }  

  }
  display.display();
}

void lock_screen(long pause = 5000) {
  beep(1);
  display.setTextSize(1);
  display.setCursor(0,31);  
  display.setTextColor(0xFFFF, 0);
  display.print(F("                "));
  display.setTextColor(BLACK, WHITE);
  display.setCursor(0,31);
  display.print(F("======= LOCK ======="));
  display.display();
  for (int i = 0; i < pause; ++i) {   
    while (digitalRead(buttonPin) == HIGH) {
      }
   }
   active = 0;
}

void po2_change() {  
  if (max_po1 == 1.3) max_po1 = 1.4;
  else if (max_po1 == 1.4) max_po1 = 1.5;
  else if (max_po1 == 1.5) max_po1 = 1.3;

  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(0,0);  
  display.setTextSize(2);
  display.println(F("pO2 set"));
  display.print(max_po1);
  display.display();
  beep(1);   
  delay(1000);
  active = 0;  
}

void max_clear() {
  result_max = 0;
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(0,0);  
  display.setTextSize(2);
  display.println(F("Max result"));
  display.print(F("cleared"));
  display.display();
  beep(1);   
  delay(1000);
  active = 0;
}

void loop(void) {


  int current = digitalRead(buttonPin);

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

  millis_held = (millis() - firstTime);
  secs_held = millis_held / 1000;

  if (millis_held > 2) {
    if (current == HIGH && previous == LOW) {
      if (secs_held <= 0) {
        lock_screen();
      }
      if (secs_held >= cal_holdTime && secs_held < mod_holdTime) {        
        calibrationv = calibrate(0);
      }
      if (secs_held >= mod_holdTime && secs_held < max_holdtime) {
        po2_change();
      }
      if (secs_held >= max_holdtime && secs_held < 10) {
        max_clear();
      }
    }
  }

  previous = current;
  prev_secs_held = secs_held;

  analysing(0,calibrationv);
  delay(200);

  active++;
}

Tienes esta linea que dice LeoADC en modo diferencial.
Si pones en Google : ADC1115 singled ended seguro tienes tu respuesta que es:

millivolts = ads1015.readADC_SingleEnded(0); // para canal 0 o le cambias al canal que gustes.

(SOLUCIONADO)
Muchas gracias por tu ayuda. Lo había buscado pero la información era un poco farragosa. Tu info ha sido clara y sencilla. Muchas gracias de nuevo

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.