Ethernet configuration from the EEPROM using the Command Line

December 10, 2018 by
Ethernet configuration from the EEPROM using the Command Line
Alejandro Jabalquinto

Introduction

In this post, it will be shown how to configure the Ethernet parameters saved in the EEPROM: MAC address and DHCP/IP address.


Requirements

Ethernet PLC:                           Ethernet PLC

Command line library:        CmdLine library     

Industrial Shields boards: How to use the mapping pins of Industrial Shields boards       

Ethernet PLC User Guide:  M-Duino Family User Guide  



Description

It is used the EEPROM library to store configuration parameters. The ‘conf_t’ structure defines the parameters that will be saved into the EEPROM: type and name.

In this case, the parameters are used to save the Ethernet configuration, so it is used also the Ethernet library (Ethernet/Ethernet2). *Ethernet for v7 and Ethernet2 for PLUS version.

It is possible to add more parameters: you can add parameters into the ‘conf_t’ structure and create the functions/commands to edit them. It is recommended to add a default value of new parameters into the default_conf variable. It can be any kind of parameter, not only network related.

Finally, there are a couple of functions used as helper functions.

It is important to notice that after setting the configuration parameters (mac, dhcp-on, dhcp-off and ip commands), is necessary to save it to he EEPROM (save command), and reset the device to use the new configuration.

It is always possible to restore the default parameters using the defaults command (remember to save before resetting the device).

It is also possible to reload the configuration from the EEPROM when a parameter is changed.

 

Implementation

The help command prints the available commands with a short description.

 

Add a new command

To add a new parameter:

  1. Add the parameter at the end of the ‘conf_t’ structure.
  2. Add the default parameter value into the ‘default_conf’ variable.
  3. Declare a function to edit the parameter : ‘void setParam(const char *arg);’.
  4. Add a command to edit the parameter into the ‘commands’ variable: ‘{“param”, setParam}’.
  5. Add the command description to the ‘printHelp’ function.
  6. Implement the new function: ‘void setParam(const char *arg) { …}’.

 

Code


// Include libraries 
#include <CmdLine.h> 
#include <EEPROM.h> 
#ifdef MDUINO_PLUS
#include <Ethernet2.h>
#else
#include <Ethernet.h>
#endif
 
// Other constants
#define VALID        0xB0070000
 
//Define the configuration structure
//It is used to define how the configuration is stored into the EEPROM
typedef struct {
  uint32_t validity;    // value used to check EEPROM validity
  uint8_t mac[6];       // local MAC address
  uint8_t dhcp;         // 0: static IP address, otherwise: DHCP address
  uint8_t ip[4];        // local IP address
 
  // NOTE: you can add more parameters: DNS server, netmask, gateway,
  // remote server IP, remote server port, ...
} conf_t;
 
//Declare the configuration variable
conf_t conf;
 
// Define the default configuration variable
const conf_t default_conf = {
  VALID,                                    // validity
  {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED},     // mac
  0,                                        // dhcp
  {10, 10, 10, 25},                         // ip
 
  // NOTE: add additional parameters added into the conf_t: default DNS server, ...
};
 
// Declare commands functions (required before defining commands)
// These functions are executed when the user type the associated command
void printHelp(const char *arg);
void setDefaultConf(const char *arg);
void saveConf(const char *arg);
void loadConf(const char *arg);
void printConf(const char *arg);
void setMac(const char *arg);
void enableDhcp(const char *arg);
void disableDhcp(const char *arg);
void setIp(const char *arg);
 
// Define commands for CmdLine library
const cmd_t commands[] = {
  {"help", printHelp},
  {"defaults", setDefaultConf},
  {"save", saveConf},
  {"reload", loadConf},
  {"print", printConf},
  {"mac", setMac},
  {"dhcp-on", enableDhcp},
  {"dhcp-off", disableDhcp},
  {"ip", setIp},
};
CmdLine cmdLine(Serial);
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  // Start serial port
  Serial.begin(9600L);
 
  // Load EEPROM configuration
  loadConf(nullptr);
 
  // Print configuration
  printConf(nullptr);
 
  // Start Ethernet using the configuration
  if (conf.dhcp) {
    // DHCP configuration
    Ethernet.begin(conf.mac);
  } else {
    // Static IP configuration
    Ethernet.begin(conf.mac, IPAddress(conf.ip));
  }
 
  // Start CmdLine
  cmdLine.begin(commands, sizeof(commands));
}
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  // Update CmdLine library
  cmdLine.update();
}
 
// CmdLine library functions //
 
////////////////////////////////////////////////////////////////////////////////////////////////////
void printHelp(const char *arg) {
  Serial.println("General commands:");
  Serial.println("help        show this help");
  Serial.println();
  Serial.println("Configuration commands:");
  Serial.println("print       print current configuration");
  Serial.println("defaults    set default configuration values");
  Serial.println("mac <MAC>   set local MAC address (default: DE:AD:BE:EF:FE:ED");
  Serial.println("dhcp-on     enable DHCP");
  Serial.println("dhcp-off    disable DHCP");
  Serial.println("ip <IP>     set local IP address (default: 10.10.10.25)");
  Serial.println();
  Serial.println("EEPROM access commands:");
  Serial.println("reload      load EEPROM to configuration");
  Serial.println("save        save configuration to EEPROM");
}
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
void printConf(const char *arg) {
  Serial.print("MAC address: ");
  for (int i = 0; i < 6; ++i) {
    if (i > 0) {
      Serial.print(':');
    }
    if (conf.mac[i] < 0x10) {
      Serial.print('0');
    }
    Serial.print(conf.mac[i], HEX);
  }
  Serial.println();
 
  Serial.print("DHCP: ");
  Serial.println(conf.dhcp ? "ON" : "OFF");
 
  Serial.print("IP address: ");
  Serial.println(IPAddress(conf.ip));
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////
void saveConf(const char *arg) {
  // Put configuration to EEPROM (EEPROM address: 0x00)
  EEPROM.put(0x00, conf);
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////
void loadConf(const char *arg) {
  // Get configuration from EEPROM (EEPROM address: 0x00)
  EEPROM.get(0x00, conf);
 
  // Check EEPROM values validity
  if (conf.validity != VALID) {
    // Set default configuration
    setDefaultConf(nullptr);
 
    Serial.println("Invalid EEPROM: using default configuration");
  }
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////
void setDefaultConf(const char *arg) {
  // Copy default configuration to the current configuration
  memcpy(&conf, &default_conf, sizeof(conf_t));
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////
void setMac(const char *arg) {
  // Parse MAC address
  // The arg MUST be a valid MAC address (12 hexadecimal digits separated by ':' or '-')
  // i.e. DE:AD:BE:EF:FE:ED or DE-AD-BE-EF-FE-ED
  for (int i = 0; i < 6; ++i) {
    conf.mac[i] = parseByte(arg);
    arg += 3;
  }
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////
void enableDhcp(const char *arg) {
  // Enable DHCP
  // The arg is ignored
  conf.dhcp = 1;
}
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
void disableDhcp(const char *arg) {
  // Disable DHCP
  // The arg is ignored
  conf.dhcp = 0;
}
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
void setIp(const char *arg) {
  // Parse IP address
  // The arg MUST be a valid IP address
  // i.e. 10.10.10.25
  IPAddress ip;
  ip.fromString(arg);
  for (int i = 0; i < 4; ++i) {
    conf.ip[i] = ip[i];
  }
}
 
// HELPER FUNCTIONS //
 
////////////////////////////////////////////////////////////////////////////////////////////////////
byte parseByte(const char *arg) {
  byte ret = parseNibble(arg++) << 4;
  return ret + parseNibble(arg);
}
 
////////////////////////////////////////////////////////////////////////////////////////////////////
byte parseNibble(const char *arg) {
  if (*arg >= '0' && *arg <= '9') {
    return *arg - '0';
  } else if (*arg >= 'a' && *arg <= 'f') {
    return *arg - 'a' + 0x0a;
  } else if (*arg >= 'A' && *arg <= 'F') {
    return *arg - 'A' + 0x0a;
  }
  return 0;
}

​Search in our Blog

Ethernet configuration from the EEPROM using the Command Line
Alejandro Jabalquinto December 10, 2018
Share this post

Looking for your ideal Programmable Logic Controller?

Take a look at this product comparison with other industrial controllers Arduino-based. 

We are comparing inputs, outputs, communications and other features with the ones of the relevant brands.


Industrial PLC comparison >>>