Ir al contenido

← Mapa de registros Modbus TCP para una planta de biorreactores

Control de biorreactoresM-DuinoModbus TCPComunicación

Mapa de registros Modbus TCP para una planta de biorreactores — ejemplo completo

Disena un mapa de registros Modbus TCP limpio en un PLC M-Duino: coils, holding e input registers para toda una planta de biorreactores. Codigo y layout.

Programa completo y ejecutable para el M-Duino (modbus-register-map.ino): incluye cabecera de conexionado, requisitos y notas de integración.

Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales

Vista de solo lectura.

/*
 * COMPLETE EXAMPLE — Whole-plant Modbus TCP register map
 *
 * Device:  M-Duino (Industrial Shields, Arduino PLC with Ethernet + RS485)
 * Based on: bioreactor control project, ModbusTCPSlaveRTUMaster.ino
 *
 * This sketch documents and publishes the Modbus TCP map (port 502) that a
 * SCADA uses to read from and command the whole bioreactor plant. It does
 * not drive the RTU bus (the "Gateway" module does that); its value is to
 * act as a live address table, verifiable with any Modbus client.
 *
 * Coils 0-17 (read/write, function 1/5/15):
 *   0..7   : 8 output relays (solenoid valves, auxiliary pumps...)
 *   8..15  : 8 pilot lights / status indicators
 *   16,17  : counter reset of the 2 flow meters
 *
 * Holding registers 0-9 (read/write, function 3/6/16):
 *   0..3   : analog outputs (0-10 V)
 *   4,5    : temperature setpoint of the 2 chillers (x10)
 *   6,7    : RPM setpoint of the 2 drives (rpm)
 *   8,9    : run command of the 2 chillers
 *
 * Input registers 0-11 (read only, function 4):
 *   0,1    : temperature of the 2 chillers (x10)
 *   2,3    : pressure
 *   4,5    : pH (x100)
 *   6..9   : accumulated liters of the 2 flow meters (32 bits each)
 *   10,11  : actual RPM of the 2 drives
 *
 * Integration: this map is the contract shared by the modules
 * "Chiller control", "Drive control" and "Flow meter reading", all
 * behind the "Gateway Modbus TCP <-> RTU".
 */

#include 

ModbusTCPSlave modbus;

// Memory blocks, sized according to the map above
bool     coils[18];
uint16_t holdingRegs[10];
uint16_t inputRegs[12];

// Named indices so the code reads like the map
enum { HR_AO0, HR_AO1, HR_AO2, HR_AO3,
       HR_TEMP_SP1, HR_TEMP_SP2,
       HR_RPM_SP1, HR_RPM_SP2,
       HR_RUN_CH1, HR_RUN_CH2 };

enum { IR_TEMP1, IR_TEMP2, IR_PRES1, IR_PRES2,
       IR_PH1, IR_PH2,
       IR_LITERS1_H, IR_LITERS1_L, IR_LITERS2_H, IR_LITERS2_L,
       IR_RPM1, IR_RPM2 };

void setup() {
  Serial.begin(115200);

  // Publish the three blocks starting at address 0
  modbus.addCoils(0, coils, 18);
  modbus.addHoldingRegisters(0, holdingRegs, 10);
  modbus.addInputRegisters(0, inputRegs, 12);
  modbus.begin();   // listen on port 502

  // Consistent initial values (what a SCADA would read on connecting)
  holdingRegs[HR_TEMP_SP1] = 185;   // 18.5 C x10
  holdingRegs[HR_TEMP_SP2] = 185;
  holdingRegs[HR_RPM_SP1]  = 250;   // 250 rpm
  holdingRegs[HR_RPM_SP2]  = 250;
}

void loop() {
  modbus.update();   // keeps the memory image alive over TCP

  // Light simulation so a client sees plausible values.
  // In the plant these input regs are filled by the gateway from the RTU bus.
  static uint32_t t = 0;
  if (millis() - t > 1000) {
    t = millis();
    inputRegs[IR_TEMP1] = holdingRegs[HR_TEMP_SP1];   // follows the setpoint
    inputRegs[IR_TEMP2] = holdingRegs[HR_TEMP_SP2];
    inputRegs[IR_RPM1]  = holdingRegs[HR_RPM_SP1];
    inputRegs[IR_RPM2]  = holdingRegs[HR_RPM_SP2];
    inputRegs[IR_PH1]   = 720;    // pH 7.20 x100
    inputRegs[IR_PH2]   = 715;

    Serial.print("Temp1=");  Serial.print(inputRegs[IR_TEMP1] / 10.0);
    Serial.print("C  RPM1="); Serial.print(inputRegs[IR_RPM1]);
    Serial.print("  pH1=");   Serial.println(inputRegs[IR_PH1] / 100.0);
  }
}
Descarga el pack completo del proyecto — gratisEste ejemplo + los relacionados + lista de materiales