# Arduino Frequency Detection

As a follow up to the Arduino Audio Input tutorial that I posted last week, I wrote a sketch which analyzes a signal coming into the Arduino's analog input and determines the frequency.  The code uses a sampling rate of 38.5kHz and is generalized for arbitrary waveshapes.  I've also turned the LED attached to pin 13 into a clipping indicator, so you know if you need to adjust your signal's amplitude as you send it into the Arduino.

Some project ideas for the code presented here include:

pitch reactive projects- change the color of RGB LEDs with pitch, or make a lock that only opens when you sing a certain pitch or melody
audio to MIDI conversion- get the Arduino to translate an incoming signal into a series of MIDI messages. See my instructable about getting the Arduino to send and receive MIDI for lots of example code to get started
audio effects- use the frequency information to reconstruct an audio signal from the tone() library or with some stored samples to make a cool effects box/synthesizer

The first step of this project is to set up the audio input circuit.  I wrote a detailed Instructable about that here.
Remove these ads by Signing Up

## Step 1: Detection of Signal Slope

First I wanted to experiment with peak detection, so I wrote a piece of code (below) that outputs a high signal when the incoming audio signal has a positive slope, and outputs a low signal when the incoming audio signal has a negative slope.  For a simple sine wave, this will generate a pulse signal with the same frequency as the sine wave and a duty cycle of 50% (a square wave).  This way, the peaks are always located where the pulse wave toggles between its high and low states.

The important portion of the code is reproduced below.  All of this code takes place in the ADC interrupt (interrupts and runs each time a new analog in value is ready from A0, more info about what interrupts are and why we use them can be found here)

prevData = newData;//store previous value
newData = ADCH;//get value from A0
if (newData > prevData){//if positive slope
PORTB |= B00010000;//set pin 12 high
}
else if (newData < prevData){if negative slope
PORTB &= B11101111;//set pin 12 low
}

I should note here that in this tutorial I use direct port manipulation to turn off and on the output pin (pin 12) of the Arduino.  I did this because port manipulation is a much faster way of addressing the Arduino's pins than the digitalWrite() command.  Since I had to put all the code above inside an interrupt routine that was going off at 38.5kHz, I needed the code to be as efficient as possible.  You can read more about port manipulation on the Arduino website, or see the comments I've written above to understand what each line does.  You'll also notice in the code below that I used some unfamiliar commands in the setup() function so that I could get the Arduino's analog input to sample at a high frequency.  More info on that can be found in my Arduino Audio Input tutorial.

Fig 1 shows the pulse output in blue and the sine wave in yellow on an oscilloscope.  Notice how the pulse output toggles each time the sine wave reaches a maximum or minimum.  Fig 2 shows the pulse output in blue for an arbitrary waveshape in yellow.  Notice here how pulse wave takes on an irregular duty cycle because the incoming signal (yellow) is much more complicated than a sine wave.

```//Detection of signal slope with 38.5kHz sampling rate and interrupts
//by Amanda Ghassaei
//http://www.instructables.com/id/Arduino-Frequency-Detection/
//Sept 2012

/*
* This program is free software; you can redistribute it and/or modify
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/

//clipping indicator variables
boolean clipping = 0;

//storage variables
byte newData = 0;
byte prevData = 0;

void setup(){

pinMode(13,OUTPUT);//led indicator pin
pinMode(12,OUTPUT);//slope indicator

cli();//disable interrupts

//set up continuous sampling of analog pin 0

ADMUX |= (1 << REFS0); //set reference voltage

sei();//enable interrupts
}

prevData = newData;//store previous value
newData = ADCH;//get value from A0
if (newData > prevData){//if increasing
PORTB |= B00010000;//set pin 12 high
}
else if (newData < prevData){
PORTB &= B11101111;//set pin 12 low
}

if (newData == 0 || newData == 1023){//if clipping
PORTB |= B00100000;//set pin 13 high- turn on clipping indicator led
clipping = 1;//currently clipping
}
}

void loop(){
if (clipping){//if currently clipping
PORTB &= B11011111;//turn off clipping indicator led
clipping = 0;
}

delay(100);
}

```
 1-40 of 137 Next »
renaissa16 days ago
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
shinew29 days ago

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!

weichi.chien1 month ago

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?

buddika1231 month ago
Hiii
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
Derpancakes1 month ago

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!

LucasP22 months ago

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="cool colors", treble= "warm colors"(or even vice versa). I feel like that would give a better experience to the music

novaninjas2 months ago

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

pierattilio3 months ago

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)?

Thanks a lot

;D

aoss4 months ago

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.

Bokononestly1 year ago
Great work! I'm trying to use this code for an automatic laser oscilloscope I am designing.

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?
amandaghassaei (author)  Bokononestly1 year ago
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:
http://arduino.cc/en/Tutorial/RCtime
http://www.instructables.com/id/Arduino-Basics-RCtime/
hope that works for what you're doing.
4 months ago

Thank you for the great article. I was just wondering can I use a microphone with a preamp to make the detection.

I have :

http://www.freetronics.com/products/microphone-sou...

Thank you very much!

arimika8 months ago

i tried to build guitar tuner http://www.instructables.com/id/Arduino-Guitar-Tun...

but arduino can't read the input from my guitar.
can you help me to solve this problem ?

amandaghassaei (author)  arimika7 months ago
do you have an oscilloscope?
7 months ago

i don't have oscilloscope.
does become a problem if I use 100nF Cap on the DC offset ?

i see your project use 47nF Cap.

amandaghassaei (author)  arimika7 months ago

no that should be fine. You will need an oscilloscope to debug this, maybe see if there's a hackerspace or school near you where you can use one for free.

7 months ago

what is the main problem that the input from guitar can not reach the Arduino?

whether the project could be completed if there is oscilloscope ?

amandaghassaei (author)  arimika7 months ago

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?

6 months ago

yes, i have.
how to make audio output from amplifier and DC offset circuit into my computer ? there are 3 outputs "A0 , 5v and GND"

andrew954347 months ago

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?

amandaghassaei (author)  andrew954347 months ago

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.

7 months ago

Do you know if there's a virtual oscilloscope which I could use? Like a PC program.

About the microphone, I'm using an Elecret Microphone with Breakout Board (amplifier included), I connect it directly to the Arduino, is everything alright?

amandaghassaei (author)  andrew954347 months ago

i guess you could use the audio input on your comp and record using Audacity or something.

sweller7 months ago

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. :-(

EthnoChris8 months ago

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 "inf" ).

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?

amandaghassaei (author)  EthnoChris8 months ago

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 datasheet. I've never used a micro unfortunately.

8 months ago

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!

amandaghassaei (author)  amandaghassaei8 months ago

http://www.atmel.com/devices/atmega32u4.aspx

raptorofaxys1 year ago
Hey there! This was a great read! I'm a fan of yours - your 'ibles are always interesting and very well put together.

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 (http://audition.ens.fr/adc/pdf/2002_JASA_YIN.pdf) on Arduino, and this worked extremely well while keeping the code simple.

The project writeup is here, and the code is freely downloadable from that page: http://deambulatorymatrix.blogspot.ca/2010/11/digital-chromatic-guitar-tuner-2008.html

All the best, and keep up the great work! :D
1 year ago
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.

Thanks,

Graham
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.
9 months ago

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.

1 year ago
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!
1 year ago
sounds like a cool project!
amandaghassaei (author)  raptorofaxys1 year ago
thanks! I like your project a lot! looks like the YIN algorithm works great. you should enter the microcontroller contest:
http://www.instructables.com/contest/
1 year ago
Hahaha, thanks for the suggestion! I knew about the contests but did not realize you had so many going in parallel. I would have loved to enter, but I live in good ol' Quebec, which makes me ineligible. :-(
RobinCh9 months ago

Hi miss Amanda!

It's really great what you have made! I tried this on my Arduino Uno and it works perfect! But now, I have a problem. I want to use this code on my other Arduino, the Arduino Due. For this, I had to download the new beta-software 1.5 (Instead of 1.0 for the other Arduino's) because the standard software doesn't support the Due (he's too recent I guess). After trying a lot of things, I could finally connect him to the software! But now I uploaded your code again with the new software to the new Arduino, and I have a lot of errors, but I changed nothing... This is the list the software gave me:

_1e_versie_Arduino_sketch.ino: In function 'void setup()':

_1e_versie_Arduino_sketch:34: error: 'cli' cannot be used as a function

_1e_versie_Arduino_sketch:39: error: 'ADCSRA' was not declared in this scope

_1e_versie_Arduino_sketch:40: error: 'ADCSRB' was not declared in this scope

_1e_versie_Arduino_sketch:42: error: 'ADMUX' was not declared in this scope

_1e_versie_Arduino_sketch:42: error: 'REFS0' was not declared in this scope

_1e_versie_Arduino_sketch:43: error: 'ADLAR' was not declared in this scope

_1e_versie_Arduino_sketch:45: error: 'ADPS2' was not declared in this scope

_1e_versie_Arduino_sketch:45: error: 'ADPS0' was not declared in this scope

_1e_versie_Arduino_sketch:46: error: 'ADATE' was not declared in this scope

_1e_versie_Arduino_sketch:47: error: 'ADIE' was not declared in this scope

_1e_versie_Arduino_sketch:48: error: 'ADEN' was not declared in this scope

_1e_versie_Arduino_sketch:49: error: 'ADSC' was not declared in this scope

_1e_versie_Arduino_sketch:51: error: 'sei' was not declared in this scope

_1e_versie_Arduino_sketch:57: error: 'ADCH' was not declared in this scope

_1e_versie_Arduino_sketch:65: error: 'PORTB' was not declared in this scope

_1e_versie_Arduino_sketch.ino: In function 'void loop()':

_1e_versie_Arduino_sketch:74: error: 'PORTB' was not declared in this scope

What do I have to do about it? I don't understand why it doesn't work in this software...

Thank you so much for the help! I really appreciate it!

Greetings,

Robin C,

Belgium

amandaghassaei (author)  RobinCh9 months ago

this code will have to be rewritten for the due, haven't used one, sorry!

9 months ago
Oh no ;s and do you know somebody who can work with this device? I have to use this one for school... ;s Thank you for your response!! :D
Ketan_Sharma9 months ago

Hi Amanda!

I was making a tengu clone using Arduino and because I wanted it to react to different frequencies in different manner, I tried to use your code for frequency detection, to detect the frequency of square wave output of comparator (which is being fed by an amplified sound wave), however when I tested it, the Serial Monitor says nothing but "inf hz", can you please tell me as to where am I going wrong? I am using an electret microphone and LM358 dual op amp IC for amplification and as a comparator.

amandaghassaei (author)  Ketan_Sharma9 months ago

what's the amplitude of the signal going into the arduino?

 1-40 of 137 Next »