[Post] Cómo monitorizar red de sensores con Ivy IoT Gateway

[Post] Cómo monitorizar red de sensores con Ivy IoT Gateway

| By:

En este artículo se explica como monitorizar un transductor digital multiparamétrico que mide intensidad, voltaje, potencia y frecuencia de un circuito DC

Ivy IoT Gateway es una pasarela de datos de fácil uso que permite interactuar de forma remota con dispositivos mediante el protocolo industrial Modbus.

En este articulo vamos a monitorizar los parámetros de voltaje, corriente y potencia de dos sensores de manera simultanea con Ivy IoT Gateway.

Lo primero que debemos hacer es documentarnos sobre los dispositivos vamos a utilizar en la realización de este ejemplo. En nuestro caso los dispositivos que vamos a utilizar son los siguientes.

Sensor 1: Digital transducer

Modelo: CE-AD11B-32ES5

Documentación: https://www.ce-transducer.com/product/details/185/103/details

Sensor 2: Digital transducer

Modelo: CE-AD11B-32GS4

Documentación: https://www.ce-transducer.com/product/details/185/108/details

Para poder comunicarnos con cada sensor debemos de saber previamente algunos datos relacionados con Modbus.

Dirección de esclavo: Es la dirección que tiene cada uno de los sensores que vamos a monitorizar. Esta deber ser diferente para cada uno de los sensores que vamos a monitorizar. En nuestro caso son:

Sensor Dirección (Hex)
Sensor 1 0x01
Sensor 2 0x02

Dirección de datos: Cada parámetro que queramos monitorizar tiene una dirección especifica. En cada dirección un registro de memoria guarda el valor del parametro para que a través de Modbus lo podamos consultar. Las direcciones que vamos a utilizar son:

Parámetro Dirección (Hex)
Voltaje 0x0010
Intensidad 0x0011
Potencia 0x0012
Potencia Activa 0x0013

Una vez tenemos todos la información, nos disponemos a utilizar Ivy IoT Gateway para la realización de este ejemplo.

Paso 1: Conexión con Ivy IoT Gateway

Ivy IoT Gateway contiene un adaptador RJ11-RS485 que nos permite a través de ella comunicarnos con cualquier dispositivo compatible con Modbus. Existen dos tipos de topología a la hora de conectar ambos dispositivos.

  • Paralelo: Consiste en tener conectados los dos dispositivos directamente al adaptador.

  • Serie: Consiste en conectar directamente al adaptador un solo dispositivo, a su vez a este dispositivo conectamos el otro dispositivo. En caso de tener más, al ultimo dispositivo se conectará el siguiente y a este último el siguiente.

Para realizar la conexión con los sensores puedes pinchar aquí.

Paso 2: Conexión de Ivy IoT Gateway con nuestro PC

Situados ambos en la misma red, nos conectaremos a Ivy IoT Gateway mediante ssh para crear nuestro programa y, posteriormente, ejecutarlo. Puedes ver como se hace aquí.

Paso 3: Creación de nuestro programa

Para poder ejecutar nuestro programa o cualquier otro que nosotros hagamos, tenemos dos opciones a la hora de crearlo:

  • En nuestro PC: Podemos crear nuestro programa con cualquier editor de texto. Una vez creado podemos enviarlo a Ivy IoT Gateway a través del protocolo SFTP.

  • En Ivy IoT Gateway: Podemos crear nuestro programa con el editor vi y ejecutarlo sin necesidad de transferencia de ficheros.

Para poder usar la libería de Modbus, debemos de importarlo y crear una instancia del mismo, para ello:

from ivy_gw.modules.modbus import modbus
m = modbus.Modbus()

Antes de seguir, se recomienda que se lea toda la información sobre Modbus de la que se dispone para una mejor comprensión de lo que acontinuación se va a realizar, para ello pinche aquí.

Inicialmente, los sensores tienen por defecto la misma dirección. Por ello lo primero que debemos hacer es cambiar la dirección de uno de los sensores. Para cambiarla debemos de modificar el registro 0x0020, escribiendo en este la nueva dirección del sensor. Para ello utilizamos la siguiente trama y con la función raw, podemos enviar la trama y cambiarla. Este paso solo se debe hacer con el sensor que queramos cambiar conectado.

slave = '\x01'
code_read = '\x10'
start_address = '\x00\x20'
num_of_registers = '\x00\x01'
data_bytes = '\x02'
data_writter = '\x02\x06'
tx_address = slave + code_read + start_address + num_of_registers + data_bytes + data_writter

tx_address=tx_address+m.get_crc(tx_address)
rx_address=m.raw(tx_address)

Este paso tan solo se va a realizar una vez, por tanto, podemos hacerlo en un script a parte de nuestro programa puesto que la dirección aunque se apague el dispositivo se guarda. Hecho esto, ya podemos elaborar nuestro programa.

1. Creación de la trama (Tx).

La trama es un conjunto de bytes que contiene toda la información necesaria para poder monitorizar nuestros dispositivos. Los campos que la componen son: dirección del dispositivo, la acción a realizar, la dirección del parámetro, y cuantos vamos a medir.

En nuestro caso vamos a medir el voltaje y la intensidad de las fases A, B, C. La primera dirección es (0x0010), el voltaje de fase A descrita en la documentación, y vamos a medir los seis siguientes parámetros.

slave = '\x01'
code_read = '\x03'
start_address = '\x00\x10'
num_of_registers = '\x00\x06'

tx = slave + code_read + start_address + num_of_registers

tx=tx+m.get_crc(tx)

Una vez que tenemos lista la trama, debemos hacer es añadirle el CRC, una extensión para asegurarnos que no se produzca ningún fallo en el envío y recepción. Para el caso del segundo sensor el código sería igual, excepto la dirección del sensor que sería \x02.

2. Envío y recepción de la trama.

Para enviarla lo hacemos a través de la función raw de Modbus. Esta función se encarga de poder transmitir la trama y recibir la respuesta.

rx=m.raw(tx)

Como podemos ver, rx es la trama de respuesta al envío de la trama tx.

3. La respuesta a nuestra trama (Rx).

Rx es la trama que recibimos del dispositivo que deseamos monitorizar. Esta trama contiene, en bytes, la información que nosotros le hemos pedido monitorizar. La trama tiene la siguiente estructura.

Trama Significado
1 Byte Dirección esclavo
1 Byte Acción
1 Byte Nº bytes de valores
2*N Bytes Valor del parámetro
2 Bytes CRC

Como vemos, la trama nos devolberá tantos pares de bytes como parámetros le digamos que nos monitorice. Cada par de bytes representa el valor de un parámetro.

Para conseguir datos de la trama, utilizamos el comando struct.unpack(), con ello podemos pasar los bytes a datos enteros. En el siguiente ejemplo podemos ver como extraer un dato de la respuesta . Para más información sobre este comando pincha aquí.

    result = struct.unpack('<H',rx[3:5])[0]

En este caso contamos con más de un parámetro para monitorizar, por ello vamos a guardar en un vector todos los parámetros. Para ello utilizamos el comando result.append() que guarda en la ultima posición del vector el valor asignado.

def parse_values(rx):

    result = []
    #Dirección del esclavo
    result.append(struct.unpack('<B',rx[0])[0])
    #Datos monitorizados
    result.append(struct.unpack('<H',rx[3:5])[0])
    result.append(struct.unpack('<H',rx[5:7])[0])
    result.append(struct.unpack('<H',rx[7:9])[0])
    result.append(struct.unpack('<H',rx[9:11])[0])
    result.append(struct.unpack('<H',rx[11:13])[0])
    result.append(struct.unpack('<H',rx[13:15])[0])

    return result

Con esta función conseguimos extraer toda la información de interés de la trama. Esto se puede hacer manera más versátil mediante el siguiente bucle, este permite extraer los datos sin cambiar el código en el caso de incrementar o disminuir el número de parámetros a monitorizar.

def parse_values(rx):

    result = []
    #Dirección del esclavo
    result.append(struct.unpack('<B',rx[0])[0])
    #Datos monitorizados
    i=len(rx)-5
    j=3
    while (i>0):
          result.append(struct.unpack('<H',rx[j:j+2])[0])
          j=j+2
          i=i-2

    return result

4. Representación de los datos.

Para poder mostrar los datos por pantalla, basta con utilizar la función print para ver los valores del vector result. Esta parte se puede hacer de muchas maneras diferentes, en este caso se ha creado una función para mostrarlos por pantalla.

def print_values(result):
    print 'Sensor', result[0]
    print '----- MEASUREMENT -----'
    if len(result)==5
      print "Voltage : "+str(result[1])+"V"
      print "Current : "+str(result[2])+"A"
      print "Power   : "+str(result[3])+"W"
      print "Active power: "+str(result[4])+"W"
    print '--------------------------'

5. Ejecución del programa.

Nuestro main debería quedar de la siguiente manera o parecida.

if __name__ == '__main__':

    tx_slave1='\x01\x03\x00\x10\x00\x06'
    tx_slave1=tx_slave1+m.get_crc(tx_slave1)

    tx_slave2='\x02\x03\x00\x10\x00\x06'
    tx_slave2=tx_slave2+m.get_crc(tx_slave2)


    while True:

        rx_slave1=m.raw(tx_slave1)
        result_slave1=parse_values(rx_slave1)
        print_values(result_slave1)

        rx_slave2=m.raw(tx_slave2)
        result_slave2=parse_values(rx_slave2)
        print_values(result_slave2)

        time.sleep(0.5)

Una vez realizado el programa, en Ivy IoT Gateway, ejecutamos el programa mediante el siguiente comando.

python ejemplo.py

Si nuestro programa no contiene ningún fallo, se debe de ejecutar perfectamente, empezar a monitorizar nuestros dos sensores y poder ver los resultados.

Si le queda alguna duda, puede ver si lo desea ver el código completo del ejemplo aqui.