ADS1115 using software i2c

Hello all,

I'm working on a project involving an ADS1115 4 channel ADC and I made the pcb design error of not connecting it to the hardware I2C pins, thinking that it would be easy peasy to make software i2c work.

I'm using an ATMEGA328-AU and have the ADS1115 connected to A2 and A3 (PC2,PC3).

The design is final (for this iteration) and the board manufactured and all soldered up in 4 layers, so I have to make it work as it is.

I have been trying to get the adafruit library to work in some mutant form with the SoftWire library, but so far no luck.

Does anyone know if an easy way to get this going? I only need the functionality of the single ended reading.

Have you tried SoftI2CMaster library?

Hi,

Yes I have been trying out SoftWire which is based on SoftI2CMaster, as I understand it.

I think my concern is that I'm not sure how to use software I2C.

I've tried using defines and i2c related functions that are outpide the ADS1115 object from the adafruit library using hardware i2c, and the readSingleEnded() function, edited to non-object form.

The program runs, but I get no data from the chip. If there is an easy way to go about it, I'd appreciate a pointer in the right direction.

Thanks

Post your code, using formatting tags </>

Hi FantomT,
Sorry for the late reply...

I should add that I have changed the ADS1x15 library to include SoftWire.h instead of Wire.h and instantiated an
object Wire in the .c file.

Here's the code so far (without defines). It compiles, but produces no value form the ADS1015.

// -*- c++ -*-

#define SDA_PORT PORTC
#define SDA_PIN 2 // = A4
#define SCL_PORT PORTC
#define SCL_PIN 3 // = A5
#include <SoftWire.h>

SoftWire Wire = SoftWire();
uint16_t  readADC_SingleEnded(uint8_t channel);

void setup(void) {
  Serial.begin(57600*2);
  Wire.begin();
}

void loop(void){
  int16_t adc0, adc1, adc2, adc3;

  adc0 = readADC_SingleEnded(0);
  adc1 = readADC_SingleEnded(1);
  adc2 = readADC_SingleEnded(2);
  adc3 = readADC_SingleEnded(3);
  Serial.print("AIN0: "); Serial.println(adc0);
  Serial.print("AIN1: "); Serial.println(adc1);
  Serial.print("AIN2: "); Serial.println(adc2);
  Serial.print("AIN3: "); Serial.println(adc3);
  Serial.println(" ");
  
  delay(1000);
}
static uint8_t i2cread(void) {
  #if ARDUINO >= 100
  return Wire.read();
  #else
  return Wire.receive();
  #endif
}
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());  
}
uint16_t readADC_SingleEnded(uint8_t channel) {
  if (channel > 3)
  {
    return 0;
  }
  
  // Start with default values
  uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE    | // Disable the comparator (default val)
                    ADS1015_REG_CONFIG_CLAT_NONLAT  | // Non-latching (default val)
                    ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low   (default val)
                    ADS1015_REG_CONFIG_CMODE_TRAD   | // Traditional comparator (default val)
                    ADS1015_REG_CONFIG_DR_1600SPS   | // 1600 samples per second (default)
                    ADS1015_REG_CONFIG_MODE_SINGLE;   // Single-shot mode (default)

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

  // Set single-ended input channel
  switch (channel)
  {
    case (0):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
      break;
    case (1):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
      break;
    case (2):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
      break;
    case (3):
      config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
      break;
  }

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

  // Write config register to the ADC
  writeRegister(0x48, ADS1015_REG_POINTER_CONFIG, config);

  // Wait for the conversion to complete
  delay(ADS1115_CONVERSIONDELAY);

  // Read the conversion results
  // Shift 12-bit results right 4 bits for the ADS1015
  return readRegister(0x48, ADS1015_REG_POINTER_CONVERT) >> 8;  
}

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

/**************************************************************************/
/*!
    @brief  Writes 16-bits to the specified destination register
*/
/**************************************************************************/
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();
}

I can't compile a code:

sketch_nov07a:9:26: error: no matching function for call to 'SoftWire::SoftWire()'
SoftWire Wire = SoftWire();
^
exit status 1
no matching function for call to 'SoftWire::SoftWire()'

BTW, SoftWire has an example, how to initialize a class, here:

SoftWire i2c(sdaPin, sclPin);

AsyncDelay samplingInterval;

and it's not like you did:

SoftWire Wire = SoftWire();