how to get ArduinoUniqueID in character array

I need the unique address I get from UniqueID8 in an array like the array test in this code.
After much searching and trying I ended up writing this code: it is not not working very well and the result is a string.

The output from UniqueID8dump(Serial); is:
UniqueID: 33 39 51 13 38 38 35 38

output from temp=id2CharArray(UniqueID8):
33 39 51 13 00 00

So the last two bytes are lost.

#include <UIPEthernet.h>
#include <ArduinoUniqueID.h>
#include <Arduino.h>

char test[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
char* temp;

char* id2CharArray(IPAddress id) {
  static char a[32];
  sprintf(a, "%02X %02X %02X %02X %02X %02X", id[0], id[1], id[2], id[3], id[4], id[5]);
  return a;
}

void setup()
{
  Serial.begin(115200);
  UniqueID8dump(Serial);

  Serial.println("output from temp=id2CharArray(UniqueID8):");
  temp=id2CharArray(UniqueID8);
  Serial.println(temp);
    
}

void loop()
{
}

Any help getting this into working code would be much appreciated.

The library creates a global variable called _UniqueID of type ArduinoUniqueID. That object has a public member variable called 'id' which is a byte array of length 'UniqueIDbuffer' where the last 'UniqueIDsize' bytes are the unique part. You have direct access to the array so you can read whatever bytes you want: "_UniqueID.id[0 through UniqueIDbuffer-1]"

There is a macro named 'UniqueID' that returns a pointer to the last "UniqueIDsize" bytes of the buffer. If you only want the unique part you can use the macro: "UniqueID[0 through UniqueIDsize-1]".

There is another macro named "UniqueID8" that returns a pointer to the last eight bytes of the buffer. If you only want the last eight bytes of the unique part you can use the macro: "UniqueID8[0 through 7]".

You are treating the last eight bytes of the buffer as a six-byte IP address which explains why you only see the first six bytes in the last eight bytes of the nine or ten byte "_UniqueID.id[]".

The 'dump' macros just generate code to send the ID (or last 8 bytes of ID) to Serial in HEX.

Thanks! You got me a bit further :slight_smile:
From your comment I got the idea to use the last 6 unique bytes as mac address, this should be unique enough for a local lan. However, I still do not get it right.

This code snippet:

for (int i=5; i<11; i++)
{
   char temp=UniqueID[i];
   mac[i]=printf("%02X", temp);
}

Results in:
UniqueID:04001833395113383835
MAC Address:3838354522

Also The mac address array only has to be 6 bytes long, but when I do this the output is even funnier:

for (int i=5; i<11; i++)
{
   char temp=UniqueID[i];
   mac[i-5]=printf("%02X", temp);
}

UniqueID:04001833395113383835
MAC Address:22222229

My complete code for testing:

#include <UIPEthernet.h>
#include <ArduinoUniqueID.h>
#include <Arduino.h>

byte mac[]  = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
char MyUID[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };

char* temp2;

char* ip2CharArray(IPAddress ip) {
  static char a[16];
  sprintf(a, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
  return a;
}

void setup()
{
  Serial.begin(115200);
  Serial.print("UniqueID:");
  for (size_t i = 0; i < UniqueIDsize-1; i++)
  {
     MyUID[i]=UniqueID[i];
  }

  for (size_t j = 0; j < UniqueIDsize-1; j++)
  {
     Serial.print(MyUID[j], HEX);  
  }
  Serial.println();

  // compose mac address from UniqueID
  Serial.print("MAC Address:");
  for (int i=5; i<11; i++)
  {
     char temp=UniqueID[i];
     mac[i-5]=printf("%02X", temp);
  }
  
  // Print mac address
  for (size_t j = 0; j < 7; j++)
  {
     Serial.print(mac[j], HEX);  
  }
  Serial.println();

  Ethernet.begin(mac);
  Serial.print("IP: ");
  temp2=ip2CharArray(Ethernet.localIP());
  Serial.println(temp2);

}

void loop()
{
}

Not printf, but sprintf.

sprintf trows: invalid conversion from 'byte' {aka 'unsigned char'} to 'const char*' [-fpermissive]

I am not surprised. sprintf needs a buffer to write into, it sounds like you just substituted sprintf for printf. Check the (basic) documentation for it.

Of course. You are right, I need a break and some coffee. :confused:

So I made this, but that's not working either.
It seems I have to gain a better understanding in how to deal with different types:

char buff[10];
  for (int i=5; i<11; i++)
  {
     char temp=UniqueID[i];
     sprintf(buff,"%02X", temp);
     mac[i-5]=buff;
  }

invalid conversion from 'char*' to 'byte'

I'm not really sure what you're trying to do here. It looks like all you really need to do is to copy six characters from one array to the other to fake up a MAC address. Be careful though, according to Wikipedia, there are some low end bits that have special meaning - no idea if it matters.

This is sufficient for copying the last 6 bytes of the UniqueID into an array called 'mac':

  for (int i = 0; i < 6; i++)
  {
    mac[i] = UniqueID[(UniqueIDsize - 6) + i];
  }

The full sketch which prints out the values in hex:

#include <UIPEthernet.h>
#include <ArduinoUniqueID.h>

byte mac[6];

char* ip2CharArray(IPAddress ip)
{
  static char a[16];
  sprintf(a, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
  return a;
}

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

  // Print the full _UniqueID
  Serial.print("_UniqueID.id[");
  Serial.print(UniqueIDbuffer);
  Serial.print("]: ");
  for (size_t i = 0; i < UniqueIDbuffer; i++)
  {
    if (_UniqueID.id[i] < 0x10)
      Serial.print('0');
    Serial.print(_UniqueID.id[i], HEX);
    Serial.print(' ');
  }
  Serial.println();

  // Print the UniqueID (last UniqueIDsize bytes of _UniqueID
  Serial.print("UniqueID[");
  Serial.print(UniqueIDsize);
  Serial.print("]: ");
  for (size_t i = 0; i < UniqueIDsize; i++)
  {
    if (UniqueID[i] < 0x10)
      Serial.print('0');
    Serial.print(UniqueID[i], HEX);
    Serial.print(' ');
  }
  Serial.println();

  // compose and print mac address from UniqueID
  Serial.print("MAC Address: ");
  for (int i = 0; i < 6; i++)
  {
    mac[i] = UniqueID[(UniqueIDsize - 6) + i];
    if (mac[i] < 0x10)
      Serial.print('0');
    Serial.print(mac[i], HEX);
    Serial.print(' ');
  }
  Serial.println();

  Ethernet.begin(mac);
  Serial.print("IP: ");
  Serial.println(ip2CharArray(Ethernet.localIP()));
}

void loop() {}

Output:

_UniqueID.id[9]: 55 35 35 33 31 30 0D 1A 25 
UniqueID[9]: 55 35 35 33 31 30 0D 1A 25 
MAC Address: 33 31 30 0D 1A 25

wildbill:
Be careful though, according to Wikipedia, there are some low end bits that have special meaning - no idea if it matters.

Thanks for this hint, I found IEEE and IANA papers on this. So I have to do some more work to avoid some patterns. (Nobody told me this even not in the masterclass ipv4 I once attended.)

Another simple method of getting a unique value (at the expense of a single pin) is to add a DS18B20

@johnwasser: Thanks!
A brilliant way and it shows me to think the other way round...

Code is running fine now.
The ethernet function still has a problem with the mac array, but I have some new code now to spend an evening with :slight_smile:

kopk:
Thanks for this hint, I found IEEE and IANA papers on this. So I have to do some more work to avoid some patterns. (Nobody told me this even not in the masterclass ipv4 I once attended.)

This should be sufficient to mark your MAC Address as a "locally administered" ID:

mac[0] |= 0x02;

Brilliant, my serial number started with a multicast address according to RFC 5342...
Murphy is in the room...
I agree, starting with 02 is a sane idea. I used this list on github List of MAC addresses with vendors identities to search a private vedor id and used it as the first 3 bytes. Now all my dhcp servers are happy.