Timer Sync Issue of Timers 0 and 2 with Timer1

I have the below two codes if any one would like to use them: the first one is an Inverted push-pull with variable frequency and variable PWM (input A0 & A1, output pin3 & 5) and the second one is a variable frequency with variable phase shift up to 180 degrees ((input A2 & A3, output pin9 & 10)).

The problem is that when combining the two codes, my outputs are out of sync. On my Scope, I can trigger on one of them at a time to see them.

I would appreciate any input on how to get these two codes in sync using GTCCR or even its possible to sync these two.

The third code or below is the combination of the two codes

Thanks in advance!!

Combo

/* Master Board */

/* Arduino pins corresponding to the outputs of Timers 0 and 2 */
#define PWM_1_PIN  5
#define PWM_2_PIN  3

/* Analog pins for potentiometers */
#define POT_PWM_PIN  A0
#define POT_FREQ_PIN  A1

/* Number of samples for potentiometer value averaging */
#define SAMPLES_NUM 8 // 8 original

/* Potentiometers sampling period in ms */
#define POT_SAMPLE_T_MS  100 //was 100

/* Ranges */
#define FREQ_MIN_HZ  5000ul    //**play around wiht this value
#define FREQ_MAX_HZ  500000ul  //**play around wiht this value
#define POT_MIN  0
#define POT_MAX  1023 // max ADC value **play around wiht this value
#define POT_RANGE  (POT_MAX - POT_MIN)
#define PWM_MIN  0
#define PWM_MAX  (OCR0A / 2) // will create an overlap if set /1
#define PWM_RANGE  (PWM_MAX - PWM_MIN)


long potPWM, potFreq;

int frequency = 800;

void setup() {

  //**************PHaseShift Hack Begin********
  PORTB=0x00;
  DDRB=0x06;
 
  ICR1=frequency; // to vary frequency was 199
  OCR1A=0;        //Was OCR1A=0;
  OCR1B=100;      //was OCR1B=100;
  
  //*********Halt Timers**********
  //GTCCR = (1<<TSM)|(1<<PSRASY)|(1<<PSRSYNC); // halt all timers
  //GTCCR = (1<<TSM)|(0<<PSRASY)|(1<<PSRSYNC); // halt timer0 and timer1 
  //GTCCR = (1<<TSM)|(1<<PSRASY)|(0<<PSRSYNC); // halt timer2 only
  //*********Halt Timers**********
  
  TCNT1=0;
  TCCR1A=0x50;
  TCCR1B=0x19;
  //**************PHaseShift Hack End********
  
  blink();
  pinMode(PWM_1_PIN, OUTPUT);
  pinMode(PWM_2_PIN, OUTPUT);

  /* Init Timer0 (millis() is not functional anymore)*/
  TCCR0A = (2 << COM0B0) | (1 << WGM00); // fast pwm, non-inverted output
  TCCR0B = (1 << WGM02) | (1 << CS01); // counting up to OCR0A **CS00 is the PRESCALER
  TIMSK0 = 0;
  /* Init Timer2 */
  TCCR2A = (3 << COM2B0) | (1 << WGM20); // fast pwm, inverted output
  TCCR2B = (1 << WGM22) | (1 << CS21); // counting up to OCR2A **CS21 is the PRESCALER
  TIMSK2 = 0;
  blink();
  /* set initial values */
  setFreq(FREQ_MAX_HZ); // max frequency initially
  setPWM(11); // 0% duty cycle initially
  blink();
  
}

//**************PHaseShift Hack Begin********
int j=0;
int i=0;
int a;
int b;
//**************PHaseShift Hack End********

void loop()
{
  //**************PHaseShift Hack Begin********
  //delay(50);
  b = analogRead(3);
  i = (b/2);
  a = analogRead(2);
  j = (a/3);      // adjust this as frequency goes down was (a/3)
  if(j>frequency) j=frequency; // must adjust these with frequecny
  //if(i>frequency) i=frequency;
  //update ocr registers with the value
  TCCR1B=0x18;
  if((PINB&0x02)!=00) TCCR1C=0x80;
  if((PINB&0x04)!=00) TCCR1C=0x40;
  TCNT1=0;
  OCR1B = j;
  ICR1 = i;
  if(j==0) TCCR1C=0x40;
  TCCR1B=0x19;
  //**************PHaseShift Hack End********
  
  delayMicroseconds(POT_SAMPLE_T_MS * 1000); // was (POT_SAMPLE_T_MS * 1000);
  /* Sample potentiometers */
  potFreq = samplePot(POT_FREQ_PIN);
  potPWM = samplePot(POT_PWM_PIN);
  /* Set frequency and duty cycle */
  setFreq(mapPotValue(potFreq, FREQ_MIN_HZ, FREQ_MAX_HZ)); // Frequency should be updated first because it will determine max OCR1x values
  setPWM(mapPotValue(potPWM, PWM_MIN, OCR0A));
}

/* Sampling with averaging to minimize noise influence */
int samplePot(int pin) {
 #if SAMPLES_NUM > 1
  int accum = 0;
  for (int i = 0; i < SAMPLES_NUM; i++) {
    accum += analogRead(pin);
  }
  return accum / SAMPLES_NUM;
 #else
  return analogRead(pin);
 #endif
}

void setFreq(long f) {
  f = checkRange(f, FREQ_MIN_HZ, FREQ_MAX_HZ);
  byte regVal = (byte)checkRange(F_CPU / f / 2 - 1, 0, 255);  //was byte regVal = (byte)checkRange(F_CPU / f / 2 - 1, 0, 255
  OCR0A = regVal;
  OCR2A = regVal;
}

void setPWM(unsigned int value) {
  byte regVal = (byte)checkRange(value, PWM_MIN, PWM_MAX);
  OCR0B = regVal;
  OCR2B = OCR0A - regVal;
}

/* Map potentiometer range to value range */
long mapPotValue(long potVal, long minVal, long maxVal) {
  long result;
  potVal = checkRange(potVal, POT_MIN, POT_MAX);
  result = potVal * (maxVal - minVal) / POT_RANGE + minVal;
  return result;
}

static __inline__ long checkRange(long value, long minVal, long maxVal) {
  return value > maxVal ? maxVal : value < minVal ? minVal : value;
}

static __inline__ void maskPWMOutputs(void) {
  /* Disconnect pins from the timers */
  TCCR0A &= ~(3 << COM0B0);
  TCCR2A &= ~(3 << COM2B0);
  digitalWrite(PWM_1_PIN, LOW);
  digitalWrite(PWM_2_PIN, LOW);
}

static __inline__ void unmaskPWMOutputs(void) {
  /* Reconnect pins to the timers */
  TCCR0A |= (2 << COM0B0);
  TCCR2A |= (3 << COM2B0);
}

static __inline__ void blink(void) {
  PORTB |= (1 << 5);
  PORTB &= ~(1 << 5);
}

InvertedPush_Pull.ino (3.27 KB)

PhaseShift180A.ino (855 Bytes)

Combo.ino (4.5 KB)

No one :slight_smile:

I'm not sure. Have you tried setting TCNT0=TCNT1=TCNT2=0?

Just curious: Why aren't you using pinMode when you set the OC1A/B pins to output?