Here is an example of generating frequencies using Timer1. It can for 0.2Hz (5 seconds per cycle) to 500 kHz.
// Generating Two 180° Out of Phase Variable-Frequency
// Square Waves on Timer1 of an Arduino UNO (Pins 9 and 10)
// Good for frequencies from 0.2 Hz to 500 kHz.
// Written June 1st, 2020 by John Wasser
void TwoPhaseBegin()
{
digitalWrite(9, LOW);
pinMode(9, OUTPUT);
digitalWrite(10, LOW);
pinMode(10, OUTPUT);
// Stop Timer/Counter1
TCCR1A = 0; // Timer/Counter1 Control Register A
TCCR1B = 0; // Timer/Counter1 Control Register B
TIMSK1 = 0; // Timer/Counter1 Interrupt Mask Register
// Set Timer/Counter1 to Waveform Generation Mode 8:
// Phase and Frequency correct PWM with TOP set by ICR1
TCCR1B |= (1 << WGM13); // WGM=8
TCCR1A |= (1 << COM1A1); // Normal PWM on Pin 9
TCCR1A |= (1 << COM1B1) | (1 << COM1B0); // Inverted PWM on Pin 10
TwoPhaseFrequency(1000.0); // Default to 1 kHz
}
bool TwoPhaseFrequency(float frequency)
{
byte prescaleBits; // 1, 2, 3, 4, 5
uint16_t prescaleFactor; // 1, 8, 64, 256, 1024
uint32_t top32;
// Find the smallest prescale factor that will fit the TOP value within 16 bits.
// frequency = F_CPU / (2 * prescale * TOP)
// TOP = F_CPU / (2UL * prescale * frequency);
prescaleBits = 1;
prescaleFactor = 1; // Used for 123 Hz to 500 kHz
top32 = F_CPU / (2UL * prescaleFactor * frequency);
if (top32 > 65535UL) // Too many clocks to count in 16 bits?
{
prescaleBits = 2;
prescaleFactor = 8; // Used for 16-122 Hz
top32 = F_CPU / (2UL * prescaleFactor * frequency);
if (top32 > 65535UL) // Too many clocks to count in 16 bits?
{
prescaleBits = 3;
prescaleFactor = 64; // Used for 2-15 Hz
top32 = F_CPU / (2UL * prescaleFactor * frequency);
if (top32 > 65535UL) // Too many clocks to count in 16 bits?
{
prescaleBits = 4;
prescaleFactor = 256; // Only used for 1 Hz
top32 = F_CPU / (2UL * prescaleFactor * frequency);
if (top32 > 65535UL) // Too many clocks to count in 16 bits?
{
prescaleBits = 5;
prescaleFactor = 1024;
top32 = F_CPU / (2UL * prescaleFactor * frequency);
if (top32 > 65535UL) // Too many clocks to count in 16 bits?
{
return false;
}
}
}
}
}
// Serial.print("Freq: ");
// Serial.print(frequency);
// Serial.print(" prescale: ");
// Serial.print(prescaleFactor);
// Serial.print(" TOP: ");
// Serial.println(top32);
if (top32 < 16)
return false; // Require at least 16 levels of PWM
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Clear the three clock select bits
TCCR1B |= prescaleBits; // Set clock prescale to prescaleBits
ICR1 = top32;
OCR1A = top32 / 2;
OCR1B = (top32 / 2) + 1;
return true;
}
void setup()
{
Serial.begin(115200);
TwoPhaseBegin(); // Start output at 1000 Hz
}
void loop()
{
// Call TwoPhaseFrequency(uint16_t frequency) any time to change the output frequency
}