Recent versions of our Ethernet-enabled Arduino compatible boards and shields incorporate an IC called a Microchip 24AA025E48, which is pre-loaded with a unique MAC address ready for you to use in your sketches. This is very convenient because you don't need to manually configure the MAC address in the sketch or keep track of which addresses you've used on your projects. With the 24AA025E48, you can run the exact same sketch on multiple boards and each one will still have a unique MAC address because it is not coded into the sketch.

Checking MAC chip presence

Older boards don't include the 24AA025E48 MAC address chip, so they will still require the MAC address to be set using another method. The MAC address chip has been included for:

Testing the MAC address chip

The example sketch below will read from the MAC address chip and report its value to the serial monitor. Load the sketch onto your Arduino and open the serial monitor at 57600bps to see the value.

 

/*
 * Retrieve the MAC address from a Microchip 24AA125E48 I2C ROM, and report it
 * to the serial console at 57600bps. The I2C address of the ROM is set to 0x50,
 * which assumes both the address pins are tied to 0V.
 */

#define I2C_ADDRESS 0x50
#include <Wire.h>

static uint8_t mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 

void setup()
{
  Wire.begin();         // Join i2c bus (I2C address is optional for the master)
  Serial.begin(57600);
  for(int i = 0; i < 30; i++)
  {
    Serial.println(" ");
  }
  Serial.println("Starting test for MAC address ROM");
  Serial.print("Getting MAC: ");
  
  mac[0] = readRegister(0xFA);
  mac[1] = readRegister(0xFB);
  mac[2] = readRegister(0xFC);
  mac[3] = readRegister(0xFD);
  mac[4] = readRegister(0xFE);
  mac[5] = readRegister(0xFF);
  
  char tmpBuf[17];
  sprintf(tmpBuf, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.println(tmpBuf);
  Serial.println(" TEST OK");
}

void loop()
{
  // Do nothing
}

byte readRegister(byte r)
{
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);  // Register to read
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1); // Read a byte
  while(!Wire.available())
  {
    // Wait
  }
  v = Wire.read();
  return v;
} 

Incorporating into your sketch

The test sketch shown above defines an array called "mac[]" to store the six elements of the MAC address, then reads each of the elements from the 24AA025E48 to populate the array. This makes the code very easy to incorporate into other projects that use Ethernet, because most examples already use an array called "mac[]" to store the MAC address.

The only difference is that instead of defining the address manually like in most examples, we can use the address provided by the 24AA025E48.

For example, in the Arduino IDE open File > Examples > Ethernet > WebServer. On line 23 you will see the definition for the MAC address:

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 

This is just like the example above, but sets a specific value. You can leave it unchanged, because the value will simply be replaced with the value taken from the MAC chip.

Just above the definition of the "mac[]" array, add these lines to specify the I2C address of the MAC chip and include the Wire library to enable I2C communications:

#define I2C_ADDRESS 0x50
#include <Wire.h>

A little further down the WebServer example at line 41 is the command to initialise the Ethernet interface:

  Ethernet.begin(mac, ip);

Immediately before this command, you can add new commands to begin communication with the MAC address chip and extract the value from it. The result (including the existing line shown above) could look like this:

  Wire.begin();
  mac[0] = readRegister(0xFA);
  mac[1] = readRegister(0xFB);
  mac[2] = readRegister(0xFC);
  mac[3] = readRegister(0xFD);
  mac[4] = readRegister(0xFE);
  mac[5] = readRegister(0xFF);
  Ethernet.begin(mac, ip);

Next, you need to add the "readRegister()" function to your sketch. Simply add this at the end of the sketch:

 

byte readRegister(byte r)
{
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(r);  // Register to read
  Wire.endTransmission();

  Wire.requestFrom(I2C_ADDRESS, 1); // Read a byte
  while(!Wire.available())
  {
    // Wait
  }
  v = Wire.read();
  return v;
}

 

That's it, you're done. The WebServer sketch will now use the MAC address from the 24AA025E48 instead of the hard-coded value. You can follow these same steps to convert almost any Ethernet sketch to use the MAC address chip.

Disabling the MAC address chip and I2C pullups

Because the 24AA025E48 uses I2C communications, boards which have it preinstalled also have pull-up resistors already fitted to the I2C SCL and SDA lines. These pull-ups are necessary for I2C communications to work. If you want to connect more I2C devices to your board you will not need to add extra pull-up resistors, because they are already included on the main board.

If you are adding another I2C device or module that already includes pull-ups, you should disable the pull-ups on that device. Only one set of pull-ups is required, and having multiple pull-ups may prevent the I2C bus from working. Freetronics modules that use I2C typically have solder jumpers to enable I2C pull-ups, so check that any modules you connect do not have the pull-ups enabled.

In some cases you may want to totally disable the 24AA025E48 MAC address chip so that you can use the SCL / SDA lines for another purpose. For example, on the EtherTen those lines are also connect to analog inputs A4 and A5, so to use those lines for reading analog values you need to disable the MAC chip and the I2C pull-up resistors.

You can do this on both the EtherTen and the EtherMega using cut-track jumpers on the bottom of the PCB, labelled either "ISOLATE MCP I2C" or "ISOLATE SDA/SCL". Use a sharp blade to cut the tiny gold link between the pairs of solder pads to disable the MAC address chip and pull-up resistors.

The pictures below show the location of the cut-track jumpers on the EtherMega and the EtherTen.

If you wish to re-enable the MAC chip and pull-up resistors for a future project, simply bridge across the two pairs of pads using solder.

Related Articles: