// https://runtimemicro.com/Projects/Arduino-Timer-Phase-Shifted-Square-Waves
// Example Nano/Uno Code from RuntimeMicro.com
// runtime adjustable Phase-Shifted Square-Waves (1000 Hz)
// NO PHASE FLIPS
// Updated -- May 6, 2023
//============ Frequency Change Constants ==================
// Un-Comment only One line for the Phase-Chg size
const unsigned int Phase_Chg_Const = 20; // use for 100 Hz to 50 kHz range
// const unsigned int Phase_Chg_Const = 2; // use for 50 kHz to 90 kHz range
// const unsigned int Phase_Chg_Const = 1; // use for 90 kHz to 900 kHz range
// Un-Comment only One line for the Loop-Delay-Constant
const unsigned int Delay_Const = 20; // use for 100 Hz to 50 kHz range
//const unsigned int Delay_Const = 50; // use for 50 kHz to 90 kHz range
// const unsigned int Delay_Const = 75; // use for 90 kHz to 900 kHz range
//================================================
int button_Pin1 = A5; // Using ADC pins for buttons on my build
int button_Pin2 = A3;
int OCR_Result; // a calculation variable
void Adjust_Phase(int Up_Down)
{
// NOTE: This Subroutine causes Scope-Jitter when called (!!!)
// Use Normal Sync, not Auto -- may be tricky to adjust
// This routine is modified RTM_TimerCalc mode-12 CTC Code
cli();
TCCR1B = 0x18; // DISABLE Timer Clock
OCR_Result = OCR1B; // Copy current OCR value
// change Phase
OCR_Result += Up_Down; // add passed parameter
// Constrain
if (OCR_Result < 1) OCR_Result = 1; // never less than 1
if (OCR_Result > ICR1-1) OCR_Result = ICR1-1; // never >= ICR
OCR1B = OCR_Result; // Pass back changed Phase value
TCNT1=0; // reset Counter
TCCR1A = 0xA0; // Set Compare-Match bit-fields for Clear-on-Match
TCCR1C = 0xC0; // Force Output Compares -- Clears Channel-AB Waveform Outputs!
TCCR1A = 0x50; // Set Compare Match bit-fields for Toggle-on-Match
TCCR1B |= 1; // Prescale=1, ENABLE Timer1 Clock
sei();
}
void setup()
{
// PUSH BUTTON PINS -- Pins need Pulled-Up Inputs
pinMode(A5, INPUT_PULLUP); // Push-button_Pin1 ADC pin
pinMode(A3, INPUT_PULLUP); // Push-button_Pin2 ADC pin
// Timer-1 16-bit, Mode-12 CTC, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR1B = 0x18; // 0001 1000, Disable Timer
TCCR1A = 0x50; // 0101 0000
ICR1 = 8000-1; // Frequency Control, use TimerCalc to determine! <<******
OCR1A = 1; // never less than 1, never more than ICR1
OCR1B = 1; // both channels in phase, OCR's not using TimerCalc values
TCNT1=0x0;
TCCR1A = 0xA0; // FOC setup to clear Wavegen output flops
TCCR1C = 0xC0; // FOC strobe
TCCR1A = 0x50; // 0101 0000
// UNO-NANO Timer-1 Pins
pinMode(9, OUTPUT); // OC1a
pinMode(10, OUTPUT); // OC1b
// 2560 Timer-1 Pins
// pinMode(11, OUTPUT); // OC1a
// pinMode(12, OUTPUT); // OC1b
TCCR1B |= 1; // Prescale=1, Enable Timer
}
void loop()
{
int buttonState_1;
int buttonState_2;
// read state of pushbutton(s):
buttonState_1 = digitalRead(button_Pin1);
buttonState_2 = digitalRead(button_Pin2);
delay(Delay_Const); // PACE loop speed
// check if pushbutton pressed.
if (buttonState_1 == LOW) Adjust_Phase(-Phase_Chg_Const); // Decrease Phase Angle
// check if pushbutton pressed.
if (buttonState_2 == LOW) Adjust_Phase(+Phase_Chg_Const); // Increase Phase Angle
}