Pages: [1]   Go Down
Author Topic: Serial.print() and interference with other interrupts  (Read 776 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 4
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I am testing some code that implements pin change interrupts, and as I do so I notice that what worked in Arduino-022 no longer works in Arduino 1.0.  That is, my interrupt code contains a lot of Serial.print() and println() statements.  At some random point fairly early in my tests, the Arduino seems to lock up.  This means that the Serial data that I had been sending to analyze my interrupt code is no longer being sent, and the flashing of LED pin 13 no longer takes place, either.  It is as if the CPU is deadlocked, it seems to me.

What sort of interference can I expect with interrupt code and the Serial.print() method in Arduino 1.0 that was not there in Arduino-022?  I don't understand why it broke.

Below is my code, which uses the PinChangeInt library.  Thanks.

Code:
#define PINMODE
#define FLASH
#include <PinChangeInt.h>

// This example demonstrates a configuration of 3 interrupting pins and 2 interrupt functions.
// All interrupts are serviced immediately, but one of the pins (pin 4) will show you immediately
// on the Terminal.  The other function connected to 2 pins sets an array member that is queried in loop().
// You can then query the array at your leisure.
// This makes loop timing non-critical.

// Pins.  We want to use pins from ports B, C and D.  So choose wisely.  Ports are show in
// this diagram of the ATmega328P chip.  PD0 shows "Port D, pin 0".  PC3 shows "Port C, Pin 3",
// PB2 shows "Port B, pin 2" and so on.  The corresponding Arduino pins are in parentheses.
// So PB2 is Arduino pin D 10, for example.
/*
                  +-\/-+
            PC6  1|    |28  PC5 (AI 5)
      (D 0) PD0  2|    |27  PC4 (AI 4)
      (D 1) PD1  3|    |26  PC3 (AI 3)
      (D 2) PD2  4|    |25  PC2 (AI 2)
 PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
      (D 4) PD4  6|    |23  PC0 (AI 0)
            VCC  7|    |22  GND
            GND  8|    |21  AREF
            PB6  9|    |20  AVCC
            PB7 10|    |19  PB5 (D 13)
 PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
 PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
      (D 7) PD7 13|    |16  PB2 (D 10) PWM
      (D 8) PB0 14|    |15  PB1 (D 9) PWM
                  +----+
*/
// For the Analog Input pins used as digital input pins, and you can use 14, 15, 16, etc.
// or you can use A0, A1, A2, etc. (the Arduino code comes with #define's
// for the Analog Input pins and will properly recognize e.g., pinMode(A0, INPUT);
#define PIN1 2  // port D
#define PIN2 3
#define PIN3 11 // Port B
#define PIN4 12
#define PIN5 A3 // Port C, also can be given as "17"
#define PIN6 A4 // starts and stops the count

uint8_t pins[6]={ PIN1, PIN2, PIN3, PIN4, PIN5, PIN6 };
uint8_t ports[6]={ 0, 0, 0, 0, 0, 0 };

uint8_t latest_interrupted_pin;
uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
uint8_t port;
uint8_t mode;
boolean start=0;

void showMode() {
  switch (mode) {
  case FALLING:
    Serial.print("*F*");
  break;
  case RISING:
    Serial.print("-R-");
  break;
  case CHANGE:
    Serial.print(" C ");
  break;
  }
}

void quicfunc0() {
  latest_interrupted_pin=PCintPort::arduinoPin;
  mode=PCintPort::pinmode;
  showMode();
  if (start==1) {
    interrupt_count[latest_interrupted_pin]++;
  }
  Serial.print("0p"); Serial.print(latest_interrupted_pin, DEC); Serial.print("-P");
  Serial.println(digitalPinToPort(latest_interrupted_pin), DEC);
  if (start !=1) Serial.println("...off, not counted.");
};

void quicfunc1() {
  latest_interrupted_pin=PCintPort::arduinoPin;
  mode=PCintPort::pinmode;
  showMode();
  if (start==1) {
    interrupt_count[latest_interrupted_pin]++;
  }
  Serial.print("1p"); Serial.print(latest_interrupted_pin, DEC); Serial.print("-P");
  Serial.println(digitalPinToPort(latest_interrupted_pin), DEC);
  if (start !=1) Serial.println("...off, not counted.");
};

void quicfunc2() {
  latest_interrupted_pin=PCintPort::arduinoPin;
  mode=PCintPort::pinmode;
  showMode();
  if (start == 1) {
    Serial.println("STOP! ...not counted.");
    start=0;
  } else {
    start=1;
    interrupt_count[latest_interrupted_pin]++;
    Serial.print("START! 2p");
    Serial.print(latest_interrupted_pin, DEC); Serial.print("-P");
    Serial.println(digitalPinToPort(latest_interrupted_pin), DEC);
  }
};

uint8_t i;
void setup() {
  for (i=0; i < 7; i++) {
    pinMode(pins[i], INPUT); digitalWrite(pins[i], HIGH);
    ports[i]=digitalPinToPort(pins[i]);
    switch (pins[i]) {
    case PIN1:
    case PIN3:
        PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING);
    break;
    case PIN2:
    case PIN4:
        PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING);
    break;
    case PIN5:
        PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE);
    break;
    case PIN6:
        PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING);
    break;
    }
  }
  Serial.begin(115200);
  Serial.println("---------------------------------------");
}

void loop() {
  uint8_t count;
  Serial.print(".");
  delay(1000);
  for (i=0; i < 20; i++) {
    if (interrupt_count[i] != 0) {
      count=interrupt_count[i];
      interrupt_count[i]=0;
      Serial.print("Count for pin ");
      if (i < 14) {
        Serial.print("D");
        Serial.print(i, DEC);
      } else {
        Serial.print("A");
        Serial.print(i-14, DEC);
      }
      Serial.print(" is ");
      Serial.println(count, DEC);
    }
  }
}
« Last Edit: February 16, 2012, 01:42:38 am by GreyGnome » Logged

Fort Lauderdale, FL
Offline Offline
Faraday Member
**
Karma: 71
Posts: 6144
Baldengineer
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

In 1.0 Serial.print() became asynchronous.  In previous version print() was a blocking call.  Sounds like an interaction between the two.  However, since Interrupt routines should be kept as short as possible, you might try not using Serial.print at all.

Quote
This means that the Serial data that I had been sending to analyze my interrupt code is no longer being sent, and the flashing of LED pin 13 no longer takes place, either.  It is as if the CPU is deadlocked, it seems to me.
Based on the code you posted, I either agree or disagree with this.
Logged

Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.c

Global Moderator
Melbourne, Australia
Online Online
Brattain Member
*****
Karma: 511
Posts: 19315
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That is, my interrupt code contains a lot of Serial.print() and println() statements.

You got away with it for a while. Not any more.

Interrupt code is supposed to be really quick. Doing Serial.print doesn't fall into that category.
Logged

http://www.gammon.com.au/electronics

Please post technical questions on the forum - not to me by personal message. Thanks a lot.

0
Offline Offline
Jr. Member
**
Karma: 4
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


You got away with it for a while. Not any more.

Interrupt code is supposed to be really quick. Doing Serial.print doesn't fall into that category.

 smiley-cool  I thought I was working incognito.  Thanks for the reply, I will figure out a new way to do it.
Logged

Pages: [1]   Go Up
Jump to: