2

I have been looking for the phase difference between two square signals and this is the code:

#include <avr/io.h>
#include <avr/interrupt.h>


void setup() {
  //Serial.begin(9600);
  pinMode(2, INPUT);    //set pins 2 and 3 as inputs and 11 as output
  pinMode(3, INPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  cli();           // disable all interrupts
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);  //set up timer2 to generate a PWM
  TCCR2B = _BV(CS20);    //set prescalar value to 1
  //TCCR1A = 0;
  //TCCR1B = _BV(CS20);
  //TCCR1B |= (1 << CS12); //256 values
  TCNT2  = 0;
  sei();             //enable all interrupts

  attachInterrupt(digitalPinToInterrupt(2), t1_ISR, RISING);     //enable interrupt service routines on pins 2 and 3
  attachInterrupt(digitalPinToInterrupt(3), t2_ISR, RISING);

  //Serial.print(OCR2A);
  //Serial.print(OCR1A);

}

volatile uint8_t t1, t2;

void loop() {
  if (t2 == t1)
  {
    OCR2A = 0;
    OCR2B = 0;
  }
  //compare time that one signal goes high to time the other signal goes high
  else if (t2 > t1)
  {
    OCR2A = (t2 - t1); //output PWM based on phase difference on pin 11
    OCR2B = 0;
  }
  else if (t2 < t1)
  {
    OCR2B = (t1 - t2);  //output PWM on pin 11
    OCR2A = 0;
  }
}
}

void t1_ISR() {         //interrupt if signal on pin 2 goes high and store counter
  t1 = TCNT2;           //value to variable t1
}

void t2_ISR() {         //interrupt if signal on pin 3 goes high and store counter
  t2 = TCNT2;           //value to variable t2
}

I want to operate the input pulses at 40 kHz, how can I do this and read the difference of phase? I am using the Arduino Mega2560

18
  • 1
    What's wrong with this code? Or the code you just described with a lot of things changed? Please post the code that you actually want help with. What does it do or not do when you run it and how does that compare with your expectations? You haven't described any symptoms yet. "It doesn't work" is a really useless statement. It does something, and it's not what you wanted. So you have to fill us in on what those things are. Doesn't that make sense? – Delta_G Nov 6 '17 at 1:06
  • 3
    No you didn't. The code in this question still doesn't say volatile. You seem to have started another question, but I marked it as a duplicate so they should close that one. You need to edit this question and put the code here. – Delta_G Nov 6 '17 at 1:34
  • 1
    DO NOT REPOST, use the "edit" button to fix this, your original question. – Chris Stratton Nov 6 '17 at 2:33
  • 1
    I have declared t1 and t2 as volatile unsigned longs - no, you haven't. – Nick Gammon Nov 6 '17 at 3:44
  • 1
    Your timer 2 outputs on pins 10 and 11? Which Arduino is this? Please, add to your question the tag appropriate for the Arduino board you are using. – Edgar Bonet Nov 6 '17 at 12:04
2

There are a few things very wrong here.

First problem: you are clocking Timer 2 with the prescaler set to 1. This means the timer will roll over every 256 CPU cycles. Your input signal, on the other hand, has a period of 25 µs, which is 400 CPU cycles (I am assuming a 16 MHz Arduino). Unless you know beforehand that the phase difference is within some window less than 16 µs wide, your readings will be ambiguous.

You have to make sure the rollover period of your timer is larger than the period of the input signal. This means either using a larger prescaler (8 should do), which will decrease your phase resolution, or using a 16-bit timer instead of an 8-bit timer.

Second problem: you are using a signed integer type for the timer readings. This makes little sense. Worse: you are computing differences like t2-t1, which can overflow. Signed integer overflow is undefined behavior in C++, and invoking it is always a bug.

You should declare t1 and t2 as unsigned, i.e. either volatile uint8_t, or volatile uint16_t (if using a 16-bit timer). Then you don't get overflows: you get instead a well-defined rollover behavior.

Third problem: you are doing comparisons like if (t2 > t1). This, again, makes no sense, if only because the timer is repeatedly rolling-over to zero. You should instead just compute t2-t1 and work your way from that.

1

how can I do this and read the difference of phase?

a few simple ways:

1) poll the input signals: For example, once a pin has gone high, wait for the other pin to go high as well.

2) xor the input signals: wait for the XOR of both inputs to go high, wait for it to go low. essentially the 1st approach;

3) use interrupts: once the first signal goes high, start a timer; once the 2nd signal to go high, stop the timer.

4) use input capture: ...

...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.