emelianov / modbus-esp8266

Most complete Modbus library for Arduino. A library that allows your Arduino board to communicate via Modbus protocol, acting as a master, slave or both. Supports network transport (Modbus TCP) and Serial line/RS-485 (Modbus RTU). Supports Modbus TCP Security for ESP8266/ESP32.
Other
530 stars 189 forks source link

How to get data from multiple RTU devices? #260

Closed Merdock1 closed 1 year ago

Merdock1 commented 1 year ago

Hello, I need help to be able to get data from several devices connected on the same RTU network. The partial solution I found was the following: MB_RTU_Config.h

#pragma once
#ifndef MB_RTU_CONFIG_H
#define MB_RTU_CONFIG_H
#include <Arduino.h>
#include <ModbusRTU.h>
#define MODBUSRTU_TIMEOUT 350

const unsigned long intervaloLecturaTemp_0 = 500; // leeremos cada 1 segundos
unsigned long tiempoAnterior_0 = 0;
const unsigned long intervaloLecturaTemp_1 = 510; // leeremos cada 1 segundos
unsigned long tiempoAnterior_1 = 0;
const unsigned long intervaloLecturaTemp_2 = 520; // leeremos cada 1 segundos
unsigned long tiempoAnterior_2 = 0;
const int ID_FEP03 = 40;
const int ID_FEP04 = 41;
const int ID_FEU01 = 42;
const uint16_t FIRST_REG = 99;
const uint16_t REG_COUNT = 16;
uint16_t CAU_array_0[16];
uint16_t CAU_array_1[16];
uint16_t CAU_array_2[16];

uint16_t MB_RTU_ERROR_Read = 0;
uint16_t MB_RTU_OK_Read = 0;

// Inicio registros caudalimetro Hemoglobina.
// Valores float.
uint16_t FEP03_HR099 = 99;  // Caudal instantáneo.
uint16_t FEP03_HR100 = 100; // Caudal instantáneo.
uint16_t FEP03_HR101 = 101; // Velocidad de flujo instantánea.
uint16_t FEP03_HR102 = 102; // Velocidad de flujo instantánea.
uint16_t FEP03_HR103 = 103; // Porcentaje de flujo.
uint16_t FEP03_HR104 = 104; // Porcentaje de flujo.
uint16_t FEP03_HR105 = 105; // Conductividad eléctrica.
uint16_t FEP03_HR106 = 106;
// Registros contadores acumulacion.
uint16_t FEP03_HR107 = 107; // Acumulación de flujo hacia adelante de entero.
uint16_t FEP03_HR108 = 108;
uint16_t FEP03_HR109 = 109; // Acumulación de flujo hacia adelante de la parte decimal aumentada 1000 veces 123 representa 0.123.
uint16_t FEP03_HR110 = 110;
uint16_t FEP03_HR111 = 111; // Acumulación de flujo inverso de entero Inverso.
uint16_t FEP03_HR112 = 112;
uint16_t FEP03_HR113 = 113; // Acumulación de flujo inverso de la parte decimal ampliada 1000 veces 123 representa 0,123.
uint16_t FEP03_HR114 = 114;

// Inicio registros caudalimetro Plasma.
// Valores float.
uint16_t FEP04_HR099 = 99;  // Caudal instantáneo.
uint16_t FEP04_HR100 = 100; // Caudal instantáneo.
uint16_t FEP04_HR101 = 101; // Velocidad de flujo instantánea.
uint16_t FEP04_HR102 = 102; // Velocidad de flujo instantánea.
uint16_t FEP04_HR103 = 103; // Porcentaje de flujo.
uint16_t FEP04_HR104 = 104; // Porcentaje de flujo.
uint16_t FEP04_HR105 = 105; // Conductividad eléctrica.
uint16_t FEP04_HR106 = 106;
// Registros contadores acumulacion.
uint16_t FEP04_HR107 = 107; // Acumulación de flujo hacia adelante de entero.
uint16_t FEP04_HR108 = 108;
uint16_t FEP04_HR109 = 109; // Acumulación de flujo hacia adelante de la parte decimal aumentada 1000 veces 123 representa 0.123.
uint16_t FEP04_HR110 = 110;
uint16_t FEP04_HR111 = 111; // Acumulación de flujo inverso de entero Inverso.
uint16_t FEP04_HR112 = 112;
uint16_t FEP04_HR113 = 113; // Acumulación de flujo inverso de la parte decimal ampliada 1000 veces 123 representa 0,123.
uint16_t FEP04_HR114 = 114;

// Inicio registros caudalimetro Plasma.
// Valores float.
uint16_t FEU01_HR099 = 99;  // Caudal instantáneo.
uint16_t FEU01_HR100 = 100; // Caudal instantáneo.
uint16_t FEU01_HR101 = 101; // Velocidad de flujo instantánea.
uint16_t FEU01_HR102 = 102; // Velocidad de flujo instantánea.
uint16_t FEU01_HR103 = 103; // Porcentaje de flujo.
uint16_t FEU01_HR104 = 104; // Porcentaje de flujo.
uint16_t FEU01_HR105 = 105; // Conductividad eléctrica.
uint16_t FEU01_HR106 = 106;
// Registros contadores acumulacion.
uint16_t FEU01_HR107 = 107; // Acumulación de flujo hacia adelante de entero.
uint16_t FEU01_HR108 = 108;
uint16_t FEU01_HR109 = 109; // Acumulación de flujo hacia adelante de la parte decimal aumentada 1000 veces 123 representa 0.123.
uint16_t FEU01_HR110 = 110;
uint16_t FEU01_HR111 = 111; // Acumulación de flujo inverso de entero Inverso.
uint16_t FEU01_HR112 = 112;
uint16_t FEU01_HR113 = 113; // Acumulación de flujo inverso de la parte decimal ampliada 1000 veces 123 representa 0,123.
uint16_t FEU01_HR114 = 114;

#endif

MB_RTU_Loop.hpp

#pragma once
#include <Arduino.h>
#include "MB_RTU_Config.h"

ModbusRTU mb_rtu;

bool cb(Modbus::ResultCode event, uint16_t transactionId, void *data)

{ // Callback to monitor errors
  if (event != Modbus::EX_SUCCESS)
  {
    //Serial.print("Request result: 0x");
    //Serial.println(event, HEX);
    MB_RTU_ERROR_Read++;
/*
    CAU_array_0[0] = 0;
    CAU_array_0[1] = 0;
    CAU_array_0[2] = 0;
    CAU_array_0[3] = 0;
    CAU_array_0[4] = 0;
    CAU_array_0[5] = 0;
    CAU_array_0[6] = 0;
    CAU_array_0[7] = 0;
    CAU_array_0[8] = 0;
    CAU_array_0[9] = 0;
    CAU_array_0[10] = 0;
    CAU_array_0[11] = 0;
    CAU_array_0[12] = 0;
    CAU_array_0[13] = 0;
    CAU_array_0[14] = 0;
    CAU_array_0[15] = 0;
*/
  }
  else if (event == Modbus::EX_SUCCESS)
  {
    MB_RTU_OK_Read++;
  }
  return true;
}

bool cbWrite(Modbus::ResultCode event, uint16_t transactionId, void *data)
{
  /*
  if (event != Modbus::EX_SUCCESS)
  {
    Serial.print("Request result: 0x");
    Serial.println(event, HEX);
  }
  */

  return true;
}

void setup_rtu() //
{
  Serial.begin(57600);
  mb_rtu.begin(&Serial);
  mb_rtu.master();
}

void loop_rtu() // Loop Comunicación Caudalimetros
{

  /* En cada iteracion de loop, guardamos en que momento de la linea temporal estamos con millis */
  unsigned long tiempoActual_0 = millis();

  /* Comprobamos si debemos lanzar el evento */
  if (tiempoActual_0 - tiempoAnterior_0 >= intervaloLecturaTemp_0)
  {
    if (!mb_rtu.slave())
    {                                                                   // Check if no transaction in progress
      mb_rtu.readHreg(ID_FEP03, FIRST_REG, CAU_array_0, REG_COUNT, cb); // Send Read Hreg from Modbus Server
      while (mb_rtu.slave())
          { // Check if transaction is active
            mb_rtu.task();
            yield();
            //delay(10);
          }
    }
    tiempoAnterior_0 = tiempoActual_0;
  }

  unsigned long tiempoActual_1 = millis();
  /* Comprobamos si debemos lanzar el evento */
  if (tiempoActual_1 - tiempoAnterior_1 >= intervaloLecturaTemp_1)
  {
    if (!mb_rtu.slave())
    {                                                                   // Check if no transaction in progress
      mb_rtu.readHreg(ID_FEP04, FIRST_REG, CAU_array_1, REG_COUNT, cb); // Send Read Hreg from Modbus Server
      while (mb_rtu.slave())
      { // Check if transaction is active
        mb_rtu.task();
        yield();
        // delay(10);
      }
    }
    tiempoAnterior_1 = tiempoActual_1;
  }
  unsigned long tiempoActual_2 = millis();
  if (tiempoActual_2 - tiempoAnterior_2 >= intervaloLecturaTemp_2)
  {
    if (!mb_rtu.slave())
    {                                                                   // Check if no transaction in progress
      mb_rtu.readHreg(ID_FEU01, FIRST_REG, CAU_array_2, REG_COUNT, cb); // Send Read Hreg from Modbus Server
      while (mb_rtu.slave())
      { // Check if transaction is active
        mb_rtu.task();
        yield();
        // delay(10);
      }
    }
    tiempoAnterior_2 = tiempoActual_2;
  }

    //yield();

    FEP03_HR099 = CAU_array_0[0];  // LSB
    FEP03_HR100 = CAU_array_0[1];  // HSB
    FEP03_HR101 = CAU_array_0[2];  // LSB
    FEP03_HR102 = CAU_array_0[3];  // HSB
    FEP03_HR103 = CAU_array_0[4];  // LSB
    FEP03_HR104 = CAU_array_0[5];  // HSB
    FEP03_HR105 = CAU_array_0[6];  // LSB
    FEP03_HR106 = CAU_array_0[7];  // HSB
    FEP03_HR107 = CAU_array_0[8];  // LSB
    FEP03_HR108 = CAU_array_0[9];  // HSB
    FEP03_HR109 = CAU_array_0[10]; // LSB
    FEP03_HR110 = CAU_array_0[11]; // HSB
    FEP03_HR111 = CAU_array_0[12]; // LSB
    FEP03_HR112 = CAU_array_0[13]; // HSB
    FEP03_HR113 = CAU_array_0[14]; // LSB
    FEP03_HR114 = CAU_array_0[15]; // HSB

    FEP04_HR099 = CAU_array_1[0];  // LSB
    FEP04_HR100 = CAU_array_1[1];  // HSB
    FEP04_HR101 = CAU_array_1[2];  // LSB
    FEP04_HR102 = CAU_array_1[3];  // HSB
    FEP04_HR103 = CAU_array_1[4];  // LSB
    FEP04_HR104 = CAU_array_1[5];  // HSB
    FEP04_HR105 = CAU_array_1[6];  // LSB
    FEP04_HR106 = CAU_array_1[7];  // HSB
    FEP04_HR107 = CAU_array_1[8];  // LSB
    FEP04_HR108 = CAU_array_1[9];  // HSB
    FEP04_HR109 = CAU_array_1[10]; // LSB
    FEP04_HR110 = CAU_array_1[11]; // HSB
    FEP04_HR111 = CAU_array_1[12]; // LSB
    FEP04_HR112 = CAU_array_1[13]; // HSB
    FEP04_HR113 = CAU_array_1[14]; // LSB
    FEP04_HR114 = CAU_array_1[15]; // HSB

    FEU01_HR099 = CAU_array_2[0];  // LSB
    FEU01_HR100 = CAU_array_2[1];  // HSB
    FEU01_HR101 = CAU_array_2[2];  // LSB
    FEU01_HR102 = CAU_array_2[3];  // HSB
    FEU01_HR103 = CAU_array_2[4];  // LSB
    FEU01_HR104 = CAU_array_2[5];  // HSB
    FEU01_HR105 = CAU_array_2[6];  // LSB
    FEU01_HR106 = CAU_array_2[7];  // HSB
    FEU01_HR107 = CAU_array_2[8];  // LSB
    FEU01_HR108 = CAU_array_2[9];  // HSB
    FEU01_HR109 = CAU_array_2[10]; // LSB
    FEU01_HR110 = CAU_array_2[11]; // HSB
    FEU01_HR111 = CAU_array_2[12]; // LSB
    FEU01_HR112 = CAU_array_2[13]; // HSB
    FEU01_HR113 = CAU_array_2[14]; // LSB
    FEU01_HR114 = CAU_array_2[15]; // HSB
  }

Is there another more efficient way to do this? Since I tried other options without results.

emelianov commented 1 year ago

As far as I can see only way you are using is possible. For RTU the client have to wait for server device answer prior to sending another request. If you need more frequent requests you may increase baudrate or use separate wiring for devices.

Merdock1 commented 1 year ago

Very Happy New Year Emiliano. Thank you very much for his answer.

emelianov commented 1 year ago

Fernando, Marry Christmas and Happy New Year. Sorry for delay in answering. I was extremely busy last months.