Ads1115 latency

Attached are 2 different codes to operate the ads1115 adc. I am using shields from adafruit. But I am not using the adafruit library. The first code at the top of the page. Works as I expect. However, it uses delay(). To change this, I implemented a state machine using a case switch. The state machine progresses through the cases 1 by 1 adding a delete between the transitions. Now the ADC updates have almost 2 seconds between them and it misses the reads from the pots giving big jumps of resolution. I was assigning the ADC output at the end of the loop in the first code. I tried assigning the ADC values within each case and I changed from millis to micros. But still no joy. Can somebody please shed some light why this code is now so slow compared to the first one which worked well. Is there another way to add a wait type function.

adc state.txt (24.2 KB)

Is this the same question : I2C data is too slow - Networking, Protocols, and Devices - Arduino Forum ?

Please remove these lines: while(Wire.available() < 2);
Please remove the Wire.endTransmission() after a Wire.requestFrom().

In the other topic I proposed to interleave both ADCs into each other and use a millis() timer. Would that help ?

Set the bus to 400kHz:

Wire.begin(); // begin I2C
Wire.setClock( 400000UL);

Instead of a Finite State Machine, you should use arrays and for-loops to get the data.

for( adc=0; adc<2; adc++)
{
  for( channel=0; channel<4; channel++)
  {
    value[adc][channel] = ...
  }
}

or when interleaving both ADCs:

  for( channel=0; channel<4; channel++)
  {
    value[0][channel] = ...
    value[1][channel] = ...
  }

This is just a global impression. When using a millis-timer, then a variable has to be used which will be incremented and not a for-loop.

Sorry for my lack of Understanding but where would I put this into my code. You also have =... =What?

I gave a few ideas and I used the three dots for the rest of the code, assuming that you can fill in those parts. It is not working code that you can just copy into your sketch.

Have you read the other topic in that link ?

I've been reading through your linked post for last hour or so still trying to understand whole thing. I am not sure how it is used with the Wire. Commands. I've never used i2 bus without using things like lcd library and adafruit library before. I was trying to do it without using the libraries other than the wire. One. I tried writing the for loop you suggested at the end of all the wire.write stuff and then do the for loop for the wire.request. so it read value[0][channel] = wire.read(). I got rid of what you said in my code. Withoit ant joy. Still just trying to work it all out. It's not really for anything else but to try and understand how to use an external ADC. Thanks for your suggestions. I'll just continue on with them.

Can you show your sketch ?
Put it between three backslash-single-quotes:

```
Your sketch
```

Sorry for my late reply koepel... Here is my code. If been trying to work with your suggestions. But I do not think I am understanding properly. In your linked post you mentioned read adc1 ch1 then adc2 channel 1 etc. Which I tried. But the posts in the topic use ads1115 lite library which I have had working on the past. I am getting the right results and everything works a expected. Just need to replace the delay.

#define ASD1115_1 0x48 // adc1
#define ASD1115_2 0x49 // adc 2

const byte address[2] = {ASD1115_1, ASD1115_2};
const byte numPot = 8;
const byte numChan = 4;
const byte numADC = 2;
const byte config_reg = 0b00000001;
byte config_buffer = 0b00000000;
unsigned int ADC_val[numChan];
byte set_channel[numADC][numChan];
byte set_sps = 0;
byte ADC_loBYTE[numADC][numChan];
byte ADC_hiBYTE[numADC][numChan];
byte pause = 2;

void setup()
{
  Serial.begin(9600);
  Wire.begin(); // begin I2C
  Wire.setClock(400000UL);
  // ASD1115
  // set config register and start conversion
  set_channel[0][0] = 0b01000010; // input 0 from adc 1
  set_channel[0][1] = 0b01010010; // input 1 from adc 1
  set_channel[0][2] = 0b01100010; // input 2 from adc 1
  set_channel[0][3] = 0b01110010; // input 3 from adc 1
  set_channel[1][0] = 0b01000010; // input 0 from adc 2
  set_channel[1][1] = 0b01010010; // input 1 from adc 2
  set_channel[1][2] = 0b01100010; // input 2 from adc 2
  set_channel[1][3] = 0b01110010; // input 3 from adc 2
  // bit 15 flag bit for single shot
  // Bits 14-12 input selection:
  // 100 ANC0; 101 ANC1; 110 ANC2; 111 ANC3
  // Bits 11-9 Amp gain. Default to 010 here 001 P19
  // Bit 8 Operational mode of the ADS1115.
  // 0 : Continuous conversion mode
  // 1 : Power-down single-shot mode (default)
  set_sps = 0b11100011; //set sample rate and disable comparator
  // Bits 7-5 data rate to 111 for 860SPS
  // Bits 4-0  comparator functions see spec sheet.
}

void loop()
{
  for (byte adc = 0; adc < numADC; adc++)
  {
    for (byte channel = 0; channel < numChan; channel++)
    {
      config_buffer = 0b00000000;                 // initialise adc return buffer
      Wire.beginTransmission(address[adc]);       // begin setup to ADC address n
      Wire.write(config_reg);                     // start adc setup...0b00000001
      Wire.write(set_channel[adc][channel]);      // set mux / mode / amp
      Wire.write(set_sps);                        // set sample rate (& comparator disable)
      Wire.endTransmission();                     // end adc setup
      Stopp();//need to remove                    // delay
      Wire.beginTransmission(address[adc]);       // begin write to ADC address n
      Wire.write(config_buffer);                  // start adc write setup byte. 0b00000000
      Wire.endTransmission();                     // end setup byte
      Stopp();//need to remove                    // delay
      Wire.requestFrom(address[adc], 2);          // take 2 bytes from adc address n
      ADC_loBYTE[adc][channel] = Wire.read();     // take first byte
      ADC_hiBYTE[adc][channel] = Wire.read();     // take second byte
      Stopp();//need to remove                    // delay
    }
  }
  ///////////////////////////////////////////////////////////
  // pass results onto variable and interleave
  ADC_val[0] = ADC_loBYTE[0][0] << 8 | ADC_hiBYTE[0][0];
  ADC_val[1] = ADC_loBYTE[0][1] << 8 | ADC_hiBYTE[0][1];
  ADC_val[2] = ADC_loBYTE[0][2] << 8 | ADC_hiBYTE[0][2];
  ADC_val[3] = ADC_loBYTE[0][3] << 8 | ADC_hiBYTE[0][3];
  ADC_val[4] = ADC_loBYTE[1][0] << 8 | ADC_hiBYTE[1][0];
  ADC_val[5] = ADC_loBYTE[1][1] << 8 | ADC_hiBYTE[1][1];
  ADC_val[6] = ADC_loBYTE[1][2] << 8 | ADC_hiBYTE[1][2];
  ADC_val[7] = ADC_loBYTE[1][3] << 8 | ADC_hiBYTE[1][3];
  ///////////////////////////////////////////////////////////
  // limit adc value.
  for (byte i = 0; i < numPot; i++)
  {
    if (ADC_val[i] > 32767)
    {
      ADC_val[i] = 0;
    }
  }
  ///////////////////////////////////////////////////////////
  // print results
  Serial.print(ADC_val[0]);
  Serial.print("   ");
  Serial.print(ADC_val[1]);
  Serial.print("   ");
  Serial.print(ADC_val[2]);
  Serial.print("   ");
  Serial.print(ADC_val[3]);
  Serial.print("   ");
  Serial.print(ADC_val[4]);
  Serial.print("   ");
  Serial.print(ADC_val[5]);
  Serial.print("   ");
  Serial.print(ADC_val[6]);
  Serial.print("   ");
  Serial.println(ADC_val[7]);
}
void Stopp()
{
  delay(pause);
}

The ADC_val list is looks as if it is commented out. However it is not. Just an error on website.

There are two ADC, let's call them ADC0 and ACD1. You select the first one and do the channels, then the other one.
With interleaving, I mean: If you would let ADC0 sample a channel, and meanwhile go to ADC1 and let that one sample a channel, then return to ADC0 to check if there is data.

If you want to use the interleaving and use millis(), then you can look at the other topic: I2C data is too slow - #11 by Koepel

Your sketch is soooooo slow :sleeping:
Suppose you send 100 characters of text in each loop() iteration with 9600 baud. That takes about 100ms. Your whole sketch might be slowed down a hundred times, because the Serial.print() functions wait until a new character can be send to the computer.

Use 115200 baud to start with, try if a higher value is possible.
Send less data to the computer, a single space or comma is enough to separate the numbers.

Have you told which Arduino board you use ? I can not find it. Some boards use the USB speed instead of the baudrate. That is even faster than the highest baudrate.

I try different baud rates but all I get is question marks and symbols.
With regards to sampling one adc then another who h I've read in the post you linked. It says read the inputs first then trigger then trigger conversion.

Is read ADC , wire.read. trigger? I'm not sure what you mean. Then trigger conversion. Is that wire.request? I'm not using the adafruit library which has the getconversion() function. Does that just convert to MV? Any help to understand is appreciated.

Not sure how apply with the wire library.

I'm using an arduino mega as well.

You have to select the right baudrate in the Serial Monitor.

The other topic uses this library, it is not hard to read: https://github.com/terryjmyers/ADS1115-Lite/blob/master/src/ADS1115_lite.cpp.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.