gonium.net » interrupt http://gonium.net/md so much time, so little to do. Sat, 11 Sep 2010 16:42:09 +0000 en hourly 1 http://wordpress.org/?v=3.0.1 I will think before I code… http://gonium.net/md/2006/12/27/i-will-think-before-i-code/ http://gonium.net/md/2006/12/27/i-will-think-before-i-code/#comments Wed, 27 Dec 2006 09:54:04 +0000 md http://gonium.net/md/2006/12/27/i-will-think-before-i-code/ #include < avr / io.h > #define INIT_TIMER_COUNT 6 #define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT int ledPin = 13; [...]]]> CosineKitty pointed out: My Arduino timer interrupt code did not work because the Prescaler bits were not set correctly. Applying basic boolean logic helps ;-) This is the working code: #include < avr / interrupt.h > #include < avr / io.h > #define INIT_TIMER_COUNT 6 #define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT int ledPin = 13; int int_counter = 0; volatile int second = 0; int oldSecond = 0; long starttime = 0; // Aruino runs at 16 Mhz, so we have 1000 Overflows per second... // 1/ ((16000000 / 64) / 256) = 1 / 1000 ISR(TIMER2_OVF_vect) { RESET_TIMER2; int_counter += 1; if (int_counter == 1000) { second+=1; int_counter = 0; } }; void setup() { Serial.begin(9600); Serial.println("Initializing timerinterrupt"); //Timer2 Settings: Timer Prescaler /64, TCCR2 |= (1< "); Serial.print(millis() - starttime); Serial.println("."); digitalWrite(ledPin, HIGH); delay(100); digitalWrite(ledPin, LOW); oldSecond = second; } } I will think before I code, I will think before I code, I will think before I code, ... The timer now works perfectly. I think the CTC mode will be more efficient, but my measurement shows that the clock has a slight skew (3 ms) when the Arduino starts up (lets say, during the first five minutes). Later, the skew is about zero. So the overflow mechanism is quite exact ;-) Note that the TIMER2 is used for PWM in the Arduino libraries, so this sketch might interfere with PWM applications - I did not test this.]]> http://gonium.net/md/2006/12/27/i-will-think-before-i-code/feed/ 24 Handling external Interrupts with Arduino http://gonium.net/md/2006/12/20/handling-external-interrupts-with-arduino/ http://gonium.net/md/2006/12/20/handling-external-interrupts-with-arduino/#comments Wed, 20 Dec 2006 21:11:53 +0000 md http://gonium.net/md/2006/12/20/handling-external-interrupts-with-arduino/ arduino-interrupt.jpg

For my DCF77 clock project, I need an understanding of handling interrupts with the ATMega8 chip – here’s my sketch.

The ATMega8 provides two pins (2 and 3) which can trigger software interrupts when the attached digital signal changes. You can use this to be “notified” when the external signal changes. Therefore, you do not need to poll the pin periodically – the interrupt routine will be invoked automatically when the specified signal change happens.

In my case, I want to be notified when the DCF77 signal changes, so I need a simple way to exchange the current value of the pin. Here is the sketch:


// Definition of interrupt names
#include < avr/io.h >
// ISR interrupt service routine
#include < avr/interrupt.h >


// LED connected to digital pin 13
int ledPin = 13;
// This is the INT0 Pin of the ATMega8
int sensePin = 2;
// We need to declare the data exchange
// variable to be volatile - the value is
// read from memory.
volatile int value = 0;

// Install the interrupt routine.
ISR(INT0_vect) {
  // check the value again - since it takes some time to
  // activate the interrupt routine, we get a clear signal.
  value = digitalRead(sensePin);
}


void setup() {
  Serial.begin(9600);
  Serial.println("Initializing ihandler");
  // sets the digital pin as output
  pinMode(ledPin, OUTPUT);
  // read from the sense pin
  pinMode(sensePin, INPUT);
  Serial.println("Processing initialization");
  // Global Enable INT0 interrupt
  GICR |= ( 1 < < INT0);
  // Signal change triggers interrupt
  MCUCR |= ( 1 << ISC00);
  MCUCR |= ( 0 << ISC01);
  Serial.println("Finished initialization");
}

void loop() {
  if (value) {
    Serial.println("Value high!");
    digitalWrite(ledPin, HIGH);
  } else {
    Serial.println("Value low!");
    digitalWrite(ledPin, LOW);
  }
  delay(100);
}

In the main loop, the value gets interpreted, but not read. This happens in the interrupt handler routine. The routine is installed with the avrgcc preprocessor macro “ISR” – this way, we do not need to fiddle with the interrupt vector directly. During the setup function, be careful to initialize the ATMega8 correctly – in this case, we need to enable the INT0 interrupt. With the MCUCR register, we can change the way the interrupt gets triggered – here, we receive an interrupt when the signal changes in both directions (HIGH -> LOW and LOW -> HIGH).

The wiring for the testing is rather simple: Use a breadboard and power it from the Arduino. Connect a pull-up resistor to positive and the other end to pin 2 of your Arduino. Connect an additional cable from the “other end” of the resistor to negative. If you pull the latter cable from negative, the current on pin 2 will go to HIGH, if you reconnect it to negative, it will go to LOW. You could also use a switch, of course ;-)

If you speak german, I highly recommend the “AVR-GCC Tutorial” of mikrocontroller.net.

]]>
http://gonium.net/md/2006/12/20/handling-external-interrupts-with-arduino/feed/ 10