domingo, 7 de julio de 2013

Uso de la libreria Modbusserial (2/2)

Después de caer en un vórtice espacio-tiempo (por muchas ocupaciones) vuelvo a escribir en el blog, muchos han preguntado como se usa la librería ModbusSerial

En la siguiente foto se pueden observar los elemento necesarios para hacer la prueba de la librería


El cable usb se conecta al PC en mi caso uso el ModSim para emular una Remota; este cable va conectado el conector RS232 el cual se coloca en el Protoboard para Arduino y con los cables se hace la conección final.

Se debe usar el código fuente base para usar la libreria Modbusserial.

Si no queremos que se muestre por la consola las respuesta de la remota solo se debe comentar la linea 

#define VERBOSE

en la libreria modbusseriallib.h

-------------------------------------------------------------
#include <SoftwareSerial.h>
#include "modbusseriallib.h"

#define RXPIN        4
#define TXPIN        5

SoftwareSerial PLCSerialPort(RXPIN, TXPIN);
ModbusSerial ModbusSerial(&PLCSerialPort);

void setup()
{
  Serial.begin(9600);
  PLCSerialPort.begin(9600);
}

void loop()
{
  // your program //
}
-------------------------------------------------------------

Como verán se puede cambiar el pin RX y TX de acuerdo a sus necesidades
El Objeto instanciado se llama ModbusSerial y se usa de la siguiente manera:

FC1
 
En caso de que deseen llamar la función fc1 de la librería deberán de tener la siguiente  consideración
* Es una función de lectura por lo tanto deben declarar una variable que reciba la información de la remota.
* Si queremos ver la respuesta utilizamos un pequeño ciclo for


Veamos el siguiente ejemplo: Si queremos preguntar por 37 discrete coils desde la direccion 20 inclusive, del Device 17 (ojo viene en formato decimal), codificamos lo siguiente: 

  byte deviceId=17;
  unsigned short start=20;
  int numValues=37;
  unsigned short values[numValues]; // aquí se almacena la respuesta
 
  ModbusSerial.fc1(deviceId,start,numValues,values);
 
  for(int i=0;i<numValues-1;i++)
      {
      Serial.print(values[i]);
      Serial.print(",");
      }
  Serial.println(values[numValues-1]);

Si tomamos en cuenta las respuestas que están en la entrada anterior "http://fernandezajp.blogspot.com/2013/01/libreria-modbus-serial-para-arduino.html", obtendríamos la respuesta de la siguiente manera

MSG:11,1,0,13,0,25,E,10
10 received.
PACKET:11,1,5,CD,6B,B2,E,1B,45,E6
Read successful
1,0,1,1,0,0,1,1,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,0,0,0,0,1,1,0,1,1


FC2
El mismo esquema aplicaría para la función fc2, en este caso la dirección de inicio es la 10197 y leeremos solo 22 valores luego lo almacenamos en la variable values.

  byte deviceId=17;
  unsigned short start=10197;
  int numValues=22;
  unsigned short values[numValues]; // aquí se almacena la respuesta
 
  ModbusSerial.fc2(deviceId, start, numValues,values);
 
  for(int i=0;i<numValues-1;i++)
      {
      Serial.print(values[i]);
      Serial.print(",");
      }
  Serial.println(values[numValues-1]);

Respuesta

MSG:11,2,0,C4,0,16,BA,8
8 received.
PACKET:11,2,3,CD,6B,32,45,C4
Read successful
1,0,1,1,0,0,1,1,1,1,0,1,0,1,1,0,0,1,0,0,1,1

FC3
Función fc3 (Read Holding Registers), ahora leeremos 3 valores a partir de la dirección 40108 y lo almacenaremos en la variable values.

  byte deviceId=17;
  unsigned short start=40108;
  int numValues=3;
  unsigned short values[numValues];
 
  ModbusSerial.fc3(deviceId, start, numValues, values);

  for(int i=0;i<numValues-1;i++)
      {
      Serial.print(values[i],HEX);
      Serial.print(",");
      }
  Serial.println(values[numValues-1],HEX);

La respuesta que obtendríamos seria

MSG:11,3,0,6B,0,3,76,11
11 received.
PACKET:11,3,6,AE,41,56,52,43,40,49,AD
Read successful

AE41,5652,4340

FC4
Función fc4 (Read Input Registers), ahora leeremos 1 valor correspondiente a la dirección 30009 y lo almacenaremos en la variable values.

  byte deviceId=17;
  unsigned short start=30009;
  int numValues=1;
  unsigned short values[numValues];
  
  ModbusSerial.fc4(deviceId, start, numValues, values);

  for(int i=0;i<numValues-1;i++)
      {
      Serial.print(values[i],HEX);
      Serial.print(",");
      }

  Serial.println(values[numValues-1],HEX);

Respuesta:

MSG:11,4,0,8,0,1,B2,7
7 received.
PACKET:11,4,2,0,A,F8,F4
10 Read successful

A

Ahora veamos ahora una de escritura

FC5
Esta función escribe un solo dato en una dirección específica por eso tiene menos parámetros
ej: escribir en la dirección 173 del DeviceId = 17 el valor de True

  byte deviceId=17;
  unsigned short start=173;
 
  ModbusSerial.fc5(deviceId, start, true);

Respuesta

MSG:11,5,0,AC,0,FF,4F,8
8 received.
PACKET:11,5,0,AC,0,FF,4F,3B
Read successful

El mismo caso aplica para los analógicos

FC6

Ej: Escribir en la dirección 40002 el valor de 3

  byte deviceId=17;
  unsigned short start=40002;
  unsigned short value=3;
 
  ModbusSerial.fc6(deviceId, start, value);

Respuesta

MSG:11,6,0,1,0,3,9A,8
8 received.
PACKET:11,6,0,1,0,3,9A,9B
Read successful


Para escribir múltiples valores discretos utilizamos la función 15

FC15

ej: Escribir un arreglo binario de 10 valores binarios en la dirección 20 del device 17.

  byte deviceId=17;
  unsigned short start=20;
  int numValues=10;
  boolean values[numValues];
 
  values[0] = 1;
  values[1] = 1;
  values[2] = 0;
  values[3] = 1;
  values[4] = 0;
  values[5] = 0;
  values[6] = 1;
  values[7] = 1;
  values[8] = 1;
  values[9] = 0;

  ModbusSerial.fc15(deviceId, start, numValues, values);

Respuesta

MSG:11,F,0,13,0,A,2,CB,1,BC,8
8 received.
PACKET:11,F,0,13,0,A,26,99
Read successful


el mismo esquema para los analógicos

FC16

Escribir un arreglo de 2 valores en la dirección 40002 del device 17.

  byte deviceId=17;
  unsigned short start=40002;
  int numValues=2;
  unsigned short values[numValues];
 
  values[0] = 0xA;
  values[1] = 0x102;

  ModbusSerial.fc16(deviceId, start, numValues, values);

Respuesta

MSG:11,10,0,1,0,2,4,0,A,1,2,C6,8
8 received.
PACKET:11,10,0,1,0,2,12,98
Read successful