How can I detect which arduino board (or which controller) in software?
Run time

To my knowledge you cannot detect the board type, but you can read the ATmega device ID. Check this question how it can be done: Can an ATmega or ATtiny device signature be read while running? Notice though when using this method, several register assignments will change, not just the pinout. Therefore your code may get significantly more complex. The advantage is that if you manage to work around all changing register assignments and other hardware dependencies, you can use a single .hex file to program your devices directly from avrdude.

Compile time

Another way to figure out the board/controller type is at compile time. Basically you compile parts of the code or set macros depending on the device type configured in the Arduino IDE. Check this code sniplet for an example:

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define DEBUG_CAPTURE_SIZE 7168
#define CAPTURE_SIZE 7168
#elif defined(__AVR_ATmega328P__)
#define DEBUG_CAPTURE_SIZE 1024
#define CAPTURE_SIZE 1024
#else
#define DEBUG_CAPTURE_SIZE 532
#define CAPTURE_SIZE 532
#endif


The code sniplet was shamelessly copied from https://github.com/gillham/logic_analyzer/wiki Check that code for some some more device specific trickery.

Depending on your host's operating system, the supported controller types can be found in the following file:


Linux: /usr/lib/avr/include/avr/io.h 
Windows: ...\Arduino\hardware\tools\avr\avr\include\avr\io.h


The use of C-preprocessor (by which the above code is handled) is probably out of scope for this site. http://stackoverflow.com would be the better place for detailed questions.

If you are on Linux you can easily find all supported controller types by typing:

grep 'defined (__AVR' /usr/lib/avr/include/avr/io.h | sed 's/^[^(]*(\([^)]*\))/\1/'