Go Down

Topic: Using COMPA and COMPB correctly (Read 4 times) previous topic - next topic

johnwasser


Quote
The code in the ISR looks like it stops the timer by setting the control registers to 0.

I wanted to put the counter at least to zero. I again read the datasheet and should have put a zero value to the TCNT1 register and not to TCCR1* control register , right?

Yes.


Quote
Perhaps you should move the code that starts the timer into start() and call it from your external interrupt instead of from setup(). 

I did not know that I started the timer...I thought it would be running anyhow. How can I start and stop it?


The timer starts when you set the Clock Select Bits in TCCR1B to something other than 0.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

soulid

#6
Dec 28, 2012, 10:49 am Last Edit: Dec 28, 2012, 01:05 pm by soulid Reason: 1
Hi,
changed the code as proposed. There is "a" reaction to what I have written, but not as expected. The (red) Interrupt rising line is not very close to the (blue) trigger HIGH expected 20 ticks after. Changing the CompB from 100 to 10.000 (which is intended to increase pulseduration but keeping the rising edge at the same position) changes the rising edge position.
Here is the code and a oscilloscope screenshot (blue line is trigger and red line is interrupt reaction- time/ dev= 50mS):

Code: [Select]
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 13

void setup(){ 
  pinMode(LEDPIN, OUTPUT);
  cli();                    // disable global interrupts
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt channel A:
  TIMSK1 |= (1 << OCIE1B);  // enable timer compare interrupt channel B:
//  TCCR1A = 0;               // set entire TCCR1A register to 0
  TCCR1A = B11110000;      //see table 16-1
  sei();                    // Enable global interrupts
  attachInterrupt(0, start, RISING);
}

void loop(){
OCR1A = 20;            // COMPA
OCR1B = 40;          // COMPB
}

void start(){
  //want to start/ restart the timer here
  TCCR1B |= (1 << CS10);    // prescaler 1- see table 16-5 and (re)start timer1
}

ISR(TIMER1_COMPA_vect){
  digitalWrite(LEDPIN, HIGH);
}

ISR(TIMER1_COMPB_vect){
  digitalWrite(LEDPIN, LOW);
  TCCR1B = 0;  //stop timer here
}
}

johnwasser

The pulses look OK to me.

100-20=80  80/16=5 microseconds.  at 0.5 milliseconds (500 microseconds) per division the pulse would be about 1/100th of a division.

10000-20 = 9980.  9980/16=623 microseconds or a little over 1 division.

I suspect the long delay before triggering is a wrap-around of the timer.  Try resetting more of the registers:
Code: [Select]


#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 13

void setup(){ 
  pinMode(LEDPIN, OUTPUT);
  cli();                    // disable global interrupts
  TCCR1A = 0;               // Clear TCCR1A
  TCCR1B = 0;               // Clear TCCR1B
  TCCR1C = 0;               // Clear TCCR1C
  TCNT1 = 0;                // Clear the timer
  TIMSK1 = 0;               // Clear the interrupt mask
 
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt channel A:
  TIMSK1 |= (1 << OCIE1B);  // enable timer compare interrupt channel B:
  TCCR1A = B11110000;      // Set OC1A/OC1B on Compare Match, clear OC1A/OC1B at BOTTOM
  OCR1A = 20;              // COMPA at 20/16ths microseconds
  OCR1B = 40;              // COMPB at 40/16th microseconds

  sei();                    // Enable global interrupts
  attachInterrupt(0, start, RISING);
}

void loop(){
}

void start(){
  //want to start/ restart the timer here
  TCNT1 = 0;                // Clear the timer
  TCCR1B |= (1 << CS10);    // prescaler=1 16 MHz clock
}

ISR(TIMER1_COMPA_vect){
  digitalWrite(LEDPIN, HIGH);
}

ISR(TIMER1_COMPB_vect){
  digitalWrite(LEDPIN, LOW);
  TCCR1B = 0;  //stop timer here
}
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

soulid

Your code works! Jihaa!  :smiley-mr-green:

I tried several values and found a "base delay" of abput 12.5us meaning that there is no Interupt control below that. From that value on the control works , but I can live with that.

Thank you for your brilliant help!

johnwasser


Your code works! Jihaa!  :smiley-mr-green:

I tried several values and found a "base delay" of abput 12.5us meaning that there is no Interupt control below that. From that value on the control works , but I can live with that.

Thank you for your brilliant help!


The digitalWrite() function takes a while and probably explains much of your 12.5 microsecond delay.  You can get faster response using direct port access.  On the UNO, Pin 13 is PORTB bit 5.  (See: https://spreadsheets.google.com/spreadsheet/pub?key=0AtfNMvfWhA_ccnRId19SNmVWTDE0MEtTOV9HOEdQa0E&gid=0

To set it HIGH:
Code: [Select]
PORTB |= 0b00100000;
To set it LOW:
Code: [Select]
PORTB &= 0b11011111;
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Go Up