29

Once you have uploaded a sketch to one of your Arduino boards, it is hard to know exactly what source code led to that sketch.

Indeed, you may change the source code of your sketch on your PC without updating it (in binary format) to your board.

I had the idea of setting up a kind of "sketch repository" that would be populated as soon as I upload a sketch to one of my boards. Then I could retrieve, later on, the source code for a sketch running on any of my boards.

For such a repository, I would first need to have an "index" that would enable me to know which board the sketch source code is linked to.

Typically, such an index should be unique for every single arduino board.

Hence my question: how can I get a unique ID for an Arduino board?

Edit:

This is my current list of boards (the miniumum list to be supported by a single unique ID approach):

  • UNO R3
  • Mega 2560
  • Yun
  • Arduino Robot (that must be 2 Leonardo equivalent boards)

In the future, I may also build my own boards (Uno equivalent but barebones, without FTDI), hence if an approach also supports these that would be better.

1
  • 1
    @jfpoilpret...just saw this post while perusing the site..did you find a solution, or best case scenario on how to implement this?
    – dinotom
    Commented May 2, 2016 at 11:06

8 Answers 8

16

There are a number of techniques you could use here to get a unique ID.

  1. FTDI chips have a unique serial number programmed onto them. This can only be accessed from the PC side of the connection as far as I am aware.
  2. Some of the chips with built in USB (e.g. ATmega8U2/16U2/32U2) have a unique ID in the signature data, normally used for USB. Can easily be accessed from both sides of the connection. This includes the ATmega16U2 that is used as the USB->Serial bridge Arduino Uno R3.
  3. Some of the chips with built in USB but no unique ID in the signature will still have a unique ID programmed into the USB stack (e.g. LUFA) used for the bootloader or DFU (Device Firmware Upgrade).
  4. There are many chips with globally unique serial IDs in them e.g. the Microchip 11AA02E48, all of the Dallas 1-Wire sensors (including the common DS18B20 temperature sensor), and other serial EEPROMS. I've used these in production hardware that must have a unique MAC address.
  5. You could modify the standard Optiboot bootloader (or whichever boat loader you use) so that it can hold and respond with a unique ID.

The problem with these is that there is no option except 5 that will work across all boards.

If your solution is going to be a generic one, I would suggest that using a USB ID is not the way forwards. I have ~30 Arduino-based boards, and only 5 of them have built in USB hardware. All the rest of them need an external FTDI cable to be programmed. This means they would all have the same ID.

4
  • 2
    What do you do with 30 boards?
    – asheeshr
    Commented Feb 18, 2014 at 10:17
  • Mainly for wireless sensor networks. I only have a few real Arduinos - a Duemilanova, a Seeeduino Mega and an Uno. All the others are Teensy, Jeenodes, WiNodes, Nanodes and RFus. Commented Feb 18, 2014 at 11:26
  • 1
    +1 for a thorough list of possible options, thanks! I'd rather avoid 4. as I don't want to add specific hardware to all my boards. 5. looks dangerous (easy to upload the same modified bootloader to 2 different boards) and cumbersome (need to have different bootloaders source code to upload for every board). So far, USB ID and FTDI seem quite good solutions, but do they work with all my current board?
    – jfpoilpret
    Commented Feb 18, 2014 at 20:36
  • Does Arduino have globally unique serial IDs ? How to read it ?
    – Enhao Lan
    Commented Dec 16, 2016 at 5:11
14

The chip doesn't have any sort of unique ID as far as I know.... but you could program one into the EEPROM of your boards.

EEPROM documetnation

You would write to a specific address and then future sketches can read the ID and do whatever with it.


You may also be able to see a unqiue ID or address on the host side. I don't know enough about USB devices to tell you more, but the chip handling USB communication might have a unique ID you could use. Your Arduino code would not be able to use this, though.

Alternatively, just use a label maker and put a label on each board.

3
  • 2
    As far as the unique aspect of the question, a GUID could solve that (within some tiny margin of error).
    – Matthew G.
    Commented Feb 18, 2014 at 1:44
  • I had originally thought of using the EEPROM for that; but that requires additional work for every board get: create a new unique ID, then write it to the EEPROM. Also, there may be incompatibilities with libraries used by my sketches (that may write to the same EEPROM address). Finally in my context, I would need to read the ID from my PC, which is more difficult. The USB unique ID seems more interesting to me.
    – jfpoilpret
    Commented Feb 18, 2014 at 4:12
  • As per my answer, if you want this to be a generic solution (for most people, and a wide range of boards), relying on the USB ID means that people using FTDI cables on boards without a USB->Serial bridge would not be able to use you system. Commented Feb 18, 2014 at 8:28
8

Some boards, when connected to a computer, publish their serial number. My Arduino Uno R3 says

[16818.451423] usb 3-2: SerialNumber: 85235353137351E02242

Though I'm not sure how unique it is.

2
  • Do all Arduino boards have such a number? It would be nice to have the list of boards that have one (or not).
    – jfpoilpret
    Commented Feb 18, 2014 at 4:14
  • 1
    Looking at mines, 32u4 based ones don't, 328 and SAM3X8E ones do have it Commented Feb 18, 2014 at 8:06
4

To the best of my knowledge the USB chips all come with a unique serial number, at least for the FTDI chips. On Linux you can easily assign unique device names from that, check my website.

Other than that, what you are describing is pretty much a simple form of version control. Make sure your source files have version numbers. To identify your Arduino, you can make it Serial.Print(); name and version of the code during setup();.

3
  • Yes version control is more or less what I want to achieve; but setting a version in code and changing it every time the code changes is not an option (too easy to forget). I currently use github for my sketches, but I'd like to easily find out what version of what sketch is currently running on one board.
    – jfpoilpret
    Commented Feb 18, 2014 at 20:18
  • 4
    There is a macro for compilation date and time __DATE__ and __TIME__. So at least you can automatically store that info in your .hex file @jfpoilpret
    – jippie
    Commented Feb 18, 2014 at 20:55
  • Good point, I hadn't thought about these macros for versioning.
    – jfpoilpret
    Commented Feb 18, 2014 at 20:59
2

I doubt that the USB interface on the Uno gives you a unique serial number. Any number would be part of the code uploaded to the chip which would therefore be the same amongst multiple Unos.

One approach is the DS2401 "Silicon Serial Number" chip which uses the One-wire interface. That would only require one free pin, and some code (the code would be the problem, possibly).

The least intrusive method, and probably the most reliable, would be to simply read back the code and sum-check it. That is exactly what I do with my chip signature detector. However that only detects (as currently written) the bootloader signature. A fairly minor change and it could MD5-sum the entire sketch code.

Example output:

Signature detector.
Written by Nick Gammon.
Signature = 1E  95  0F 
Fuses
Low = FF High = D6 Ext = FF Lock = CF

Processor = ATmega328P
Flash memory size = 32768
Bootloader in use: Yes
EEPROM preserved through erase: Yes
Watchdog timer always on: No
Bootloader is 512 bytes starting at 7E00

Bootloader:

7E00: 02 01 02 03 0405 06 07 08 09 0A 0B 0C 0D 0E 0F 
7E10: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7E20: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7E30: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
...
7FB0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FC0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FD0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FE0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 
7FF0: 02 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 

MD5 sum of bootloader = 56 72 75 2D 5D B5 0D BA 25 10 DF BE 87 D2 A1 27 

That MD5 sum (last line) is effectively the signature of that particular bootloader. In fact the most recent version looks them up in a table:

MD5 sum of bootloader = FB F4 9B 7B 59 73 7F 65 E8 D0 F8 A5 08 12 E7 9F 
Bootloader name: optiboot_atmega328

So what you could do is, when uploading a sketch, generate a MD5 sum of the hex code. There are fairly simple ways of doing that. Then you could do a "git tag" operation on your source code, and then (using some automated or manual process) remember that a particular MD5 sum of hex code represents the sketch code at a particular moment.

Some sort of database like:

Chip: Uno
MD5 sum: D8 8C 70 6D FE 1F DC 38 82 1E CE AE 23 B2 E6 E7 
Sketch: My_robot_sketch_42.ino
Git tag: version666

Now to locate the source from the board, you establish the MD5 sum of the code (by reading it back from the board) and then look it up in your database.

1

I connected a one wire temp sensor that each come with an unique I'd. All the sketches read the I'd on boot and wrote the address on every serial connection. I made a shield with all the hardware I needed so if I needed to upgrade from Uno to Mega the device kept its unique I'd.

1

There is tiny library for reading and writing your custom hardware ID to EEPROM. You can use it to avoid pushing wrong sketch to your Arduino or to identify device for other purposes.

https://github.com/skoumalcz/arduino-id-guard

Disclaimer: I'm author of the library :-)

0
#include <avr/boot.h>
#ifdef __AVR_ATmega2560__  /// check if a MEGA2560 is in use
#define USEMEGA_ID         ///
void setup()
{
#ifdef __AVR_ATmega2560__
  cli();
  int data3, data4;
  data3 = boot_signature_byte_get(0x04) * 256;
  data4 = boot_signature_byte_get(0x01);
  sei();
  MegaID = data3 + data4;
#endif
Serial.begin(115200);
  Serial.print("MegaID             \t: "); Serial.println(MegaID);
}

// This will show you a 3 digit MegaID
// You can now create different setups for different MEGA2560  with the same source code
2
  • The number returned by this code seems to be based both on the device signature (which is the same for all ATmega2560 devices) and the factory-stored oscillator calibration byte (which can vary between boards). It is not guaranteed to be unique. I wonder what is the typical spread of the calibration bytes: this conditions the likelihood of ID collisions. Commented Apr 4, 2023 at 19:01
  • correct!There only 3 numbers. so they are 999 possibilities. this is not much or secure, but practical, when you have only a few boards an like to have different setups with the same code.
    – ESP Blynk
    Commented Apr 6, 2023 at 12:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.