Arduino Nano Timer 1 interrupt example for 100 Hz sampling

100 Hz sampling using Timer 1 interrupt

//
// Arduino Nano interrupt example
// This program uses the Timer 1 interrupt to implement
// 100 Hz sampling on pin A0. The Timer 1 interrupt service
// routine reads a sample from A0, then prints it out over
// the serial connection to the PC.
//  
// Written by Ted Burke 4-Apr-2022
//

// Timer 1 interrupt service routine (ISR)
ISR(TIMER1_COMPA_vect)
{
  Serial.println(analogRead(0)); // Sample voltage on pin A0
}

void setup()
{
  Serial.begin(9600); // Serial connection to print samples
  
  cli(); // disable interrupts during setup

  // Configure Timer 1 interrupt
  // F_clock = 16e6 Hz, prescaler = 64, Fs = 100 Hz
  TCCR1A = 0;
  TCCR1B = 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10;
  TCNT1 = 0;          // reset Timer 1 counter
  // OCR1A = ((F_clock / prescaler) / Fs) - 1 = 2499
  OCR1A = 2499;       // Set sampling frequency Fs = 100 Hz
  TIMSK1 = 1<<OCIE1A; // Enable Timer 1 interrupt

  sei(); // re-enable interrupts
}

void loop()
{
  // Let the ISR do all the work
}

100 Hz sampling with moving average

//
// Arduino Nano interrupt example
// Calculates moving average of last N analog samples on pin A0
//
// Written by Ted Burke 6-Apr-2022
//

// Allocate a sample buffer to store N samples
const int N = 4;
int s[N] = {0};
int n = 0; // used as an index variable for the sample buffer

//
// This is the Timer 1 interrupt service routine (ISR).
// This ISR is triggered every 10 ms (i.e. 100 Hz) by Timer 1.
// Each time it is called, it takes a sample from pin A0,
// stores it to the sample buffer (array s[]) and calculates
// the average of all N samples in the buffer.
// For debugging purposes, it prints out the raw samples
// and the moving average, but this would presumably be
// removed in production code, because it's time consuming.
//
ISR(TIMER1_COMPA_vect)
{
  int average;

  // Increment sample number, but reset to 0 when it reaches N
  // Note that "%" is the modulo operator in C
  n = (n + 1) % N;

  // Sample the voltage on pin A0 and store to the nth element of array s
  s[n] = analogRead(0);

  // Calculate average of all N samples in array s
  average = 0;
  for (int m=0 ; m<4 ; ++m) average += s[m]; 
  average = average / N;

  // Print out the latest sample and the average of the last N samples
  Serial.print(s[n]);      // most recent sample
  Serial.print(" ");       // print space between values
  Serial.println(average); // average of last N samples
}

void setup()
{
  Serial.begin(9600); // Serial connection to print samples
  
  cli(); // disable interrupts during setup

  // Configure Timer 1 interrupt
  // F_clock = 16e6 Hz, prescaler = 64, Fs = 100 Hz
  TCCR1A = 0;
  TCCR1B = 1<<WGM12 | 0<<CS12 | 1<<CS11 | 1<<CS10;
  TCNT1 = 0;          // reset Timer 1 counter
  // OCR1A = ((F_clock / prescaler) / Fs) - 1 = 2499
  OCR1A = 2499;       // Set sampling frequency Fs = 100 Hz
  TIMSK1 = 1<<OCIE1A; // Enable Timer 1 interrupt

  sei(); // re-enable interrupts
}

void loop()
{
  // Let the ISR do all the work
}

Advertisement
This entry was posted in Uncategorized. Bookmark the permalink.

4 Responses to Arduino Nano Timer 1 interrupt example for 100 Hz sampling

  1. Jørgen says:

    This will not work:
     OCR1A = 2499
    because ORC1A is a 8bit register
    https://timer-interrupt-calculator.simsso.de/ tells me you should use
    1024 as prescaler and 155 for the compare register

  2. Jørgen says:

    Ok, thank for the response. I mixed it up with OCR0A, which is 8 bit. Yes, OCR1A is 16 bit, sorry for the confusion.

  3. batchloaf says:

    No problem. Best of luck getting it working!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s