Show Posts
Pages: 1 2 [3] 4 5 ... 7
31  Community / Exhibition / Gallery / Version 2.01beta is now out. ...Includes speedups to the ISR! on: June 28, 2012, 12:56:44 pm
June 28, 2012: Version 2.01beta has been released! I had a brainstorm and modified how the ISR loops over the list of possible pins, thereby saving 2 microseconds in the ISR. Look at the notes for the download (here: or read the VERSIONS section of PinChangeInt.h for more information.
32  General Category / General Discussion / Re: Default licence of examples on Arduino Playground? on: June 23, 2012, 07:48:41 pm
Hello, GreyGnome here... I've been maintaining the PinChangeInt library.

Thanks for bringing up the issue of the licenses.  In my eagerness to update the library, I just took it and ran with it without cleaning up the original "johnboiles" attribution, which should really go to ckiick as he posted the original page in December 2008.

Personally, my contract with the user of the library is that, in exchange for my time and efforts, I would like the code to remain free: hence I "impose" the GPL.  See  I'm not interested in the popularity of my changes, I'm more interested in the freedom of the code, and I'm not interested in the lgpl (the Arduino's authors' choice notwithstanding).

That said, not following up on the PCint derivation was a mistake that I hope to rectify.

- GreyGnome

33  Community / Exhibition / Gallery / Version 1.81beta is now out. Adds MEGA support. on: June 23, 2012, 07:28:08 pm
PinChangeInt Library version 1.81beta has now been released.  It adds MEGA support, for the ATmega1280 and its brethren.  See

From the release notes:

To sum it up for the Mega: No Port C, no Port D. Instead, you get Port J and Port K. Port B remains. Port J, however, is practically useless because there is only 1 pin available for interrupts. Most of the Port J pins are not even connected to a header connector. Caveat Programmer.

From cserveny's (the author of the MEGA stuff) notes:

Mega and friends are using port B, J and K for interrupts. B is working without any modifications.

J is mostly useless, because of the hardware UART. I was not able to get pin change notifications from the TX pin (14), so only 15 left. All other (PORT J) pins are not connected on the Arduino boards. If you can verify this for me, I would love to know for user. Please send me an email or post to the bug reports section. Thanks. -Ed

K controls Arduino pin A8-A15, working fine.

328/168 boards use C and D. So in case the lib is compiled with Mega target, the C and D will be disabled. Also you cannot see port J/K with other targets. For J and K new flags introduced:


My MEGA changes have not been tested.  The library compiles and runs on my Duemilanove, but I don't have an Arduino Mega.  I would appreciate feedback.  Thanks.
- GreyGnome
34  Using Arduino / Programming Questions / Re: Using PinChangeInt in multiple libraries on: June 23, 2012, 07:21:01 pm
Sorry, laziness on my part. I meant PCintPort::attachInterrupt() and PCintPort::detachInterrupt()

Not intending to be attaching and detaching continually. Just wanted to hide the low level configuration from the end user of a library, so that the attaching is not done in the top sketch. I suppose I could define a preprocessor macro in the library header file, which then gets put in the top sketch, and expanded when the PCintPort methods are in the compiler scope.

Point taken about the $5 chip though...

Thanks for your input.

In the header of the PinChangeInt.h file, I write:

The library has been modified so it can be used in other libraries, such as my AdaEncoder library
   (  When #include'd by another library you should #define
   the LIBCALL_PINCHANGEINT macro.  For example:
   #ifndef PinChangeInt_h
   #include "../PinChangeInt/PinChangeInt.h"
   This is necessary because the IDE compiles both your sketch and the .cpp file of your library, and
   the .h file is included in both places.  But since the .h file actually contains the code, any variable
   or function definitions would occur twice and cause compilation errors- unless #ifdef'ed out.

Hopefully that helps.  See
35  Community / Exhibition / Gallery / Re: Tigger library released: A library for reading digital switches on the Arduino on: March 24, 2012, 02:11:38 pm
Thanks.  I hope you like it!
36  Community / Exhibition / Gallery / Tigger library released: A library for reading digital switches on the Arduino on: March 21, 2012, 07:36:32 pm
Tigger - A library for reading switches from the Arduino's digital pins. Why Tigger? "Because I'm a Tigger, and Tiggers bounce!"  See the webpage at:

The Tigger library is designed to make it easy to attach and utilize digital switches on the Arduino. "Digital switches" are those such as pushbuttons, toggles, slide switches, that sort of thing- what you might think of when you think "switch". A perennial problem with basic electronic switches is handling bounce. The Tigger library handles bounce in software. It also uses interrupts to manage switch events. This frees the programmer from considering how fast to poll the switch, and from needing to introduce delays in the main loop which may slow down overall instruction processing.

See the Wiki for more information.

This library depends on the ooPinChangeInt library, available here:
37  Community / Exhibition / Gallery / ooPinChangeInt library released: Pin Change Interrupts, object style on: March 20, 2012, 10:31:33 pm
Announcing the release of Version 1.02 of the ooPinChangeInt library.  Though labeled "1.02", this is actually the maiden release of this library.  See it at .

The ooPinChangeInt library was derived from the PinChangeInt library (, but it features a more object-oriented approach.  It allows you to call an object's method rather than rely on a C-style function attached to an Arduino pin.  See the included examples for more details.

The ooPinChangeInt library implements Pin Change interrupts for the Arduino environment. This library was designed for the Arduino Uno/Duemilanove. It will likely work with other ATmega328- or ATmega168-based Arduinos; it has been reported to work just fine on the Nano. It will probably not work on the Arduino Mega without some serious updating.

What are Pin Change interrupts? The ATmega328p processor at the heart of the Arduino has two different kinds of interrupts: “external”, and “pin change”. There are only two external interrupt pins, INT0 and INT1, and they are mapped to Arduino pins 2 and 3. These interrupts can be set to trigger on RISING or FALLING signal edges, or on low level. The triggers are interpreted by hardware, and the interrupt is very fast. On the other hand there are only 2 such pins on the ATmega328p in the Arduino Uno and Duemilanove.

On the other hand the pin change interrupts can be enabled on any or all of the Arduino's signal pins. They are triggered equally on RISING or FALLING signal edges, so it is up to the interrupt code to set the proper pins to receive interrupts, to determine what happened (which pin? ...did the signal rise, or fall?), and to handle it properly. Furthermore, the pin change interrupts are grouped into 3 “port”s on the MCU, so there are only 3 interrupt vectors (subroutines) for the entire body of 20 pins. This makes the job of resolving the action on a single interrupt even more complicated. The interrupt routine should be fast, but complication is the enemy of speed. The ooPinChangeInt library is designed to handle the Arduino's pin change interrupts as quickly and reasonably as possible.
38  Community / Exhibition / Gallery / Version 1.72 RELEASE is available for download. on: March 20, 2012, 07:24:39 am
I have stuck a fork in the beta version 1.71 and called it "DONE!".  Thus, the release version 1.72 is now available.  There are no code changes since the 1.71beta release.

Also I uploaded a new version of the Speed Tests document.
39  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: March 10, 2012, 02:39:25 pm
Version 1.71beta is now available for upload.  From the Release Notes:

Code reordering: Starting in version 1.3 of this library, I put the code that enables
    interrupts for the given pin, and the code that enables Pin Change Interrupts, ahead of actually
    setting the user's function for the pin.  Thus in the small interval between turning on the
    interrupts and actually creating a valid link to an interrupt handler, it is possible to get an
    interrupt.  At that point the value of the pointer is 0, so this means that the Arduino
    will start over again from memory location 0- just as if you'd pressed the reset button.  Oops!

    I corrected it so the code now operates in the proper order.
    (EDITORIAL NOTE:  If you want to really learn something, teach it!)

    Minor code clean-up:  All references to PCintPort::curr are now explicit.  This changes the compiled
    hex code not one whit.  I just sleep better at night.

    Numbering:  Changed the numbering scheme.  Beta versions will end with an odd number in the hundredths
    place- because they may be odd- and continue to be marked "beta".  I'll just sleep better at night. :-)
40  Community / Exhibition / Gallery / AdaEncoder: a library for use with simple quadrature encoders on: March 01, 2012, 12:11:16 am
Announcing the release of Version 0.5 of the AdaEncoder library.

This library was intended to make it easy for you to use 1 or more rotary encoders as found at Sparkfun or Adafruit on your Arduino. Don't worry about debouncing, the library's functions take care of that for you.

This library interfaces with 2-pin encoders (2 pins A and B, then a common pin C). It does not indicate every state change, rather, it reports only when the decoder is turned from one detent position to the next. It is interrupt-driven and designed to be fast and easy to use. The interrupt routine is lightweight, and the programmer is then able to read the direction the encoder turned at their leisure (within reason; what's important is that the library is reasonably forgiving). The library is designed to be easy to use (it bears repeating :-) ) and it is reasonably immune to switch bounce.

The library uses tight code (no digitalRead() or digitalWrite()) and in use requires only two methods. The amount of code in the interrupt routines is kept small.

The library can be found at

The library requires the PinChangeInt library, version 1.70beta or newer, found at
41  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: February 28, 2012, 08:33:39 am
Version 1.70beta is out as of yesterday.  Includes the following enhancements; from the Release Notes:

Happy Birthday to me!  Happy Birthday tooooo meee!  Happy Birthday, Dear Meeeeee-eeeee!  Happy Birthday to me!

Yes, it is on this auspicious occasion of mine (and Elizabeth Taylor's [R.I.P.]) birthday that I humbly submit to you, gracious Arduino PinChangeInt user, version 1.70beta of the PinChangeInt library.  I hope you enjoy it.

New in this release:
    The PinChangeIntTest sketch was created, which can be found in the Examples directory.  It exercises:
  • Two interrupting pins, one on each of the Arduino's PORTs.
  • detachInterrupt().
Hopefully this will help avoid the embarrassing bugs that I have heretofore missed.

As well, it has come to this author's (GreyGnome) attention that the Serial class in Arduino 1.0 uses an interrupt that, if you attempt to print from an interrupt (which is what I was doing in my tests) can easily lock up the Arduino.  So I have taken SigurðurOrn's excellent ByteBuffer library and modified it for my own nefarious purposes.  (see  The zipfile comes complete with the ByteBuffer library; see the ByteBuffer/ByteBuffer.h file for a list of changes, and see the PinChangeIntTest sketch for a usage scenario.  Now the (interrupt-less and) relatively fast operation of filling a circular buffer is used in the interrupt routines.  The buffer is then printed from loop().

The library has been modified so it can be used in other libraries, such as my AdaEncoder library (  When #include'd by another library you should #define the LIBCALL_PINCHANGEINT macro.  For example:
        #ifndef PinChangeInt_h
        #include "../PinChangeInt/PinChangeInt.h"
This is necessary because the IDE compiles both your sketch and the .cpp file of your library, and the .h file is included in both places.  But since the .h file actually contains the code, any variable or function definitions would occur twice and cause compilation errors- unless #ifdef'ed out.
42  Community / Exhibition / Gallery / Re: PinChangeInt library- To attach interrupts to multiple Arduino (Uno/Due) pins on: February 18, 2012, 01:37:50 am
I created another bug :-(.  Version 1.6 is out; includes a couple of enhancements.  The changes are these:

Set the value of the current register settings, first thing in each ISR; e.g.,
ISR(PCINT0_vect) {
       PCintPort::curr = portB.portInputReg; // version 1.6
 ...instead of at the beginning of the PCintPort::PCint() static method.
This means that the port is read closer to the beginning of the interrupt,
and may be slightly more accurate- only by a couple of microseconds, really,
but it's a cheap win.

Fixed a bug- a BUG!- in the attachInterrupt() and detachInterrupt() methods.
I didn't have breaks in my switch statements!  Augh!  What am I, a (UNIX) shell
programmer?  ...Uh, generally, yes...

Added the PINMODE define and the PCintPort::pinmode variable.  See the Usage
Wiki page on the website for more info.
43  Using Arduino / Programming Questions / Re: Serial.print() and interference with other interrupts on: February 16, 2012, 08:12:40 am

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.
44  Using Arduino / Programming Questions / Serial.print() and interference with other interrupts on: February 16, 2012, 01:36:50 am
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.

#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:
  case RISING:
  case CHANGE:
    Serial.print(" C ");

void quicfunc0() {
  if (start==1) {
  Serial.print("0p"); Serial.print(latest_interrupted_pin, DEC); Serial.print("-P");
  Serial.println(digitalPinToPort(latest_interrupted_pin), DEC);
  if (start !=1) Serial.println(", not counted.");

void quicfunc1() {
  if (start==1) {
  Serial.print("1p"); Serial.print(latest_interrupted_pin, DEC); Serial.print("-P");
  Serial.println(digitalPinToPort(latest_interrupted_pin), DEC);
  if (start !=1) Serial.println(", not counted.");

void quicfunc2() {
  if (start == 1) {
    Serial.println("STOP! ...not counted.");
  } else {
    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);
    switch (pins[i]) {
    case PIN1:
    case PIN3:
        PCintPort::attachInterrupt(pins[i], &quicfunc0, FALLING);
    case PIN2:
    case PIN4:
        PCintPort::attachInterrupt(pins[i], &quicfunc0, RISING);
    case PIN5:
        PCintPort::attachInterrupt(pins[i], &quicfunc1, CHANGE);
    case PIN6:
        PCintPort::attachInterrupt(pins[i], &quicfunc2, FALLING);

void loop() {
  uint8_t count;
  for (i=0; i < 20; i++) {
    if (interrupt_count[i] != 0) {
      Serial.print("Count for pin ");
      if (i < 14) {
        Serial.print(i, DEC);
      } else {
        Serial.print(i-14, DEC);
      Serial.print(" is ");
      Serial.println(count, DEC);
45  Using Arduino / Programming Questions / Re: Mixing C with Assembler: Assembly code before push instructions in a function on: February 10, 2012, 12:49:41 am
Well in my test, the generated code ... Only had this before saving the port:

ISR (PCINT0_vect)
 100: 1f 92        push r1
 102: 0f 92        push r0
 104: 0f b6        in r0, 0x3f ; 63
 106: 0f 92        push r0
 108: 11 24        eor r1, r1
 10a: 8f 93        push r24
  savedPort = PINB;
 10c: 83 b1        in r24, 0x03 ; 3
 10e: 80 93 00 01 sts 0x0100, r24

Which isn't much worse than you can do with assembler. You have to save the status register, and before you do that you have to save R0.

In this small case I would agree.  As a matter of fact, it's exactly what I would do with assembler.  Interestingly, I have created a silly ISR that calls a function with a large number of varargs: 45 arguments, to be exact.  The ISR created this set of push instructions:

ISR(PCINT2_vect) {
 12c:   1f 92           push    r1
 12e:   0f 92           push    r0
 130:   0f b6           in      r0, 0x3f        ; 63
 132:   0f 92           push    r0
 134:   11 24           eor     r1, r1
 136:   2f 92           push    r2
 138:   3f 92           push    r3
 13a:   4f 92           push    r4
 13c:   5f 92           push    r5
 13e:   6f 92           push    r6
 140:   7f 92           push    r7
 142:   8f 92           push    r8
 144:   9f 92           push    r9
 146:   af 92           push    r10
 148:   bf 92           push    r11
 14a:   cf 92           push    r12
 14c:   df 92           push    r13
 14e:   ef 92           push    r14
 150:   ff 92           push    r15
 152:   0f 93           push    r16
 154:   1f 93           push    r17
 156:   2f 93           push    r18
 158:   3f 93           push    r19
 15a:   4f 93           push    r20
 15c:   5f 93           push    r21
 15e:   6f 93           push    r22
 160:   7f 93           push    r23
 162:   8f 93           push    r24
 164:   9f 93           push    r25
 166:   af 93           push    r26
 168:   bf 93           push    r27
 16a:   ef 93           push    r30
 16c:   ff 93           push    r31
 16e:   df 93           push    r29
 170:   cf 93           push    r28

Now I caution you about getting too carried away about shaving nanoseconds off ISRs. ...

So what I have learned, and what I suspected from everybody's dire warnings and general uncomfortableness with my idea, is that the compiler will create a variable number of push instructions, up to and including pushing the entire set of registers.  And, even though the only thing my ISR does is call another function, some of the registers used in the function are not pushed in the function.  The registers are pushed by the ISR.  Thus, trying to outsmart the compiler writers is probably a bad idea.  If I wanted to do the compiler's work and create a "naked" ISR, I would by necessity need to save all the registers, all the time.

So my little experiment puts the final smackdown on my idea.  Not to mention, again, everyone's general uncomfortableness with my plan.

I think the only time I would use ISR_NAKED is if I was writing a hand-assembled ISR and I knew the static set of registers that were going to be utilized.

Thanks everybody for taking your time.  I have learned a lot, believe it or not.  I am going to write my humble little ISR like this:

ISR(PCINT0_vect) {
    PCintPort::curr = portB.portInputReg;

...Saving the input register's state into the PCintPort::curr static class variable as soon as is prudently possible.  I'll leave the assembly code for the super low-level guys.

Pages: 1 2 [3] 4 5 ... 7