Amplitude Detection

Hi All,

I'm working on a class project and I need (urgent!) help in figuring something out. I have a microphone that goes through a low pass filter. If we run 1000Hz sound from our phone, on the Oscilloscope it is giving an amplitude of 300 mV and if we run a 10K Hz sound through the microphone, it is giving an amplitude of 30 mV or so. However, we are unable to detect the amplitude of these sine waves on the Arduino, and we realized that the analogRead function is giving us the DC-RMS voltage(1.6V in this case) for both frequencies. We need to know how to figure out the amplitude so we can differentiate between the 1K and 10K hertz frequencies from our phones. Here's a test program I've been writing to figure this out:

int sensorPinLowPass = A3;
int sensorPinHighPass = A0;
int sensorValueLowPass  = 0;
int sensorValueHighPass = 0;
float counter = 0;
float sum = 0;
int counterFinal = 10000;
int testNum = 1000;
int testCounter = 0;

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

void loop() {
  while( counter < counterFinal){
    // read the value from the sensor:
    sensorValueLowPass = analogRead(sensorPinLowPass);
    //sensorValueHighPass = analogRead(sensorPinHighPass);  
    //Serial.println("Amp Low Pass");
    //Serial.println(sensorValueLowPass);
    //Serial.println("Amp High Pass");
    //Serial.println(pow(sensorValueHighPass, 2));
    sum  += pow(sensorValueLowPass, 2);
    //Serial.println(sum);
    counter++;
  }
  
  if(counter == counterFinal && testCounter < testNum){  
    float finalVal = sqrt(sum/counter);
    Serial.println("finalVal");
    Serial.println(finalVal);
    sum = 0;
    counter = 0;
    testCounter++;
  }
  
}

and we realized that the analogRead function is giving us the DC-RMS voltage(1.6V in this case) for both frequencies.

No it is not, it is giving you a sample which can be anywhere between the maximum and minimum peak values.

To get the envelope you need to either:-

  1. Put an envelope follower between the audio output and the arduino input. This can be as simple as a series diode and a capacitor to ground.

  2. Sample as quick as possible and record the maximum value you get and hope you get somewhere close to the peak value. However as the analogue to digital converter can only sample at 10KHz then you will probbly not get very close to this.

Hi Grumpy Mike,

We've decided we'd rather pursue the second option. Can you give us any example code or links to adjust the sampling speed?

learning something new today... I've never seen: 'int sensorPinLowPass = A3;' before.

Is 'A3' (and so on) # defined in the IDE ?

I thought maybe hex, but that would be 0xA3.

You need to ensure that your hardware circuit is set to pass the waveform to the analogue input.

Set up A/D for fast mode:-

// set up fast ADC mode
   ADCSRA = (ADCSRA & 0xf8) | 0x04; // set 16 times division

Code for trying to find the maximum:-

int max = 0, reading;
for(int i = 0; i<times; i++) {
   reading = analogRead(0); // change number for pin you are using
   if(reading > max) max = reading;
}

This uses a variable "times" which you have previously set to determine the number of samples you want to look at to try and find the maximum.

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

How you connect the signal to the arduino is also important.
What model arduino controller are you using?

Tom... :slight_smile:

I use a [u]Peak detector[/u] (for my sound activated lighting effects). The peak detector quickly charges-up to the (positive) peak value and slowly discharges. This means I can read the voltage relatively slowly instead of sampling the audio waveform at thousands of times per second. I usually read the amplitude about 10 times per second (or faster).

The peak detector throws-away the negative half of the waveform, so it protects the Arduino from negative voltages. You can damage the Arduino by applying negative voltages greater than -0.5V. (300 mV should be OK... As you may know, a 300mV RMS waveform has positive & negative peaks of about 4.2V.)

Anothercommon way to handle the negative half of the waveform is to use a [u]DC bias circuit[/u].

Hey guys,

Grumpy Mike, will that code be usable on the Arduino Uno?

To everyone else suggesting hardware solutions, this is a school project so it's due very soon and I'd rather not implement a hardware solution that will definitely cause a lot of debugging problems and be time consuming.

Tom George, I've attached a picture and wanted to let you know that I've created the low pass and high pass filters based on these:

Also an overview of your project, we're basically trying to rotate a servo motor with a fan on top of it. One frequency will be used to turn the servo in a certain direction and the other frequency will be used to turn the fan on.

Edit: Unable to attach picture for some reason.

Grumpy Mike, will that code be usable on the Arduino Uno?

Yes.

Edit: Unable to attach picture for some reason.

Select reply rather than quick reply. Click on the triangle in the lower left of the reply. Click on attachments and hit the brows button. Then navigate to your file and upload.

The code I posted will only work if your method of attaching the audio into the Arduino is correct. You know you can't just attach an audio wire to an analogue input don't you?

I've attached the image to this reply.

Grumpy_Mike, then how do you attach the audio to the Arduino? Right now we pass the output from the microphone directly to the analogue input.

how do you attach the audio to the Arduino?

Analog input to two 10K resistors, one going to 5V and the other going to ground. Then the analog input also goes to one end of a capacitor, 1uF should do but anywhere up to 10uF. The other end of the capacitor goes to the audio signal, with the ground of the audio going to the ground on the arduino.