Arduino – MAC address in EEPROM


Auto generated, persistent MAC address for Arduino Ethernet

Most serious Arduino projects are network connected using Ethernet, probably the most annoying thing about Arduino Ethernet shields is that they don’t each have a unique MAC address. This means that if you’re deploying a number (any number more than one, actually) on a local network then you’re going to run into trouble.

A lot of people and most examples on the Internet hard-code the MAC address into the sketch. This works for a one off project but becomes a liability when deploying multiple boards and puts a dependency in your code that presents issues down the track.

Generating a random MAC address is useful and quite simple but ideally we don’t what the MAC address of each node to change each time it boots, this can cause issues with DHCP and also having a persistent MAC address is useful for sending with messages over the network to uniquely identify which node it came from.

Below is a simple example sketch which generates a random MAC address and stores it in EEPROM (non-volatile memory, a typical Arduino has around 1K). The random MAC address is generated on first boot, on each subsequent boot after that it is read back out of EEPROM to ensure it stays the same.

#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>

byte mac[6] = { 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x00 };
char macstr[18];

void setup() {
  Serial.begin(9600);
  // Random MAC address stored in EEPROM
  if (EEPROM.read(1) == '#') {
    for (int i = 2; i < 6; i++) {
      mac[i] = EEPROM.read(i);
    }
  } else {
    randomSeed(analogRead(0));
    for (int i = 2; i < 6; i++) {
      mac[i] = random(0, 255);
      EEPROM.write(i, mac[i]);
    }
    EEPROM.write(1, '#');
  }
  snprintf(macstr, 18, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  // Start up networking
  Serial.print("DHCP (");
  Serial.print(macstr);
  Serial.print(")...");
  Ethernet.begin(mac);
  Serial.print("success: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
}

Feel free to use this example code for whatever you wish. The only thing to watch out for is if you are using EEPROM elsewhere in your sketch that you don’t clobber the values. You can remove the macstr variable and associated print lines to save on program space and RAM (memory) if you need it.

Below are some simple “C” routines to read and write the MAC string a different way.

#include <EEPROM.h>
#include "mac_eeprom.h"

uint8_t *getMACFromEEPROM()
{
	uint8_t mac[6];
	for (int i = 0; i < 6; i++) {
		mac[i] = EEPROM.read(EEPROM_MAC_OFFSET + i);
	}
	return mac;
}

void setMACToEEPROM(uint8_t *mac)
{
	for (int i = 0; i < 6; i++) {
		EEPROM.write(EEPROM_MAC_OFFSET + i, mac[i]);
	}
}
Header File “EEPROM.h”:
#ifndef mac_eeprom__h
#define mac_eeprom__h 1
#define EEPROM_MAC_OFFSET 0
uint8_t *getMACFromEEPROM();
void setMACToEEPROM(uint8_t *mac);
#endif

Enjoy!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s