Timer value and pulse width produced.

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

 

Hi All,

 

I am using ATmega1608(28 pin). I am trying to produce a pulse width in the range of 1us-20us using singleshot mode of Timer B. Singleshot mode works fine i.e it is producing the pulse when the event occurs on it. The issue I am facing here is that the pulse width is not matching the CCMP value I am putting in the singleshot function. My CLK_MAIN is 20MHz internal oscillator, CLK_PER is 3.3MHz(this is timer B frequency). Below excel sheet snapshot shows the pulse width error as seen on scope. I am also posting my timer B configuration for help.

 

void timer_init()
{
    TCB1.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc | TCB_ASYNC_bm;
    TCB1.EVCTRL = TCB_FILTER_bm | TCB_CAPTEI_bm;
}
void timer_singleshot(int pulse)
{
    if(!TCB1.CTRLA)
    {
        timer_init();
    }
    else
    {  
        // ***** If counter is not running , the wait for atleast one pulse to start ***** //
        while(!(TCB1.STATUS & TCB_RUN_bm));
        // ***** If counter is running, wait for pulse to end ***** //
        while(TCB1.STATUS & TCB_RUN_bm);      //wait for count to stop
    }
    // ***** Disabling the module ***** //
    TCB1.CTRLA = 0;
    
    // ***** writing top to cnt  ***** //
    TCB1.CNT = TCB1.CCMP = pulse;
    
    // ***** Starting the timer module and 3.3MHz clk ***** //
    TCB1.CTRLA |= TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;
}

 

 

This topic has a solution.
Last Edited: Mon. Sep 26, 2022 - 03:30 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Your code is incomplete and I couldn't get it to work.
So I modified the code and tested it.
The code below successfully generates a pulse of 300ns and 3us.

 

#include <avr/io.h>

void timer_init(void){
    TCB1.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc;
    TCB1.EVCTRL = TCB_CAPTEI_bm;
}

void timer_singleshot(int pulse){
    while(TCB1.STATUS & TCB_RUN_bm);
    TCB1.CTRLA = 0;
    TCB1.CNT = TCB1.CCMP = pulse;
    TCB1.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;
    TCB1.CNT = 0;
}

int main(void){
    timer_init();
    timer_singleshot(1);
    timer_singleshot(10);
    while (1){}
}

 

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

.

Last Edited: Wed. Sep 21, 2022 - 08:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sanka1p wrote:

kabasan wrote:

Your code is incomplete and I couldn't get it to work.
So I modified the code and tested it.
The code below successfully generates a pulse of 300ns and 3us.

 

#include <avr/io.h>

void timer_init(void){
    TCB1.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc;
    TCB1.EVCTRL = TCB_CAPTEI_bm;
}

void timer_singleshot(int pulse){
    while(TCB1.STATUS & TCB_RUN_bm);
    TCB1.CTRLA = 0;
    TCB1.CNT = TCB1.CCMP = pulse;
    TCB1.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;
    TCB1.CNT = 0;
}

int main(void){
    timer_init();
    timer_singleshot(1);
    timer_singleshot(10);
    while (1){}
}

 

Why you do not have ASYNC update ON in CTRLB? The program I posted is completely working for me expect the pulse width issue.

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

Sanka1p wrote:

Why you do not have ASYNC update ON in CTRLB? The program I posted is completely working for me expect the pulse width issue.

 

I don't understand why you need ASYNC.
I just stripped the code down to the bare minimum.

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

To respond to event as fast as possible. 

Last Edited: Thu. Sep 22, 2022 - 02:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your post and code are incomplete, so I wasn't sure if you were using events.
I have provided minimal and complete code where the one shot timer outputs the correct time.
Please refer to what is different from your code.
It seems that this is all I can do.

 

Good luck

Last Edited: Thu. Sep 22, 2022 - 02:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kabasan wrote:

Your code is incomplete and I couldn't get it to work.
So I modified the code and tested it.
The code below successfully generates a pulse of 300ns and 3us.

 

#include <avr/io.h>

void timer_init(void){
    TCB1.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc;
    TCB1.EVCTRL = TCB_CAPTEI_bm;
}

void timer_singleshot(int pulse){
    while(TCB1.STATUS & TCB_RUN_bm);
    TCB1.CTRLA = 0;
    TCB1.CNT = TCB1.CCMP = pulse;
    TCB1.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;
    TCB1.CNT = 0;
}

int main(void){
    timer_init();
    timer_singleshot(1);
    timer_singleshot(10);
    while (1){}
}

 

Used this, I am getting a double pulse glitch. I have explained this glitch in more detail here " https://www.avrfreaks.net/forum/... ". Your function is giving me exact time pulse but glitch is also there. when I use ASYNC bit, the glitch goes away but my pulse width is wider than expected.

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

I cannot reproduce your problem.

 

There are tricks to getting good advice.
It is to post code that satisfies the following three conditions.
1, Buildable.
2, Your problem can be reproduced.
3, be as minimal as possible.

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


In regards to your ASYNC question, I've had the chance to use scopes and just observed them.

I don't use the event system in my example, so it's easy to guess what the culprit is there.

I ran it at 10MHz to make the ticks easier to read.

 

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

Starting with TCB1.CNT = 0 results in correct single-shot time.

 

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

If started by the event system, it takes one extra clock to stop. (as the datasheet says)

 

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

When ASYNC is enabled, the output turns on immediately, but adds 2 clocks to the event synchronization delay and 2 clocks to the TCB start delay.

 

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

Enabling FILTER adds 3 clock periods as additional samples.

 

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

As a result, 8 clocks are added to the specified single shot time.

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


Added observations.

Output waveform when event duration is too short.

 

Is this the glitch you're talking about?

 

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


kabasan wrote:

Added observations.

Output waveform when event duration is too short.

 

Is this the glitch you're talking about?

 

No this is not the glitch I am talking about. The glitch is a double pulse produced by timer. I am attaching a scope plot of what a glitch looks like. The fourth rising pulse from left is glitch pulse here.

 

 

 

This is what my timer_singleshot function looks right now when I see this glitch while writing a new compare value in the timer function.

 

 

void timer_init()

{

    TCB1.CTRLB = TCB_CCMPEN_bm | TCB_CNTMODE_SINGLE_gc;

    TCB1.EVCTRL= TCB_FILTER_bm | TCB_CAPTEI_bm;

}

 

void timer_singleshot(int pulse)

{

    if(!TCB1.CTRLA)

    {

        timer_init();

    }

    else

    {  

        // ***** If counter is not running , the wait for atleast one pulse to start ***** //

        while(!(TCB1.STATUS & TCB_RUN_bm));

        

        // ***** If counter is running, wait for pulse to end ***** //

        while( TCB1.STATUS & TCB_RUN_bm );      //wait for count to stop

    }

    // ***** Disabling the module ***** //

    TCB1.CTRLA = 0;

    

    // ***** writing top to cnt  ***** //

    TCB1.CNT =  TCB1.CCMP = pulse;

    

    // ***** Starting the timer module and 3.3MHz clk ***** //

    TCB1.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;

    

    

}

 

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

Is that so.
I can't give you any advice because I can't reproduce it.

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

Has OP ever posted a >>complete<< test program that demonstrates the symptoms?  I can only speculate that there are other forces at work.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.