ADS1x15 change sampling rate

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

ADS1x15 change sampling rate

Post by Nergal »

Long timer reader, first time poster - I am almost certain that this question must have been asked before, but I cannot find an answer...

How do I change the sampling rate of the ADS1015 converter ?

I have played with the library (changed #define ADS1015_REG_CONFIG_DR_1600SPS (0x00C0) // max samples per second (default) for ADS1115 and #define ADS1115_CONVERSIONDELAY (1) //(8) Just Testin' ) for the ADS1115(!!!) and it seemed to actually increase the sampling speed to 125Hz per channel on a MEGA2560, single ended reading on the 1115. This number seems to be in the ball park range of what other users have reported)

Now, I am a bit baffled how to change the sampling rate to max on the ADS1015 - I have changed #define ADS1015_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default) for ADS1015 to 0x00C0 so that the default rate would be 3300SPS but nevertheless, I still got only 125Hz per channel.


The actual benchmark section of the code is attached below. Thanks for any assistance, I am sure that there is a command or simple solution.





#include <Wire.h>
#include <Adafruit_ADS1015.h>

struct { //Container for Channel ADC0 to ADC3
int16_t CH0;
int16_t CH1;
int16_t CH2;
int16_t CH_3;
}
ADS_Data;

unsigned long t_Start, t_Stop;
int Benchmarks = 1000; //loops per test


float Hz = 0.0;

Adafruit_ADS1015 ADS_0(0x48);




t_Start = micros();
for (int CNT=0; CNT<Benchmarks-1; CNT++)
{ //uncomment to measure AIn sampling rate
// int A0 = analogRead(A0);
// int A1 = analogRead(A1);
// int A2 = analogRead(A2);
// int A3 = analogRead(A3);

ADS_Data.CH0 = ADS_0.readADC_SingleEnded(0);
ADS_Data.CH1 = ADS_0.readADC_SingleEnded(1);
ADS_Data.CH2 = ADS_0.readADC_SingleEnded(2);
ADS_Data.CH_3 = ADS_0.readADC_SingleEnded(3);
}

t_Stop = micros();
Hz = Benchmarks / ( (t_Stop - t_Start)/1000000.0);

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

The Adafruit library doesn't support changing the sample rate directly, but you can use the readRegister() and writeRegister() functions along with macros defined in the header file:

Code: Select all

const uint8_t adcAddress  = 0x48;
const uint8_t configRegister = 0x01;

uint16_t configValue = readRegister( adcAddress, configRegister ) & !ADS1015_REG_CONFIG_DR_MASK;
configValue = configValue | ADS1015_REG_CONFIG_DR_128SPS;   //  128 sps mode
writeRegister( adcAddress, configRegister, configValue );

Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

Re: ADS1x15 change sampling rate

Post by Nergal »

Cheers Mike - thanks heaps for the assistance. Couldn't that be implemented in a function that goes in the library ?

Oh, and where do I find the read/writeRegister functions ? Are these the ones in the SPI library sketch ?

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

The functions are included in the ADS1x15 library code, but they aren't written as object methods. They're just helper functions used by the object methods.

They're defined for the global scope, but I didn't really dig into the definitions to see if their scope was limited to the file where they're written. If so, you should be able to copy them to your own code without causing too many problems.

When you're writing libraries, you have to make tradeoffs between the things you want to use, the things you want to advertise, and the things you want to hide. There's no 'right' answer, just a range of different options that do different things. The more functions you expose, the more flexibility you have, but the more complicated working with the library can be. Smaller interfaces are easier to work with, but tend to be less flexible.

That's the nice thing about Open Source: if the decisions we made don't fit your project, you can tweak the code to get a version that does things the way you want. ;-)

Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

Re: ADS1x15 change sampling rate

Post by Nergal »

Thanks for your effort - but I am totally lost now. I have tried to knock up some code (which I barely understand) by copy and pasting from the Adafruit_ADS1015.cpp on github.

However, nothing seems to change, although the compiler does not throw an error message, which is comforting. Anyway, would someone be able to help me out here ? I am stuck, have been sitting over the ADS datasheet for hours now and try to make sense out of the commands. I assume it is just a minor thing that is missing. I am not overly familiar with the very basics of i2c communication, so I cannot even test whether the ADS is talking to me or not.


Any input appreciated !




Code Snippets:

#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include <SPI.h>

Adafruit_ADS1015 ADS_0(0x48);

void setup()
{
const uint8_t adcAddress = 0x48;
const uint8_t configRegister = 0x01;
uint16_t configValue = readRegister( adcAddress, configRegister ) & !ADS1015_REG_CONFIG_DR_MASK;
configValue = configValue | ADS1015_REG_CONFIG_DR_3300SPS;
writeRegister( adcAddress, configRegister, configValue );
}




'and nicked from Adafruit_ADS1015.cpp

static void writeRegister(uint8_t i2cAddress, uint8_t reg, uint16_t value) {
Wire.beginTransmission(i2cAddress);
i2cwrite((uint8_t)reg);
i2cwrite((uint8_t)(value>>8));
i2cwrite((uint8_t)(value & 0xFF));
Wire.endTransmission();
}


static uint16_t readRegister(uint8_t i2cAddress, uint8_t reg) {
Wire.beginTransmission(i2cAddress);
i2cwrite(ADS1015_REG_POINTER_CONVERT);
Wire.endTransmission();
Wire.requestFrom(i2cAddress, (uint8_t)2);
return ((i2cread() << 8) | i2cread());
}



static uint8_t i2cread(void) {
#if ARDUINO >= 100
return Wire.read();
#else
return Wire.receive();
#endif
}





static void i2cwrite(uint8_t x) {
#if ARDUINO >= 100
Wire.write((uint8_t)x);
#else
Wire.send(x);
#endif
}

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

The simplest thing to do is add Serial.print() statements that check the values you receive from the ADC:

Code: Select all

void setup() 
{ 
	const uint8_t adcAddress = 0x48;
	const uint8_t configRegister = 0x01;
	uint16_t configValue = readRegister( adcAddress, configRegister );
	
	Serial.print( "read config value 0x" );
	Serial.println( configValue, HEX );
	
	configValue = ( configValue & !ADS1015_REG_CONFIG_DR_MASK) | ADS1015_REG_CONFIG_DR_3300SPS; 
	writeRegister( adcAddress, configRegister, configValue );

	Serial.print( "sent config value 0x" );
	Serial.println( configValue, HEX );

	configValue = readRegister( adcAddress, configRegister );

	Serial.print( "verifying by rereading config value 0x" );
	Serial.println( configValue, HEX );
}

Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

Re: ADS1x15 change sampling rate

Post by Nergal »

Thanks, at least I am able to communicate with the A/D and read the registers. However I am still off the track and cannot figure out, why.

Code: Select all

  const uint8_t adcAddress = 0x48;
  const uint8_t configRegister = 0x01;

  uint16_t configValue = readRegister( adcAddress, configRegister );
  Serial.print( "read config value b" );
  Serial.println( configValue, BIN );


  Serial.print("data rate: ");
  Serial.print( configValue & ADS1015_REG_CONFIG_DR_MASK , BIN );
  Serial.print("  /  0x");
  Serial.println( configValue & ADS1015_REG_CONFIG_DR_MASK , HEX );

  Serial.print("gain: ");
  Serial.print( configValue & ADS1015_REG_CONFIG_PGA_MASK, BIN );
  Serial.print("  /  0x");
  Serial.println( configValue & ADS1015_REG_CONFIG_PGA_MASK, HEX );   
  Serial.println("");


  delay(5000);



The answer (no changes made on the Arduino, just sitting there running) is printed below for the first loops.

Why is the config register reading different configurations nearly each time ?
Is my masking correct and the readings make sense ?

I just needed someone to look through the code and the results since this is beyond my experience.


Arduino connected !
read config value b1111111111110000
data rate: 11100000 / 0xE0
gain: 111000000000 / 0xE00

read config value b1111111111110000
data rate: 11100000 / 0xE0
gain: 111000000000 / 0xE00

read config value b1111111101100000
data rate: 1100000 / 0x60
gain: 111000000000 / 0xE00

read config value b1111111110100000
data rate: 10100000 / 0xA0
gain: 111000000000 / 0xE00

read config value b1111111110100000
data rate: 10100000 / 0xA0
gain: 111000000000 / 0xE00

read config value b1111111110110000
data rate: 10100000 / 0xA0
gain: 111000000000 / 0xE00

read config value b1111111110110000
data rate: 10100000 / 0xA0
gain: 111000000000 / 0xE00

read config value b1111111111010000
data rate: 11000000 / 0xC0
gain: 111000000000 / 0xE00

read config value b1000000
data rate: 1000000 / 0x40
gain: 0 / 0x0

read config value b1111111111100000
data rate: 11100000 / 0xE0
gain: 111000000000 / 0xE00

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

Hmm.. it looks like the readRegister() function from the library is hardcoded to the conversion register:

Code: Select all

static uint16_t readRegister(uint8_t i2cAddress, uint8_t reg) {
  Wire.beginTransmission(i2cAddress);

//  i2cwrite(ADS1015_REG_POINTER_CONVERT);  // <--- (existing version) this always 
                                            //      chooses the conversion register
//  i2cwrite(ADS1015_REG_POINTER_CONFIG);  // <--- this would always choose the config register

  i2cwrite( reg );  // use this to select the register with the given parameter

  Wire.endTransmission();
  Wire.requestFrom(i2cAddress, (uint8_t)2);
  return (( i2cread() << 8 ) | i2cread());
}

Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

Re: ADS1x15 change sampling rate

Post by Nergal »

That was the obvious problem - thanks heaps ! I figured it out now. However, even with the highest sample rate (3300 SPS, 0xC0) I only get approximately 125Hz on each channel - the same value as with all other sampling rates. I have double checked the register and it reads the correct bytes.

SOOOOO - has anybody EVER been able to effectively change the sampling rate on either the ADS1115 or the ADS1015 ? Would love to hear from you, because I desperately need more than 125 Hz per channel.

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

How many channels are you using?

The chip only has a single ADC and the inputs are multiplexed to that. Your maximum sampling rate will be the ADC rate divided by the number of channels in use.

Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

Re: ADS1x15 change sampling rate

Post by Nergal »

yes, I am aware of that, thanks for the heads-up anyway, Mike. For the test I used all 4 channels - a sampling rate of 3300SPS should still give me approx 800 SPS on each channel. I checked the sampling rates for 1 to 4 channels in use, results as below.

1 Channel: 500Hz
2 Channels: 250Hz
3 Channels: 170Hz
4 Channels: 125Hz

Code is still the same as above, I can use whatever sampling rate I want, the results are the same although the register reads the correct value - feel free to double check the code.
With 4 channels being a bit of an outlayer it is a fairly linear reduction in sample rate per channel as assumed. The only concern is that the max sample rate is 500Hz only. I would love to hear from someone who has actually changed sampling rates successfully on an I2C bus / Arduino - google does not come up with significant hits though.

Code: Select all

void SetSamplerate(byte SPS_Definition)
{  
  const byte adcAddress = 0x48;
  const byte configRegister = 0x01;

  uint16_t configValue = readRegister( adcAddress, configRegister );
  configValue = readRegister( adcAddress, configRegister );
  lcd.setCursor(0,4);
  lcd.print(configValue & ADS1015_REG_CONFIG_DR_MASK , HEX);
  configValue = configValue & 00011111;
  configValue = configValue | ADS1015_REG_CONFIG_DR_128SPS ;
  writeRegister(adcAddress,  configRegister, configValue);

  configValue = readRegister( adcAddress, configRegister );
  lcd.setCursor(8,4);
  lcd.print(configValue & ADS1015_REG_CONFIG_DR_MASK , HEX);
}

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

Hmm.. I'll have to dig through the datasheets and the library code to see what's going on.

It's possible that the library has built-in delays to let the ADC finish its reading. That's more polite than hijacking interrupts the user doesn't know about, and easier than doing something like ACK polling.

Nergal
 
Posts: 7
Joined: Thu Mar 20, 2014 8:54 pm

Re: ADS1x15 change sampling rate

Post by Nergal »

yeah mate, I'd really appreciate that since it defo goes beyond my knowledge - if it helps you, I seem to get the same sampling rates for both the 1015 and 1115 if I use 4 channels and it looks like i cannot change the sampling rate on either A/D

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: ADS1x15 change sampling rate

Post by adafruit_support_mike »

Finally found time to dig through the code looking for timing information, and there *is* a value named ADS1015_CONVERSIONDELAY that specifies the amount of time to wait for a conversion to finish.

The default value is 1ms, which would impose an upper limit of 1ksps on the sampling rate.

You can probably play with that by looking for lines that read:

Code: Select all

  delay(m_conversionDelay);
and replacing them with:

Code: Select all

  delayMicroseconds(m_conversionDelay);
That will give you finer-grained control over the wait time without having to write interrupt-based code that watches the ALRT pin. Then you can set the delay from the header file on the line that reads:

Code: Select all

    #define ADS1015_CONVERSIONDELAY         (1)
You'll have to play with the values to find the rate that gives you the best combination of speed and reliability, but the mechanics shouldn't be too bad.

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”