Electronic – How to calculate phase shift between two sine wavefroms

analogcmicrocontrollerprogramming

I two sinewave signals with same frequency. I want to measure phase shift between two signals. There will be a small phase difference between two signals. I am using ATmega32-A micro controller and external ADC AD7798 to read the voltage of both signal. I am able to read both signal voltages using SPI communication. How to find Phase difference between two sine signals. I am using CodeVisionAVR compiler.

I know that phase shift between two signals can be find out using the fallowing formula.

A(t)= Am sin(Wt+/-theta).

I know only amplitude(Am) and w =2*pi*f. But How to calculate phase difference between two sinewave signals with knowing amplitude and frequency. Any suggestions please.

I have implemented timer functionality to get zero crossing points using the fallowing code.

void main(void){

    init();                                     //Initialize controller

    debug = 0;                                  //Controls output during motor running      

    while (1){

        if(rx_counter0) getCom();
        if(Command)     runCom(); 

        if(logInt > 0){
            if(now){
            if(!(unixTime % logInt)){
                    if(flag){
                    flag = 0;
                }
                now = 0;                  
               }
          }
        }

        #asm("WDR");        //Reset WD timer 

    }  // EOF "while(1)"   

   } // EOF "main(void)"

void init(void){

#asm("cli");        //Disable global interrupt

// Input/Output Ports initialization
// Port B initialization
DDRB=0xBF;
// Port C initialization
DDRC=0xC3;
// Port D initialization
DDRD=0xFC;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x67;
UCSRA=0x00;
UCSRB=0xD8;
//UCSRC=0x86;

// ADC initialization
// ADC Clock frequency: 1000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: None
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
// ADC4: On, ADC5: On
//DIDR0=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x84;

//Global enable interrupts
#asm("sei")
}

unsigned int timer_phase (void)
{
  ResetTimer1();    //reset timer to zero

  while(selcase(1) > 0)
   {
    //do nothing until input channel crosses zero
   }
  StartTimer1();    //start timer counting

  while(selcase(5) > 0)
   {
   //do nothing until output channel crosses zero
   }
  StopTimer1();    //stop timer counting

  time_delay_ticks = get_timer_ticks();    //get the number of timer ticks between zero crossings 

  time_delay = ticks_to_time(time_delay_ticks);    //need to get timer ticks into time domain

  period = 1 / WaveFreq;    //get the period from the known frequency
  phase_delay = (time_delay_ticks / period) * 360;    //calculate phase delay */  
  return phase_delay;
} 

interrupt [TIM1_COMPA] void timer1_compa_isr(void){
 unixTime++;
 now = 1;
 }

void StartTimer1(void)
{
    TCNT1H = 0x00;
    TCNT1L = 0x00;      //Start counting from 0

    OCR1AH = 0x0E;
    OCR1AL = 0x0E;      //Timer 1 reload value OCR1A = fCLK/(fOC1A*2*n)-1    REMEMBER 2 * OCR1A!

    TIMSK = 0x02;      //Enable timer 1 output compare A interrupt    

    TCCR1A = 0x00;
    TCCR1B = 0x0D;      //Start timer 1 in CTC-mode (4) with prescale 1024
}      

void StopTimer1(void)
{
   TCCR1A = 0x00;
   TCCR1B = 0x00; //Stop timer 1
    TIMSK = 0x00;  //Switch of interrupt
} 

void ResetTimer1(void)
{
   TCCR1A = 0x00;
   TCCR1B = 0x00; //Stop timer 1
    TCNT1H = 0x00;
    TCNT1L = 0x00;
    TIMSK = 0x00;  //Switch of interrupt
}

unsigned int get_timer_ticks(void)
{      
unsigned int i;
i= TCNT1H;
i= i|TCNT1L;
return i;
} 

when i run this code I am not getting any errors, But I am not able to enter any command from hyper terminal. When comment this whole function then only i am able to get output and i am able to enter commands from hyper terminal.
Help me if any thing with timer function start and stop and reset and get_delay_tricks. Or any thing wrong with interrupts.

Best Answer

You need to use Olin's idea of determining the zero crossings of the signals to get the time delay. Then plug the time delay into Scott's equation to get the phase delay.

The following is pseudo-code. I'll leave it up to you to implement each function since they should either be trivial to implement or you should already have something similar written.

reset_timer();    //reset timer to zero

while(get_amplitude(INPUT_CHANNEL) > 0.0)
{
    //do nothing until input channel crosses zero
}

start_timer();    //start timer counting

while(get_amplitude(OUTPUT_CHANNEL) > 0.0)
{
    //do nothing until output channel crosses zero
}

stop_timer();    //stop timer counting

time_delay_ticks = get_timer_ticks();    //get the number of timer ticks between zero crossings 
time_delay = ticks_to_time(time_delay_ticks);    //need to get timer ticks into time domain

period = 1 / frequency;    //get the period from the known frequency

phase_delay = (time_delay / period) * 360;    //calculate phase delay

It's important to read the documentation on the timer you will be using so that you know how to convert from timer ticks into time.