Mapping 4 channel with ads1115

Hi all,

I'm not only new here, I'm new to the world of Arduino but finding these very useful.

This is my first experience with ads1115 and it's been a struggle for me.

Here's what I am attempting to do, create a pressure reader using 4 transducers all of the same value
the output is 0-5v and the range is 0.28-7bar. In the code below I am reading them in Kpa. Reading one seems to be fine (I'm sure my code is not the greatest) however where I am struggling is mapping the four outputs of the adc to four sensors, believe me I have been trying for many hours.

Any help or advice with this would be greatly appreciated.

Here's my code that's been stripped of all the other stuff not related to adc.

[#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1115 ads;
int16_t adc0, adc1, adc2, adc3;
void calcPressure (uint16_t Input, uint16_t Zero, uint16_t Max)
{
uint16_t Span = Max - Zero;
uint16_t Map = map( Input, Zero, Max, 0, 700);
float adc0 = (((Input - Zero) /(float)Span)*700.0);
Serial.print("AIN0: "); Serial.println(adc0);
}
void setup(void)
{
Serial.begin(9600);
ads.begin();
}
void loop(void)
{
adc0 = ads.readADC_SingleEnded(0);
calcPressure (adc0,1000, 26700);
delay(2000);
}]

This is one of the many attempts that I've tried. Am I on the right track? I am sure the would be a better option as all the sensor values are the same. where I struggle is mapping them to the individual channels.

#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1115 ads;
int16_t adc0, adc1, adc2, adc3;
void calcPressure (uint16_t Input, uint16_t Zero, uint16_t Max);
void calcPressure1 (uint16_t Input1, uint16_t Zero1, uint16_t Max1);
void calcPressure2 (uint16_t Input2, uint16_t Zero2, uint16_t Max2);
void calcPressure3 (uint16_t Input3, uint16_t Zero3, uint16_t Max3)
{
 uint16_t Span = Max - Zero;
 uint16_t Map = map( Input, Zero, Max, 0, 700);
 float adc0 = (((Input - Zero) /(float)Span)*700.0);
 Serial.print("AIN0: "); Serial.println(adc0);
    
 uint16_t Span1 = Max11 - Zero1;
 uint16_t Map1 = map( Input1, Zero1, Max1, 0, 700);
 float adc1 = (((Input1 - Zero1) /(float)Span1)*700.0);
 Serial.print("AIN1: "); Serial.println(adc1); 
   
 uint16_t Span2 = Max2 - Zero2;
 uint16_t Map2 = map( Input2, Zero2, Max2, 0, 700);
 float adc2 = (((Input2 - Zero2) /(float)Span2)*700.0);
 Serial.print("AIN2: "); Serial.println(adc2);
    
 uint16_t Span3 = Max3 - Zero3;
 uint16_t Map3 = map( Input3, Zero3, Max3, 0, 700);
 float adc3 = (((Input3 - Zero3) /(float)Span3)*700.0);
 Serial.print("AIN3: "); Serial.println(adc3); 
 
 }
void setup(void)
{
Serial.begin(9600);
ads.begin();
}
void loop(void)
{
adc0 = ads.readADC_SingleEnded(0);
adc1 = ads.readADC_SingleEnded(1);
adc2 = ads.readADC_SingleEnded(2);
adc3 = ads.readADC_SingleEnded(3);

calcPressure (adc0,1000, 26700); 
calcPressure1 (adc1,1000, 26700); 
calcPressure2 (adc2,1000, 26700); 
calcPressure3 (adc3,1000, 26700); 

delay(2000);
}

Anyone please

I'm not 100% sure what your trying to do, I'm no expert but looking through your code your zero,max values do not hold any data like your set it to Max = 100 say.

I think you need to break it down into smaller parts and may be read up on the map function

First part: just use a pot connected to 5V then get channel 1(sensor 1) reading the voltage from the pot first then add the other channels then once your happy that all 4 channels are reading correct then the---

Second part: then work on your min and max values for sensor 1 again once happy with sensor 1 working then just repeat the code.

What does the sensor output voltage at 0.28 bar and what's the max voltage at 7 Bar ?

for example lets say at 0.28 bar = 1.00 volt and the Raw value of unit16_t input1 reads 1500 then set Zero1 to 1500 and if 7 Bar reads 4.98 volts and the unit16_t input1 reads 3100 then this is your max1 value. This way you set your Min/Max values as for converting it into reading bar I would not know as you have give us no data for them other than 0-5V

Here is some code that I've used for the ADS115 kind of changed it to your wording variables in your code, Only channel 0 reads at the moment the other channels are highlighted out and just un-highlight one channel at a time so it should get you started, You may need to download the Timeactions library

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <TimedAction.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
#include <Adafruit_ADS1015.h>
#define ADS1115_REG_CONFIG_DR_860SPS//Set A/D converter regisiters
#define VOLTS_CHAN0 0 //Pressure 1 
#define VOLTS_CHAN1 1 //Pressure 2 
#define VOLTS_CHAN2 2 //Pressure 3 
#define VOLTS_CHAN2 3 //Pressure 4 

Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
int16_t CHAN0, CHAN1, CHAN2, CHAN3; ///Read channels 0-3 of the ADS1115
float Vmultiplier = 0.0001875F;  // used to convet readings to decimal
float voltage; // holds the float reading

uint16_t Input1; //sensor 1
uint16_t Zero1 = 15; // Set the min
uint16_t Max1 = 1057;//Set the max value
/*
  uint16_t Input2; //sensor 2
  uint16_t Zero2 = 15; // Set the min
  uint16_t Max2 = 1057;//Set the max value

  uint16_t Input3; //sensor 3
  uint16_t Zero3 = 15; // Set the min
  uint16_t Max3 = 1057;//Set the max value

  uint16_t Input4; //sensor 4
  uint16_t Zero4 = 15; // Set the min
  uint16_t Max4 = 1057;//Set the max value
*/
void TimerService01();// ADC ROUTINE Timed action
TimedAction Timedact01 = TimedAction(100, TimerService01);// mS
void TimerService02();// Write to the LCD
TimedAction Timedact02 = TimedAction(250, TimerService02);// mS
void setup(void)
{
  Serial.begin(9600);
  ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
  ads.begin();  //start the 16bit A/D converter
  lcd.begin(16, 2);
}
void loop(void)
{
  Timedact01.check(); // Read the ADC Channels every 100Ms
  Timedact02.check(); // Write to the LCD 250Ms

  // delay(2000);
}

void TimerService01() { //Read the ADC cahnnels
  //###############
  //Read cahnnel 0
  //##############
  CHAN0 = ads.readADC_SingleEnded(VOLTS_CHAN0)  ;   // Ch.0 (3) 16bit 16bit
  Input1 =  map(CHAN0, 0, 32767, Zero1, Max1); ///place your max an min values here 32767
  voltage = Input1  * Vmultiplier; //used to convert to voltage reading
  /*
    //###############
    //Read cahnnel 1
    //##############
    CHAN1 = ads.readADC_SingleEnded(VOLTS_CHAN1)  ;   // Ch.0 (3) 16bit 16bit
    Input2 =  map(CHAN1, 0, 32767, Zero2, Max2); ///place your max an min values here 32767
    voltage = Input  * Vmultiplier; //used to convert to voltage reading
    //###############
    //Read cahnnel 2
    //##############
    CHAN2 = ads.readADC_SingleEnded(VOLTS_CHAN2)  ;   // Ch.0 (3) 16bit 16bit
    Input3 =  map(CHAN2, 0, 32767, Zero3, Max3); ///place your max an min values here 32767
    voltage = Input  * Vmultiplier; //used to convert to voltage reading
    //###############
    //Read cahnnel 3
    //##############
    CHAN3= ads.readADC_SingleEnded(VOLTS_CHAN3)  ;   // Ch.0 (3) 16bit 16bit
    Input4 =  map(CHAN3, 0, 32767, Zero4, Max4); ///place your max an min values here 32767
    voltage = Input  * Vmultiplier; //used to convert to voltage reading
  */
}

void TimerService02() { //Display the data
  lcd.setCursor(0, 0);
  lcd.print("VALUE: ");
  lcd.print(Input1);
  lcd.print("    ");
  lcd.setCursor(0, 1);
  lcd.print("REAL: ");
  lcd.print(voltage);
  lcd.print("    ");
}

Use the select button and copy code but paste it into wordpad first then from wordpad paste into the IDE as I found pasting it into the IDE first you may get you get stray 306 error

Thanks for your reply Steveiboy much appreciated.

I have a code that is working now but I must say I do prefer your code with the separate min/max for the sensors the problem is I cant for the life of me figure out how to get your code displaying decimal places.

below are the specs from the sensors.

supply 7-32vdc
output signal 0-5v 3wire
-0.28- 7Barg

low range output calibration -0.001v
Full range output calibration 4.998v
Span 4.999v

Sorry forgot to add here's the code I'm using

#include "Wire.h"
#include <HCRTC.h>
#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <SD.h>
#define I2CDS1307Add 0x68
File myFile;
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE);
Adafruit_ADS1115 ads;     /* Use this for the 16-bit version */  
HCRTC HCRTC;

int16_t adc0;
int16_t adc1;
int16_t adc2;
int16_t adc3;

uint16_t adcMax   = 26280;     // Max Valule for ads0,1,2 or 3 seen in serial monitor, when sensor is at max (minus a few for error/ voltage spikes)this is for pin mapping 5v input = 27000ish
uint16_t adcZero  = 1000;      // Min Valule for ads0,1,2 or 3 seen in serial monitor, when sensor is at min (minus a few for error/ voltage spikes)
uint16_t adcsensor = 700;       // Max valve as stated on sensor eg. 700 = 7Bar


float adc0Pressure;
float adc1Pressure;
float adc2Pressure;
float adc3Pressure;

uint16_t adc0Map;
uint16_t adc1Map;
uint16_t adc2Map;
uint16_t adc3Map;

float calcPressure ( uint16_t Input, uint16_t Zero, uint16_t Max, uint16_t MaxOut )
   
 
{
uint16_t Span = Max - Zero;
return (((Input - Zero) /(float)Span) * MaxOut );
} 
uint16_t mapPressure( uint16_t Input, uint16_t Zero, uint16_t Max,  uint16_t MaxOut )
{
return (map( Input, Zero, Max, 0, MaxOut));  
}


void setup(void)
{
  Serial.begin(9600);
  ads.begin();
  lcd.begin (20,4);
 
 while (!Serial) {                                                     // wait for serial port to connect. Needed for native USB port only
    
  }

  if (!SD.begin(10)) {
  lcd.setCursor(0,0);
  lcd.print("Insert SD Card");
  lcd.setCursor(0,1);
  lcd.print("Before switching");
  lcd.setCursor(0,2);
  lcd.print("OFF and back ON");
    while (1);
  }
}           

void loop(void)

{
adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);                                    //change the middle value to just below the  lowest number seen in serial monitor (INPUT)

  HCRTC.RTCRead(I2CDS1307Add);

  lcd.setCursor(0,0);
  lcd.print("P0    ");
  lcd.print( calcPressure ( adc0, adcZero, adcMax, adcsensor ),2 );
   lcd.setCursor(15,0);
  lcd.print(" Kpa ");
  
  lcd.setCursor(0,1);
  lcd.print("P1    ");
  lcd.print( calcPressure ( adc1, adcZero, adcMax, adcsensor ),2 );
   lcd.setCursor(15,1);
  lcd.print(" Kpa ");
  
  
  lcd.setCursor(0,2);
  lcd.print("P2    ");
  lcd.print( calcPressure ( adc2, adcZero, adcMax, adcsensor ),2 ); 
   lcd.setCursor(15,2);
  lcd.print(" Kpa ");  
  
  lcd.setCursor(0,3);
  lcd.print("P3    ");  
  lcd.print( calcPressure ( adc3, adcZero, adcMax, adcsensor ),2 ); 
   lcd.setCursor(15,3);
  lcd.print(" Kpa ");
  

  myFile = SD.open("Data.csv", FILE_WRITE);                            // open the file. note that only one file can be open at a time, 

 
  if (myFile) {                                                        // if the file opened okay, data write:

    
   
  myFile.print(HCRTC.GetDateString());
  myFile.print(" ,"); 
  myFile.print(HCRTC.GetTimeString());
  myFile.print(" ,"); 
  myFile.print("P0,");
  myFile.print( calcPressure ( adc0, adcZero, adcMax, adcsensor ),2 );
  myFile.print(" ,"); 
  myFile.print("P1,");
  myFile.print( calcPressure ( adc1, adcZero, adcMax, adcsensor ),2 );
  myFile.print(" ,"); 
  myFile.print("P2,");
  myFile.print( calcPressure ( adc2, adcZero, adcMax, adcsensor ),2 );
  myFile.print(" ,"); 
  myFile.print("P3,");
  myFile.print( calcPressure ( adc3, adcZero, adcMax, adcsensor ),2 );
  myFile.println(" ,"); 
  myFile.close();                                                       // close the file:

    
  } else 

  myFile = SD.open("Data.csv");                                         // re-open the file for reading:
  if (myFile) {
    

    
  while (myFile.available()) {                                        // read from the file until there's nothing else in it:
  Serial.write(myFile.read());
  }
   
  myFile.close();                                                      // close the file:


} 

  Serial.print(HCRTC.GetDateString());
  Serial.print(" ");
  Serial.print(HCRTC.GetTimeString());
  Serial.print("      adc0 "); 
  Serial.print(adc0);
  Serial.print("      P0 = ");  
  Serial.print( calcPressure ( adc0, adcZero, adcMax, adcsensor ),2 );
  Serial.print(" Kpa");
  Serial.print("      adc1 ");   
  Serial.print(adc1);
  Serial.print("      P1 = ");
  Serial.print( calcPressure ( adc1, adcZero, adcMax, adcsensor ),2 );
  Serial.print(" Kpa");
  Serial.print("       adc2 "); 
  Serial.print(adc2);
  Serial.print("      P2 = ");  
  Serial.print( calcPressure ( adc2, adcZero, adcMax, adcsensor ),2 );
  Serial.print(" Kpa");
  Serial.print("      adc3 " );   
  Serial.print(adc3);
  Serial.print("      P3 = ");
  Serial.print( calcPressure ( adc3, adcZero, adcMax, adcsensor ),2 );
  Serial.println(" Kpa");

  delay(500);

} // loop

Hi I’m away from my computer for the next 2 weeks, if you want to add decimal places just use this
Lcd.print(voltage,2) this will give you 2 decimal places, but of only of the real voltage coming in from your sensors, you would have to do the calculations for your sensors to convert it.

Once I’m back I can look closer at your code

Thanks very much for your reply, I have tried to add the comer the decimal places. I will continue to look at the code and the calculations for my sensors.

I appreciate you offering to look at my code once your back, hopefully I will have it sorted by then if not that would be great. Hope you have a good time away and its not work :slight_smile:

The ADS is an absolute/voltage A/D, and not really suitable for ratiometric pressure sensors.
If you want to use ratiometric sensors with this A/D, then you must power the sensors from a very stable dedicated 5volt supply, not just Arduino's 5volt pin.
Maybe easier to just use Arduino's (ratiometric) A/D.
Leo..

Have you got a link for the spec/data sheet for the info on the sensors you’re using ?

Thanks for the reply’s.

I don’t have a spec sheet as such, it seems these sensors have been configured. Here’s a link to the manufacturer’s configuration tool. The part number I have is PMP 5074-TB-A3-CA-H0-PA.

Information from the calibration certificate is as follows.

Supply voltage 7-32vdc
Output signal 0-5v (3 wire)
Low range ouput -0.001v
Full range output 4.998v
Span 4.999v

I do have the sensor perfoming well I have checked the repeatability and the acuracy against a Fluke comparator and all seems well. As Wawa says I do need to give this a regulated supply I was thinking along the lines of a 12v input regulated to 9v this supply could then be split/teed one going directly to the sensor and the other to the barrel connection. The reason behind this is 12v as used in automotive and regulated to 9v so both sensor and Arduino can run from a single power supply if this makes sense.

The problem I’m having with the code is being able to have the four sensors with separate floats for min/max values as the calibrations are slightly different as expected from sensors.