Configuración de Ethernet desde la EEPROM utilizando la línea de comandos

10 de diciembre de 2018 por
Configuración de Ethernet desde la EEPROM utilizando la línea de comandos
Alejandro Jabalquinto

Introducción

En este post, se mostrará cómo configurar los parámetros de Ethernet guardados en la EEPROM: dirección MAC y dirección DHCP/IP.


Requisitos

Ethernet PLC:                           Ethernet PLC

Librería de línea de comandos:        Librería CmdLine      

Placas Industrial Shields: Cómo utilizar los pines de mapeo de las placas Industrial shields       

Guía del usuario del PLC Ethernet:  Guía del usuario de la familia M-Duino  



Descripción

Se utiliza la Librería EEPROM para almacenar los parámetros de configuración. La estructura 'conf_t' define los parámetros que se guardarán en la EEPROM: tipo y nombre.

En este caso, los parámetros se utilizan para guardar la configuración de Ethernet, por lo que se utiliza también la Librería Ethernet (Ethernet/Ethernet2). *Ethernet para la versión v7 y Ethernet2 para la versión PLUS.

Es posible añadir más parámetros: puedes añadir parámetros en la estructura 'conf_t' y crear las funciones/comandos para editarlos. Se recomienda añadir un valor por defecto de los nuevos parámetros en la variable default_conf. Puede ser cualquier tipo de parámetro, no sólo relacionado con la red.

Por último, hay un par de funciones que se utilizan como funciones de ayuda.

Es importante tener en cuenta que después de establecer los parámetros de configuración (comandos mac, dhcp-on, dhcp-off e ip), es necesario guardarlo en la EEPROM (comando save), y reiniciar el dispositivo para utilizar la nueva configuración. 

Siempre es posible restaurar los parámetros por defecto utilizando el comando defaults (recuerda guardar antes de reiniciar el dispositivo). 

También es posible recargar la configuración desde la EEPROM cuando se modifica un parámetro.

 

Implementación

El comando de ayuda imprime los comandos disponibles con una breve descripción.

 

Añadir un nuevo comando

Para añadir un nuevo parámetro:

  1. Añade el parámetro al final de la estructura 'conf_t'.
  2. Añade el valor del parámetro por defecto en la variable 'default_conf'.
  3. Declarar una función para editar el parámetro : 'void setParam(const char *arg);'.
  4. Añade un comando para editar el parámetro en la variable 'commands': '{"param", setParam}'.
  5. Añade la descripción del comando a la función 'printHelp'.
  6. Implementa la nueva función: 'void setParam(const char *arg) { ...}'.

 

Código


// 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
// See https://github.com/IndustrialShields/arduino-CmdLine
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;
}

Buscar en nuestro blog

Configuración de Ethernet desde la EEPROM utilizando la línea de comandos
Alejandro Jabalquinto 10 de diciembre de 2018
Compartir

¿Estás buscando tu Controlador Lógico Programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.


Industrial PLC comparison >>>