Arduino escribiendo Protocolo Mewtocol de PLC’S Panasonic

Gracias a las solicitud de  uno de mis suscriptores he creado este tutorial, en el cual se escribirá en registros de un PLC Panasonic (Nais) de la  Familia FPX Series, Estos PLC son muy prácticos y un alto porcentaje de maquinas lo tienen como unidad de control.

En esta ocasion utilizare un Arduino MEGA 2560 R3 y un convertidor MAX232  (RS232) para escribir en registros DT del PLC, dado que en la red estan los manuales del Protocolo Mewtocol de panasonic que es utilizado por PLC’S, HMI Pantallas, Variadores, Servo Drives entre otros dispositivos industriales.






El Arduino se comunicara por el Toolport, puerto de programación del PLC que soporta la configuración como Maestro-esclavo Mewtocol- Computer Link y propósito general (Basculas, lectores de codigo de barras)

El protocolo Mewtocol tiene similitudes a Modbus, aunque el Mewtocol mezcla Hexadecimal y Ascii en sus tramas,  con 2 convertidores seriales usb, 1 PLC y una panatalla panasonic, me tome la tarea de espiar físicamente la trama, comprenderla y replicarla en Arduino IDE.

Realterm

Realterm

Solo hemos implementado una parte de Mewtocol, específicamente las tramas [WD] Write data area  que escriben en solo permite escribir  los registros  DT, LD, y FL, Solo de escritura.

Descripcion de Trama Mewtocol

Esta trama permite escribir en los registros:

  • DT  Data Registers
  • LD  Link Data Registers
  • FL  File Registers

Frame-Mewtocol

Arduino IDE

Funcion addcero

Esta funcion concatena una serie de ceros a la izquierda «0000» a una variable de entrada segun el tamaño maximo que se requiere de salida y la retorna de salida. parametros de entrada String (Variable a concatenar )  int tamaño o cantidad de ceros  maximo a adicionar.

ejemplo: addcero(«10»,5)   retorna  «10»+»000″.

 String addcero(String value ,int Max )
{
int Tam = value.length() ;
String ceroadd="";

for (int i=0; i <  (Max - Tam) ; i++){ 
 ceroadd+="0";
}
value=ceroadd+value;
return value;

}

 Funcion WD_Mewtocol

La funcion principal es  WD_Mewtocol  que genera y envia  la trama mewtocol, esta funcion  requiere 2 parametros de entrada

  1.  String Direccion de registro, ejemplo «DT100».
  2.  int 16 bits  valor que se escribira en el «DT100»

Encabezado

Indica el inicio de trama e indica el tipo de registro sobre el cual se quiere escribir:

ejemplo: %EE#WD» + Datacode (D or L or F).

////////////// Header - Encabezado /////////////////////////
String DT = "D"; /// Data Registers
String LD = "L"; /// Link Data Registers
String FL = "F"; /// File Registers
String Datacode = DT; ///// DT Registers
String Encabezado="%EE#WD"+Datacode; 
///////////////////////////////////////////////////////////////

Tipo de Registro y Direccion de Registro

Separa la direccion del tipo de registro y concatenamos ceros.

 ejemplo  «DT»,»1000″

String DireccionDT = RegistroDT.substring(2,6) ;
DireccionDT = addcero(DireccionDT,5);

 Conversion de valor  int, Hex a Ascii

El valor a enviar requiere un proceso para adicionarlo  a la trama.

  1. Se debe separa la capa alta y baja de del valor utilizamos la funciones highByte y lowByte.
  2. convertir ambos registros de hex a String.
  3. convertir a Mayusculas.
  4. Rellenar con ceros a la izquierda funcion addcero.
////////          High and Low Value, conversion int to HEX and String 
/////////         Parte Alta y Baja de Valor , conversion int a HEX y String 
byte hi, lo; // 8 bits C/U 
hi = highByte(valor); 
lo = lowByte(valor); 

String valorH=String(hi, HEX);
String valorL=String(lo, HEX);

valorL.toUpperCase();
valorL = addcero(valorL,2);// Add padding zeros left

valorH.toUpperCase();
valorH = addcero(valorH,2); /// Add padding zeros left

Concatenación de Trama

//////////// Frame Concatenation ////////////////////////////////////
//////////// Concatenación de trama ////////////////////////////////////
Trama = (Encabezado + DireccionDT + DireccionDT + valorL + valorH );
Trama.toUpperCase();
///////////////////////////////////////////////////////////////////////////

Calculo BCC

BCC (código de verificación de bloque)
– El BCC es un código que realiza una comprobación de errores mediante paridad horizontal, para
Mejorar la fiabilidad de los datos que se envían.
– El BCC utiliza un OR exclusivo desde el encabezado (%) hasta el carácter final del
Texto y convierte los datos de 8 bits en un código ASCII de 2 caracteres.

BCC-Mewtocol

BCC en Arduino

Tomamos la trama completa, y con la funcion getBytes la movemos a un array de byte y el bucle for  realiza una or exclusiva con los registros y el resultado BCC lo convertimos a String y lo concatenamos a al final de la trama, si el BCC esta erroneo el PLC panasonic descartara la trama automaticamente.

 int TramaTam =Trama.length(); // Longitud Trama // Length Frame
byte tram_arreglo [TramaTam]; // Array Bytes
Trama.getBytes(tram_arreglo,TramaTam+1); /// Stores Frame in BYTES Array 

byte bcc = 0; 
String BCC;

 for (int i=0; i <= (TramaTam - 1); i++){ 
 bcc ^= tram_arreglo[i]; /// exclusive or 
 }
BCC =String(bcc, HEX); ////// BCC to String

/////////////////////Concatenate BCC to frame////////////////////
Trama = Trama + BCC ;
Trama.toUpperCase();
/////////////////////////////////////////////////////////////////

Envio de Trama

Finalmente enviamos la trama por el Puerto Serial1 y concatenamos solo  CR.

Serial1.print(Trama+"\r");

Confirmacion de Respuesta de PLC

Luego de enviar la trama, el PLC envia como respuesta una trama,  indicando si es correcta  enviara algo similar a esto «%EE$WD12 « y en error  de trama «%EE!4202».

String respuesta =(Serial1.readString());
String Error = respuesta;
Serial1.setTimeout(200); //////Timeout 
String Validacion = respuesta.substring(0,6);
 
 if(Validacion =="%EE$WD") //Normal response (Write successful)
 {
 
 Serial.print(RegistroDT);
 Serial.println(" = OK");
 digitalWrite(13, HIGH); 
 }
 else
 { 
 Serial.print(RegistroDT);
 Serial.print(" = FAIL !!!! Error = "); 
 Serial.println(Error);
 digitalWrite(13, LOW); 
 }

Codigo Completo

Nota: Descarga codigo desde Github enlace en parte inferior:

/*
 * Rutina de escritura Protocolo Mewtocol WD Write data area, creada para Equipos 
 * Industriales Panasonic Principalmente PLC'S y HMI' entre otros dispositivos
 * Write Routine Protocol Mewtocol WD Write data area, created for Panasonic Industrial 
 * Equipment Mainly PLC'S and HMI 'among other devices
 * 
 * Created by PDAControl
 * Write DT'S Registers
 * 
 * More info : http://pdacontrolen.com
 * Mas informacion: http://pdacontroles.com
 * Channel Youtube https://www.youtube.com/c/JhonValenciaPDAcontrol/videos 
 * 
 * 
 * Routine write-only in registers - Rutina solo escritura en registros
 * DT = Data Registers
 * LD = Link Data Registers
 * FL = File Registers
 * 
 */

void setup() {
 

pinMode(13, OUTPUT); // ON= "Communication OK" OFF = "Communication ERROR or OFF PLC "
Serial.begin(9600); /// Debug serial
Serial1.begin(9600,SERIAL_8O1); /// Communication PLC Panasonic

}




// Funtion ADDCERO
//////////////////////////////////////////////////////////////////
///Esta funcion rellena con ceros a la izquierda dependiendo del tamaño requerido
///This function fills with leading zeros depending on the required size example in(10,5) = 10000 add 3 zeros 

String addcero(String value ,int Max )
{
int Tam = value.length() ;
String ceroadd="";

for (int i=0; i < (Max - Tam) ; i++){ 
 ceroadd+="0";
}
value=ceroadd+value;
return value;

}
////////////////////////////////////////////////////////////////////////



////////////////////Funtion WD_MEWTOCOL ////////////////////////////////////////////////////////////////////////////////

// EXAMPLE DT300 = 100 // Value 100 = 64 hex ->> invertir L (64) H (100)
// This function takes input data and creates the entire write frame. Mewtocol performs the following:
// Header + REGISTRY TYPE + Address Register + Address Register + Conversion of int value to HEX to value in ASCII + Checksum (BCC)
// %EE#WD-----------D ------------00300-------------00300----------------64 00-------------------------------------------53

// Ejemplo DT300 = 100 // Valor 100 = 64 hex ->> invertir L (64) H (100)
// Esta funcion toma datos de entrada y crea toda la trama de escritura Mewtocol realiza lo siguiente:
/// Encabezado + TIPO REGISTRO + Direccion Registro + Direccion Registro + Conversion de Valor int a HEX a valor en ASCII + Checksum (BCC) 
// %EE#WD-----------D ------------------00300-----------------00300----------------64 00--------------------------------------53 

void WD_Mewtocol(String RegistroDT, int valor )
{
 
 //String Trama ="%EE#WDD0030000300640053"; // test 
String Trama=""; 

////////////// Header - Encabezado /////////////////////////
String DT = "D"; /// Data Registers
String LD = "L"; /// Link Data Registers
String FL = "F"; /// File Registers
String Datacode = DT; ///// DT Registers
String Encabezado="%EE#WD"+Datacode; 
///////////////////////////////////////////////////////////////

/////////////////////////TIPO REGISTRO//////////////////////////////////////
String DireccionDT = RegistroDT.substring(2,6) ; /// Recorta direccion DT ej: DT1000 ---> //// Cut DT direction eg: DT1000 ---> 1000
DireccionDT = addcero(DireccionDT,5); /// agrega relleno ceros ala izquierda /// Add padding zeros left
///////////////////////////////////////////////////////////////

//////////////////////High and Low Value, conversion int to HEX and String //////////////////
//////////////////////Parte Alta y Baja de Valor , conversion int a HEX y String ///////////////////
byte hi, lo; // 8 bits C/U 
hi = highByte(valor); 
lo = lowByte(valor); 

String valorH=String(hi, HEX);
String valorL=String(lo, HEX);

valorL.toUpperCase();
valorL = addcero(valorL,2); /// agrega relleno ceros ala izquierda /// Add padding zeros left
//Serial.println(valorL);

valorH.toUpperCase();
valorH = addcero(valorH,2); /// agrega relleno ceros ala izquierda /// Add padding zeros left
//Serial.println(valorH);
//Serial.println(valorL+valorH);
/////////////////////////////////////////////////////////////////////////////////////////////////////////


//////////// Frame Concatenation ////////////////////////////////////
//////////// Concatenación de trama ////////////////////////////////////
Trama = (Encabezado + DireccionDT + DireccionDT + valorL + valorH );
Trama.toUpperCase(); /////////CONVERTING String to upper case - CONVERSIÓN DE String a mayúsculas
///////////////////////////////////////////////////////////////////////////



/////////////////////////CALCULO BCC (Checksum de seguridad)////////////////////////////////////////////////
///////////////////////// BCC CALCULO (Security Checksum)//////////////////////////////////////////////////
/* 
 * El BCC es un código que realiza la verificación de errores de paridad horizontal para Mejorar la fiabilidad de los datos que se envían.
 * El BCC utiliza un OR exclusivo desde el encabezado (%) hasta el carácter final del Texto y convierte los datos de 8 bits en un código ASCII de 2 caracteres.
 * 
 * The BCC is a code that performs horizontal parity error checking to Improve the reliability of the data being sent.
 * The BCC uses an exclusive OR from the header (%) to the final character of the Text and converts the 8-bit data into a 2-character ASCII code. * 
 */
 
int TramaTam =Trama.length(); // Longitud Trama // Length Frame
byte tram_arreglo [TramaTam]; // Array Bytes
Trama.getBytes(tram_arreglo,TramaTam+1); // almacena Trama en BYTES Array // Stores Frame in BYTES Array 

byte bcc = 0; 
String BCC;

 for (int i=0; i <= (TramaTam - 1); i++){ 
 bcc ^= tram_arreglo[i]; /// exclusive or 
 }
BCC =String(bcc, HEX); ////// BCC to String 
////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////Concatenate BCC to frame///////////////////////////////////////////////////////////
Trama = Trama + BCC ;
Trama.toUpperCase();
///////////////////////////////////////////////////////////////////////////////////////////////////////


////////////////Sends Frame for Serial1 Port "Arduino Mega"/////////////////
Serial1.print(Trama+"\r");
///////////////////////////////////////////////////////////////////////////


/////////////////////////Confirmation response from PLC //////////////////////////////////////////////////
/////////////////////////Respuesta de confirmacion desde PLC////////////////////////////////////////////////+
/////////////////// %EE$WD12 = OK


String respuesta =(Serial1.readString());
String Error = respuesta;
Serial1.setTimeout(200); //////Timeout 
String Validacion = respuesta.substring(0,6);
 
 if(Validacion =="%EE$WD") //Normal response (Write successful)
 {
 
 Serial.print(RegistroDT);
 Serial.println(" = OK");
 digitalWrite(13, HIGH); 
 }
 else
 { 
 Serial.print(RegistroDT);
 Serial.print(" = FAIL !!!! Error = "); 
 Serial.println(Error);
 digitalWrite(13, LOW); 
 }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


 
}



void loop() {

 int adc = analogRead(A0);
 Serial.println(adc);
 delay(50);
 
 WD_Mewtocol("DT100",adc); 
 delay(50);
 WD_Mewtocol("DT101",adc); // 65537
 delay(50);
 WD_Mewtocol("DT102",adc); //32768
 delay(50);



}

Materiales

  • Arduino MEGA 2560 R3
  • Convertidor MAX232
  • Equipo Industrial Panasonic, PLC o Pantalla





Montaje

Arduino_PLC_Panasonic

Conclusiones

En este caso se ha creado esta trama para un PLC Panasonic pero con la destreza 2 convertidores seriales y el dispositivo en cuestion y la documentación pueden generar la trama de comunicación para cualquier marca  dispositivo sea PLC o HMI.

Tener en cuenta  funcion  WD_Mewtocol,  funciona correctamente, pero aun esta en prueba, pero en caso de encontrar algun error.

La función solo permite la Escritura en registros, Para lectura de registros se debe crear una nueva trama que solicite datos de un registro especifico y el PLC enviara la respuesta que debe ser interpretada en arduino.

Con este ejemplo podrán escribir en cualquier registro DT principalmente de las familias de PLC Panasonic Fpx, FP0, FP0R, FP2, FP2SH y FPSigma entre otras familias existentes.

Actualmente se esta creando una  libreria Mewtocol para Arduino o ESP8266.

Facilmente este ejemplo que solo escribe en DT’S se puede modificar para la escritura de otros registros tales como Relay R, y Salidas Y, WR y WY.

Referencias

Descargas

Codigo Arduino IDE Arduino-Mewtocol-WriteArea

 





Deja una respuesta