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


7 comentarios:

  1. me gusto tu programa, estoy tratando de aprender de redes por una materia de la universidad!

    podrías ayudarme, que parametros le diste al MODSIM, lo que pasa es que siempree leo errores...

    una ves que le dices que puerto quieres conectar,
    que valores le das a
    Data bits
    Stop bits
    Parity

    y Hardwar flow control?

    saludos, gracias :)

    ResponderEliminar
  2. Hola, el conector rs232 a ttl se lee sin control de flujo por hardware en el caso que uses el Arduino, asegurate de que abras en el PC el puerto serial adecuado solo por aclarar te digo:

    La linea "Serial.begin(9600)" del Arduino se refiere al puerto de programacion y/o debug del Arduino en este caso a 9600bps sin hardware flow control
    La linea "PLCSerialPort.begin(9600)" indica que te vas a conectar a la remota a esta velocidad igualmente sin control de flujo por hardware.

    ResponderEliminar
  3. Disculpa que te pregunte tanto Alvaro, pero sigo teniendo CRC error...

    tengo modsim -> usb a db9 -> convertidor rs232 a ttl (con MAX232) -> y arduino.... podrias explicarme mas detallado para ver si doy con el error que traigo??

    ResponderEliminar
  4. Ah ok entiendo, el CRC error se presenta especificamente entre el ModSim y el Arduino, debes asegurarte de que la configuración sea 9600bps databits 8 stopbit 1 Parity None protocolo RTU para el caso de ejemplo que subí en el GitHub

    ResponderEliminar
  5. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
    Respuestas
    1. Mmm ni idea no debería faltar nada voy a hacer una prueba yo mismo a ver que pasa

      Eliminar
  6. Estan geniales las 2 partes del uso de la libreria !!! son muy utiles !!!

    Podrías explicarme la conección del RS232 TTL al protoboard y del board al Arduino??


    SALUDOS !!!

    ResponderEliminar