I'm developing a little weather station. It has a GSM module attached to send weather data to the server. The GSM Shield use pin 7 and 8 for reading and writing data using the SoftwareSerial library.
The windspeed sensor gives two pulses per rotation and is attached to pin 10. I use the PinChangeInt library to define an interrupt on this pin.
I'm currently trying to get this to work on Arduino 1.0. I had it working on 023 but wanted to move to 1.0. In 023 I used NewSoftSerial which is now the SoftwareSerial in 1.0. Though SoftwareSerial defines interrupts for all Pin Change Interrupts and thus without removing some in SoftwareSerial I cannot get PinChangeInt to compile.
In a more normal C environment a couple of defines in the beginning of the code could easily make the compiler to include enough interrupts definitions needed but due to Arduinos a bit weird preprocessor it does not work to something like this in my sketch:
#define DO_NOT_USE_PORTC // disable SoftwareSerial interrupts on A0-A5
#define DO_NOT_USE_PORTB // disable SoftwareSerial interrupts on D9-D13
#define NO_PORTD_PINCHANGES // disable PinChangeInt on D0-D8
So right now my solution is to go into the Arduino installation, change the SoftwareSerial.cpp file in the installation to only use PORTD and PinChangeInt has a PinChangeIntConfig.h file where I can define which ports it should use. But this is not manageble in the long run, when I start my next project my hardware might look completely different and I need to change the installed files and thus this project wont compile any longer....
So how do you solve these kind of issues? One Arduino installation per project? But wont Preferences start to conflict? I would like to hear how you sort this out without ending up in a mess of libraries all created for specific projects...
To answer the question in the header:
Best practice for sharing is to do nothing unless the User asks for it. Thus, the SoftwareSerial library should not modify interrupts for ports other than what you specifically request.
Relying on defines is troublesome because the same files may be included from different sources with different defines.
The problem with Arduino IDE is that it wont help to have those defined in the sketch. And even more problematic is that SoftwareSerial includes the following code:
which wont mask out any interrupt definitions but I added #ifndef DO_NOT_USE_PORT for each to be able to mask them aout but still I have to define in SoftwareSerila.h and not in my sketch which to use/not use which makes it very unpractical in the long run.
But as jwatte suggest it would be a better practice for both PinChangeInt and SoftwareSerial to require the one using the library to do the following in his/her sketch:
// make SoftwareSerial catch interrupts on pin 7 and 8, port D
ISR(PCINT2_vect)
{
SoftwareSerial::handle_interrupt();
}
and
// make PinChangeInt catch interrupts on pin 10, port B
ISR(PCINT0_vect) {
PCintPort::pcIntPorts[0].PCint();
}
This all takes time. It might be overdesign for what is basically a tiny processor system.
In your case, why not just use D2/D3 hardware interrupts? Personally I don't particularly like pin-change interrupts, because for one thing the interrupt code is shared. Short of your vectoring idea, it isn't particularly easy to make a pin-change interrupt just for one pin for library A, and another one for library B.
What are D2/D3 hardware interrupts?? I'm not very familiar with the hardware details of Arduino, I'm much more of a software guy as you might have noticed and for me i't's natural to create something that is modular and easily re-useable. And SoftwareSerial nor PinChangeInt are my constructions, the first is part of the Arduino IDE and the second a library I downloaded. And I'm just trying to figure out a way to have them play along nicely which doesn't seem to be the case.
Both pins generate a dedicated interrupt on rising, falling, change or low signals. This seems an ideal place to attach your windspeed sensor. And it won't conflict with the software serial interrupts.
Son of a gun, I got pin 2&3 mixed up with PD2&PD3 some time back and it kinda made sense that hardware serial would use the interrupts. But I look at the pin map and sure enough INT0&INT1 are clear. Good news for me.
Mostly I dedicate IDE is whole Ardunio folder for a project. Rename the folder with my project name. play , make any changes needed. i change the necessary changes to the core files. as the need of my project. I edit core for time critical routines. like which i need to run on defined timer. like i edit timer0 for my need removing off its millis and all that stuff. set my timer as my application needs. then write another code for delay where i can do delay(), but most of my functions are just based on counter that runs in timer isr. when the counter is reached. function specific flag is made high. in this way my single counter sets as many function flags. these flags are continue-sly checked in loop() and if it finds set respective function is called. and during execution the flag is cleared too. but I always dedicate one IDE for each project. in other words I only bother to take pains where functions are critical, for rest I use spoon feed by arduino.
I_think:
Mostly I dedicate IDE is whole Ardunio folder for a project. Rename the folder with my project name. play , make any changes needed. i change the necessary changes to the core files. as the need of my project. I edit core for time critical routines. like which i need to run on defined timer. like i edit timer0 for my need removing off its millis and all that stuff [...] but I always dedicate one IDE for each project.
Just a question, maybe this is possible and I just missed how to do this.
However, I'd like to do this in a more clean way.
Maybe there exists an environment variable that you can modify so that an application-specific library directory can take precedence to the common library directories?
This would be very nice if you have to make project-specific library changes/optimizations.
Anyway, this is just one of the difficulties with the IDE why I am atm trying to get the makefile approach work, just to avoid cumbersome and error-prone kludging with the IDE.
As Nick said, if you have an Arduino Uno and have only 2 interrupt pins, the "External Interrupt" pins (pins 2 and 3 of the Arduino) are probably your best bet. If you need to interrupt more than 2 pins, Pin Change interrupts are the only way to go.