0
unsigned long Htime;
unsigned long Ltime;
unsigned long Ttime;
unsigned long f;
int N;


void setup() {
  // put your setup code here, to run once:
cli();      
  TCNT2 = 0;
  TCCR2A = 0;
  TCCR2B = 0;
  Serial.begin(9600);
  pinMode(5,INPUT);
  pinMode(3,OUTPUT);
  pinMode(11,OUTPUT);
  TCCR2A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM21) | (1 << WGM20);
  TCCR2B = (1 << WGM22) | (1 << CS22) | (1 << CS21) | (1 << CS20);
  TIMSK2 = (1 << OCIE2A);   
}


void loop() {
  // put your main code here, to run repeatedly:
  Htime = pulseIn(5, HIGH);
  Ltime = pulseIn(5, LOW);
  Ttime = Htime + Ltime;
  f = 1000000 / Ttime;
  Serial.println(f);
  N = (16000000 / 1024 / f ) - 1;
  OCR2A = N;
  OCR2B = N/2;

}

Hi this is what i have written. and i need output a square wave with timer, its frequency is measured from input signal in pin 5. After connecting the oscilloscope, i see the problem, there is phase shift between 2 signals. enter image description hereHow could i synchronize this 2 signals?(rising edge to rising edge, falling edge to falling edge) Thank u so much for your help!

  • You assume a 1:1 HIGH-LOW ratio for your square output, correct? With that assumption you can get rid of the unsure location of the rising edge. – DataFiddler Oct 23 at 16:26
  • move the println after the OCR settings – Juraj Oct 23 at 17:36
  • The signal at CH1 is an external signal, right? – Sim Son Oct 23 at 18:32
  • the top signal has a rising edge of almost 5 ms .... how do you expect to synchronize that? – jsotola Oct 23 at 18:32
  • I haven't fully understood what you want to achieve, but you can clear TCNT2 on a falling edge of the CH1 to synchronize them – Sim Son Oct 23 at 18:34
1

Given that only the falling edge of your input is sharp and well defined, I suggest the following approach:

  • Use the input-capture feature of Timer 1 to get a timestamp on the falling edge and trigger an interrupt.

  • In the ISR, start by toggling the output in order to set it low. Then compute the period of the signal (timestamp of this falling edge minus timestamp of the previous one) and program a compare register to trigger a compare match event after half a period.

  • The compare match would automatically toggle the output pin again, by using the “toggle on compare match” timer output mode.

The following program attempts to implement this approach. Note that it is completely untested. Input is on pin 8 (i.e. PB0 and ICP1). Output is on pin 9 (i.e. PB1 and OC1A). The timer is set to run at F_CPU/8 in order to accommodate frequencies as low as about 30.1 Hz. A different prescaler should be used if lower frequencies are needed. The program does not rely on the Arduino core, and thus defines its own main() instead of setup() and loop().

ISR(TIMER1_CAPT_vect)
{
    TCCR1C = _BV(FOC1A);  // force output compare -> toggle output
    static uint16_t last_capture;
    uint16_t capture = ICR1;
    uint16_t period = capture - last_capture;
    last_capture = capture;
    OCR1A = capture + period/2;  // compare match after 1/2 period

    // If output is high, toggle again.
    if (bit_is_set(PINB, PB0))
        TCCR1C = _BV(FOC1A);
}

int main()
{
    // Set OC1A = PB1 = digital 9 as output.
    DDRB = _BV(PB1);

    // Configure Timer 1.
    TCCR1A = _BV(COM1A0);  // toggle OC1A on compare match
    TCCR1B = _BV(CS11);    // clock at F_CPU/8
    TCCR1C = _BV(FOC1A);   // force output compare -> toggle output
    TIFR1  = _BV(ICF1);    // clear capture flag
    TIMSK1 = _BV(ICIE1);   // enable capture interrupt
    sei();

    for (;;) {}
}
  • thank u so much, this code works perfect. And now i need to transform this square wave to sine wave. I tried set PB2 to change duty cycle and use RC-filter, but when i writte DDRB = _BV(PB2) and OCR1B = ... in programme then can't even get the square wave.why happens that? – Xtasy1988 Nov 4 at 15:51

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.