Sound speed measurement with 2 piezo

Good evening everyone,

I am using a couple of piezoelectric sensors connected to an amplification circuit built based on David Houlding's personal blog. The correctly amplified signal is then inputted to an ARDUINO UNO. I would like to measure the speed of sound propagating through a wooden table using the two piezo sensors as checkpoints. I have set the ADC prescaler to 4 bits to increase the sampling rate.

I was thinking to save the time stamp at which a given threashold is exceeded by the signal coming in every analog pin and output the time difference in microseconds.

I am currently using the following code

unsigned long time0 = 0; 
unsigned long time1 = 0;

int threshold = 350;

void setup() {
  Serial.begin(2000000); 
  ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits
  ADCSRA |= bit (ADPS1);                               //   setting the prescaler to 4 bits 
  delay(2500); // Allow time for the serial monitor to open
}

void loop() {
 

    if (analogRead(A0) > threshold && time0 == 0) {
      time0 = micros(); 

      while(1){

        if (analogRead(A1) > threshold && time1 == 0) {
          time1 = micros();
          Serial.println(time1 - time0); 
          time0 = 0;
          time1 = 0;
          delay(1000);
          break;
        }
      }
    }

    if (analogRead(A1) > threshold && time1 == 0) {
      time1 = micros(); 

      while(1){
        
        if (analogRead(A0) > threshold && time0 == 0) {
          time0 = micros();
          Serial.println(time1 - time0); 
          time0 = 0;
          time1 = 0;
          delay(1000);
          break;
        }
      }
    }
}

The problem I face is with the output in microseconds I get... I don't understand why most of the time it is extremely large, for example:

4294967284
4294967284
4294967288
4294967284
4292064684
4284993872
12
8
8
4294967288

You could attempt to debug your code by printing the analogRead(A0) value. Print the threshold value and print time0 values. Perhaps there is a logic problem.

That is the expected result of unsigned long subtraction, when time1 is less than time0 in this line:

         Serial.println(time1 - time0); 

With signed arithmetic, the result would be negative.

1 Like

microseconds is a 32 bit counter that wraps around, overflows, at 4 294 967 295 and becomes 0. This happens every one hour++.

Save the Serial.print() for after data is captured. It is slow.

unsigned long time0 = 0;
unsigned long time1 = 0;
int threshold = 350;

void setup() {
  Serial.begin(115200);
}

void loop() {
  if (analogRead(A0) > threshold) {
    time0 = micros();
  }
  if (analogRead(A1) > threshold) {
    time1 = micros();
  }
  if (time0 && time1) { // both sensors have a reading
    if (time1 > time0) // time0 was first
      Serial.println(time1 - time0);
    else // time1 was first
      Serial.println(time0 - time1);
    time0 = 0; time1 = 0; // reset times
    delay(250); // avoid ringing 
  }
}

Why use the ADC? The project you say you copied includes a comparator, whose output...

...provides a direct input to Arduino Uno digital pin

Which is certainly faster than the ADC, regardless of prescaler. And would be suitable for the other fast timing capabilities of the Arduino.

Thank you very much for your suggestion!

I initially thought the ADC was necessary because sometimes the comparator output has minor noise spikes (closer to 0V than 5V). My idea was to eliminate these spikes by setting the threshold at 350. However, you made me realize that with digital read, I am intrinsically setting a threshold, and the signal values close to 0V are still treated as if they are exactly 0V.

I will make the modification as soon as possible!

1 Like

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