tom321
March 18, 2026, 4:12pm
1
Hi
This code is producing 2.7kHz triangle wave instead 8 MHz square. What is wrong ?
void setup() {
// Set pin 9 (OC1A) as an output
pinMode(9, OUTPUT);
// Set up Timer 1 for Toggle on Compare Match
// WGM12: CTC mode (clear timer on compare match)
// COM1A0: Toggle OC1A on Compare Match
// CS10: No prescaling
TCCR1A = bit(COM1A0);
TCCR1B = bit(WGM12) | bit(CS10);
// OCR1A = 0 (Toggle every timer tick)
// 16 MHz / (2 * (1 + 0)) = 8 MHz
OCR1A = 0;
}
void loop() {
// Do nothing
}
I don't have an Arduino Nano handy to test.
However I ran your code on an Arduino Uno R3, which uses the same ATmega328P microcontroller.
The result was an 8MHz square wave:
How are you observing the waveform?
I can only assume that what you are seeing is an artifact of using too low a sampling frequency, or too low a memory depth on your oscilloscope.
This is a phenomena known as aliasing .
Please post your annotated schematic and a photo of the waveform. I assumed you used a scope to determine this waveform shape and frequency. Also what scope probe did you use and if adjustable divide by ? show that as well. A link to it would be a big help.
tom321
March 18, 2026, 10:11pm
4
probably my 50 MHz Hitachi V- 522 oscilloscope is failing
tom321
March 18, 2026, 10:26pm
5
@ JohnLincoln
can you check this code please ?
void setup() {
// 8 MHz
// Set Pin 3 (OC2B) as output
pinMode(3, OUTPUT);
// Set Timer 2 to Fast PWM mode with top at OCR2A
// COM2B1: Clear OC2B on compare match, set at top (50% duty cycle)
// WGM21+WGM20: Fast PWM Mode 7
TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20); // No prescaler, CS20 = 1
OCR2A = 1; // TOP sets frequency (16MHz / (1+1) = 8MHz)
OCR2B = 0; // Duty cycle
//========================= 10.5 kHZ
pinMode(10, OUTPUT);
// Stop interrupts
noInterrupts();
// Reset Timer1 Control Registers
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
// Set CTC Mode (Mode 4: CTC, Top = OCR1A)
TCCR1B |= (1 << WGM12);
// Set Toggle OC1B on Compare Match (50% duty cycle)
TCCR1A |= (1 << COM1B0);
// Set Prescaler to 1 (No prescaling)
TCCR1B |= (1 << CS10);
// Set the Frequency (10.5 kHz)
// Formula: 16MHz / (2 * Prescaler * Freq) - 1
// 16,000,000 / (2 * 1 * 10,500) - 1 = 760.9
OCR1A = 760; // 760 gives exactly 10.526 kHz, closer than 761
// Resume interrupts
interrupts();
}
void loop() {
// Do nothing
}
// Set Toggle OC1B on Compare Match (50% duty cycle)
TCCR1A |= (1 << COM1B0);
// Set Prescaler to 1 (No prescaling)
TCCR1B |= (1 << CS10);
// Set the Frequency (10.5 kHz)
// Formula: 16MHz / (2 * Prescaler * Freq) - 1
// 16,000,000 / (2 * 1 * 10,500) - 1 = 760.9
OCR1A = 760; // 760 gives exactly 10.526 kHz, closer than 761
// Resume interrupts
interrupts();
}
void loop() {
// Do nothing
}
TCCR1B |= (1 << WGM12);
// Set Toggle OC1B on Compare Match (50% duty cycle)
TCCR1A |= (1 << COM1B0);
// Set Prescaler to 1 (No prescaling)
TCCR1B |= (1 << CS10);
// Set the Frequency (10.5 kHz)
// Formula: 16MHz / (2 * Prescaler * Freq) - 1
// 16,000,000 / (2 * 1 * 10,500) - 1 = 760.9
OCR1A = 760; // 760 gives exactly 10.526 kHz, closer than 761
// Resume interrupts
interrupts();
}
void loop() {
// Do nothing
}
The code is a nonsense.
You seem to have three empty loop functions, why?
Your braces do not match. Hint click on an opening brace and you will see the closing brace outlined. Conversely click on a closing brace and you will see the matching opening brace outlined.
That last code will not even compile.
void setup() {
// 8 MHz
// Set Pin 3 (OC2B) as output
pinMode(3, OUTPUT);
// Set Timer 2 to Fast PWM mode with top at OCR2A
// COM2B1: Clear OC2B on compare match, set at top (50% duty cycle)
// WGM21+WGM20: Fast PWM Mode 7
TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS20); // No prescaler, CS20 = 1
OCR2A = 1; // TOP sets frequency (16MHz / (1+1) = 8MHz)
OCR2B = 0; // Duty cycle
//========================= 10.5 kHZ
pinMode(10, OUTPUT);
// Stop interrupts
noInterrupts();
// Reset Timer1 Control Registers
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
// Set CTC Mode (Mode 4: CTC, Top = OCR1A)
TCCR1B |= (1 << WGM12);
// Set Toggle OC1B on Compare Match (50% duty cycle)
TCCR1A |= (1 << COM1B0);
// Set Prescaler to 1 (No prescaling)
TCCR1B |= (1 << CS10);
// Set the Frequency (10.5 kHz)
// Formula: 16MHz / (2 * Prescaler * Freq) - 1
// 16,000,000 / (2 * 1 * 10,500) - 1 = 760.9
OCR1A = 760; // 760 gives exactly 10.526 kHz, closer than 761
// Resume interrupts
interrupts();
}
void loop() {
// Do nothing
}
/*
// Set Toggle OC1B on Compare Match (50% duty cycle)
TCCR1A |= (1 << COM1B0);
// Set Prescaler to 1 (No prescaling)
TCCR1B |= (1 << CS10);
// Set the Frequency (10.5 kHz)
// Formula: 16MHz / (2 * Prescaler * Freq) - 1
// 16,000,000 / (2 * 1 * 10,500) - 1 = 760.9
OCR1A = 760; // 760 gives exactly 10.526 kHz, closer than 761
// Resume interrupts
interrupts();
}
void loop() {
// Do nothing
}
TCCR1B |= (1 << WGM12);
// Set Toggle OC1B on Compare Match (50% duty cycle)
TCCR1A |= (1 << COM1B0);
// Set Prescaler to 1 (No prescaling)
TCCR1B |= (1 << CS10);
// Set the Frequency (10.5 kHz)
// Formula: 16MHz / (2 * Prescaler * Freq) - 1
// 16,000,000 / (2 * 1 * 10,500) - 1 = 760.9
OCR1A = 760; // 760 gives exactly 10.526 kHz, closer than 761
// Resume interrupts
interrupts();
}
void loop() {
// Do nothing
}*/
The code that has had portions commented out by @GolamMostafa compiles.
That code produces an 8MHz square wave on pin 3, and a 10.5kHz square wave on pin 10.
I've turned the zoom on to show the 8MHz signal.