Arduino 8MHz Variable Frequency Generator

 Here it is shown how one can generate signal with adjustable frequency upto 8MHz using Arduino Timer in CTC mode. There are basically 8-bit or 16-bit timers in Arduino Uno, Arduino Nano, Arduino Meg2560 etc. Depending upon whether 8 bit or 16 bit timer is used the lower frequency can be 31.25KHz for 8 bit timer or 61KHz for 16 bit timer but the highest frequency of the signal that can be generated is 8MHz. The output square wave signal from CTC mode has frequency that depends upon the count value(C) that can be loaded into the OCRnX register for timer n(n=0,1,2 etc) with compare module X(X=A,B) and the pre-scalar value. 

The frequency of the output square wave in CTC mode for 8 bit timer and 16 bit timer is the same and is given by the following equation.

\(Fw = \frac{F_{cpu}}{2N(1+C)}\)

where \(F_{cpu}\) is the frequency of the Arduino CPU or the oscillator frequency which is 16MHz, N is the pre-scalar and C is the count value that is loaded in to the OCRnX register. Regardless of the pre-scalar value, which ranges from 1 to 1024, the highest frequency that can be generated with Arduino is 8MHz. We can use the ATmega online calculator to calculate the value of count to be loaded into the OCRnX register for specified output frequency.

Watch the following video of how the Arduino 8MHz Variable Signal Generator works.

Here Arduino Mega 2560 is used generate adjustable frequency square wave in CTC mode. The frequency of the output wave can be adjusted using a 10KOhm potentiometer(100KOhm POT could be better). The process presented here and the program code can also be used for other Arduino board like Arduino Uno, Arduino Nano etc.

The Arduino square wave generator with variable frequency  is simple to build. We connect a 10KOhm potentiometer to the analog input pin A0(or others). The variable frequency square wave output is taken from one of the output compare pin which depends upon which timer is used. Here Timer 0 is used. The Timer 0 in Arduino Mega has two output compare hardware unit- OCR0A and OCR0B. We use the A unit and therefore the output appears at the output compare pin OC0A which is pin 13 on Arduino Mega. 

The following shows the Arduino 8MHz Variable Frequency Generator implementation on breadboard.

Arduino 8MHz Variable Frequency Generator  (2)

The circuit diagram to generate variable frequency signal is shown below.

Variable frequency Signal generator Arduino Mega

The program code to generate variable frequency square wave is also easy. We configure the Arduino Timer 0 in CTC mode and the toggle mode within the CTC mode, configure the pre-scalar value using the TCCR0A, TCCR0B registers. Then in the continuous loop we read in the analog value from the potentiometer connected to analog pin A0 and obtain the digital equivalent value using the ADC(Analog to Digital Converter). We map the ADC value to range of OCR0A value which can be from 0 to 255. Then we load this count value(C) into the OCR0A register. The tutorial Arduino CTC mode Programming with Examples has example worked for CTC mode where Arduino Uno is used but the program code can be easily ported to work with Arduino Mega and other Arduino board.

The following is the Arduino program code to generate adjustable frequency square wave using the CTC toggle mode.

const int N=1;
const float Fcpu = 16000000;

void setup() {
  //set OC0A as output
  pinMode(13, OUTPUT);

  // reset timer 0 control registers
  TCCR0B = 0;  
  TCCR0A = 0;
   // Load 255 to generate 31.25 kHz sq.wave
  OCR0A = 255; 
   // Toggle OC0A on compare match, WGM 2 (CTC)
  TCCR0A = (1 << COM0A0) | (1 << WGM01); 
  // Start the timer, no prescalar
  TCCR0B = (1 << CS00); 


void loop() {
  int anaValue = analogRead(A0);
  OCR0A = map(anaValue, 0,1023, 0, 255);
  float Fw = (Fcpu)/((1+OCR0A)*2*N);
  Serial.print("OCR0A: ");
  Serial.print("Freq.: ");  

In the above Arduino square wave generator code, we have used pre-scalar of N=1, so no pre-scalar. Notice that we have to setup the output compare pin OC0A(pin 13 on Arduino Mega) as an output pin. The Timer 0 is configured in CTC toggle mode by configuring TCCR0A and TCCR0B. This was explained in details in the previous post Programming Arduino Mega in CTC mode.  Just to mention we have loaded a default initial count value of 255 into the OCR0A register which generates lowest frequency 31.25KHz signal. At the end we print out the value to serial monitor to see the count value loaded and the frequency that was generated.

Watch the following animation of the Arduino frequency generator.

Tests and results

Following pictures shows some of the results obtained.

31.25KHz signal from the Arduino signal generator on oscilloscope.

31.25KHz signal from the Arduino signal generator

Serial monitor showing OCR0A register value and the frequency.

Arduino 31.25KHz signal on serial monitor

4MHz signal from the Arduino signal generator on oscilloscope.

4MHz signal from the Arduino signal generator

 Serial monitor showing OCR0A register value and the frequency.

Arduino 4MHz signal on serial monitor

 8MHz signal from the Arduino signal generator on oscilloscope.

Arduino 8MHz signal

 Serial monitor showing OCR0A register value and the frequency.

Arduino 8MHz signal on serial monitor

By using filters at the output we can easily generate sine wave and other types of waveforms and so with little addition of external components one can build a variable frequency waveform generator with Arduino. 

See How to generate Sine Wave with Arduino tutorial on how to use filter to convert square wave to sine wave. Here we have used Timer 0, similar process and code can be used to make function generator using other arduino timers. Since here Arduino Timer 0 is used it may hinder in program codes where delay(), milli() functions are required since they depend on timer 0. In this situation we can make use of Time Delay with Arduino Timer 1 or Time Delay with Arduino Timer 2 .

Also if you want DIY home electronics testing tools then see the following tutorials.

- Arduino UNO sine wave generator

DIY LCR meter using PC

Post a Comment

Previous Post Next Post