Arduino AC + DC voltage measurement

Thread Starter

rpschultz

Joined Nov 23, 2022
808
I'm working on designing a guitar tuner in Arduino (esp32), which can read analog signals from 0-3.3v. Typically an offset voltage is applied to any AC signal, so like a 100k voltage divider on the 3v3 source would give a DC voltage of 1.65vdc. Then the AC signal that you are trying to measure is applied to that pin that has the 1.65vdc. I just don't understand how this works, AC + DC voltages. And I don't really know what the amplitude of a guitar signal will be. But lets say the guitar signal amplitude is +/- 100 mV, does the AC and DC just add? So it would be 1.65 +- 0.1 V total?
 

ronsimpson

Joined Oct 7, 2019
4,647
(Guitar signal = +/-100mVac) + (DC=1.65dc) = 1.55 to 1.75V.
The average of the signal is 1.65. The -100mV will pull the signal down by that much.
The +100mV part will push the signal up to 1.75.
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
OK, so it does work like that, AC + DC. I've seen Youtube video's of hot humbuckers pushing a 2V peak to peak signal, but that would still work with a 0-3.3v range centered at 1.65v.

I'm not sure if I need to gain up the signal or not. Would it be beneficial to put a buffer on the guitar signal, even if it only has a gain of 1?
 

Jerry-Hat-Trick

Joined Aug 31, 2022
777
You need to amplify the guitar signal, for a single picked string it could be as low as 20mV AC. Ideally use a low noise, low voltage, rail to rail op amp. If you bias the +ve input to around 1.65V DC by connecting 1M resistors from the input to the the 3.3V rail and the other to ground. Then input the guitar signal AC coupled into the +ve input with a 1uF capacitor.

If you are only using for tuning, not as a preamp for hearing the sound, you could introduce higher gain. 20mV AC is around 60mV peak to peak so a gain of 30 would probably be okay. a 27K resistor from the output back to the -ve input of the op amp, then a 1K resistor from the -ve input to a 10uF capacitor to ground should do the trick. The capacior makes sure only the AC signal is amplified. The output will be an AC signal offset by 1.65V so it doesn't try to go below zero. Connect to an ADC pin of the processor.

The difficult bit is how to extract the fundamental note from the guitar. If you look at the signal on a scope it's incredibly noisy - all over the place - and I don't think the ESP32 has enough memory for you to do a Fast Fourier Transform to get the 82 to 330 frequency of the open fret strings.

If my explanation of the circuit is not clear let me know - I can sketch it. Hope this helps!
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
Yes the fundamental is the tough part. There are 3 primary ways to do it:
  1. Zero crossing, counting or determining period from how often it crosses a reference voltage. Easy, but doesn't work well with noisy signals like a guitar.
  2. FFT. Processor intensive.
  3. Autocorrelation, using math, determines period from the time between 2 similar copies.

Here's an autocorrelation code I want to try:
Code:
#define LENGTH 512

byte rawData[LENGTH];
int count;

// Sample Frequency in kHz
const float sample_freq = 8919;

int len = sizeof(rawData);
int i,k;
long sum, sum_old;
int thresh = 0;
float freq_per = 0;
byte pd_state = 0;

void setup(){
  analogReference(EXTERNAL);   // Connect to 3.3V
  analogRead(A0);
  Serial.begin(115200);
  count = 0;
}


void loop(){
  
  if (count < LENGTH) {
    count++;
    rawData[count] = analogRead(A0)>>2;
  }
  else {
    sum = 0;
    pd_state = 0;
    int period = 0;
    for(i=0; i < len; i++)
    {
      // Autocorrelation
      sum_old = sum;
      sum = 0;
      for(k=0; k < len-i; k++) sum += (rawData[k]-128)*(rawData[k+i]-128)/256;
      // Serial.println(sum);
      
      // Peak Detect State Machine
      if (pd_state == 2 && (sum-sum_old) <=0) 
      {
        period = i;
        pd_state = 3;
      }
      if (pd_state == 1 && (sum > thresh) && (sum-sum_old) > 0) pd_state = 2;
      if (!i) {
        thresh = sum * 0.5;
        pd_state = 1;
      }
    }
    // for(i=0; i < len; i++) Serial.println(rawData[i]);
    // Frequency identified in Hz
    if (thresh >100) {
      freq_per = sample_freq/period;
      Serial.println(freq_per);
    }
    count = 0;
  }
}
Moderators note : used code tags
 
Last edited by a moderator:

panic mode

Joined Oct 10, 2011
4,866
never had guitar but ... FFT is needed if you are looking at the spectrum...
but tuning guitar should not need that... plucking string should produce single frequency...
and amplitude does not matter - it is the frequency that is the key... so i would imagine that just using high gain to amplify signal to make it practically square. and that is easy... then you can measure frequency by counting pulses in some time or measuring time between edges. this too is easy and does not require much resources, any micro should be able to do it..
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
never had guitar but ... FFT is needed if you are looking at the spectrum...
but tuning guitar should not need that... plucking string should produce single frequency...
and amplitude does not matter - it is the frequency that is the key... so i would imagine that just using high gain to amplify signal to make it practically square. and that is easy... then you can measure frequency by counting pulses in some time or measuring time between edges. this too is easy and does not require much resources, any micro should be able to do it..
Interesting you say "practically square", so clipping the signal is OK for tuning. Never thought of that. Autocorrelation may work better. Thanks for the tip.
 

panic mode

Joined Oct 10, 2011
4,866
i would say it is not just simpler but also more reliable than sampling analog value of decaying signals that may contain noise. this is why FM radio was such a breakthrough ... amplify it senseless so the peaks (and noise) are removed and only look at the frequency of the signal. no noise...
 
I hinted at the square wave idea when suggesting you could increase the amp gain if you are not hoping to listen to the audio. But I’m still skeptical about whether you will be able to see the fundamental with crossovers coming from harmonics.

Please let us know if and how you get a result. If not, maybe FFT with some extra memory to get a sufficiently large sample should work.
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
Going back to post #5, I have wondered if there may be a better hybrid method that could use this method or that method at different frequencies. Lower frequencies tend to be harder to maintain accuracy because being off 1 Hz at 82 Hz (low E) is a larger fraction than 1 Hz at 324 Hz. Others on the internet have referenced below 150 Hz as some arbitrary frequency at which is gets harder, I'm not sure exactly why. 3 strings are above 150 Hz, 3 strings are below. Musically speaking, there are 100 semitones between 1/2 steps. But because each octave is a doubling of frequencies, semitones get smaller as they go up in frequency.

Anyway, I don't think FFT is a good method for various reasons. But I have had success with a zero-crossings method, and I think it worked better at one end or the other, I can't remember. I think autocorrelation also has promise. Maybe marry the two together somehow.
 

MrChips

Joined Oct 2, 2009
34,628
Plucked stringed instruments do not produce the fundamental alone. There are a lot of harmonics. Zero crossing will not work unless you filter out the harmonics. FFT will work and is doable on many MCUs. You just need to choose the proper MCU and the FFT implementation to suit the application.
 

MisterBill2

Joined Jan 23, 2018
27,186
The reason for adding the DC offset is because the audio signal varies in both directions, while the input only reads positive voltage. The explanation in post #2 is correct, but maybe not that obvious. The issue with excessive squaring is the creation of harmonics that may confuse the frequency sensing part of the system.
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
If anyone has a source code or suggestions for this sort of thing, I’m all ears. I’ll start with what’s in post #5
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
You need to amplify the guitar signal, for a single picked string it could be as low as 20mV AC. Ideally use a low noise, low voltage, rail to rail op amp. If you bias the +ve input to around 1.65V DC by connecting 1M resistors from the input to the the 3.3V rail and the other to ground. Then input the guitar signal AC coupled into the +ve input with a 1uF capacitor.

If you are only using for tuning, not as a preamp for hearing the sound, you could introduce higher gain. 20mV AC is around 60mV peak to peak so a gain of 30 would probably be okay. a 27K resistor from the output back to the -ve input of the op amp, then a 1K resistor from the -ve input to a 10uF capacitor to ground should do the trick. The capacior makes sure only the AC signal is amplified. The output will be an AC signal offset by 1.65V so it doesn't try to go below zero. Connect to an ADC pin of the processor.
Here's a sketch by the guy who wrote the code in post #5. He's using an LM358, I have more experience with TL07x and have plenty of them (don't have any LM358's). But you're right, the audio isn't passing through so sound quality isn't important. This circuit, the gain is 47/3+1 = 16.7.

Suggestions?

1720718871964.png
 
Here's a sketch by the guy who wrote the code in post #5. He's using an LM358, I have more experience with TL07x and have plenty of them (don't have any LM358's). But you're right, the audio isn't passing through so sound quality isn't important. This circuit, the gain is 47/3+1 = 16.7.
Exactly right! The LM358 is rubbish for audio whereas the TL07x series are great - but probaly either will do. Neither is rail to rail but it shouldn't matter. Using the TLO7x you may find it goes non linear about 1.0V from ground and 0.5V from the top rail so a 3.3V supply means you only get around 1,8V of linear. For audio, it's worth adjusting the +ve input bias resistors to move that voltage from 1.65V to about 1.8V but as previously discussed, you are not looking for audio quality.

Please tell us if your code does the job
 
Does the offset voltage divider need to be before the op amp or could it be after?
It has to be before the op amp - By putting a DC offset voltage into the +ve op amp input you are arranging for that same voltage to appear at the output of the op amp when there is no signal coming from the guitar. Guitar pickups produce millivolts of AC with very little power, so they like to see a high impedance input which is why you should use 1M resistors or higher - the guitar will see an impedance equal to the two resistors as if they were in parallel together with the the op amp impedance which is pretty high. The purpose of the AC coupling input capacitor is to avoid the guitar pickups seeing that DC offset voltage which they certainly don't like. Effectively the input capacitor is a block to DC but a short circuit to AC.

Similarly, the larger value capacitor to ground means that only the AC signal is amplified so the output of the op amp varies between the input offset voltage and the peak to peak value of the amplified guitar signal. If the capacitor was shorted out, you'd be amplifying the DC signal so the output would simply swing to the 3.3V rail. Because no DC current can flow through the feedback loop to ground with the capacitor in place, in the absence of a guitar signal the output simply rises to the offset voltage to match the -ve input with the +ve input.

The pinout of the LM358 and the TL072 (twin op amp) are the same. I recommend building according to the schematic you showed, just replacing the LM358 with the TL072.
 

Thread Starter

rpschultz

Joined Nov 23, 2022
808
Ah, great explanation. I am a mechanical engineer but have played with circuits for many years - even taught a HS electronics course. But I never understood the AC DC thing, nor what the capacitors where for. Now I do!
 
Top