Hi folks,
Iam using Arduino Mega 2560 & trying to generate 3 PWM signals with 50% duty cycle and 120 degree phase shifts between all 3 signals using Timer1(pin11), Timer3(pin5) and Timer4(pin6). So far Iam able to achieve this all with manually varying frequency from 10Hz to 2KHz in loop, but Iam not able to achieve exact phaseshift of 120degree when Iam varying my frequency using POT and reading it using ADC. Help me find out the issue and modification to be done in the code to achieve this. Thank you.
Below is the code
int i = 1;
#define ICRVALUE(i) (125000 / (1 * i))
ISR(TIMER5_COMPA_vect) {
TCCR3B |= 3; // DELAYED START Timer 3, 120 degrees
}
ISR(TIMER5_COMPB_vect) {
TCCR4B |= 3; // DELAYED START Timer 4, 240 degrees
}
ISR(TIMER1_OVF_vect) {
}
ISR(TIMER3_OVF_vect) {
}
ISR(TIMER4_OVF_vect) {
}
// Use multiple timers (Timer1, Timer3, Timer4, Timer5) on the ATmega2560 to generate PWM signals.
// Set each timer's PWM frequency based on the ADC value and adjust each output pin compare match to introduce phase shifts.
// Set up the ADC to continuously read the voltage from a potentiometer, which dictates the PWM frequency.
uint8_t PRESCALER = 1;
void setupADC() {
ADMUX = (1 << REFS0); // AVcc as reference
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 128
}
// uint16_t readADC()
// {
// ADCSRA |= (1<<ADSC); // Start conversion
// while (ADCSRA & (1<<ADSC)); // Wait for conversion to finish
// return ADC;
// }
void setup() {
Serial.begin(9600);
setupADC();
// Timer-5 16-bit, Mode-14 FAST, Top=ICR
// 1000 Hz Frequency, Clock is 16 MHz
// Only this Timer is using Fast-PWM
TCCR5B = 0x18; // 0001 1000, Disable Timer
TCCR5A = 0x50; // 0101 0000
ICR5 = 16000 - 1;
OCR5A = (int)(ICR5 * 0.33333); // 120 degrees at Freq
OCR5B = (int)(ICR5 * 0.66666); // 240 degrees at Freq
TCNT5 = 0x0;
TIMSK5 = 0x06; // Enable CompA and CompB Interrupts
//////////////////////////////////////////////
// Timer-1 16-bit, Mode-10 Phase-PWM, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR1B = 0x10; // 0001 1000, Disable Timer
TCCR1A = 0x82; // 1000 0010
ICR1 = 8000 - 1;
OCR1A = (int)(ICR1 * 0.5);
TCNT1 = 0x0;
TIMSK1 = 0x01; // OVF Channel-A Center Pulse Interrupt
pinMode(11, OUTPUT); // OC1a, 0 degrees phase shift
//////////////////////////////////////////////////
// Timer-3 16-bit, Mode-10 Phase, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR3B = 0x10; // 0001 1000, Disable Timer
TCCR3A = 0x82; // 1010 0010
ICR3 = 8000 - 1;
OCR3A = (int)(ICR3 * 0.5);
TCNT3 = 0x0;
TIMSK3 = 0x01; // OVF Center Pulse Interrupt
pinMode(5, OUTPUT); // OC3a, 120 degrees from Timer-1
///////////////////////////////////////////////////
// Timer-4 16-bit, Mode-10 Phase, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR4B = 0x10; // 0001 1000, Disable Timer
TCCR4A = 0x82; // 1010 0010
ICR4 = 8000 - 1;
OCR4A = (int)(ICR4 * 0.5);
TCNT4 = 0x0;
TIMSK4 = 0x01; // OVF Center Pulse Interrupt
pinMode(6, OUTPUT); // OC4a, 240 degrees from Timer-1
// Center Pulse Marker Pins
pinMode(14, OUTPUT); // Center-Pulse Marker T1-Channel-A
pinMode(15, OUTPUT); // Center-Pulse Marker T3-Channel-A
pinMode(16, OUTPUT); // Center-Pulse Marker T4-Channel-A
pinMode(18, OUTPUT); // Setup Marker Pulse
// UPDATE
// Synchronize Start of Timers 1 and 5
GTCCR = 0x81; // Timer Sync Control -- STOP ALL TIMERS, Clear preScalers
TCCR5B |= 3; // Prescale=1, ENABLE Timer 5
TCCR1B |= 3; // Prescale=1, ENABLE Timer 1
GTCCR = 0x0; // START ALL TIMERS
// Place Marker Pulse to watch Timer(s) startup
digitalWrite(18, HIGH);
digitalWrite(18, LOW);
} // end setup
void loop() {
static uint16_t previous_freq = 0xFFFF;
while (1)
//for(int i=1;i<=200;i++)
{
uint16_t adcValue = analogRead(A1);
Serial.print("ADC value = \n");
Serial.println(adcValue);
float voltage = adcValue * (5.0 / 1023.0);
uint16_t newFrequency = (uint16_t)adcValue * 2; //(i*0.004*1000)/2;; //map(voltage, 0.004, 5.0, 2, 2048);
Serial.print("Mapped value = \n");
Serial.println(newFrequency);
////////////////////////////////////////////////////////////////////////////
// Timer-5 16-bit, Mode-14 FAST, Top=ICR
// 1000 Hz Frequency, Clock is 16 MHz
// Only this Timer is using Fast-PWM
TCCR5B = 0x18; // 0001 1000, Disable Timer
TCCR5A = 0x50; // 0101 0000
ICR5 = (ICRVALUE(newFrequency) * 2) - 1; //16000 - 1;
OCR5A = (int)(ICR5 * 0.33333); // 120 degrees at Freq
OCR5B = (int)(ICR5 * 0.66666); // 240 degrees at Freq
TCNT5 = 0x0;
TIMSK5 = 0x06; // Enable CompA and CompB Interrupts
///////////////////////////////////////////////////////////////////////////////////
// Timer-1 16-bit, Mode-10 Phase-PWM, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR1B = 0x10; // 0001 1000, Disable Timer
TCCR1A = 0x82; // 1000 0010
ICR1 = ICRVALUE(newFrequency) - 1; //8000 - 1;
OCR1A = (int)(ICR1 * 0.5);
TCNT1 = 0x0;
TIMSK1 = 0x01; // OVF Channel-A Center Pulse Interrupt
pinMode(11, OUTPUT); // OC1a, 0 degrees phase shift
///////////////////////////////////////////////////////////////////////////////////
// Timer-3 16-bit, Mode-10 Phase, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR3B = 0x10; // 0001 1000, Disable Timer
TCCR3A = 0x82; // 1010 0010
ICR3 = ICRVALUE(newFrequency) - 1; //8000 - 1;
OCR3A = (int)(ICR3 * 0.5);
TCNT3 = 0x0;
TIMSK3 = 0x01; // OVF Center Pulse Interrupt
pinMode(5, OUTPUT); // OC3a, 120 degrees from Timer-1
///////////////////////////////////////////////////////////////////////////////////
// Timer-4 16-bit, Mode-10 Phase, Top=ICR
// 1,000 Hz Frequency, Clock is 16 MHz
TCCR4B = 0x10; // 0001 1000, Disable Timer
TCCR4A = 0x82; // 1010 0010
ICR4 = ICRVALUE(newFrequency) - 1; //8000 - 1;
OCR4A = (int)(ICR4 * 0.5);
TCNT4 = 0x0;
TIMSK4 = 0x01; // OVF Center Pulse Interrupt
pinMode(6, OUTPUT); // OC4a, 240 degrees from Timer-1
// Center Pulse Marker Pins
pinMode(14, OUTPUT); // Center-Pulse Marker T1-Channel-A
pinMode(15, OUTPUT); // Center-Pulse Marker T3-Channel-A
pinMode(16, OUTPUT); // Center-Pulse Marker T4-Channel-A
pinMode(18, OUTPUT); // Setup Marker Pulse
///////////////////////////////////////////////////////////////////////////////////
// UPDATE
// Synchronize Start of Timers 1 and 5
GTCCR = 0x81; // Timer Sync Control -- STOP ALL TIMERS, Clear preScalers
TCCR5B |= 3; // Prescale=1, ENABLE Timer 5
TCCR1B |= 3; // Prescale=1, ENABLE Timer 1
GTCCR = 0x0; // START ALL TIMERS
sei();
delay(1000);
cli();
} //end of while loop
} // end loop()