Step 3: Sine Wave Frequency Detection

Next I measured the period of an incoming sine wave, calculated the frequency, and printed the frequency.  To do this I set up a timer in the ADC interrupt that increments each time the interrupt executes (a rate of 38462Hz).  Each time the incoming signal crosses 2.5V with a rising slope I sent the current value of the timer to a variable called "period" and reset the timer to 0.  That code is reproduced below (all takes place within the ADC interrupt).

  prevData = newData;//store previous value
  newData = ADCH;//get value from A0
  if (prevData < 127 && newData >= 127){//if increasing and crossing midpoint
    period = timer;//get period from current timer value
    timer = 0;//reset timer

 timer++;//increment timer

Then in the main loop() function, I calculated the frequency by dividing the timer rate by the period.  I used Serial.print to print these results in the Arduino serial monitor.

  frequency = 38462/period;//timer rate/period
  //print results
  Serial.println(" hz");

Fig 1 shows the signal coming into A0.  The start and end of one cycle measured by timer is indicated by the image note.  Fig 2 shows the output from the serial monitor (command/ctrl+shift+m).  This technique works great for sine waves, but when wave become more complicated (and cross 2.5V more than twice in one cycle) this technique breaks down.

<p>Thanks a lot for posting this very clear and helpful project. <br>I build it but using the soundcard output of a computer(or a similar one, like a phone or mediaplayer) as an input. Since these signals are much stronger I left out the opamp. For the rest the setup is similar: one resistor(+) and a potmeter (-) as a voltage divider before the 10uF Cap and two resistors (+&amp;-) as a voltage divider on the other side. And the 47nF Capacitor between signal and (-).<br>It works fairly good but the readings show inconsistencies f.i.: many lines of an almost perfect 80,80-82,01Hz and all of a sudden a 25,94Hz (and strikingly often half the values of the signal) or say a 12820,67Hz passing by. And often similar erratic glitches pop up at the beginning and/or at the end of a signal.<br>For an artwork I want to steer a servo with this technique, with something moving in sinc with a video (either directly (frequency is position) or through a ssc32 (frequency is position and signallength is speed) with charstrings passed over). Therefor these jumps are quite annoying. I tried tweaking a lot with the settings in your program (ampThreshold, timingTol, slopeTol) and on the hardwareside with capacitors to get the ripples out but so far with no luck. Any suggestions?</p><p>My iduino is powered by the computer to be able to read the readings, and I don't have an oscilloscope to check the signal-output of the computer. I tried other sources though, with similar outcome.</p><p>Many thanks anyway for the instructable which already helped me a lot and many thanks in advance.</p><p>Matthijs</p><p>ps:<br>steering servos this way seems a kind of a detour but manually putting the right blocksignals in the right place and play them with the mediaplayer appeared to be even more work. Using the frequency technique makes it far more flexible and ubiquitous. </p>
<p>Thanks for the great project info. I've tried it out using an electret microphone with an amplifier, but I'm not getting a clean output on the serial monitor. Basically, the frequencies it spits out are all over the map. For instance, if I play it a note around 70Hz (I'm planning on putting it on my upright bass, so I've been using that to test) it will give me a bunch of frequencies that could be from 10Hz to 7000Hz, then give me several in a row that are about 70Hz, then back to all over, etc. Even when I played a 440Hz note from a tuner it gave me a decent amount of randomness. <br><br>My guess is that I need to adjust the slopeTol and timerTol values, since the random frequencies are often (though often not) some multiple of the one I'm looking for, making me think that it's missing some crossings. Am I thinking right? I don't really know which one to change and by how much; I've messed with them both and they're currently at slopeTol = 2 and timerTol = 15. Any ideas on some ballpark ranges for these if I'm looking to measure tones from my bass? Is there some other part that I should tweak? Thanks for the help. I'd really like to use your method instead of FFT or FHT, since it seems much more efficient for my project.</p>
<p>One thing I thought of: right now I'm powering the Arduino through the USB, since I'm using the serial monitor to debug. Would using the USB as a power source be adding noise to the signal? My project will be powered by a 9V battery and I have one hooked up now, just turned off. Would it help to have the 9V source on in addition to being plugged in to the USB? I have to keep it plugged in to use the serial monitor, but if that's what's causing the problems...</p>
<p>Thank you for your sharing Amanda!! I don't have to start from the zero point on my automatic guitar tuner project!</p><p>But I have a question.Can I use a piezo to pick up the vibration or the sound instead of using a mic,which enables the tuner to work in noisy environment?</p>
<p>Yes you can. Im using it on a violin. At the moment the algorithm is a little sporadic but if you turn down the time and slope tolerances it works a little better. I think if you restructure the code to get the full 10 bit resolution instead of 8 bits, you should be able to make this code work better. But the extra instruction cycles might hinder any other operations... </p>
<p>I've got a project along these lines as well, and I wondered that same thing about picking up noise from other sources (or instruments, since I plan on using it while playing). Using a piezo came to mind, glad to see someone has done it successfully. I was wondering, what did you use to stick your piezo on your instrument? I don't want do anything that would damage the wood. Did you use some sort of adhesive that's safe for string instruments?</p>
<p>I tried a under the bridge pick up, as well as a bridge stick on pickup; A generic rod piezo and a Shadow SH 3001 respectively. I used it on a dedicated electric so the rod piezo was appropriate and much cheaper, but there are film-type under the bridge pickups like Realist pickups that should work for you. I have found that blending both types of pickups (horizontal and veritcal) through a cheap behringer micromix mx400 gives really good results, although you'll have to contend with two wires instead of just one. </p>
<p>Gotcha, thanks. I'll see if I can find something like that for my upright bass. I'm planning on using it to control an LED strip, so I probably don't need the quality to be quite that high; one pickup should do it. Did you need to wire it up with the whole op amp setup from the Audio Input tutorial, or do some have amplifiers built in?</p>
<p>Yes, you'll need to amplify it a little bit based upon the voltage response characteristics of the element you are using. You'll have to tinker because no two piezo's are the same. There are a lot of projects for arduino out there on how to do this, just search &quot;arduino audio input&quot; if the above schematic isn't descriptive enough for you.</p>
<p>So with this arduino code I would be able to control a the light's frequency with the frequency of the sound? I want to build a lighting system for my room and car that will react with the sound, but in a way so that bass=&quot;cool colors&quot;, treble= &quot;warm colors&quot;(or even vice versa). I feel like that would give a better experience to the music</p>
<p>Did you manage to get your idea working? I have a similar project idea.</p>
<p>Hi Amanda,</p><p>Thanks for the very usefull work you have done, nou I can measure the frquency from my agriculture application that use a exciter ring.</p><p>I have one qustion how can I change to another analog pin in the ide?</p><p>Thanks,</p><p>Rien Brand</p><p>Netherlands</p>
<p>Not sure if you found the answer to your quesiton, but if you look up ADMUX register in the datasheet for your particular atmega you'll see how to change the analog to digital converter.</p><p>Here's a link to understand ADMUX</p><p>http://www.robotplatform.com/knowledge/ADC/adc_tutorial_3.html</p>
<p>We did it, finally facing problems. We used electric guitar for this purpose. Thanku Amanda. Keep up the good work !</p>
<p>Hello Amanda thanks for your sharing. i want to ask about this one..<br>so i am developing an Arduino human scream detection is it possible to me detect human help scream voice using this kind of Arduino program? because i want to build up the component consist by band pass filter , gain, and rectifier circuit and then look for its pitch detection and voice duration..<br><br>Do you have any idea about the circuit that i`ll need to complete my project?<br>Or is it possible enough to use some Arduino library and write the speech recognition code?</p>
<p>Hi Amanda, thank you very much for this source!! very amazing!!!</p><p>but... little problem my arduino...</p><p>your source is exellent !!</p><p>but.. my arduino is not working </p><p>my arduino version...is...</p><p>8-bit<br>Microcontroller<br>with 256K Bytes<br>In-System<br>Programmable<br>Flash</p><p>maybe...</p><p>version is problem is different???</p>
<p>Hi Amanda, thank you very much for this instructable! Very useful!</p><p>I prefer this simpler code version (integrated with amp treshold), because I want to make a sound analyzer , where you whistle or sing a &quot;oooh&quot; note and then you have the frequency. Making a portable built with a 4 digit display and there it is a perfect gadget for any sound engineer or musician, who wants to know which frequency causes microphones feedbacks.</p><p>Does it make any sense collecting a number of measurements and make a mathematical average? as I don't need a fast process, but a slower and more solid (without &quot;garbage&quot; measurements); I tried some &quot;for&quot; cycle with a simple array, but it doesn't seem to add any precision (maybe I don't know where to put it).. </p>
Hi amanda...your instructables on arduino are great..however i want to know if it is possible to measure a amplitude of sine wave on arduino
<p>Thanks for the instruction! I just put together a circuit with an amplified electret mic signal using opamp feeding into it. However, when I'm looking at the serial output, it only seems to work for the first second or 2, then it stops working with the last line looks like attached image. Any idea what could be the cause? thanks!</p>
<p>Hi, this is an excellent project. It works fine on my arduino uno. However, I need it to run on a arduino mega with ethernet shield. When adding the codes to my ethernet project, the connection to internet is brocken (I'm uploading data onto xively server). Any suggestion?</p>
Hiii<br>How we meaured the frequency ....I want to detect frequncy range 60Hz to 100Hz....can I use this progtame thanks and quick reply from you
<p>This is awesome! I'm looking in to a guitar-MIDI pedal, but a DIY solution is cheaper and way cooler. Props to you for this awesome bit of code!</p>
<p>Hi, has anybody completed this project (possibly, with a diff sort of mic) and wouldn't mind sharing about it? Am a beginner and would really like to try this so.. slightly more detailed steps would be most helpful :D</p>
<p>Hi amanda, i want to congratulate with you on this instructable, really powerful :D I have a question, that is is it possible to check the frequencies of a playing song in this way, through an aux signal from i.e. an MP3 player or the notebook audio headphones output (after the right managment of the signal like in your instructable on arduino auido input)?</p><p>Thanks a lot</p><p>;D</p>
<p>Has anyone made this project with ChipKit Uno32. I am really looking for projects like that for my Uno32 developement board because I need to read analog signal frequency coming from optical rotation sensor.</p>
Great work! I'm trying to use this code for an automatic laser oscilloscope I am designing. <br> <br>I've found that the code stops measuring frequencies as soon as I try analogRead() from a different analog pin. At the moment I don't fully understand the lower level programming of the ADC that you've done. Is there any way to read from the other analog pins without interfering with the pitch measurement?
yes, the way this is set up, all of the other analog pins are deactivated. you can read an analog value from a digital pin by using RCTime: <br />http://arduino.cc/en/Tutorial/RCtime <br />http://www.instructables.com/id/Arduino-Basics-RCtime/ <br />hope that works for what you're doing.
<p>Thank you for the great article. I was just wondering can I use a microphone with a preamp to make the detection.</p><p>I have :</p><p><a href="http://www.freetronics.com/products/microphone-sound-input-module" rel="nofollow">http://www.freetronics.com/products/microphone-sou...</a></p><p>Thank you very much!</p>
<p>i tried to build guitar tuner <a href="http://www.instructables.com/id/Arduino-Guitar-Tuner/?ALLSTEPS" rel="nofollow">http://www.instructables.com/id/Arduino-Guitar-Tun...</a></p><p>but arduino can't read the input from my guitar.<br>can you help me to solve this problem ?</p>
do you have an oscilloscope?
<p>i don't have oscilloscope.<br>does become a problem if I use 100nF Cap on the DC offset ?</p><p>i see your project use 47nF Cap.<br></p>
<p>no that should be fine. You will need an oscilloscope to debug this, maybe see if there's a <a target="_blank" href="http://hackerspaces.org/wiki/List_of_Hacker_Spaces">hackerspace</a> or school near you where you can use one for free.</p>
<p>what is the main problem that the input from guitar can not reach the Arduino?<br><br>whether the project could be completed if there is oscilloscope ?</p>
<p>you could try using a computer running audacity as a makeshift oscilloscope, to find out where the signal is getting lost. Do you have an audio input on your computer?</p>
<p>yes, i have.<br>how to make audio output from amplifier and DC offset circuit into my computer ? there are 3 outputs &quot;A0 , 5v and GND&quot;</p>
<p>I'm new in Arduino, I want to make this but with an Electret Microphone, I think it's very different than the microphone you used. How can I make the circuit with an Electret Microphone?</p>
<p>it shouldn't be too different, but you might need to change the gain on the amplifier going into the Arduino's analog pin. You will probably want an oscilloscope handy so you can see what you're doing.</p>
<p> Do you know if there's a virtual oscilloscope which I could use? Like a PC program. </p><p> About the microphone, I'm using an Elecret Microphone with Breakout Board (amplifier included), I connect it directly to the Arduino, is everything alright?</p>
<p>i guess you could use the audio input on your comp and record using Audacity or something.</p>
<p>I'm so happy I stumbled onto your Instructable! This is *exactly* what I'm attempting to do. Unfortunately, I'm trying to do it with a Picaxe. :-(</p>
<p>Hey Amanda! Awesome Instructable. This has been a great learning experience. I managed to get the code ( and circuit from your Arduino Audio Input Instructable ) working fine on an Uno clone, but when uploading the same sketch to an Arduino Micro it doesn't seem to update the output values when I print the variable ( I just get &quot;inf&quot; ).<br><br>Is there a difference in the Micro that would prevent this sketch from working? I'm using the same sketch and circuit for both versions ( I've only swapped out the Uno to a Micro ), but have I potentially done something incorrectly?</p>
<p>yeah the micro uses an atmega32 (as opposed to a 328), so I think the code will have to be adjusted for the chip. You can take a shot using the info from the <a target="_blank" href="http://www.atmel.com/dyn/resources/prod_documents/7766S.pdf">datasheet</a>. I've never used a micro unfortunately.</p>
<p>Thanks for the quick response. Converting it over might be a bit over my head, so I'll stick with the Uno for now. Cheers for the information!</p>
<p>bad link, here it is:</p><p>http://www.atmel.com/devices/atmega32u4.aspx</p>
Hey there! This was a great read! I'm a fan of yours - your 'ibles are always interesting and very well put together.<br> <br> I just wanted to mention that a few years ago I built an Arduino-based guitar tuner and had also tried this kind of frequency detection approach, but, as you mention yourself, I ultimately found it to be unruly when fed arbitrary waveforms. After some research, I implemented a modified YIN (<a href="http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf" rel="nofollow">http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf</a>) on Arduino, and this worked extremely well while keeping the code simple.<br> <br> The project writeup is here, and the code is freely downloadable from that page: <a href="http://deambulatorymatrix.blogspot.ca/2010/11/digital-chromatic-guitar-tuner-2008.html" rel="nofollow">http://deambulatorymatrix.blogspot.ca/2010/11/digital-chromatic-guitar-tuner-2008.html</a><br> <br> All the best, and keep up the great work! :D
I think I may use your code - thanks for posting it. I want to build a system to adjust the tension on bicycle spokes by pinging the spokes and determining the resonant frequency, then adjusting all the spokes to match the mean - an extremely similar process to guitar tuning (if a guitar had 6 identical strings :-) ), which is actually what gave me the idea. The frequency of the spokes on my bike is centered around 350Hz, so amandaghassaei's code probably won't do, as she says that it starts to become inaccurate at 350Hz. Of course I could use something faster than an arduino, maybe one of the arm-based arduino-alikes, but the thought of building this with an atmega is very tempting. <br> <br>Thanks, <br> <br>Graham <br>PS I expect most people's bike spokes will resonate at a lower frequency, but I have shorter spokes as it's an e-bike with a hub motor.
<p>Quick FYI, the whole point of adjusting spokes tension is to true the wheel (make it straight as possible). In my experience (mostly Free ride style), tension on the spokes varies according to any warp in the rim itself.. and in the case of my bikes, after doing a few 6ft drops the rims get tweaked and some of the spokes need to really be cranked up to get the rim trued again. hope this helps in any troubleshooting you might be having problems with.</p>
Wow, that sounds like quite an original use for this kind of setup! I know my dad tunes his own spokes using a piano, but using electronics would probably be more accurate :) Best of luck, and keep us posted!
sounds like a cool project!
thanks! I like your project a lot! looks like the YIN algorithm works great. you should enter the microcontroller contest: <br />http://www.instructables.com/contest/

About This Instructable


322 favorites


Bio: I'm a grad student at the Center for Bits and Atoms at MIT Media Lab. Before that I worked at Instructables, writing code for ... More »
More by amandaghassaei: OTCA Metapixel - Conway's Game of Life "9 Degrees of Freedom" IMU Twitter Controlled Pet Feeder
Add instructable to: