dhorton668
Published © CC BY-SA

Pardon Me for Interrupting (Part Deux)

You've conquered timer interrupts in Pardon Me, part 1. Now, keep that timer synced to an external source with pin change interrupts.

IntermediateFull instructions provided231
Pardon Me for Interrupting (Part Deux)

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
LED (generic)
LED (generic)
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×1

Hand tools and fabrication machines

Microchip ATmega328P data sheet

Story

Read more

Schematics

External LED

How to attach the external LED.

LED and Switch

Adding a momentary push-button switch.

Self-Triggering Sync

Attaching output to input.

Code

Sync'd LEDs using timer and pin change interrupts.

Arduino
A demonstration sketch for setting up interrupts on the ATmega328.
/*
 * Flash an LED two different ways. One with delay() and one with timer interrupts.
 * The interrupt driven LED is kept in sync using pin change interrupts.
 */

#define LED 9
#define BUTTON 7

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  
  // Disable interrupts while things are being set up.
  cli();

  // Set up Timer/Counter Control Registers. See ATmega328P data sheet section 15.11 (Remember, bits are numbered from zero.)
  TCCR1A = B00000000;  // All bits zero for "normal" port operation. 
  TCCR1B = B00001100;  // Bit 3 is Clear Timer on Compare match (CTC) and bit 2 specifies a divide by 256 prescaler.
  TIMSK1 = B00000010;  // Bit 1 to raise an interrupt on timer Output Compare Register A (OCR1A) match.
  OCR1A = 62500;       // Counter compare match value. 16MHz / prescaler * delay time (in seconds.)
   
  // Set up Pin Change Interrupt Control Registers to detect incoming transitions.
  PCICR = B00000100;   // Enable only PCINT2 (PCINT23..16 or Arduino pins D0..D7).
  PCMSK2 = B10000000;  // Enable only INT23 (Arduino D7 pin).

  // Reenable the interrupts 
  sei();
}

void loop() {
  digitalWrite(LED, LOW);
  delay(1000);
  digitalWrite(LED, HIGH);
  delay(1000);
}

// Interrupt handler for timer match.
ISR(TIMER1_COMPA_vect)
{
  // Access pin 13 directly performing an XOR on Port B (digital pins 8 - 13).
  // Same as "digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN))"
  PORTB ^= B00100000;  // Toggle bit 5, which maps to pin13.
}

// Interrupt handler for pin change.
ISR(PCINT2_vect)
{
  // To ensure the incoming bit is sampled in the middle for a more accurate reading, the timer counter
  // should be at the middle of its maximum value when the pin change happens. The digital counter is
  // extremely accurate, so speeding or slowing its frequency is not needed so much as simply ensuring
  // the counter is at 1/2 its maximum value when the pin change interrupt occurs.
  TCNT1 = OCR1A >> 1; 
}

Credits

dhorton668
4 projects • 5 followers
Contact

Comments

Please log in or sign up to comment.