Skip to content

Commit

Permalink
Merge pull request #76 from matthewlai/master
Browse files Browse the repository at this point in the history
Refactoring, and exposing continuous mode
  • Loading branch information
caternuson authored Feb 8, 2022
2 parents da24495 + 14a894e commit 7301423
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 139 deletions.
195 changes: 57 additions & 138 deletions Adafruit_ADS1X15.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,41 +117,7 @@ int16_t Adafruit_ADS1X15::readADC_SingleEnded(uint8_t channel) {
return 0;
}

// Start with default values
uint16_t config =
ADS1X15_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1X15_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1X15_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)

// Set PGA/voltage range
config |= m_gain;

// Set data rate
config |= m_dataRate;

// Set single-ended input channel
switch (channel) {
case (0):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_0;
break;
case (1):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_1;
break;
case (2):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_2;
break;
case (3):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_3;
break;
}

// Set 'start single-conversion' bit
config |= ADS1X15_REG_CONFIG_OS_SINGLE;

// Write config register to the ADC
writeRegister(ADS1X15_REG_POINTER_CONFIG, config);
startADCReading(MUX_BY_CHANNEL[channel], /*continuous=*/false);

// Wait for the conversion to complete
while (!conversionComplete())
Expand All @@ -172,28 +138,7 @@ int16_t Adafruit_ADS1X15::readADC_SingleEnded(uint8_t channel) {
*/
/**************************************************************************/
int16_t Adafruit_ADS1X15::readADC_Differential_0_1() {
// Start with default values
uint16_t config =
ADS1X15_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1X15_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1X15_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)

// Set PGA/voltage range
config |= m_gain;

// Set data rate
config |= m_dataRate;

// Set channels
config |= ADS1X15_REG_CONFIG_MUX_DIFF_0_1; // AIN0 = P, AIN1 = N

// Set 'start single-conversion' bit
config |= ADS1X15_REG_CONFIG_OS_SINGLE;

// Write config register to the ADC
writeRegister(ADS1X15_REG_POINTER_CONFIG, config);
startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_0_1, /*continuous=*/false);

// Wait for the conversion to complete
while (!conversionComplete())
Expand All @@ -213,28 +158,7 @@ int16_t Adafruit_ADS1X15::readADC_Differential_0_1() {
*/
/**************************************************************************/
int16_t Adafruit_ADS1X15::readADC_Differential_0_3() {
// Start with default values
uint16_t config =
ADS1X15_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1X15_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1X15_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)

// Set PGA/voltage range
config |= m_gain;

// Set data rate
config |= m_dataRate;

// Set channels
config |= ADS1X15_REG_CONFIG_MUX_DIFF_0_3; // AIN0 = P, AIN3 = N

// Set 'start single-conversion' bit
config |= ADS1X15_REG_CONFIG_OS_SINGLE;

// Write config register to the ADC
writeRegister(ADS1X15_REG_POINTER_CONFIG, config);
startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_0_3, /*continuous=*/false);

// Wait for the conversion to complete
while (!conversionComplete())
Expand All @@ -254,28 +178,7 @@ int16_t Adafruit_ADS1X15::readADC_Differential_0_3() {
*/
/**************************************************************************/
int16_t Adafruit_ADS1X15::readADC_Differential_1_3() {
// Start with default values
uint16_t config =
ADS1X15_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1X15_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1X15_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)

// Set PGA/voltage range
config |= m_gain;

// Set data rate
config |= m_dataRate;

// Set channels
config |= ADS1X15_REG_CONFIG_MUX_DIFF_1_3; // AIN1 = P, AIN3 = N

// Set 'start single-conversion' bit
config |= ADS1X15_REG_CONFIG_OS_SINGLE;

// Write config register to the ADC
writeRegister(ADS1X15_REG_POINTER_CONFIG, config);
startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_1_3, /*continuous=*/false);

// Wait for the conversion to complete
while (!conversionComplete())
Expand All @@ -296,28 +199,7 @@ int16_t Adafruit_ADS1X15::readADC_Differential_1_3() {
*/
/**************************************************************************/
int16_t Adafruit_ADS1X15::readADC_Differential_2_3() {
// Start with default values
uint16_t config =
ADS1X15_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1X15_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1X15_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)

// Set PGA/voltage range
config |= m_gain;

// Set data rate
config |= m_dataRate;

// Set channels
config |= ADS1X15_REG_CONFIG_MUX_DIFF_2_3; // AIN2 = P, AIN3 = N

// Set 'start single-conversion' bit
config |= ADS1X15_REG_CONFIG_OS_SINGLE;

// Write config register to the ADC
writeRegister(ADS1X15_REG_POINTER_CONFIG, config);
startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_2_3, /*continuous=*/false);

// Wait for the conversion to complete
while (!conversionComplete())
Expand Down Expand Up @@ -357,21 +239,7 @@ void Adafruit_ADS1X15::startComparator_SingleEnded(uint8_t channel,
// Set data rate
config |= m_dataRate;

// Set single-ended input channel
switch (channel) {
case (0):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_0;
break;
case (1):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_1;
break;
case (2):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_2;
break;
case (3):
config |= ADS1X15_REG_CONFIG_MUX_SINGLE_3;
break;
}
config |= MUX_BY_CHANNEL[channel];

// Set the high threshold register
// Shift 12-bit results left 4 bits for the ADS1015
Expand Down Expand Up @@ -443,9 +311,60 @@ float Adafruit_ADS1X15::computeVolts(int16_t counts) {
return counts * (fsRange / (32768 >> m_bitShift));
}

/**************************************************************************/
/*!
@brief Non-blocking start conversion function
Call getLastConversionResults() once conversionComplete() returns true.
In continuous mode, getLastConversionResults() will always return the
latest result.
ALERT/RDY pin is set to RDY mode, and a 8us pulse is generated every
time new data is ready.
@param mux mux field value
@param continuous continuous if set, otherwise single shot
*/
/**************************************************************************/
void Adafruit_ADS1X15::startADCReading(uint16_t mux, bool continuous) {
// Start with default values
uint16_t config =
ADS1X15_REG_CONFIG_CQUE_1CONV | // Set CQUE to any value other than
// None so we can use it in RDY mode
ADS1X15_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1X15_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1X15_REG_CONFIG_CMODE_TRAD; // Traditional comparator (default val)

if (continuous) {
config |= ADS1X15_REG_CONFIG_MODE_CONTIN;
} else {
config |= ADS1X15_REG_CONFIG_MODE_SINGLE;
}

// Set PGA/voltage range
config |= m_gain;

// Set data rate
config |= m_dataRate;

// Set channels
config |= mux;

// Set 'start single-conversion' bit
config |= ADS1X15_REG_CONFIG_OS_SINGLE;

// Write config register to the ADC
writeRegister(ADS1X15_REG_POINTER_CONFIG, config);

// Set ALERT/RDY to RDY mode.
writeRegister(ADS1X15_REG_POINTER_HITHRESH, 0x8000);
writeRegister(ADS1X15_REG_POINTER_LOWTHRESH, 0x0000);
}

/**************************************************************************/
/*!
@brief Returns true if conversion is complete, false otherwise.
@return True if conversion is complete, false otherwise.
*/
/**************************************************************************/
bool Adafruit_ADS1X15::conversionComplete() {
Expand Down
12 changes: 11 additions & 1 deletion Adafruit_ADS1X15.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@
#define ADS1X15_REG_CONFIG_MUX_SINGLE_2 (0x6000) ///< Single-ended AIN2
#define ADS1X15_REG_CONFIG_MUX_SINGLE_3 (0x7000) ///< Single-ended AIN3

constexpr uint16_t MUX_BY_CHANNEL[] = {
ADS1X15_REG_CONFIG_MUX_SINGLE_0, ///< Single-ended AIN0
ADS1X15_REG_CONFIG_MUX_SINGLE_1, ///< Single-ended AIN1
ADS1X15_REG_CONFIG_MUX_SINGLE_2, ///< Single-ended AIN2
ADS1X15_REG_CONFIG_MUX_SINGLE_3 ///< Single-ended AIN3
}; ///< MUX config by channel

#define ADS1X15_REG_CONFIG_PGA_MASK (0x0E00) ///< PGA Mask
#define ADS1X15_REG_CONFIG_PGA_6_144V (0x0000) ///< +/-6.144V range = Gain 2/3
#define ADS1X15_REG_CONFIG_PGA_4_096V (0x0200) ///< +/-4.096V range = Gain 1
Expand Down Expand Up @@ -161,8 +168,11 @@ class Adafruit_ADS1X15 {
void setDataRate(uint16_t rate);
uint16_t getDataRate();

private:
void startADCReading(uint16_t mux, bool continuous);

bool conversionComplete();

private:
void writeRegister(uint8_t reg, uint16_t value);
uint16_t readRegister(uint8_t reg);
uint8_t buffer[3];
Expand Down
71 changes: 71 additions & 0 deletions examples/continuous/continuous.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <Adafruit_ADS1X15.h>

// Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
Adafruit_ADS1015 ads; /* Use this for the 12-bit version */

// Pin connected to the ALERT/RDY signal for new sample notification.
constexpr int READY_PIN = 3;

// This is required on ESP32 to put the ISR in IRAM. Define as
// empty for other platforms. Be careful - other platforms may have
// other requirements.
#ifndef IRAM_ATTR
#define IRAM_ATTR
#endif

volatile bool new_data = false;
void IRAM_ATTR NewDataReadyISR() {
new_data = true;
}

void setup(void)
{
Serial.begin(9600);
Serial.println("Hello!");

Serial.println("Getting differential reading from AIN0 (P) and AIN1 (N)");
Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");

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

if (!ads.begin()) {
Serial.println("Failed to initialize ADS.");
while (1);
}

pinMode(READY_PIN, INPUT);
// We get a falling edge every time a new sample is ready.
attachInterrupt(digitalPinToInterrupt(READY_PIN), NewDataReadyISR, FALLING);

// Start continuous conversions.
ads.startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_0_1, /*continuous=*/true);
}

void loop(void)
{
// If we don't have new data, skip this iteration.
if (!new_data) {
return;
}

int16_t results = ads.getLastConversionResults();

Serial.print("Differential: "); Serial.print(results); Serial.print("("); Serial.print(ads.computeVolts(results)); Serial.println("mV)");

new_data = false;

// In a real application we probably don't want to do a delay here if we are doing interrupt-based sampling, but we have a delay
// in this example to avoid writing too much data to the serial port.
delay(1000);
}
51 changes: 51 additions & 0 deletions examples/nonblocking/nonblocking.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <Adafruit_ADS1X15.h>

// Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
Adafruit_ADS1015 ads; /* Use this for the 12-bit version */

void setup(void)
{
Serial.begin(9600);
Serial.println("Hello!");

Serial.println("Getting differential reading from AIN0 (P) and AIN1 (N)");
Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");

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

if (!ads.begin()) {
Serial.println("Failed to initialize ADS.");
while (1);
}

// Start the first conversion.
ads.startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_0_1, /*continuous=*/false);
}

void loop(void)
{
// If we don't have new data, skip this iteration.
if (!ads.conversionComplete()) {
return;
}

int16_t results = ads.getLastConversionResults();

Serial.print("Differential: "); Serial.print(results); Serial.print("("); Serial.print(ads.computeVolts(results)); Serial.println("mV)");

// Start another conversion.
ads.startADCReading(ADS1X15_REG_CONFIG_MUX_DIFF_0_1, /*continuous=*/false);

delay(1000);
}

0 comments on commit 7301423

Please sign in to comment.