Introduction: Arduino Guitar Pitch Detection

This Instructable will demonstrate how to make a simple pitch detector for an electric guitar. The project focuses on picking out only 1 note at a time via strumming the guitar. Before diving too deep into the project credit must be given where it's due. For inspiration and reference the following Instructables by user amandaghassaei were used throughout this build:

Arduino Audio Input

Arduino Frequency Detection

This Instructable aims to follow the format of the "Arduino Audio Input" Instructable listed above. References back to this webpage will be made fairly often, and the style will be somewhat similar.

Above is one of the videos that demonstrates the completed project working. More such videos can be found here.

Parts List:

Note that if access to an Analog Discovery isn't available, any other oscilloscope can be substituted if waveforms are required. The circuit used in this Instructable is powered with the pin-outs of the Analog Discovery, but two 9V batteries can also be substituted as shown in the "Arduino Audio Input" Instructable linked above.

To follow through the progress of testing and building this project in more detail, please see the project journal here. This website will provide more tips for troubleshooting and walk through some items in a bit more detail.

Step 1: Understanding Pitch Versus Frequency

Before getting started it's important that we understand what this project aims to accomplish. The goal is to determine the pitch of an electric guitar by outputting a specific color for each of the 6 notes played. The 6 possible notes and their associated colors for the electric guitar used are as follows:

  • E4 (329.63 Hz) Purple
  • B3 (246.94 Hz) Blue
  • G3 (196 Hz) Light Blue
  • D3 (146.83 Hz) Green
  • A2 (110 Hz) Yellow-Green
  • E2 (82.41 Hz) Red

So, then what is pitch and what is frequency? How are they different? Frequency and pitch are very closely related and are often used interchangeably, but they are not exactly the same thing.

Frequency is the amount of oscillations per cycle (Hertz or Hz) of a waveform. 1 Hz is the most common measurement for frequency and in this case is 1 wave from peak to crest (top to bottom) in one second. This is purely measurable and doesn't mean much to a human listener, but it is directly related to how a sound, sounds to a person.

Pitch is human perception of frequency, and is subjective and slightly different from person to person. A high-pitched sound will come from a high frequency wave (such as the note E4 from the electric guitar) and a low-pitch sound will come from a low frequency wave (such as note E2 from the electric guitar). E2 is a thicker, heavier string than E4 is, so it vibrates at a slower rate than E2 does. This is what causes E4 to have a higher pitch than E2.

Because pitch is subjective, each note listed above will actually have a small range in which the code will pick it up. E4, for example has a range of 324-340 Hz in the code for this implementation. This means that any frequency between 324 and 340 Hz will be recognized as E4, instead of exactly 329.63 Hz. This simulates some of the subjectivity of pitch that humans have.

Step 2: Processing Circuit for the Arduino

All audio signals are recorded as waveforms like the ones shown above. These signals will typically oscillate around 0V, which isn't ideal for Arduino signal processing. This is due to the fact that the Arduino can only process positive voltages between 0V and 5V. As such, the input to the Arduino needs to be centered around 2.5V, with an amplitude (voltage swing) of no more than 2.5V. This will keep the voltage between 0V and 5V, as desired. The way to accomplish this is to build a circuit with a DC offset of 2.5V.

The input signal from the electric guitar was found to have an amplitude of between 150 and 300 mV depending on how high the volume knob was turned on the guitar. This is an issue because once the signal is centered around 2.5V the desired output is an amplitude of 2.5V so that we have the maximum available voltage range of the Arduino. This is important because it allows the most distinct points to be recorded by the Arduino, which gives a better waveform and a more stable pitch reading. In order to change the amplitude of the input voltage we will walk through building a simple amplifying circuit.

After amplification, the signal goes through a low pass filter before being input into the Arduino. A low pass filter does exactly that; it allows low frequency signals to be passed through while filtering off high frequency signals. We use a low-pass filter with a cutoff frequency of 500 Hz, which will help to get rid of any frequencies over 500 Hz. This is especially useful because the frequencies we are interested in lie between 82Hz and 330Hz, so high frequency signals will be more easily ignored if they're filtered out.

Finally, the circuit uses some MOSFETs and a 5 meter RGB LED strip to add some life to the pitch detection system. The MOSFETs are used to boost the power output from the Arduino to the LED strip. This is necessary because although LEDs consume very little power individually, our strip has 300 LEDs on it, which the Arduino can't power without the help of MOSFETs.

All of these circuit elements will be dived into with more detail in the following steps.

Step 3: Preparing Audio Jack

This step is quite literally identical to the step from amandaghassaei's Instructable. Please see that step here.

Step 4: Amplification Circuit

Because the input voltage to our circuit is so small, it must be amplified for better processing. The way that we will do this is by using a non-inverting amplifier (called non-inverting because a positive signal will remain positive at output). This works by using an electronic device called an op-amp. The op-amp we're using is the OP27G. This op-amp was chosen because it is widely available, inexpensive, and has relatively low noise and high enough processing speed for our use.

The Analog Discovery USB device was used in order to build and test the circuit as progress was made. This device is an oscilloscope, logic analyzer, and variable power supply that uses USB to communicate with any computer. In the final design implementation the Analog Discovery is used solely as a power source.

The Analog Discovery was used to provide +- 5V to the op amp on pins 7 and 4 of the OP27G, respectively. The signal pin of the audio jack was used as an input to pin 3, with the ground pin of the audio jack hooked up to ground. A 100kOhm resistor was wired from the output on pin 6 to the input on pin 2. The 10kOhm potentiometer was then wired from pin 2 to ground. Click here to download the fritzing diagram(s) for manipulation.

An op-amp takes an incoming signal and amplifies the voltage by using the following formula:

Vout/Vin= 1 + R2/R1 (This is called gain)


Where R2 is the 100kOhm resistor across the op-amp and R1 is the 10kOhm potentiometer. This gives a variable gain (how much the signal is boosted), which allows the amplifier to work for a range of smaller signals. This is perfect, since we have an input voltage between 150mV and 300mV.

See the picture above for an example of the amplification circuit working. The amplitude is 2.508V which is just a little above what is desired, but turning the potentiometer very slightly will give an amplitude slightly less than 2.5V, which is ideal.

Step 5: DC Offset

As discussed before, the Arduino can only process signals between 0V and 5V. Now that we've got our amplification circuit working, the next step is to get the DC offset (average value) up to 2.5V so that the signal is never lower than 0V or higher than 5V.

To build the DC offset, two 100kOhm resistors, a 47nF capacitor, and a 10uF capacitor were used. The two 100kOhm resistors were wired in series from the 5v rail to the ground rail on the breadboard. This creates a voltage divider with a value of 2.5 volts at the junction between the two resistors. The 10uF capacitor is then wired so that the negative lead of the capacitor (usually the shorter one) is wired to the output of the op amp on pin 6, and the positive lead of the capacitor is wired to the junction between the two resistors. This creates a voltage that constantly charges and discharges across the capacitor, creating an average value, or DC offset, of 2.5 volts. The 47nF capacitor is then wired from 2.5 volts to ground, which creates a more smooth and constant 2.5 volts DC with less ripple.

Step 6: Low Pass Filter

The low pass filter design used in this project is called a passive low pass filter. This is a simple series combination of a resistor and a capacitor, with the output voltage measured across the capacitor. A low pass filter has a cutoff frequency, which is the maximum frequency that will be passed through the filter. The filter we want to use has a cutoff frequency of 500 Hz, so that any frequencies higher than 500 Hz will be attenuated (their amplitudes will be decreased so that the Arduino doesn't pick them up).

To figure out the components to use in the low pass filter the following equation must be used:

fc = 1/(2*pi*r*c)


Where fc is the cutoff frequency, r is the resistor value needed, and c is the capacitor value needed. We will choose a stock value of .1uF (100nF) for the capacitor, and the cutoff frequency desired is 500Hz. Solving the equation above, the ideal resistor value needed is 3.18kOhm, but for the purposes of this build 3.3kOhm is within the acceptable margin of error.

Step 7: MOSFETs, LED Strip, Completed Circuit

The final portion of the circuit is used to boost the output power of the Arduino so that the LED strip can be properly driven. Without the MOSFETs, the Arduino can't output enough current to light up the LED strip in any capacity. The specific function of MOSFET can be seen here, but for the purposes of the project just think of them as drivers for the LED strip.

Each MOSFET has a gate, drain, and source from left to right (pins 1, 2, and 3 consecutively from left to right). The gate (pin 1 of the MOSFET) has a 220 Ohm resistor wired up to it, with the appropriate pin-out of the Arduino wired into the input of the resistor. The blue strip is hooked up to pin 7 on the Arduino, the green strip to pin 6, and the red strip to pin 5. The source (pin 3 of the MOSFET) is hooked up to ground. Finally, the drain (pin 2 of the MOSFET) is used as an output to the LED strip. Each color MOSFET corresponds to the same color on the LED strip, meaning blue to blue, green to green, etc. The VIN (9V) output of the Arduino is then wired up to the white input on the LED strip.

Note that in order for the Arduino to supply this 9V output the power plug that came with the light strip must be used as a plug for the Arduino. This is because USB has a maximum voltage of 5V, meaning that the Arduino won't put out 9V if it's only hooked up via USB to a computer.

Now we're finally ready to dive into the code used for this project.

Step 8: Original Software

For our software base we began with what was originally developed in user amandaghassaei's instructable which can be found here:

Arduino Frequency Detection

The way this part of the code works is it uses midpoint detection to determine the frequency of whatever wave is input. As discussed earlier, the typical midpoint of any sound wave is 0V. However, through the use of the voltage divider we were able to bump the midpoint of our wave up to 2.5V. This is necessary because the Arduino is only able to read voltages between 0V-5V.

The way the algorithm works is it essentially measures the rate of change of the voltage by seeing how much the voltage has either increased or decreased between samples. It is then able to determine how many times the wave crosses the midpoint in one cycle by looking at the slope of the sample each time a voltage measurement is taken and crosses the midpoint. Essentially what the algorithm does is it picks out the largest slope corresponding to a midpoint crossing. Then, each time the wave crosses the midpoint, it is able to determine if one complete cycle has occurred by comparing the current slope to the largest slope it has registered. If the slopes are the same then the algorithm knows a cycle has occurred. If the slopes are different then the algorithm can determine that a cycle has not occurred, just another midpoint crossing in the periodic waveform.

While doing all this the algorithm also keeps track of the time to measure how long it takes for one cycle to complete. It essentially does this by counting how many samples are taken in one cycle as we know our sampling rate. After measuring this it is then trivial to determine the frequency as it can be calculated by taking the inverse of the period.

Again, all this was in the code developed by user amandaghassaei in their instructable. Our additions to the code were to optimize this midpoint frequency detection algorithm for the strings played on an electric guitar.

Step 9: Software Modifications

Here is a light frequency color wheel corresponding to the combinations of RGB colors. Additionally, here is the light spectrum where lower frequency light is on the right and higher frequency light is on the left:

The first step we took towards optimizing the code was to play with the slope and timer tolerance levels. The goal was to set them to values that would work well with the frequency range of an electric guitar which would allow us to better measure the frequency of sound that comes from each guitar string. This was done by running a sine wave through our circuit into the arduino {pin A0} at frequency ranges corresponding to those of electric guitar. After some testing we determined that the best values were to set the slope tolerance to 25 and the timer tolerance to 10.

The next modification we made to the code was to determine the actual frequency of each string from the guitar. This was accomplished by loading the code onto the Arduino board, taking it and the circuit to the lab and hooking it up to the guitar, and playing each string. We knew that the output pitch of each string should be close to values we had researched {you can find the average frequency of each string easily online} but we wanted to actually test what they were for this specific guitar so we could craft if statements that would better be able to determine which individual string had been played. {Note: a cool addition to this project would be to actually use our circuit and code to help tune a guitar!!}

After connecting our guitar to the circuit and the Arduino and opening up the built in serial monitor in the Arduino software development package we were able to measure the actual frequency value of each individual string on this specific guitar. We then crafted a series of if statements saying that if the measured frequency fell within a range of 16 Hertz around our measured frequency {8 Hertz above or 8 Hertz below} for each string then it could be determined that that specific string had been played. Note that this range could be set even smaller if a better tuned guitar is being tested!

Our next modification to the software wrote a one or zero to three different output ports based on the string that had been played. The output device we connected to was a RGB LED strip so the way we crafted our code was to light up the strip with frequencies of sound corresponding to frequencies of light. For example, we wanted our lowest pitch string, E2, to correspond to the lowest frequency of light that could be produced by the strip, red. Similarly, we wanted our highest pitch string, E4, to correspond to the highest frequency light we could produce, magenta/purple which is a combination of red and blue light using the LED strip.

Our software uses three output ports; pin 7 on the Arduino for blue, pin 6 on the Arduino for green, and pin 5 on the Arduino for red. Based on the string that has been played we activate a combination of these ports in order to make the LED strip a certain color. For example, say string G3 has been played, the string with the 3rd highest frequency on the electric guitar. Our software will write a 1 to pins 6 and 7 making them 3.3V and a 0 to pin 5 making it 0V. These pins are then connected to our remaining circuit and their corresponding MOSFET's in order to boost the current and activate both the green and blue lights on our LED strip resulting in an output color of light blue.

The final modification we made to our software was that if we are not able to determine if any string has been played on the electric guitar{from a bad frequency reading/measurement} then our output ports remain the same and the LED strip doesn't change colors. This aspect of our code helps to ensure that erroneous measurements don't affect our output and that the LED strip stays active with the correct final output color.

Our final software can be found at the following link: Code