Project Journal

Group Meeting: April 9, 2017

Today our group met to discuss the project and ways we could go about implementing a pitch detection design.

The first thing we did at our group meeting was to search online for similar projects to get an idea for what we could build to go about achieving the final goal of being able to differentiate one guitar string from another based on pitch.

Some websites we came across that are helpful are as follows:

After doing some research the group then devised a plan for what to do in the future. First we decided that the path we wanted to follow in implementing our design was to use an Arduino board connected to a microphone in order to read in the signal in real time.

We figured that using the Arduino would be best because there is already a lot of software available for the Arduino to process the signal and determine the frequency of the sound. We figured we could use portions of this software with some modifications to achieve our desired goal.

After processing the signal with the Arduino and determining its frequency components we then figured we would be able to break the sound up and determine the actual guitar string that was played because pitch is in essence a frequency. However, this may take some testing to get the code working completely right as we will have to determine a relative range of frequencies for each guitar string so we then can modify the algorithm to be able to correctly decide which string has been played.

After correctly analyzing the signal and determining the string that has been played from the guitar the last thing we determined we wanted to do with the project was to add some flare to it was to then light up a LED strip with a different colored LED based on which string has been played. We figured that this would be a nice visual to go along with what we are trying to do and would help to show if our project is working correctly.

After deciding on this course of action the last thing we did at the group meeting was to split up different parts of the project to different team members. For example, we decided on who was going to work on the hardware {circuit board, attaching the microphone, LED strips, etc.} portions and who would work on the software aspects {the signal processing and frequency detection algorithm, activating the LED strips, etc.}.

Dillon Pulliam: April 9, 2017

Individual Testing: April 12, 2017

Updated 4/17/17 with fritzing diagrams

Today we built and tested the amplifying section of our circuit. We determined that the input signal from the microphone would only have an amplitude on the order of about 100-200 mV. As such, the signal needed to be amplified prior to our signal processing with the Arduino.

We decided to use an Analog Discovery USB device in order to build and test our circuits. This device is an oscilloscope, logic analyzer, and variable power supply that uses USB as default communication with any computer. It’s very useful in displaying waveforms in real time, allowing us to determine if our circuits are operating as desired.IMG_20170412_175225194

To amplify our signal we used an OP27G op amp which provided high gain with relatively little noise. Because we are unsure of the amplitude of the input signal, we used a 10kOhm potentiometer as a variable resistor across the op amp so that the gain (the amount of amplification) can be adjusted as needed. A pin-out of the OP27G can be seen below for ease of reference.

OP-27G

The Analog Discovery was used to provide +- 5V to the op amp on pins 7 and 4, respectively. A waveform generator (W1) was used as an input to pin 3, with (W2) grounded. 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. Finally, channel 1 of the oscilloscope was hooked up to read from the output on pin 6 to ground in order to determine our amplified voltage. Below are a couple pictures of the circuit. Click here to download the fritzing diagram for manipulation.

After applying a 1 kHz, 200mV sinusoidal voltage to the circuit with the waveform generator, the circuit output a maximum value of 2.508 volts with an average of approximately -100 mV. This is important because the Arduino can only read voltages between 0 and 5 volts. Because of this, the circuit also requires a DC offset of 2.5 volts so that these values will range between 0 and 5 volts.

Non-Offset Circuit

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. Click here to download the fritzing diagram for manipulation.

After applying the same 1 kHz, 200 mV sinusoidal voltage to the circuit as above, and hooking up channel 2 of the oscilloscope to read the shifted output of the circuit, the circuit output an average of 2.37 volts with a maximum of 4.776 volts. This represents a 2.458 volt DC offset when comparing the average value of channel 1 to that of channel 2. If we wanted to get even closer to a 2.5 volt offset, more closely matched resistors could be chosen in the future to create a more precise voltage. As is, however, the voltages vary between 0 and 4.776.

Offset Circuit

-Scott Newton: April 12, 2017

Individual Testing: April 15, 2017

After getting the circuit completely operational we figured the next thing that needed to be done was to load in the source code provided from the Instructable titled “Arduino Frequency Detection”. After downloading the code we then opened it up in the built in Arduino development application and compiled it and loaded it onto our Arduino board. We then reconnected our working circuit to the analog discovery in order to test the code by sending in a sine/cosine wave of 0.2 V with varying frequency.  Next we connected the output of the circuit to pin A0 of the Arduino as this is the pin coded used to determine the frequency.

After making the circuit connections we then opened up Putty in order to make a serial connection to the Arduino so we could visually see the frequency outputs. In order to connect to Putty we first had to open up the device manager option on our laptop in order to determine what COM port our Arduino board was connected to {in this case it was COM5}. After determining the correct COM port it was then a very easy process to click the serial option in Putty and change the port number to allow communications to flow.

After setting up communications we then set up the Arduino and began sending in varying signals with different frequencies to judge how accurately the source code worked. One thing we noticed right away is that by varying the SlopeTol variable we could have more accurate readings of the true frequency based on if we knew the incoming signal had a frequency that was very high or a very low value. We determined that the way this relationship seemed to work is that the greater the incoming frequency the greater the SlopeTol variable needed to be set {Note: this variable can be set between 0-255 since it is an 8 bit value}. Similarly, the smaller the incoming frequency, the smaller the SlopeTol variable needed to be in order to get more accurate measurements.

Also, note that what we mean by more accurate measurements is that it seems that if the SlopeTol variable is set at a bad value then the output frequency readings may be wrong every 3 to 4 outputs {due to the way the samples are taken and the way the frequency is calculated in the code}. However, by correctly adjusting the SlopeTol variable you can create a system that very accurately calculates the incoming frequency and only has a bad reading about once every 15 to 25 readings/outputs.

The other variable that can be adjusted in the source code is the TimerTol variable. However, after extensive testing we arrived at the conclusion that adjusting this variable seems to have no impact on how accurate the system works and how close the output frequency is to what is input. Therefore we left this variable alone at a value of 10.

After going through the code and playing with different frequency values through the use of the Analog discovery kit we figured the best course of action would be to look up the actual frequency values of different guitar strings being played and test them in order to set the SlopeTol variable at a level that led to the most correct frequency readings. The frequency values for different guitar strings are as follows:

1.       String: E          329.63 Hz        Name: E4
Midpoint: 288.29 Hz
2.       String: B         246.94 Hz         Name: B3
Midpoint: 221.47 Hz
3.       String: G        196.00 Hz          Name: G3
Midpoint: 171.42 Hz
4.       String: D        146.83 Hz          Name: D3
Midpoint: 128.42 Hz
5.       String: A        110.00 Hz          Name: A2
Midpoint: 96.05 Hz
6.       String: E        82.41 Hz            Name: E2

After testing these frequencies we determined that the SlopeTol level that seemed to lead to most accurate output frequency readings was about 25.

The final step we took was to make a few other slight adjustments to our code. After outputting the frequency values to the screen through the use of the serial communications port we then created a series of if statements that could be used to determine which string has been played and then take a certain course of action. The way we set these if statements up was simply based on our research  of the average frequency value of each guitar string.

For example, lets look at the string G, named G3. In order to create an if statement for it we will compare the frequency value to see if it is below 221.47 Hz and above 171.42 Hz as these are the midpoint values of the frequencies of the strings above and below it compared to itself. If the frequency value falls in each of these ranges then we say that yes, the string that was played is G.

After setting up this series of if statements we then added in a section of code in each block that would write a 1 to a certain pin in port D while keeping all other pins at logic 0 {5V = logic 1; 0V = logic 0}. This allowed us to connect an LED in series with a resistor to each port to see if we could light up a different LED based on the input frequency which in turn was modeled after the frequency value of each string.

Our code correctly achieved this goal! However, one adjustment that will need to be made in the future is that when we actually do live testing of our design with the guitar the frequency values of the if statements may need to be changed. The guitar may create sounds for each string that is at a slightly different frequency then the average value we found when doing research.

Our Source code used can be found at the following site:

http://docdro.id/kR5GsrF

-Dillon Pulliam: April 15, 2017

Group Testing / Update: April 23, 2017

First, a quick update of what we’ve been up to for the past week or so.

We had ordered a microphone and a 1/4″ mono panel-mount audio jack in order for our circuit to have the ability to actively gather data in real time, rather than parsing in a prepared audio file such as the example Dr. Lau had provided for us. This was necessary, as one of the requirements for the project was that the final solution must be able to determine frequency in real time, and be actively demonstrated. Because we’re using an electric guitar as the source for this project, the use of a 1/4″ audio jack is also beneficial because it allows us to bypass the microphone input altogether if necessary. The only change that would need to be made is unplugging the microphone from the audio jack, replacing it with the guitar plug directly, and adjusting the potentiometer so that the gain puts the output signal of the guitar between 0 and 5 volts. Because the group doesn’t have access to an electric guitar, we are using the microphone as an intermediary to test our design before demonstrating it with the guitar. 

We received the parts on April 18, and on April 19 we soldered the wires to the audio jack as explained in step 2 of the Arduino audio input instructable linked at the top of this page. On the April 19 we also discussed what we would like to do for the output of our circuit, and decided that we would like to light up a strip of RGB lights a unique color for each of the 6 guitar notes. The circuit for the RGB light strip has been designed and will be uploaded to this website soon as well. 

On April 23 we met and tested the microphone as an input to our design and we were pleased with the overall results. We ran into a couple of problems, however, which will be detailed below.

First, we replaced W1 from the Analog Discovery with the signal pin of the audio jack, as seen in the circuit schematic below (the fritzing diagram can be downloaded here). This allows the microphone to be used as an input for the amplifying circuit instead of the waveform generator on the Analog Discovery. We used a small speaker placed directly in front of the microphone (see the picture below) in order to give the microphone an input that more accurately reflects the electric guitar.

We began testing the microphone as an input by running the 6 frequencies through the speaker with this tone generator that simulates the notes we’re trying to sample. We began with E4, stepping down through B3, G3, D3, A2, and finally E2. We set the gain of the circuit based on the E4 string, as this would have the highest peak voltage of all of the 6 frequencies tested. As the frequencies stepped down, the amplitude of the voltage also stepped down, as can be seen in the images below. The peak voltage of E4 at 329.63 Hz was 4.776 volts with a minimum of 2 mV which is the maximum difference we were able to get without going below 0V, which the Arduino can’t read. This gives the highest possible range of values for the Arduino to differentiate between, in turn giving the highest possible resolution of voltage values. When using the same gain, however, E2 only gave a peak voltage of 2.497 volts with a minimum of 2.233 volts, which isn’t a very wide range to differentiate. This causes the waveform to be extremely noisy and hard to read, as shown below. This results in the Analog Discovery determining the frequency of the E2 waveform to be 67.88 Hz (a percent difference of 19.34%) as opposed to the frequency of the E4 waveform as 329.46 Hz (a percent difference of .05%). 

This posed the first issue for the design, as the gain of the circuit can’t be turned up any higher for better resolution for E2, or else E4 will saturate the op-amp and be outside of the range of the Arduino. All of the frequencies can be accurately sampled at the set gain except for E2, which we will need to address. If we could dynamically change the resistance of the circuit when we suspected that E2 was being played this would solve the problem, but we’ll have to look into other alternatives as this doesn’t seem possible. We will most likely have to use a different sampling algorithm since the fairly simplistic midpoint-value algorithm we’re using now will be able to identify all test tones except for E2. We are looking into the AMDF algorithm linked at the top of this page.

The second issue of our design came when we played the sample audio file Dr. Lau provided for us. This file contains a simple strum of each of the strings on the electric guitar. When playing back the file we had very nasty waveforms with harmonics of the notes as seen below. Again, this will be impossible to sample with out rudimentary midpoint-value algorithm, so we’re leaning toward the AMDF algorithm since it was designed to alleviate these harmonics. We may face another challenge in the fact that our Arduino is only 8-bit which will limit the resolution of the AMDF algorithm, but this will be further discussed in a subsequent post.

We will meet tomorrow to discuss our path forward and to work on implementing the new sampling algorithm to account for these design flaws. Expect an update with the circuit for the RGB light strip and the Arduino included soon!

-Scott Newton: April 24, 2017

Update: April 25, 2017

The group decided to do some individual testing and code manipulation tonight. We agreed to pursue the AMDF algorithm, which we’re working to implement before our team meeting tomorrow afternoon. We switched speakers we were using as an input to the microphone and found that the new speaker outputs a better waveform as input to the circuit. With the new speaker our design accurately outputs the correct note when using the tone generator 100% of the time. Using the audio file our design still only accurately outputs the correct note about 40% of the time, which is obviously not a good threshold for success. As such, we’re swiftly working to update our software to account for this error. We will post more information with our new algorithm, final design, the rest of the completed circuit, etc. in the coming days.

-Scott Newton: April 25, 2017

Update: April 26, 2017

On April 25th, after team member Dillon Pulliam was able to implement and test the AMDF algorithm with our circuit, inaccuracies with the algorithm were discovered and  it was decided by the team over group chat that the best implementation would be to continue with the mid-point algorithm. We decided to meet today to hook up the guitar into the microphone, test the input frequencies live, and make adjustments to the mid-point algorithm as needed to improve it’s accuracy when outputting to the LEDs.

The first step the group did was play each of the 6 individual strings of the guitar and note if our original ranges of frequencies for the notes (found online) matched the true frequencies of the notes played on the guitar. The ranges were very similar, so it was concluded that it was not necessary to modify the bounds of our if-else statements in our code that checked for frequencies. With use of the serial communication port, we were able to view the outputting frequency values to the screen and noticed that when strumming the notes of the guitar, that there would be several extremely high (1000 Hz or higher) and also very low frequencies (around 10 Hz) in between each valid notes frequencies getting picked up.

The team decided to modify the code such that if a frequency above 500 Hz or below 50 Hz was detected, then the LED light would just retain the value of the last valid note range that had been last seen, ignoring these outlying frequencies completely. This was implemented by simply adding an additional if statement to catch if frequency > 500 Hz or below 50 Hz and in the conditional, we first tried using PORTD = PORTD in hope that it would retain the previous value of the valid LED that had been turned on. When testing this method with the guitar it was resulting in several extremely high frequencies on the screen (around 19000 Hz) and the team concluded to remove the PORTD = PORTD statement all together.

Next, another if-else statement method was implemented in the code to try and eliminate the cutoff frequencies we had previously determined (above 500 Hz and below 50 Hz). We decided that the conditional within the cutoff statements would be to simply do nothing in hopes that the previous valid frequency read would keep its corresponding LED lit. Unfortunately, this method did not prove to be working as we continued to observe frequencies of 19000 Hz on the screen. The conditionals for cutoff were then removed.

The testing resumed and it was then noticed by a team member that the waveforms of the incoming signal were very saturated. After picking a set volume on the guitar, the team was then able to adjust the gain of the circuit with the potentiometer and test how it affected the output frequencies. It was found that if the gain was adjusted very high or very low, then the high frequencies notes would output several valid output frequencies while the lower frequencies would have almost no valid readings when their string was plucked. The gain had to be carefully adjusted and balanced such that valid frequencies outputs were being received from both the high and low frequency notes.

In summation, at the end of testing, when each string of the guitar was plucked, the corresponding LED would stay lit for approximately 2-4 seconds, then fluctuate to another LED color, which was good behavior but could be improved. The next step for the team is to further optimize the code in order to keep the correct LED lit for a longer time frame and ignore the very high and very low frequencies. Our team hopes to finish fine-tuning the code soon then we can convert the individual LED output to an LED strip output for better visuals and to film our live demonstration.

-Kristina Shaffer: April 26th, 2017

Software Modification: April 27, 2017

After going through testing yesterday as a group with the actual guitar we were able to learn more about how our software was actually functioning and the frequency it seemed to be outputting for different strings due to their pitch as well as higher harmonics. One thing we quickly noticed with our software was that even when it was best optimized it only seemed to read the correct frequency value about 3-5 times in a row before outputting an ultra high frequency as the string stopped vibrating {or a clipping error occurred}. Additionally, even when we appeared to be getting very good readings often times we would have one bad reading in the middle of a bunch of good ones. For example, say we played string G3 which has a frequency of about 200 Hz. The typical output we would get from our original software may look like this: 200.15 Hz, 200.15 Hz, 1345.67 Hz, 200.15 Hz, 200.15 Hz. 2 good readings sandwiched on either side of a bad one.

After seeing the actual real live output with the electric guitar we figured we could make some changes to the software to get better readings. The first thing we decided to do was to modify our algorithm to only output the frequency values and in turn possibly light up particular LEDs if the frequency detection code arrived at a frequency between 60 and 400 Hz {the guitar should never cause a frequency reading outside of this overall range}.

After implementing this change we then changed the upper and lower frequency limits for each particular string in their corresponding if statements that would allow the LED outputs to be changed {their corresponding port}. The reason why we chose to do this is because as we were testing we noticed that when we got a good reading for a particular string its average output frequency didn’t seem to vary much. For example, going back to the G3 string from earlier, playing this string typically caused an output frequency from about 199 Hz to 201 Hz. We figured that by limiting the overall range of each particular string’s if statement we would be able to eliminate many bad readings as playing the G3 string should never cause a frequency output varying far from 200 Hz.

The limits on the upper and lower bounds for each particular string were set by subtracting/adding 8 Hz from/to the average frequency value for each string. Note that this consequent range of 16 Hz for each string is actually probably too much. However, we figured that by giving ourselves a wider range we would have a little more room for error if the guitar somehow got out of tune or if we had some excess noise in our overall system.

The final change we made to our code was to add a final else statement onto the end of all the strings if/else-if statements that says if we can’t determine that any of the particular strings have been played {as none of our readings our within each string’s corresponding range} then our code does nothing and the LED that was lit up from the cycle before remains activated. What this final else statement allows us to do is say we have the reading from earlier for the G3 string; 200.15 Hz, 200.15 Hz, 1345.67 Hz, 200.15 Hz, 200.15 Hz. Instead of this code lighting up the wrong LED for the bad reading of 1345.67 Hz our new code will now keep the same/correct LED turned on for our G3 string as this bad frequency value doesn’t fall into any of our other ranges for the other five strings in the system.

Overall, these changes allow us to have better, more accurate output that almost completely eliminates the problem of having bad frequency readings in the middle of good ones. We have modified the code to so where this bad reading is having no overall effect on the system and its frequency output and LED light indicators.

New source code can be found at the following link:

http://docdro.id/1VDPzAL

-Dillon Pulliam: April 27, 2017

Software Modification: April 28, 2017

Today we made another modification to the Arduino software base. We changed our software to now output to 3 pins on the Arduino versus the 6 pins we originally were outputting to. The reason for the change is instead of outputting to 6 LEDs we now are outputting to an RGB LED strip. Therefore we only need 3 connections, one to Red, one to Green, and one to Blue.

Another change we have made in the software is that for each string that has been played {corresponding to a frequency range in our code base} we are going to activate a certain portion of either the red, green, or blue LEDs in our strip. The way this will work is similar to that of a color wheel / spectrum where lower frequency sounds are mapped to lower frequency light and higher frequency sounds are mapped to higher frequency light.  The light spectrum has the following pattern from low frequency to high frequency: red, yellow, green, light blue, blue, and purple.

Essentially what our code will now do is E2, the lowest frequency string, will now be mapped to red light, the lowest frequency light. This is done by setting only the pin connected to the red portion of the LED strip high. Next, the A2 string, the 2nd lowest frequency sound, will be mapped to yellow light, the next lowest frequency light. This is done by setting both the red and green pins to high where their light will combine to make a yellow output. This pattern is then followed for the remaining strings and pin mappings to create a nice visual to go along with our project where the sound frequencies are mapped to their corresponding light frequencies.

Updated code:

http://docdro.id/oGXlZm8

-Dillon Pulliam : April 28, 2017

Final Update: April 28, 2017

Today we were able to successfully test our design with Dr. Lau’s electric guitar. The design worked very well, and the LED strip was much more visually appealing than the 6 individual LEDs that we were using before. See our instructable for the final circuit details, design, step by step process, code, etc. This will be our guide through our project so that others may replicate it.

-Scott Newton: April 28, 2017