Interrup change

I found this great piece of code by Geert Langereis, see below.

This code reads only analog pins using interrupts. My project needs to read both analog and digital pins. I'm newbie so i have no idea how to modify this. His code looks much simpler than other interrupt codes i have seen.

Pin Change Interrupt on Arduino

http://www.geertlangereis.nl/Electronics/Pin_Change_Interrupts/PinChange_en.html

If you need more pins, or other physical pins, there is a mechanism to generate an interrupt when any pin is changed in one of the ports of 8 bits. You don't know which single bit, but only which port. The example below generates an interrupt when one of the ADC0 to ADC5 pins (used as a digital input) is changed. In that case, the interrupt service routine ISR(PCINT1_vect) is called. In the routine you can figure out which of the specific pins within that port it has been.
First, the Pin Change Interrupt Enable flags have to be set in the PCICR register. These are bits PCIE0, PCIE1 and PCIE2 for the groups of pins PCINT7..0, PCINT14..8 and PCINT23..16 respectively. The individual pins can be enabled or dsiabled in the PCMSK0, PCMSK1 and PCMSK2 registers. In the Arduino circuit, in combination with the Atmel Atmega328 datasheet, you can figure out that the PCINT0 pin corresponds to pin 0 in port B (called PB0). This is pin 14 on the DIL version of the chip and digital pin 8 on the Arduino Uno. Another example is pin A0 on the Arduino board, which can be used as a digital input like in the example below. It is pin 23 on the Atmega328 (DIL version) which is called ADC0. The datasheet shows that it is PCINT8 which means it is part of PCINT14..8 and therefore enabled by the bit PCIE1 in PCICR.

void setup()
{
  Serial.begin(9600);
  Serial.println("Boe");
  InitialiseIO();
  InitialiseInterrupt();
}

void loop() {
  /* Nothing to do: the program jumps automatically to Interrupt Service Routine "blink"
   in case of a hardware interrupt  */
}  

void InitialiseIO(){
  pinMode(A0, INPUT);	   // Pin A0 is input to which a switch is connected
  digitalWrite(A0, HIGH);   // Configure internal pull-up resistor
  pinMode(A1, INPUT);	   // Pin A1 is input to which a switch is connected
  digitalWrite(A1, HIGH);   // Configure internal pull-up resistor
  pinMode(A2, INPUT);	   // Pin A2 is input to which a switch is connected
  digitalWrite(A2, HIGH);   // Configure internal pull-up resistor
}

void InitialiseInterrupt(){
  cli();		// switch interrupts off while messing with their settings  
  PCICR =0x02;          // Enable PCINT1 interrupt
  PCMSK1 = 0b00000111;
  sei();		// turn interrupts back on
}

ISR(PCINT1_vect) {    // Interrupt service routine. Every single PCINT8..14 (=ADC0..5) change
            // will generate an interrupt: but this will always be the same interrupt routine
  if (digitalRead(A0)==0)  Serial.println("A0");
  if (digitalRead(A1)==0)  Serial.println("A1");
  if (digitalRead(A2)==0)  Serial.println("A2");
}

Have a look at Pin Change Interrupts and Pin Change Interrupt library

I'm newbie so i have no idea how to modify this.

Modify it to do what?

Note: Don't do Serial.print in an ISR
See:

Ardunaut:
As far as i know you cant have an analog based interrupt, only digital

Geert code above uses interrupt in analog pins, so i think it should work???

UKHeliBob:
Have a look at Pin Change Interrupts and Pin Change Interrupt library

Thanks for links.

LarryD:
Modify it to do what? Note: Don't do Serial.print in an ISR

I have Uno and i want to log these 3 sensors to sd-card:

Optocoupler (can be used as analog or digital sensor). This changes rarely. When it changes, it changes rapidly for about 1 second on/off/on...

Ordinary momentary switch. Triggered 15 times in 10 seconds (or less) continuously

Analog? digital? Grove - Ear-clip Heart Rate Sensor SeeedStudio MED03212P
http://www.seeedstudio.com/wiki/Grove_-_Heart_rate_ear_clip_kit

Ardunaut:
Any analog pin can be used as digital aswell.

He is using the analog pins, but he is using it like a digital pin, not analog. So there is only HIGH or LOW, YES or NO, 1 or 0.

Thanks. I didn't know that.

Switch and optocoupler can be digital but i'm not sure if Ear-clip Heart Rate Sensor is digital.

How i can log to SD-card? I tried to add SD-card examples to this code but it fails.

It don't need to save all the time. It could save less often, maybe once a minute?

I found another "log to SD-card" example and it failed too.

I know how to log to SD-card in normal Sketches, but since this uses interrupts, i'm clueless.

Please post one of your attempts that failed and explain exactly what happens when you run it.

I tried many different SD-examples. For instance i added all the necessary SD-code from "SD card read/write" example in Arduino IDE to Geert code and then changed this:

if (digitalRead(A0)==0) Serial.println("A0");

to this:

if (digitalRead(A0)==0) myFile.println("testing 1, 2, 3.");

Since i'm totally clueless in these things especially since there is interrupt, i have no clue how to make this work. And what is the right way to do it so it don't brake those interrupts.

Show us that you are not doing serial prints in an ISR. Also you can't log to an SD card in an ISR.

I have no idea what i’m doing. This is my current code:

#include <SPI.h>
#include <SD.h>

File myFile;

void setup()
{
  Serial.begin(9600);
  
  InitialiseIO();
  InitialiseInterrupt();

  Serial.print("Initializing SD card...");
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  myFile = SD.open("test.txt", FILE_WRITE);
}

void loop() {
}  

void InitialiseIO(){
  pinMode(A0, INPUT);
  digitalWrite(A0, HIGH);
  pinMode(A1, INPUT);
  digitalWrite(A1, HIGH);
  pinMode(A2, INPUT);
  digitalWrite(A2, HIGH);
}

void InitialiseInterrupt(){
  cli(); 
  PCICR =0x02;
  PCMSK1 = 0b00000111;
  sei();
}

ISR(PCINT1_vect) {
  if (digitalRead(A0)==0)  heartRateLogger();
  if (digitalRead(A1)==0)  optocouplerLogger();
  if (digitalRead(A2)==0)  switchLogger();
}

void heartRateLogger () {
      myFile.println("Heart");
}
void optocouplerLogger () {
    myFile.println("Opto");
}
void switchLogger () {
      myFile.println("Switch");
}

You can't write to a file inside an ISR function.

Why are you using interrupts anyway. This doesn't look like the kind of thing that requires them. It looks like you're trying to use the interrupt to detect a button press. How fast can you really press a button? Unless you can press and release a button in less than 1ms (you can't) then ditch the interrupt and just poll the buttons in the loop function.

Delta_G:
You can't write to a file inside an ISR function.

Why are you using interrupts anyway. This doesn't look like the kind of thing that requires them. It looks like you're trying to use the interrupt to detect a button press. How fast can you really press a button? Unless you can press and release a button in less than 1ms (you can't) then ditch the interrupt and just poll the buttons in the loop function.

How i can log to file if i use interrupts?

I try to log these:

Optocoupler (can be used as analog or digital sensor). This changes rarely, but it changes, it changes rapidly about 30 times in second

Ordinary momentary switch. Triggered 15 times in 10 seconds (or less) continuously

Analog? digital? Grove - Ear-clip Heart Rate Sensor SeeedStudio MED03212P
http://www.seeedstudio.com/wiki/Grove_-_Heart_rate_ear_clip_kit

30 times a second sounds fast to a human. To a computer that's slow. Very slow.

The answer to your problem is not to use interrupts. Poll your pins from loop and take the appropriate actions when needed.