External event synchronization for timers

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello!

I have 2 microcontrollers. The first generate 400 Hz PWM. The second microcontroller must synchronize his 400 Hz timer using rising edge of external sygnal.

My code:


#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "uart.h"

int TOP=39999;	//Задаем период в битах
uint8_t Timer3Counter=0;
uint16_t Timer3Data=0;


void Timer1_400Hz_ini(void)
{
	ICR1=TOP;
	OCR1A=10000;
	TCCR1A|=(1<<COM1A1)|(1<<WGM11);
	TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS10);
}

void ExtSourceTrig(void)
{
	EIMSK|=(1<<INT0);
	EICRA|=(1<<ISC01)|(1<<ISC00);
}

void Timer3_10ms_ini(void)
{
	ICR3=19999; //For 10 ms
	OCR3A =2000;
	TCCR3A|=(1<<COM3A1)|(1<<WGM31);	
	TCCR3B = (1 << WGM33) |(1 << WGM32) | (1 << CS31); //CTC div 8
	TIMSK3 = (1 << OCIE3A); //Output compare match A int enable
	
}

int main(void)
{
    /* Replace with your application code */
	UART_init(103);
	UART_puts("Hello...\r\n");
	Timer3_10ms_ini();
	ExtSourceTrig();
	
	DDRB|=(1<<PB5);
	PORTB|=(1<<PB5);


	DDRE|=(1<<PE3);	
	PORTE|=(1<<PE3);	
	sei();
    while (1) 
    {
    }
}

ISR(TIMER3_COMPA_vect) 
{
	Timer3Counter++;	
}

ISR(INT0_vect)
{
	ICR1=0;
	OCR1A=0;
	TCCR1A=0;
	TCCR1B=0;	
	Timer1_400Hz_ini();			
/*
	PORTB|=(1<<PB5);
	_delay_us(50);
	PORTB&=~(1<<PB5);
*/
	
}

I use oscilloscope to control signals. Synchronization does not work. If the external signal is static on the screen. controlled signal is "running away". Frequency of the controlled signal is insignifficant different, that is why the signal running away.

The only one solution that I found - forget about the using timers as the PWM source. Use it like a counter to calculate the frequency, duty ratio and toggle the pin. 

Is it possible to find another solution of this problem?

P.S. I cannot to use clock source of the external signal.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Sounds like you need to read up on Digital Phase Lock Loops.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Something new for me, but it looks like what I'm looking for:)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The second microcontroller must synchronize his 400 Hz timer using rising edge of external sygnal.

So each has its own duty cycle, say A is 23% and B is 47%

You want the leading edge of each to match, correct?   How often must they be rematched?  Every pulse, or once a minute?

 

The easiest way BY FAR is to simply generate PWMA.  For B, look for the leading edge of A signal (use IRQ or even polling*) and set the B PWM pin high when you see it.  

At that moment, set a B timer (IRQ or polled), based on B's duty cycle.  When that time is up, set B PWM pin low. 

When PWMA halts, so will PWMB.

----------------------------------------------

*400Hz is slow so you can synch relatively good in that timescaling with polling, if you are not too busy with other things.

Otherwise, an IRQ can respond in sub-microseonds, assuming you don't have other IRQ blocking.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

They must be rematched every pulse

Thank you for advice, I will try this

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This may be done if both sources are precise (with X-osc). In moment of external source interrupt, do read counter that produces own 400Hz.

Ideally, each time of external Interrupt this value should be the same, but will not, that is why synchronization is necessary.

Assign one to three values in the middle of OCR value for 'sync'. For example, OCR2 may be 100, then value 49, 50, 51 will be safe.

If over, do prepare r16 to be 255. If less, r16 will be 1. Finally:

 jqt03Done:
    in   r17, TCNT2
    add  r17, r16
    out  TCNT2, r17

You may try this, I did it for external 1Hz source toward internal 1Hz.

Only if the phase distortion is not an issue.

Last Edited: Thu. May 12, 2022 - 05:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm sorry, did I understad your correctly?

When the interruption is happened I should start count the ticks of internal timer (3 or 4 or 5 times to calculate the average) and correct the value of the internal timer. Is that correct?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When the interrupt is happened, you should read value of TCNT2 in my example. Or, any else timer that produce your 400Hz.

Sync principle tends to keep this value in the middle of sync range which is in the middle of OCR value.

May I see your Timer code, please.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you don't think the idea in #4 will be suitable, then you can try making the two PWM counters match up (sync).

PWMA will go high at the beginning of the cycle when its timer is zero and go low sometime before timer reaches the max count (thus giving some duty %).

When PWMA goes high, PWM B timer should have the same count (zero).

So merely set a rising edge irq for PWMA going into B.  When that IRQ happens on device B, set timer B value to zero. ...then the timebases will have the same count (neglecting the small amount of time it takes to do so).  You could even add a small offset to account for the delay, say use 5 counts (for example) rather than zero.

This is crude, but might be plenty good enough for your purpose.  In this method if PWMA is turned off PWMB will continue on (different than idea #4).

Try both ways, see what you like, they each can be put in place in a few minutes.

You will certainly want to see both waves on your scope to look for proper operation and ascertain if jitter is acceptable.

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Thu. May 12, 2022 - 08:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

unfortunately, you don't write what controller you use.
If it has an event system, there are other synchonisations possible - eg. to generate a restart signal.
You should describe how much jitter and synchroizity you need.

If you synchronize your clock-in signal with your 400Hz ref. then once you synchronized your timers, it's done.
I used an own (sampling) PLL with a VCXO from SItime ( SiT3808 ) and a fast switch (ADG701L).
With a XOR you can provide the short pulses from both reference edges.
This works fine if your reference signal stems from an accurate crystal.
If you are interested, I can supply more info on that.

Amazingly, as soon as you're doing it right, it works!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My example suits well for 1Hz (64Hz, to be precise), where own X-clock is 32kHz and TCNT2 is 0...63 to made 64Hz (a sync is on 15.6ms timeframe). But, yes, it can be done more radical, external interrupt can restart own counter (either CTC or PWM).

 

It depends on requirements. In case of my clock, no sudden sync was allowed, to eliminate incorrect time. Total sync is over several seconds, one minute max.

 

To resume: either brute force, or soft solution, take your choice.