Simple Way To Give Arduinos Unique ID

I'm building a radio control system for operating a model railway layout. It has one Tx that broadcasts data that's received by several Rxs. Each Rx controls nearby servos, relays or motor drivers. Every Rx runs the same sketch, and identifies which data sent by the Tx is relevant to it by having a unique ID (Rx1, Rx2 etc.). At the moment I have to edit the sketch before uploading it, to comment out assigning the IDs that relate to the other Rxs, as in the code extract below.

//*******SETUP EACH Rx*******
//Only enable one option!

//*******Baseboard 1, Rx1*******
byte rxID = 1; //Left hand board
bool rxController = false;

/*
  //*******Baseboard 2, Rx2*******
  byte rxID = 2; //Right hand board
  bool rxController = false;
*/
/*
  //*******Baseboard 1, Rx3*******
  byte rxID = 3; //Loco controller on left hand board
  bool rxController = true;
*/

It would be easier if I could give each board a unique ID that it reads on startup, so I don't need to edit the sketch.

What I've thought of so far is to use a voltage divider (either a preset pot or two resistors) on one of the analogue pins, with different values on each board. I'm using a Nano with an expansion board that has power pins next to each I/O pin, so it could be made as a simple plug in key, that's easy to swap if the board needs replacing.

Is this a good idea, or is there a better way?

You could write the value of rxID in EEPROM, and let the sketch read that at startup.

Or you could use 2 digital inputs (with INPUT_PULLUP) and connect 1, 2 or both of them to GND with a simple wire. Even simpler and cheaper… :wink:

You can also add a DS18B20 temperature sensor to your design. Each sensor has a unique ID. And you can also control a temperature of some critical parts.

Store a unique ID in each Arduino's EEPROM, can be programmed separately from program memory.

+1 for the DS18B20 sensor. Or just the ID chip that provides the guaranteed unique number, those are available separately as well.

Personally I would favour the approaches suggested by Erik_Baas. No additional hardware required unless one runs out of pins.

The DS18B20 is more work and code than it’s worth. Do you really want/need a 64 bit number?

As already mentioned: 1) Put the ID in eeprom 2) Using i/o pins to set the address is about as simple as you can get. Dip switch, jumper blocks, whatever. And one more: 3) Use one analog pin and two resistors, one fixed, one variable as a divider for unique analog values.

Hi, I'm doing a T-Trak system for my brother. I'm using CanBus and each module has a 4 bit address using dip switches.

The main reason is because the number of modules used in a setup can be variable and this makes changing the ID simple. I can't see him using more than 16 modules, its a simple end to end layout with platforms on each module and the odd railway crossing control. The master will send a master ID command, and each module, using the Canbus system to prevent collisions, will respond.

For larger numbers of units, @Erik_baas suggestion would be ideal. The number of different available addresses would be large enough for each unit to have its own lifetime ID. Like MAC addresses.

Tom... :)

It seems that the ATMega328P might have an (undocumented) UID. See this article for details.

John_SB:
I’m building a radio control system for operating a model railway layout. It has one Tx that broadcasts data that’s received by several Rxs. Each Rx controls nearby servos, relays or motor drivers. Every Rx runs the same sketch, and identifies which data sent by the Tx is relevant to it by having a unique ID (Rx1, Rx2 etc.).

I have a somewhat similar system for radio control of my model trains. IMHO it is not worth the trouble to figure out a solution to this problem. I just change the code so it includes the ID for the locomotive I’m uploading for.

How many different slaves are you using?

…R

Thanks everyone.

The temperature sensor suggestion is too complicated for what I want, and adds a lot of work and significant cost to what I’ve managed to make a very cheap device. I also just need a series of clean, simple, numbers.

I must admit that I haven’t used EEPROM before, so it didn’t cross my mind!!! However, it’s a simple solution that allows me to store up to 255 IDs very easily. This is far more than I need, as about 10 should be more than enough!

The variations on my hardware key idea are interesting. I do like the idea of a plug-in key though, as it makes it easy to swap Arduinos if I ever get one fail.

And the winner is…EEPROM! I’ve written a simple sketch to set the ID, that I can edit to the required number, and it will only be needed once for each Rx, unless I need to replace a failed Arduino. And it only needs two lines of code in the Rx sketch, that I’ve changed and tested.

#include <EEPROM.h>

void setup() {
  //Set value to unique Rx ID (1 - 255) for Arduino to be configured
  byte rxID = 1;


  Serial.begin(9600);
  EEPROM.write(0, rxID);
  byte storedID = EEPROM.read(0);
  if (storedID == rxID) {
    Serial.print("Successfully stored rxID");
    Serial.println(storedID);
  } else {
    Serial.print("FAILED to store new rxID");
    Serial.println(rxID);
    Serial.print("Stored value is ");
    Serial.println(storedID);
  }

}

void loop() {


}

Robin2: I have a somewhat similar system for radio control of my model trains. IMHO it is not worth the trouble to figure out a solution to this problem. I just change the code so it includes the ID for the locomotive I'm uploading for.

How many different slaves are you using?

...R

It will vary Robin. I've got about 6 part built small layouts at the moment, and I want to use this system for controlling all of them. There will probably be one Rx per baseboard for controlling servos and relays, and one for the loco controller, that may be DC or DCC++. I want to use BPRC on one or more layouts, so each loco will have an Rx. I'd also like to experiment with animation and RC vehicles, and I have a few devices like turntables and traversers to make, that it's going to best to give their own Rx.

So the answer to your slave question is a lot! I think storing the ID so I don't have to edit the sketch every time I upload it will help towards saving my sanity!

You can probably integrate the storing of the ID in the existing sketch. Prompt the user (you) for an ID using e.g. serial monitor, enter it and store it.

I think that a cleared eeprom (factory default) only contains 0xFF; you can test for that and only prompt if the value is 0xFF as it means the address was not set. Alternatively you can use a crc: a cleared eeprom will have an invalid crc. If that happens, prompt, store, recalculate crc and ssve in eeprom.

Better offer that prompt always, so you can later change the ID easily.

Or generate an ID randomly. Set the randomSeed() and then create an 8-byte ID. Chances of two being the same are extremely low.

The separate setter-sketch seems workable for the requirements. If you have to change an ID, upload that sketch and then re-upload the real sketch.

I commonly store a lot more configuration parameters in EEPROM, so many of my sketches have a large menu system. The menu code is relatively messy, so it isn't worth including in every sketch. One day I will make a menu library.

John_SB:
So the answer to your slave question is a lot!

In that case it might be a good idea to give them all the same address to start with and as each of them is first contacted by the master it will allocate a new address to be stored in the EEPROM.

…R

Robin2: In that case it might be a good idea to give them all the same address to start with and as each of them is first contacted by the master it will allocate a new address to be stored in the EEPROM.

...R

The problem is that each Rx needs to know which devices are connected to it, and that's written into the sketch. On the layout I'm currently working on, Rx1 has point servos 2 and 8-11 attached to pins A0 to A4, and Rx2 has point servos 1 and 3-7 attached to pins A0 to A5. The data for all servos is stored in a multi-dimensional array, including the ID of the Rx each is attached to. The Tx sends the required state of every servo to every Rx, and each Rx loops through the array, and when it finds a servo it controls, it checks its current state against what the Tx sent, and switches it if necessary. If the IDs got mixed up, it would still work, but change the wrong points! So it's a choice between having a sketch that can run unmodified on every Rx, that includes all data and code for all Rxs, or I complicate it by storing data specific to each Rx in EEPROM. Which is why I need to allocate the ID of each Rx, and to avoid confusion stick a big label on each one to identify it!

Maybe I'll do something more sophisticated one day, but right now I need to keep the first version as simple as possible

sterretje: You can probably integrate the storing of the ID in the existing sketch. Prompt the user (you) for an ID using e.g. serial monitor, enter it and store it.

I think that a cleared eeprom (factory default) only contains 0xFF; you can test for that and only prompt if the value is 0xFF as it means the address was not set. Alternatively you can use a crc: a cleared eeprom will have an invalid crc. If that happens, prompt, store, recalculate crc and ssve in eeprom.

As I make progress with this, I may store more data in EEPROM, and entering it through the serial monitor would get difficult, so I don't think it's worth adding anything to the sketch to do it. I think I'd have to write something in Processing to have anything remotely user friendly, and I've got too much else to work on to do that at the moment. An alternative is to add a setup menu to the Tx, and make sure only the Rx I want to update is running, but that's a lot of work too. But the Tx only has a 128x64 OLED, and my computer has a 1920x1080 screen that is much easier to work on!

I think it's much easier to use, and change, the setup sketch for now.

Even more fun would be for the sketch to see it has no name, pick a random number, store it in eeprom and then tell you what it’s name is..

I had forgotten that I am building another system which will have several slave boards for controlling turnouts, uncouplers and signals. The slave boards will have identical hardware and software and will be identified by jumper settings on the board that are read at startup. This means if there is a board failure a spare board can be inserted at any location and take the identity of the board it replaces.

All the intelligence will be in a Mega attached to the control panel.

If you need a greater number of IDs you could use an 8-pin DIP switch as a selector.

...R