i would like to generate Chirp Signal (Frequency Sweep) using Arduino. i have searched a lot in internet but didn't find anything.

Basically, any parameters is also ok. But the concept is what i am searching for. The signal will be sent to the DAC of the Arduino board.

Edit I would like to generate sine wave signal from 3kHz up to 100kHz sweep frequency with amplitude peak to peak 1.5 volt.

thanks for your support.

  • 1
    That's a potentially complex subject. Providing more detail about what you are trying to do and why will help you to get better answers (or any answers). I assume you mean chirp in the DSP sense - swept-frequency cosine signal with unity amplitude and continuous phase. OR you could mean simply a frequency swept signal - as people sometimes use the term. Or you may be talking about crickets :-).So ...? Commented Feb 4, 2015 at 9:52
  • 1
    (1) What frequency range, and what sweep rate, do you want? (2) Why do you want it? ie, what is it for? (3) What "DAC module" do you mean? Some shield? [Please edit your question to answer these items, rather than answering in comments.] Commented Feb 4, 2015 at 17:27

3 Answers 3


If you're ok with starting with square wave signals, this can be done on an Arduino. You need to do the following:

  1. Configure a 16-bit Timer to CTC mode
  2. Select the right prescaling
  3. Add a RC low pass filter to the output and voltage divider

Configure a 16-bit Timer to CTC mode

Assuming I'm using Timer 1 and OCR1A:

TCCR1A |= (1<<COM1A0); // Toggle OC1A on match
TCCR1B |= (1<<WGM12); // Clear to Compare mode
TCCR1B |= (1<<CS10); // No prescale

Select the right prescaling

In case you're wondering, prescales are used when the MCU clock is much faster than the output you desire. Without prescaling, the highest frequency is 16MHz/2 = 8MHz, and the lowest frequency would be 8MHz / 2^16 = 122Hz . Which covers the range of frequencies that we want.

Setting OCR1A value to 80 gives you a frequency of 100kHz Setting OCR1A value to 2667 gives you a frequency of 2.9996kHz

You can then control the chirp like so:

// Linear rise in wave period
int x = 10;
for (int x=80; x < 2668; ++x){
  OCR1A = x; 
  delay(10); // 10ms delay

Add a RC low pass filter to the output and voltage divider

Making the perfect sine waves may be too troublesome, so we'll resort to the poor man's sine wave.

Here's the poor man's implementation by TI (still require quite a few parts.)

Personally, I'm cheap so I'd go for the RLC approach. ;-)


Recommend to use a VCO PLL as external hardware device to get the wanted variable-frequency signal. The DAC output from Arduino can control the voltage to external VCO PLL module. Here is the link for an app note for VCO PLL from Vectron.


Hope it helps.


Since you mentioned SINE wave, I think you're seeking a SWEEP signal. A chirp is a much more complex sound.

To get a sine wave sweep, you probably want a sine function that doesn't use up most of the Arduino executable space.

You can use one of the compact sin(theta) functions that leverage a simple table of values. Just pull the code you need from the cordic.c here: https://people.sc.fsu.edu/~jburkardt/c_src/cordic/cordic.html. C runs in Arduino sketches almost out of the box. You may or may not need some things from the cordic.h. That's why I said "almost". The cordic_prb.c test file has a function test002() that shows you how to call the sine function.

Letting theta = t * (t + k), you will get your sweep, with your instantaneous frequency, f = 2 * pi * (t + k). You will need to calculate the correct k and set t_max to end your loop. This can be obtained from the above formula and your f_min of 3kHz and f_max of 100kHz.

You can use a linear translation to get the sample in the range of values that you want: s = s_center + s_peak * sin(theta) / 2, but you will need to calculate your s_ave and s_peak from your center voltage, V_center, and your peak to peak voltage, V_peak. So there are two translations. This second one depends on the Voltage range of your Arduino board DAC.

Record your sample and voltage range for the board and then Work backward from Voltage range to V_center and V_peak to s_center and s_peak to your two coefficients to multiply and add to your sin(theta) result.

It's just a little algebra and some integration of some code, and you've got your SWEEP generator.

Also remember that boards like the Uno and Mega do not have a real D-to-A converter, so they will only give you a rectangular wave that has digital noise over the primary harmonic that approximates your sweep. Use the Due to avoid lots of digital noise. That's the down side of the pulse width modulation of the lower end Arduino chips.

Either way, you may want to attenuate higher frequencies from any type of D-to-A conversion with a simple passive (RC) or active (op amp) low pass filter.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.