In one of my last blogs I made a small test-sketch to print some audio data from an ADS1015 Analog to Digital Converter (ADC) capturing the input from an electric guitar using the Arduino loop(). In real life however, we want to drive the capturing of the samples with a timer. A first naive implementation was awfully failing because the ESP32 does not allow I2C calls in the timer interrupts. The solution is to create a separate task and drive the processing from the interrupt.

This sounds awfully complicated and therefore I decided to package the solution in a reusable class: that’s how the TimerCallbackAudioStream was born:

The Arduino Sketch

#include "AudioTools.h"
#include <Adafruit_ADS1X15.h>

using namespace audio_tools;  

const int sample_rate = 3000;
const int channels = 1;
const int bits_per_sample = 16;

Adafruit_ADS1015 ads1015; // ads1015 device  
TimerCallbackAudioStream in; 
CsvStream<int16_t> out(Serial);                        
StreamCopy copier(out, in); // copy in to out

// Provides the data from the ADS1015
uint16_t IRAM_ATTR getADS1015(uint8_t *data, uint16_t len){
    int16_t sample = ads1015.readADC_Differential_0_1();
    memcpy(data,(void*) &sample, sizeof(int16_t));
    return sizeof(int16_t);

// Arduino Setup
void setup(void) {
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);

  // setup gain and start ads1015 

  // Open stream from ads1015  
  auto cfg = in.defaultConfig();
  cfg.rx_tx_mode = RX_MODE;
  cfg.sample_rate = sample_rate;
  cfg.channels = channels;
  cfg.bits_per_sample = bits_per_sample;
  cfg.callback = getADS1015;
  cfg.secure_timer = true;

  // Output as CSV to serial 


// Arduino loop - copy data 
void loop() {

The solution is very simple: The data is provided with the help of a simple callback method: In our example this is getADS1015().

As usual, we also need to setup the ADS1015 and configure the input class with the audio data, a callback method and we need to indicate that we want to execute the processing in a separate task: This is done by setting the secure_timer to true.

Finally we set up the output and copy the input data to the output…


No change, so please consult my last blog


Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *