Pseudo Hardcoded MAC

The EtherTen combines an Uno-equivalent Arduino-compatible board and Wiznet-based Ethernet support, along with a microSD card slot and Power-over-Ethernet support. [Product page]
RedDogInCan
Posts: 7
Joined: Sat Nov 03, 2012 8:24 am

Pseudo Hardcoded MAC

Postby RedDogInCan » Fri Apr 19, 2013 9:39 pm

I have a few Ethertens in use on my network and I needed a way to give them a hardcoded MAC address for DHCP purposes. There are a few different solutions on the Internet but they were either based on random numbers or required additional hardware (like a 1-wire device). All I needed was a simple solution to set the MAC address once only per board and not require unique sketches for each board.

The solution I came up with is to save the MAC address in eeprom. There are two parts - the first part is a simple sketch (below) that accepts the MAC address from the serial terminal and writes it to eeprom. This only has to run once per board to initialise the MAC address on that board, though you can run it again if you want to change the address.

Code: Select all

#include <EEPROM.h>
const int eepromMacFlag = 0; // 1 byte
const int eepromMacAddress = 1; // 3 bytes

/*
  Set_MAC_Address
 
  Prompts for a MAC address from the serial port and stores it in EEPROM for use by later sketches.
 
  */
 
// Set up ethernet
// assign a MAC address for the ethernet controller.
// MAC address is stored in EEPROM on initial run
byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x00, 0x00};

byte loadMAC = true;

int SerialReadHexDigit() {

  while (Serial.available() == 0) {
    // do nothing
  }
  byte c = (byte) Serial.read();
  Serial.print((char)c);
  if (c >= '0' && c <= '9') {
    return c - '0';
  }
  else if (c >= 'a' && c <= 'f') {
    return c - 'a' + 10;
  }
  else if (c >= 'A' && c <= 'F') {
    return c - 'A' + 10;
  }
  else {
    return -1;   // getting here is bad: it means the character was invalid
  }
}

int SerialReadHexByte() {
  byte a = SerialReadHexDigit();
  byte b = SerialReadHexDigit();
  if (a<0 || b<0) {
    return -1;  // an invalid hex character was encountered
  }
  else {
    return (a*16) + b;
  }
}

char * printMac(byte * mac) {
  char macstr[18];
  snprintf(macstr, 18, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  Serial.println(macstr);
}


void setup() {
  // start serial port:
  Serial.begin(9600);

  Serial.println("");

  // Retrieve MAC address from EEPROM if present
  if (EEPROM.read(eepromMacFlag) == '#') {
    Serial.print("MAC address already in EEPROM: ");
    for (int i = 0; i < 3; i++) {
      mac[i+3] = EEPROM.read(eepromMacAddress + i);
    }
    printMac(mac);
   
    Serial.print("Overwrite (Y/n)? ");
    while (Serial.available() == 0) {
      // do nothing
    }
    char c = Serial.read();
   
    if (c == 'n' || c == 'N') { loadMAC = false; }

    Serial.println("");
  }
 
  if (loadMAC) {
   
    Serial.println("Initialising MAC address");

    byte macchar[2];

    for (int i = 0; i < 3; i++) {
      Serial.println("");
      Serial.print("Enter MAC address byte ");
      Serial.print(i+3);
      Serial.print(": ");

      mac[i+3] = SerialReadHexByte();
      EEPROM.write(eepromMacAddress + i, mac[i+3]);
    }
    EEPROM.write(eepromMacFlag, '#');

    Serial.println("");

    Serial.print("Saved MAC Address:");
    printMac(mac);
  } else {
    Serial.println("Aborted");
  }
 
}

void loop(){
}


The second part (below) is the code added to any ethernet sketch to retrieve the MAC address from eeprom.

Code: Select all

#include <SPI.h>
#include <util.h>
#include <EEPROM.h>
// EEPROM locations
const int eepromMacFlag = 0; // 1 byte
const int eepromMacAddress = 1; // 3 bytes

#include <Ethernet.h>

// Default MAC address for the ethernet controller.
// Unique MAC address can be stored in EEPROM using Set_MAC_Address sketch
byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0xFF, 0xFF};

const int outputStringLen = 200;
char outputString[outputStringLen];  // buffer used for constructing output strings

void setup() {
  // start serial port:
  Serial.begin(9600);

  // start the Ethernet connection and the server:
  // Retrieve MAC address from EEPROM if present
  if (EEPROM.read(eepromMacFlag) == '#') {
    Serial.println("Retrieving MAC address from EEPROM");
    for (int i = 0; i < 3; i++) {
      mac[i+3] = EEPROM.read(eepromMacAddress + i);
    }
  }
  else {
    Serial.println("No MAC address stored in EEPROM");
    Serial.println("Using default MAC address");
  } 

  snprintf(outputString, outputStringLen, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  Serial.print("MAC Address: ");
  Serial.println(outputString);

  Serial.println("DHCP...");

  while (Ethernet.begin(mac) == 0) {
    Serial.println("No DHCP");
    delay(1000);
    Serial.println("DHCP...");
  }
  Serial.println("IP address: ");
  Serial.println(Ethernet.localIP());

}
Last edited by RedDogInCan on Mon Apr 29, 2013 1:52 pm, edited 1 time in total.

User avatar
tronixstuff
Freetronics Staff
Freetronics Staff
Posts: 341
Joined: Tue Nov 01, 2011 10:03 am
Location: Melbourne, Australia

Re: Psuedo Hardcoded MAC

Postby tronixstuff » Sat Apr 20, 2013 1:24 am

That's an excellent solution to your problem - well done :)


Return to “EtherTen”

Who is online

Users browsing this forum: No registered users and 1 guest

cron