External interrupt to trigger n samples using free running ADC

DFirst time posting on a forum*
My question is: how can I use an external interrupt to trigger a series of ADC measurements (say 1000 samples) but then stop sampling. I’ve seen examples online but they seem to just loop indefinitely and print over serial some metrics based on the last number of samples.

Here was a good resource I found, which provided the basic template for the code below:

Background:
I am trying to measure ocean currents between two sites using 2 hydrophones per site (4 in total). The sites will be approximately 100 feet apart.

–site A— --siteB–
set ‘mode’ to TX or RX set ‘mode’ to the opposite of site A (TX or RX)
ADC1_A / hydrophone 1A ADC1_B / hydrophone 1B
ADC2_A / hydrophone 2A ADC2_B / hydrophone 2B

Each site can be either the ‘transmitter’ or ‘receiver’ in a given instance. Even when acting as the ‘transmitter’ the site will need to measure the waveform that it has generated on (rather than assuming the electronics have acted ideally to the input waveform). When acting as the ‘receiver’ it will ‘listen’ on both hydrophones for a specific period of time / number of samples.

I.E. Hydrophone 1A is being driven at 12.5 kHz, hydrophone 2A will listen for the wave form it created while Hydrophone 1B and hydrophone 2B will both also be listening to receive the sound waves generated once it has reached their site. The time-domain variation in what is observed at site A and B will be used to derive the ocean current speed in one-dimension. That part is out of the scope of this post.

The two sites will be cabled to shore so I can have a common external interrupt trigger them (which should hopefully provide a sufficient time sync as well).

Transmitted frequency is 12.5 kHz for the hydrophones so I will need to use the free-running ADC to get the required sampling rate (76.8 kHz should be good).

The biggest question outstanding for me is, how do I disable the free-running ADC once it has started (until the next time the external interrupt is triggered). Also, how do I alternate the ADC read so that I read both hydrophones during the same sampling session.

I plan on writing the ADC reads to a 2-D array of bytes, i.e. bytes samples[channel][sampleNumber]; and writing the contents of the array over the serial port once the samples are all completed.

Here is the ‘code’ although it is missing quite a bit of detail, hence the post. The opposing site would have the same code running on its arduino.

Things that need to be implemented:
1-this code only sets up one ADC for free-running mode (as far as I know)
2-the ISR(ADC_vect) only will trigger / sample one ADC ( I need 2)
3- serial interfacing to change mode and report back samples (this is the most trivial part, I can handle that on my own)
4- perhaps something I’ve forgotten

Thanks for any help you can provide!

//Sketch to trigger a free-running set of ADC samples
//if mode = 0 (TX) then only require one set of samples
//if mode = 1 (RX) then record both ADC channels

int numSamples=0;//initalize counter to zero
long t, t0;//time variables to calculate elapsed time
int mode=1;//assumes it will be an RX unless told otherwise
int maxSamples = 1000;//one byte per sample
int channel; //should be 0 or 1, representing the two hydrophones at this site
byte samples[channel][maxSamples];//2-D array to store values from ADC0 and ADC1
int interruptPin = 3; 

void setup()
{
  Serial.begin(9600);

  //setup external interrupt
  attachInterrupt(digitalPinToInterrupt(interruptPin), startSampling, RISING);

  //initalize registers
  ADCSRA = 0;             // clear ADCSRA register
  ADCSRB = 0;             // clear ADCSRB register
  ADMUX |= (0 & 0x07);    // set A0 analog input pin
  ADMUX |= (1 << REFS0);  // set reference voltage
  ADMUX |= (1 << ADLAR);  // left align ADC value to 8 bits from ADCH register

  // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]
  // for Arduino Uno ADC clock is 16 MHz and a conversion takes 13 clock cycles
  ADCSRA |= (1 << ADPS2);                     // 16 prescaler for 76.9 KHz

//sets the ADC to 'free-running mode'
  ADCSRA |= (1 << ADATE); // enable auto trigger
  ADCSRA |= (1 << ADIE);  // enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN);  // enable ADC
  ADCSRA |= (1 << ADSC);  // start ADC measurements
}

//upon interrupt, store an ADC read and increment the sample counter
//ISR is used for INTERNAL interrupts
//However, the samples should be triggered by an EXTERNAL interrupt initially
ISR(ADC_vect)
{
  samples[channel][numSamples] = ADCH;  // read 8 bit value from ADC into 2-D array
  numSamples++;
}

//
void startSampling(){
  // initiate free-running ADC measurement series here. samples will continue based on ISR(ADC_vect)
    t0 = micros();//initiate time variables 
    numSamples=0;//reset sample counter
    ISR(ADC_vect)
    //now how do I stop this ISR() / cycle?
}

void loop()
{
  if (numSamples>=maxSamples)//if required number of samples has been taken
  {
    t = micros()-t0;  // calculate elapsed time
 
    //write contents of samples[][] over serial here and include the time elapsed at the end
   //<not yet implemented>

    // should enter an 'idle' state, perhaps sleep here until the next interrupt.
  }
}

Perhaps you can just program to ignore the ADC until you need to read the values.

Paul

The AVR's have only one adc, with multiplexed input. So you can read only one input at a time.
An interrupt can initiate anything you can control with code.