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/'

As stated in the Arduino hardware specification, the Arduino IDE now defines a macro for each board, as defined in the boards.txt build.board property. That value is appended to ARDUINO_ so, for example, the macros for the boards you're interested in are:

  • Uno: ARDUINO_AVR_UNO
  • Mega 2560: ARDUINO_AVR_MEGA2560
  • Due: ARDUINO_SAM_DUE

Example of how you can use these macros in your code:

#if defined(ARDUINO_AVR_UNO)
//Uno specific code
#elif defined(ARDUINO_AVR_MEGA2560)
//Mega 2560 specific code
#elif defined(ARDUINO_SAM_DUE)
//Due specific code
#else
#error Unsupported hardware
#endif

An easy way to do board sniffing is to use a library such as ArduinoManager. With this you can very easily get the board name and features https://github.com/backupbrain/ArduinoBoardManager

It uses the technique described above to reveal lots of information about almost every Arduino board, so it's great for making projects that might get deployed on a lot different environments.

Just download and include in your Arduino project.

#include "ArduinoBoardManager.h"

ArduinoBoardManager arduino = ArduinoBoardManager(); // required if you want to know the board name and specific features

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

  Serial.print("Board is compatible with Arduino ");
  Serial.println(arduino.BOARD_NAME);

  Serial.println("Speed/SRAM/Flash: ");
  Serial.print(ArduinoBoardManager::MAX_MHZ);
  Serial.println(ArduinoBoardManager::SRAM_SIZE);
  Serial.println(ArduinoBoardManager::FLASH_SIZE);

  // Board features (multiple serial ports on Mega, for example)
  if (arduino.featureExists(ArduinoBoardManager::FEATURE_MULTIPLE_SERIAL)) {
    Serial.println("Your board supports multiple serial connections");
  }

}

void loop() {
}

The resulting output on Arduino Uno is:

Board is compatible with Arduino UNO

Speed/SRAM/Flash: 
16000000
2048
33554432

The process for making this library (including example code) to determine an Arduino board model and version is described in detail on my blog.

Tags:

Arduino