Pages: [1] 2   Go Down
Author Topic: Timer programming  (Read 2976 times)
0 Members and 1 Guest are viewing this topic.
Pisa - Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,
I'm new on Arduino and I'm trying to program TIMER2 for a fast pulse output.
This is the code:
Code:
unsigned int n;
byte m;

void setup()
{
  pinMode(13,OUTPUT); 
  PORTB&=~32;
  m=1;
  cli(); 
  TCCR1B= 0x00;
  TCCR0B= 0x00; //stop   
  TCCR2B= 0x00;
 
  TCNT0= 0x00; 
 
  OCR2A= 10;   //  16 MHz clock - prescaler=1
  OCR2B= 54;
   
  TCCR2A= 0x00;
 
  n=0;

  TIMSK0= 0;
  TIMSK1= 0;
  TIMSK2= 6;    // timer2 output compare A & B match enabled
  TCCR2B= 1;    // start timer2 - prescaler=1
 
  EIMSK=0;

  sei();
}


ISR(TIMER2_COMPA_vect)
{
    PORTB|=32;     
}

ISR(TIMER2_COMPB_vect)
{
    PORTB&=~32;     
}

void loop()
{
  while (n==0) {}
  n=0;
}


the problem is changing OCR2A and OCR2B values I've no variation in pulse width output on pin 13 (PORTB.5) .
I'm sure timer's ISR is call and works because I have a pulse output on pin 13, but the width is costantly about 1.8uS not depending from the value  OCR2B-OCR2A.
I need some help ...
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What's the role of n and m ?
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Why do you use 32 instead of 8?

What values have you tried?

Did you see this?

"The Output Compare unit can be used to generate interrupts at some given time. Using the Output
Compare to generate waveforms in Normal mode is not recommended, since this will
occupy too much of the CPU time."

Why not don't you use a CTC mode?

Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Pisa - Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, n and m haves no rule, are variables of a previous program .

If I understand well the question, value 32 on PORTB set pin 13. I think it doesn't matter which one is the bit I toggle, pin 13 or another.  I know programming timer for fast interrupt, occupy lot of CPU time but if all the CPU job is made by ISR, that is the faster and more precise timing we can obtain and It's what I need. In my real program ISR should update a 16bit DAC, in this code I just set pin 13 for checking the timing on oscilloscope. I haven't tried CTC mode because I don't need really to toggle a bit on a port, I need to update some port and toggle few bits in the interrupt service rountine. But I can't understand why this program doesn't works. I can suppose Arduino compiler puts some extra code on mine but I can't find any confirm to this supposition.
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm new on Arduino and I'm trying to program TIMER2 for a fast pulse output.

I would propose a slightly different structure to your approach: use a timer overflow to set (or clear) the output pin and use the ch A or B to clear (or set) the output pin.

Something like this:

Code:
void tmr2_init(void) {
  //configure the timer
  //enable timer interrupts but not yet global interrupt
}

#define tmr2a_setdc(dc) OCR2A = (dc) //set ch a duty cycle

ISR(TIMER2_COMPA_vect) {
  //clear output pin
}

ISR(TIMER2_OVF_vect) {
  //set output pin
}

void setup(void) {
  //initialize the pins
  tmr2_init(); //reset the timer
  tmr2a_setdc(23); //ch a duty cycle to 23/256%
  interrupts(); //enable global interrupt
}

void loop(void) {
  //do something
  //change the duty cycle if desired
}

You can potentially pass the prescaler to tmr2_init(). With this approach, you can easily build up your library and duplicate it to tmr0/tmr1.
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
In my real program ISR should update a 16bit DAC

If that's the goal, AVR's adc module can be set up to be triggered automatically and periodically. It is fairly easy to set up. I can post a piece of code there if you want.
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If that's the goal, AVR's adc module can be set up to be triggered automatically and periodically. It is fairly easy to set up. I can post a piece of code there if you want.

DAC != ADC...

If I understand well the question, value 32 on PORTB set pin 13. I think it doesn't matter which one is the bit I toggle, pin 13 or another.  I know programming timer for fast interrupt, occupy lot of CPU time but if all the CPU job is made by ISR, that is the faster and more precise timing we can obtain and It's what I need. In my real program ISR should update a 16bit DAC, in this code I just set pin 13 for checking the timing on oscilloscope. I haven't tried CTC mode because I don't need really to toggle a bit on a port, I need to update some port and toggle few bits in the interrupt service rountine. But I can't understand why this program doesn't works. I can suppose Arduino compiler puts some extra code on mine but I can't find any confirm to this supposition.

What you did with the 32 was set and reset 4 bytes. Not the port.

If you want to set or reset bits in the Arduino faster, this is the way.
Code:
//setting
PORTB |= 1 << 5;

//clearing
PORTB &= ~(1 << 5);

PORTB 5 is pin 13 in ARduino.

To toggle a pin:

Code:
PORTB ^= 1 << 5;

But how does this relate to a DAC???
Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What you did with the 32 was set and reset 4 bytes.

32 = 1 << 5.

So his code is setting / clearing a particular pin, and is identical to your code.

Quote
But how does this relate to a DAC???

For debugging purposes. He is trying to try to the code so it flips a pin - to be observed by a scope that signals that the timing portion of the code is working. He can then add the DAC portion of the code.

A fairly common way to build up and debug one's code.
Logged

'round the world...
Offline Offline
Faraday Member
**
Karma: 42
Posts: 3287
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

For debugging purposes. He is trying to try to the code so it flips a pin - to be observed by a scope that signals that the timing portion of the code is working. He can then add the DAC portion of the code.

A fairly common way to build up and debug one's code.

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?
And, most importantly, if the timing part underestimates the load that driving the DAC will have on the program, then all this is useless. First, test the DAC, see how fast can the Arduino drive it without timings and then worry about triggering the times at a rate the arduino can handle. Since no PWM is really needed, go for the simplest timing arrangement, with an overflow or with an Clear to count and overflow to better adjust the desired frequency.

Logged

Eu não sou o teu criado. Se respondo no fórum é para ajudar todos mediante a minha disponibilidade e disposição. Responder por mensagem pessoal iria contra o propósito do fórum e por isso evito-o.
Se realmente pretendes que eu te ajude por mensagem pessoal, então podemos chegar a um acordo e contrato onde me pagas pela ajuda que eu fornecer e poderás então definir os termos de confidencialidade do meu serviço. De forma contrária toda e qualquer ajuda que eu der tem de ser visível a todos os participantes do fórum (será boa ideia, veres o significado da palavra fórum).
Nota também que eu não me responsabilizo por parvoíces escritas neste espaço pelo que se vais seguir algo dito por mim, entende que o farás por tua conta e risco.

Dito isto, mensagens pessoais só se forem pessoais, ou seja, se já interagimos de alguma forma no passado ou se me pretendes convidar para uma churrascada com cerveja (paga por ti, obviamente).

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?

Not really sure about the "interrupts keeping the processor busy all the time" part. Interrupts are useful precisely because they do not keep the processor busy - they interrupt the processor only when certain conditions are met.

Quote
And, most importantly, if the timing part underestimates the load that driving the DAC will have on the program, ...

I do not know how the DAC part is to be implemented. The DAC could be really fast - a parallel DAC for example, or it could be preloaded by the main loop and strobed / activated by the isr. It could be implemented without causing excessive delays in the isr, rendering your question moot.

Quote
First, test the DAC, ...

Different ways of skinning the cat. Without knowing all the details, it is impossible to assert if one approach is better than another.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?

Not really sure about the "interrupts keeping the processor busy all the time" part. Interrupts are useful precisely because they do not keep the processor busy - they interrupt the processor only when certain conditions are met.

Interrupts _can_ keep the processor busy. If they fire too frequently and/or take too long, the CPU will have only little time to execute loop() code.
Logged

Pisa - Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm really grateful to everybody for all the comments and the debate, meanwhile, unfortunately, the point of my question is fading away. My trouble is "why this code doesn't works?" I know you could write the code in a different way but this should works and generate a pulse on pin 13 at a frequency of 62.5KHz  (16MHz clock/256 - and it do it exactly) but with a variable pulse width related to the value OCR2B-OCR2A, while the output pulse is about 1.8uS wide for any value of OCR2B and OCR2A I've tested.
 I can't understand why . I'm going to put the same code on Arduino board using GNU Ccompiler, AVRstudio  and ISP to check if I've the same problem. I'll keep you updated.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 495
Posts: 19040
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You lost me here:

Code:
n=0;

...

void loop()
{
  while (n==0) {}
  n=0;
}


This might help:

http://www.gammon.com.au/forum/?id=11504
Logged


Pisa - Italy
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset



Thanks Nick your link is useful for timers programming even if this is not my problem at the moment.
As I say in previous post I've tested the code compiled with WInAVR and put on the same Arduino Uno with ISP .
This is the adapted code
Code:
unsigned int n;
char m;

void setup()
{
  DDRB=255; 
  PORTB&=~32;
  m=1;
  cli(); 
  TCCR1B= 0x00;
  TCCR0B= 0x00; //stop   
  TCCR2B= 0x00;
 
  TCNT0= 0x00; 
 
  OCR2A= 20;   // 
  OCR2B= 40;
   
  TCCR2A= 0x00;
 
  n=0;

  TIMSK0= 0;
  TIMSK1= 0;
  TIMSK2= 6;    // timer2 output compare A & B match enabled
  TCCR2B= 1;    // start timer2 - prescaler=1 - 16 MHz clock
 
  EIMSK=0;

  sei();
}


ISR(TIMER2_COMPA_vect)
{
    PORTB|=32;   
}

ISR(TIMER2_COMPB_vect)
{
    PORTB&=~32;     
}

void main()
{
  setup();
  while (n==0) {}
  n=0;
}
In this case it works fine  and if( OCR2A-OCR2B) > 30  we obtain a pulse width equal to ((OCR2A-OCR2B) * 62.5nS) as it should happens in previous  case. The limit of 30 for OCR2A-OCR2B is probably due to the time for ISR call, the storing and retrieving of registers, ect.
What I would like to know is how Arduino waste all that time and, if is possible, where can I find the assembly code of my C source compiled in Arduino environment ?  What Arduino is doing in "loop() "?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 495
Posts: 19040
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Glad it helped.

My advice is: don't use ISRs if you want accurate timer output. Use the timer hardware.
Logged


Pages: [1] 2   Go Up
Jump to: