Programming with different Arduinos in mind: fewer/more pins

I'm working on a simple flightsim / spacesim project that could potentially use all the pins on an Arduino, but I'd like to share the project with people who may be using Arduinos with different numbers of pins: anything from a Micro right up to a Mega. I've written my code so far with a Mega in mind, but of course this code won't compile onto something with fewer pins.

Is there an elegant way to build my code such that it adapts to Arduinos with different numbers of analog and digital pins, without me having to ask users to comment out lines that won't work on their board?

I am using the Michael Adams "button.h" library to handle debouncing and UI events in general, so on an Uno my code won't get past the line "btnD14.begin();" because, well... there is no digital pin number 14.

If the board used by someone has less pins then your sketch will only be able to provide less limited functionality. Is that what you have in mind ?

You can use conditional compilation and the common #define to differentiate between target boards when compiling

Yes, essentially this sketch is designed to take button input from an instrument panel and send information on button presses over serial. If run on an Arduino with fewer pins, it'll accommodate fewer buttons, but that's OK. I'd just like to avoid needing to maintain separate code for every possible arduino.

Ideal would be: "If Arduino only has 14 digital pins, ignore the next twenty lines while compiling"

"Conditional Compilation" sounds promising, this gives me something new to search for. Is there a good source of info on how this would work?

Hello efrg
Take a view here.

See this discussion for boards’ #defune

If you look in the code of many libraries you’ll see they do use this, for example here in the servo library

You can build a HAL (Hardware Abstraction Layer).

Make this class and others aware of port extenders. The user has to specify the addressing of his extenders (SPI, I2C...) and a range or list of assigned GPIO pins. Your code constructs the applicable objects (direct or redirected pins) and uses the methods of these objects instead of direct pin access.