Go Down

Topic: two ADS1115 on the same Arduino (Read 406 times) previous topic - next topic

hddforensic

HI,

I have two project on arduino that work ok separatly on their own arduino board but I want to put them together on the same arduino and same LCD.

Each of my sensor are connected to their own ADS1115.

Is it possible to install two ADS1115 on One Arduino ?  I made the first one work on 0x48 and the second on 0x49 so they have a different address.


Question

How do I put that in the code ? I need to give them a different name and then set different gain and scalefactor for each.
 

Johnny010

#1
Jul 15, 2017, 09:42 pm Last Edit: Jul 15, 2017, 09:48 pm by Johnny010
Yes. Read the datasheet.

http://www.ti.com/lit/ds/symlink/ads1114.pdf

There is section 9.5.1:

Quote
I 2 C Address Selection
The ADS111x have one address pin, ADDR, that configures the I 2 C address of the device. This pin can be
connected to GND, VDD, SDA, or SCL, allowing for four different addresses to be selected with one pin, as
shown in Table 4. The state of address pin ADDR is sampled continuously. Use the GND, VDD and SCL
addresses first. If SDA is used as the device address, hold the SDA line low for at least 100 ns after the SCL line
goes low to make sure the device decodes the address correctly during I 2 C communication.
Basically, you get 4 different addresses depending on if you attach pin 1 of the ADS111x to either GND, VCC, SDA or SCL. The address is dependent on the pin you tie pin 1 to is in a table in section 9.5.1 of the datasheet.

PS: I would tie the first IC pin1 HIGH for address 1001001 and the other IC with pin1 tied to GND for address 1001000.

Johnny010

OK...I didn't read the whole of your post...but I will be back soon with a more through software solution.

hddforensic

Hi Johnny

I found how to renamed and address them independently in the code but I'm still looking on how to set a different gain and scalefactor for each of them.

Another user told me that it's possible to simply connect my two sensors on the same ADS1115 since it is a 4 channels.  they are different sensor.  One is 0-10 volts output and the second is working with differential ma



But I don't have any code example on how to set the gain and scalefactor independently for each channel.


Wawa

Know you use 0-4volt for the pressure sensor, but that could be changed to suit the other measurement.
Don't know why/how you have connected the 'millivolt' sensor.
Don't know which library you use.
The Adafruit library might do one differential and one (or two) single-ended at the same time.

raw1 = ads.readADC_Differential_0_1(); // first two inputs differentail
raw2 = ads.readADC_SingleEnded(2); // third input single ended

NOT tested!
Leo..

hddforensic

I understand, it is not easy to help someone with all those ???

For now it's working fine with two ADS1115 so I won't try to do it with only one.

Thanks for the help you gave me since Yesterday.



Now I'm reading and searching on how to:


Installing a few button to:


Installing button #1 to switch on and off my compressor (On Off with the same button)


Button #2 will switch on a relay until I press button #2 again (that one will be to open and close my oxygen solenoid valve)

I need a button #3 that will start a relay/timer.  press the button and it begin the timer.
6 minutes off / half a second on / 6 minutes off / half a minute on,  until I press button #3 again


When I will be done with those 3 buttons, I need to find a way to make the compressor stop when I reach 3,200 PSI.  The oxygen solenoid need to stop 5 second before the compressor


Finally, I want to see all that on my iPhone via wi-fi and or Bluetooth and control the same thing remotely.


Nice project for a first time.

I may have some questions on the way :-)



Wawa

Seems an easy task for an ESP8266-12 based Arduino (Wemos/NodeMCU) and a single ADS breakout board.
Leo..

wvmarle

Indeed. NodeMCU and a single ADS1115 would do great for a project like this.

If you can afford to lose some resolution and scale factors are not too different (it seems you have a 0-10V and a 0-4V signal so that seems OK) you can set it to the lowest gain and connect both sensors to the same ADS1115. Saves one component.

Otherwise indeed create two ADS1115 objects with different name (use the Adafruit library, for example), say ADS1 and ADS2, each with their respective I2C address, and then you can use them independently in your code.

For your buttons: do a search on this forum on how to connect buttons and how to debounce them (to prevent you relay from switching off instantly). The code is simple.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

hddforensic

Hi Leo,

I have two ESP8266 and two Feather Huzzah ESP8266.  I will keep my actual project with the Arduino UNO and add later the ESP8266 to it for the wi-fi.

 

hddforensic

So far so good,

I have 3 buttons installed and each one control a LED.  I will replace the LEDs for relays when my tests are finish.

I have condition (If PSI > 3200) it will LOW the LED 1
same thing for LED2 with the oxygen %



Now my bug is the following


I want the LED no 3 to blink when I push the button no 3 but I don't want the delay of the blinking to delayed the rest of the program


I want six minutes off and then 1 second on,  ( six minutes off, one second on ) like that until I press the button #3 again.


I'm sure that there is a better way to blink a led without "blinking the program at the same time"


Still reading on Google :-)

wvmarle

Check out "blink without delay"
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

hddforensic

Hi

Yes I'm looking at that subject.  Since I already have a code for all the other options, it's hard to see for me on where I can apply the example to my existing code.

Since I only received my first Arduino 3 days ago and I never program any code before, I have to fight with a lot of unknown here.


This is my code to read One Air pressure sensor (PSI)
to read an Oxygen sensor (O2)
To send the result to a LCD 16,2
One button to calibrate the O2 sensor
3 buttons to control 3 LED


All this is working but now I need to make the LED #3 to flash when I press the button #3

six minute off, one second on, six minutes on one second off until I press the button again

*********************************
This code is coming from 3 different person and example on the web.  I'm sure that one day
I will clean it but for now I'm just happy that it's working not so bad



//#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_O2 (0x49);
Adafruit_ADS1115 ads_PSI (0x48);


// activer les LED et boutons
int pinButton1 = 8;
int LED1 = 3;
int stateLED1 = LOW;
int stateButton1;

int pinButton2 = 9;
int LED2 = 4;
int stateLED2 = LOW;
int stateButton2;

int pinButton3 = 10;
int LED3 = 5;
int stateLED3 = LOW;
int stateButton3;

// debounce
int previous = LOW;
long time = 0;
long debounce = 300;


// section pour le PSI
int16_t rawADCvalue;  // The is where we store the value we receive from the ADS1115
float scalefactor = 0.1250F; // This is the scale factor for the default +/- 4096 Volt Range we will use
float PSI = 0.0; // The result of applying the scale factor to the raw value

LiquidCrystal_I2C lcd(0x27,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_O2.readADC_Differential_0_1();
    RA.addValue(millivolts);
  }

}

void setup(void)

{

  //input output 3 boutons
  pinMode(pinButton1, INPUT);
  pinMode(LED1, OUTPUT);

  pinMode(pinButton2, INPUT);
  pinMode(LED2, OUTPUT);

  pinMode(pinButton3, INPUT);
  pinMode(LED3, OUTPUT);
 

  #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_O2.begin(); // ads1115 Pour O2 initialize
  ads_PSI.begin(); // ads1115 pour PSI initialize
 
  ads_O2.setGain(GAIN_TWO);
  multiplier = 0.0625F;

  ads_PSI.setGain(GAIN_ONE);
  // multiplier = 0.1250F;


  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

  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("Pression = ");
    lcd.print(PSI,0);

  Serial.begin(9600);
 
  Serial.print("Oxygen ");
  Serial.print(result,1);
  Serial.print("% ");
  Serial.print(mv,1);
  Serial.print("mv");

 

if (result > 30)
{
  stateLED2 = LOW;
}



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

// section pour le PSI
rawADCvalue = ads_PSI.readADC_SingleEnded(0);
PSI = (rawADCvalue * scalefactor) -35.0;

if (PSI > 500)
{
  stateLED1 = LOW;
  stateLED2 = LOW;
}

{

Serial.begin(9600);

 // Serial.print("Raw data pressure = ");
 // Serial.print(rawADCvalue);
  Serial.print("\tPSI = ");
  Serial.println(PSI,0);
  Serial.println();

}

lcd.clear();
lcd.home();

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

{

  //bouton 1
  stateButton1 = digitalRead(pinButton1); 
  if(stateButton1 == HIGH && previous == LOW && millis() - time > debounce) { //if button is pressed and LED is off
    if(stateLED1 == HIGH){
      stateLED1 = LOW;
    } else {
       stateLED1 = HIGH;
    }
    time = millis();
  }
  digitalWrite(LED1, stateLED1);
  previous == stateButton1;

  // bouton 2
  stateButton2 = digitalRead(pinButton2); 
  if(stateButton2 == HIGH && previous == LOW && millis() - time > debounce) { //if button is pressed and LED is off
    if(stateLED2 == HIGH){
      stateLED2 = LOW;
    } else {
       stateLED2 = HIGH;
    }
    time = millis();
  }
  digitalWrite(LED2, stateLED2);
  previous == stateButton2;

   //bouton 3
    stateButton3 = digitalRead(pinButton3); 
  if(stateButton3 == HIGH && previous == LOW && millis() - time > debounce) { //if button is pressed and LED is off
    if(stateLED3 == HIGH){
      stateLED3 = LOW;
    } else {
       stateLED3 = HIGH;
    }
    time = millis();
  }
 
  digitalWrite(LED3, stateLED3);
  previous == stateButton3;

}

}




Johnny010

#12
Jul 16, 2017, 08:33 pm Last Edit: Jul 16, 2017, 08:34 pm by Johnny010
Or use a Timer pin as the LED out and use the hardware to generate the "blinks", completely removing the software barrier for the toggling. If this pin is still available of course.

I am unsure what I have done wrong here...but I must be missing something, but here is an example (some could maybe fix this) that should have given a "500ms" toggle of an LED (On for 500ms, off 500ms, on etc...)


Code: [Select]
void setup() {

pinMode(9,OUTPUT);

}

void loop() {
  LED_ON();
  delay(100);
}

void LED_ON(){

TCCR1A , TCCR1B = 0;
 
TCCR1A |= (1<<COM1A0);  // Set the pin to "toggle".

TCCR1B |=(1<<WGM12);    // CTC mode = WGM13:0 = 13(0) 12(1) 11(0) 10(0) = "4".

TCCR1B |=(1<<CS12) | (1<<CS10); // Set the 16Mhz to divide by 1024 = 16Khz "ticks" = 64uS per tick.

// Now say we want to go "On->Off" every 500ms (half seconds...):
// 500ms / 64uS =~ 7812 "ticks".
// So now we set the 16 bit register (has a high byte and low) to equal 7812:

 unsigned int compare_value = 7812;
byte LB = compare_value;
byte HB = compare_value >> 8;

OCR1AH = HB;       // Shift 8 bits right to get the 8 most significant in to the 8bit register half.
OCR1AL = LB;               // Takes the last 8 bits of the value in to the low byte.
 
}

hddforensic

Hi
I can see that your code is in a scroll box.  My code take a lot of space.  I'm new to this forum. 

How do I enter my code in a scroll box like yours ?

Thanks

Johnny010

Hi
I can see that your code is in a scroll box.  My code take a lot of space.  I'm new to this forum.  

How do I enter my code in a scroll box like yours ?

Thanks
enclose it with [ c o d e] and [/ c o d e] (no spaces).

Go Up