Measuring Data rate of an ADC connected via I2C

Hi everybody,
I´m new to Arduino and for my first project I need to read out the Data rate with which my Analog-Digital-Converter (ADS1115) connected via I2C is sending Data to my ESP32 (Adafruit HUZZAH32 - ESP32 Feather). It says in the Data sheet of the ADS1115 that there is about a 10% error in the Data rate. For my application I need to know the Datarate quite exactly, since I want to use the Data to create Audiofiles and if I get the Samplerate wrong it shifts the frequencies. (Yes, I know that with ADS1115 I´m limited to 860 SPS, therefore i can get maximum 430 Hz in the Audiofile, but thats a problem for another time).
I tried measuring the Data rate with the following little sketch.

After initialising the ADS1115 in the setup with a Datarate of 860 Samples per Seconds (SPS), I measure the time (tdiff) it takes for the ADS1115 to send a set number of data (int a) and calculate the data rate with these values (Data rate = a/tdiff).
But I get way higher data rates than expected (~7000 SPS). I assume that is because the ESP32 reads out one data point sent by the ADS1115 more than once. I think i dont understand the stop parameter from the Wire.requestfrom( , ,true/false) function correctly. I thought that when it is set to true, a stop message would be sent, that results in the ESP32 not reading out the ADS1115 again until “new” data would be presented. (“New” doesn´t necesseraily mean a new value but a refreshed measurement). But that was probably naive thinking. I tried adding if(Wire.available()) around the in the sketch commented “*” just to see if that helps, but nothing changed.

How can I fix this? I can´t use any timers with interrupts, because i dont know the exact timing yet, as this is just what i´m trying to measure here.

If its important for any help, the sensor connected to the ADS1115 is an opt101 optical Sensor.

Thanks in advance!

#include <Wire.h>

#define ads1115 (0x48)     // I2C Adress  ADS1115
const byte numChars = 32;
char receivedChars[numChars];

void setup() {
  
  Wire.begin();               
  Wire.setClock(400000);
   
  Serial.begin(115200);       
  
  // Initialise ADS1115
  Wire.beginTransmission(ads1115);      
  Wire.write(0x01);           // Adress Config Register
  Wire.write(0b00000000);     // AINP=AIN0 and AINN=AIN1; FSR= ±6.144V; cont. mode
  Wire.write(0b11100011);     // 860 SPS; comparator off
  Wire.endTransmission();

  // Pointer to conversion Register
  Wire.beginTransmission(ads1115);      /
  Wire.write(0x00);           // Conversion Register address
  Wire.endTransmission();
}


void loop() {
  unsigned long time1 = millis();
  byte ADC0h;
  byte ADC0l;
  int a = 10000;
  for (int i=0; i< a; i++)
  {
    Wire.requestFrom(ads1115, 2, true);
   // if(Wire.available()) {  //*
    Wire.read();
    Wire.read();   
   // } // *
  }
  unsigned long time2 = millis();
  float tdiff = (float)(time2-time1)/1000;
  Serial.print("Time difference: ");
  Serial.print(tdiff, 3);
  Serial.println(" s");
  Serial.print("Data rate: ");
  Serial.print((float)a/tdiff);
  Serial.println(" SPS");

}```

isn’t I2C a master/slave bus? won’t the data rate be how quickly code makes an I2C request?

should the AD be polled to determine when a sample is available?

Have you considered a Codec. There are Codec shields. In hardware, audio codec refers to a single device that encodes analog audio as digital signals and decodes digital back into analog. Simply stated it contains both an analog-to-digital converter (ADC) and digital-to-analog converter (DAC) running off the same clock signal.

without specifying a device, it’s unclear what the benefit is. ( wouldn’t have thought of an ADC with an I2C interface, but i don’t know what the requirements are)

i’m familiar with u-Law codecs use by the phone company. they have a serial interface, sample at 8 kHz and compress 14-bits of linear input to 8 u-Law bits.

i used DSPs with serial interface very compatible with the codecs i’ve used and more than capable of processing several 8 khz sample channels

i’m curious about using Arduino’s for sampling audio. i don’t believe they are fast enough to process audio data. As said, telephone quality audio is sampled at 8 kHz, music at 44/48kHz. Not sure what quality is possible when sampling at < 1kHz

basic sampling theory says you need to sample at twice the highest frequency, telephone audio bandwidth is ~3.5kHz. i think minimal audio quality is ~2.5 kHz (military quality is presumably sufficient to understand what is said but not by who) and would require ~5kHz sampling

i’m curious what this application is intended to do

An 8-bit AVR “Arduino” would likely be limited. But, throw a more powerful processor at it and you can get pretty impressive results. Take a look at the Teensy Audio Library. Several folks have use this to implement sophisticated projects such as Software Defined Radio.

real time audio processing required much more horsepower than a software defined radios which i retired from

Take a look at the library. It can do real time processing on multiple channels of 16-bit audio sampled at 44 KSample / second and above. I’ve used on 96 KSample / second SPDIF audio converted to I2S.

That doesn’t make sense, SDR can have large IF bandwidths (many MHz), requiring vastly more raw throughput than audio (although the processing might be fairly limited, ie just
short-form FFT conversion, rather than convolving with the acoustics of a cathedral.

audio processing typically requires processing each sample. (some applications off-load this processing to separate HW)

software defined radios typically requires configuring hardware for the desired radio band, frequency and bandwidth and doesn’t require real-time processing to maintain it

at least in the radios i worked on, generating 2.5G, 3G, 4G symbols was performed by a chain of DSPs while an ARM processor was more than sufficient to configure the radio

The SDF project I linked does the IF demodulation, filtering, and audio processing in software running on the Teensy’s ARM.

As I said, the Teensy Audio Library can process multiple channels of CD-quality audio using just the ARM. DAC and ADC functions are performed with external CODECs which stream in and out of the ARM over I2S. But, the ARM is doing all the processing at sampling rates faster than 44 Ksamples / second.

i doubt the Teensy is converting a baseband signal thru IF to RF, that’s what those RF chips are for and are optimized for and meet FCC requirements as well. presumably the Teensy is processing a baseband signal at audio bandwidths.

i wanted to look more at the Teensy 4.1 web page. i didn’t realize the Teensy is an ARM processor and not a microcontroller. and it looks like it has a crypto sub-processor and some high-speed i/o channels. (it seems many chips composed mostly of DSP (Tensilica) processors have an ARM processor that runs Linux)

it’s not clear what processing of CD quality audio is being done (e.g. mpeg compression) by the processor or if DMA channels are just being used to move it from one interface to another.

it looks like the Teensy 4.1 is substantially more powerful than the 3.6 and it supports DSP instructions. i’m not sure what other Teensy processors are capable and what peripheral board do

we found that we needed over 200+ MIPs to do voice recognition on a RISC processor which we could do with a 40 MIP DSP. the vender explained to us the problems with branching on a RISC processor and recommended one of there other chips that had both RISC and DSP processors. in other words, the audio processing is done on the DSP not the ARM.

I never said anything about RF. in that project:
https://www.dropbox.com/s/zvh9y60i6a8pd84/Teensy%20SDR%20Documentation%20DD4WH.pdf?dl=0

You should probably take a look at the library before stubbornly insisting it can’t do what many people have used it to do.

do you think IF is audio? if it’s even used. most SDR use direct conversion and don’t even use IF

i didn’t say the device doesn’t do it, simply that i doubt it’s done in software.

Which just goes to prove you didn’t look at the project I linked or the Audio Library.

i did look at the link, found it interesting and did look a little deeper at some of the hardware it was compatible with and Teensy’s capabilities. no i did not study the library.

i’ve commented on what YOU have suggested and my work experience with these technologies

Thans for your responses.

If I were to use the data rate determined by how quickly the code makes a request, the resulting wave form would be terrace like because the same measured data point would be read out multiple times. As a result it would sound like there are more high frequencies present than actually measured sort of like a distortion. Obviosly not something I want. That´s why I need the data rate of the ADC.

What I´m currently doing is Polling. My code checks every X ms what the Signal is like. What I need is sort of an interrupt with I2C. Every time the external ADS1115 has new Data i want to record it. This sounds to me as if I need the ADS1115 to be the master and my Microcontroller the slave, but thats not possible according to the datasheet.

No, I haven´t. That might be worth looking into for the later stages. For now I record the Data into an array and send it via the serialprint in an external loop (so save time during the recording) to my Pc where I convert it with a cpp Programm into a wave file. In the cpp program I then need the information about the actual data rate.
During the development phase I also want to look at the measured data in some spreadsheet program. So I need the pc for now.

why doesn’t this work? presumably you’re checking a sample ready bit in the AD not “what the Signal is like”

of course it would be nice if the AD could generate an interrupt which would avoid polling

I don´t follow. As mentioned in the original post, I tried wether checking with Wire.available() made a difference, which it didn´t. The value of Wire.available was always 2 no matter if the particular sample has already been read out be the ESP32 or not.

maybe you think a conversion is done whenever you read an AD. conversion is (relatively) time consuming.

when reading a sample from the AD, you need to make sure a conversion has been completed. this has nothing to do with the I2C bus.

looks like there is an ADS115 has an alert/rdy pin (pg5) that indicates a conversion is complete. this could be connected to an interrupt so that your SW knows when to read

the description on pg 1 says it can be configured for continuous or single conversions. presumably the config register needs to be set

looks like bit-15 of the conversion register (pg 28) indicates if a conversion is complete