Timer Variable

Hi, I have been trying to set the timer constant of OCR1A to the variable Timer_count so that when I change Sfreq it automatically updates Timer_count and hence OCR1A. Does anyone know how to and what kind of variable I set Timer_count to? Many thanks!

#include <SoftwareSerial.h> 
#include <avr/io.h>

int i;
int r_pin = A0;
int sample_output;
int Sfreq = 1000;
unsigned long Timer_count;

void setup (){
  noInterrupts();
  Timer_count = (16*10^6) / (Sfreq*1024) - 1;
  Serial.begin (9600);
  ADCSRA |= (1 << ADPS0) |  (1 << ADPS1) | (1 << ADPS2);  // ADC Prescaler of 128

  //set timer1 interrupt at Sfreq Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = Timer_count;// = (16*10^6) / (Sfreq*Timer Prescaler) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and and CS11 and CS10 bits for prescaler <----
  TCCR1B |= (1 << CS12) | (1 << CS10); //-- 1024
//  TCCR1B |= (1 << CS12);               //-- 256
//  TCCR1B |= (1 << CS11) | (1 << CS10); //-- 64
//  TCCR1B |= (1 << CS11);               //-- 8
//  TCCR1B |= (1 << CS10);               //-- 1

  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

  interrupts();
}  // end of setup

Hi,
Essentially I am trying to make my code print a value from Serial.read() for 1 second and then stop. So i have the COMPA_vect for the timer in printing and the OVF_vect to see if it has reached 1 second or not. Is this the right approach? Please could someone help as the OVF_vect is not working (COMPA_vect is working), many thanks!

Code:

#include <SoftwareSerial.h> 
#include <avr/io.h>

int i;
int r_pin = A0;
int sample_output;
int Sfreq = 1;
unsigned long Timer_count;

void setup (){
//  Timer_count = (16*10^6) / (Sfreq*1024) - 1;
  noInterrupts();
  
  Serial.begin (9600);
  ADCSRA |= (1 << ADPS0) |  (1 << ADPS1) | (1 << ADPS2);  // ADC Prescaler of 128

// ------ For Sampling Frequency ------ //
  //set timer1 interrupt at Sfreq Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 124;// = (16*10^6) / (Sfreq*Timer Prescaler) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS11 and CS10 bits for prescaler <----
//  TCCR1B |= (1 << CS12) | (1 << CS10); //-- 1024
  TCCR1B |= (1 << CS12);               //-- 256
//  TCCR1B |= (1 << CS11) | (1 << CS10); //-- 64
//  TCCR1B |= (1 << CS11);               //-- 8
//  TCCR1B |= (1 << CS10);               //-- 1


  // enable timer COMPARE interrupt
  TIMSK1 |= (1 << OCIE1A);

// ----- Timer Overflow ----- //
  TCCR0A = 0;
  TCCR0B = 0;
  
  TCNT0 = 177;                                // preload timer (65536-16MHz/256/10Hz)
  TCCR0B |= (1 << CS00) | (1 << CS02);        // 1024 prescaler 
  TIMSK0 |= (1 << TOIE0);                     // enable timer OVERFLOW interrupt

  interrupts();
}  // end of setup

ISR(TIMER1_COMPA_vect){
//   Serial.println(i);
//   i++;
//  sample_output = analogRead (r_pin);
  Serial.print(i);  
  Serial.print(' ');
  Serial.print(Sfreq);
  Serial.print(' ');
  Serial.println(i);
  i++;
}
ISR(TIMER0_OVF_vect) {
  TCNT0 = 177;
  TIMSK1 ^= (1 << TOIE0);
}
void loop (){
}

For one thing, you cannot print in an ISR.

You shouldn’t be printing in interrupt context, but if you do, you should increase the serial line rate.

However, it’s unclear to me why you’re even considering using a timer interrupt for this purpose.

I am able to print in the ISR, without the overflow it has worked perfectly fine. But now i am simply trying to stop the COMPA via OVF after 1 second

@saaqib_m

Your topic was Moved to it's current location / section as it is more suitable.

Could you also take a few moments to Learn How To Use The Forum.

Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

Wiat.. You just want to print out whatever comes in from Serial.read() for 1 second? What starts the 1 second time? A button? The start of the program?

-jim lee

saaqib_m:
I am able to print in the ISR, without the overflow it has worked perfectly fine.

And it will continue to work fine..... until it doesn't....

There is absolutely NO reason to muck with a timer to accomplish that. Use millis() or micros().

jimLee:
Wiat.. You just want to print out whatever comes in from Serial.read() for 1 second? What starts the 1 second time? A button? The start of the program?

-jim lee

Hi,
Yes. Well let's say for 10 seconds for example. And yes after I start the program

Since I am being told I can’t print inside an ISR, please have a look at this. The first timer is for the ADC conversion time and timer 0 is meant to counter this first timer. I am still working on this but any advice at this early stage would be great thanks.

#include <SoftwareSerial.h> 
#include <avr/io.h>

int i=0;
int r_pin = A0;
int sample_output;
int Sfreq = 1;
int Timer_count = (16*10^6) / (Sfreq*1024) - 1;
//const byte adcPin = 0;
//volatile int adcReading;
//volatile boolean adcDone;
//boolean adcStarted;


// -------- Functions --------- //
static inline void initTimer1(void) {
  // ------ For Sampling Frequency ------ //
  
  //set timer1 interrupt at Sfreq Hz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = 1245;// = (16*10^6) / (Sfreq*Timer Prescaler) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS12 and CS11 and CS10 bits for prescaler <----
  TCCR1B |= (1 << CS12) | (1 << CS10); //-- 1024
//  TCCR1B |= (1 << CS12);               //-- 256
//  TCCR1B |= (1 << CS11) | (1 << CS10); //-- 64
//  TCCR1B |= (1 << CS11);               //-- 8
//  TCCR1B |= (1 << CS10);               //-- 1
  
  // enable timer COMPARE interrupt
  TIMSK1 |= (1 << OCIE1A);
}

//static inline void initTimer0(void) {
//  // ----- Timer Overflow ----- //
//  TCCR0A = 0;
//  TCCR0B = 0;
//  
//  TCNT0 = 177;                                // preload timer (65536-16MHz/256/10Hz)
//  TCCR0B |= (1 << CS00) | (1 << CS02);        // 1024 prescaler 
//  TIMSK0 |= (1 << TOIE0);                     // enable timer OVERFLOW interrupt
//}
static inline void initADC(void) {
  //cli();
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);    // 128 prescale for 16Mhz
  //ADCSRA |= (1 << ADATE);    // Set this bit to enable trigger source
  ADCSRB |= (1 << ADTS1) | (1 << ADTS2);   // Triggered by Timer/Counter1 overflow
  ADCSRA |= (1 << ADEN);    // Enable the ADC
  ADCSRA |= (1 << ADIE);    // Enable Interrupts 
  ADCSRA |= (1<< ADSC);
  //sei();
}
ISR(TIMER1_COMPA_vect){
  OCR1A = 1245;
  TIMSK1 |= (1 << OCIE1A);
//  sample_output = analogRead (r_pin);
//   Serial.println(i);
//   i++;
//  sample_output = analogRead (r_pin);
}

//ISR(TIMER0_OVF_vect) {
//  TCNT0 = 177;
//  TIMSK1 ^= (1 << TOIE0);
//}

ISR (ADC_vect){
  sample_output = analogRead (r_pin);
}  

int main(void) {
  Serial.begin(9600);
  noInterrupts();           
//  initIOPorts();
  initTimer1();
//  initTimer0();
  initADC();
  interrupts();
  
  Serial.print(sample_output);  
  Serial.print(' ');
  Serial.print(Sfreq);
  Serial.print(' ');
  Serial.println(i);
  i++;
}

No, you are being told that you shouldn’t print in interrupt context.

Well, this does what you say you want.

#include <timeObj.h>

timeObj  theTimer(10000);            // A 10 second timer, starting NOW.

void setup(void) {

  Serial.begin(9600);   // Start the serial stuff.
}


void loop(void) {

   char  aChar;
   
   if (!theTimer.ding()) {   // If the timer has NOT expired..
      if (Serial.available()) {   // If we have a char to read..
         aChar = Serial.read();   // Read the char.
         Serial.print(aChar);   // Write the char.
      }
   }
}

Grab LC_baseTools from the library manager to get this to compile.

-jim lee

Similar to Jim's code above my tutorial on How to write Timers and Delays in Arduino has examples using the millisDelay class to do these types of timers.

jimLee:
Well, this does what you say you want.

#include <timeObj.h>

timeObj  theTimer(10000);            // A 10 second timer, starting NOW.

void setup(void) {

Serial.begin(9600);   // Start the serial stuff.
}

void loop(void) {

char  aChar;
 
  if (!theTimer.ding()) {   // If the timer has NOT expired…
     if (Serial.available()) {   // If we have a char to read…
        aChar = Serial.read();   // Read the char.
        Serial.print(aChar);   // Write the char.
     }
  }
}




Grab LC_baseTools from the library manager to get this to compile.

-jim lee

Hi Jim, thank you for your response. Do you know how I would be able to combine this with my ISR_COMPA_vect to make it stop after a certain amount of time? Many thanks.

It does stop after a certain amount of time already.

-jim lee

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.