dynamic modbus devices

kurtk
2025-08-19
2026-02-13
  • kurtk - 2025-08-19

    I am CODESYS neophyte getting my wheels on.
    My goal is to re-platform an existing PLC application written in 61131 ST
    I've got the majority of the code/variables in a compilable form - excluding all the IO and comms nuances
    I am not sure whether this the right forum

    An important functionality which I implemented on the other platform was totally dynamic modbus devices...
    Most configurations I have come across impose static MB configs in which
    all configured devices MUST be present and functional...
    I have monkeyed around with MB enough to know that herding a half dozen MB cats into a working config can be tricky. I just do them one at a time
    and dynamically turn them on/off in whatever combination is convenient
    with ID, IP, baud, parity etc being runtime tweakable.

    I am totally curious whether this is possible with codesys, or whether
    its device configuration corrals one into a static cage which requires
    re-building the code to support flexible variations.

    Best regards

     
  • risele - 2026-02-13

    Have the same issue: I'm making a test setup for modbus devices testing and calibration.

    One is run for every possible address, and it starts with minimal request: if the device is found, it continue to work with it, otherwise it's set to Disabled temporary. Those state machines are running under FOR cycle, and disabled are just skipped. Every instance have its own timer for not running too frequently and a start delay, so the actual requests are separate in time. I also check not for a single error, but have some timer to allow one-two timeouts.

    The small program disables and re-enables devices temporary (manually, since i could not iterate over MB devices).

    VAR
    Reset:ARRAY[1..GVL_MB.MD_COUNT] OF R_TRIG;
    i:INT;
    END_VAR
    
    {IF hasconstantvalue(GVL_MB.MD_COUNT, 1, >= )}
        i:=1;
        MD_1.Enable:=GVL_MB.MDPortsEnable[i];
        Reset[i](CLK:=GVL_MB.MDPortsEnable[i]);
        MD_1.xReset:=Reset[i].Q;
    {END_IF}
    {IF hasconstantvalue(GVL_MB.MD_COUNT, 2, >= )}
        i:=2;
        MD_2.Enable:=GVL_MB.MDPortsEnable[i];
        Reset[i](CLK:=GVL_MB.MDPortsEnable[i]);
        MD_2.xReset:=Reset[i].Q;
    {END_IF}
    

    There is also program to re-enable devices periodically.

    METHOD ScanBus
    VAR_INPUT
    END_VAR
    VAR
        j:INT;
    
        (*block auto scanning if calibration is running for any device 
        since it's data-reach process that should not be interrupted with modbus timeouts *)
        CalibrationBusy:BOOL:=FALSE; 
    END_VAR
    
    CalibrationBusy:=FALSE;
    FOR j:=1 TO GVL_MB.MD_COUNT DO
            CalibrationBusy:=CalibrationBusy OR MD_Calibrate.AutoTesters[j].xBusy;
    END_FOR;
    IF CalibrationBusy THEN
        RETURN;
    END_IF
    tBusScanSchedule(IN:=(NOT tBusScanSchedule.Q), PT:=tBusScanPeriod);
    IF  (NOT tBusScanDelayer.Q) AND (tBusScanSchedule.Q OR (NOT xFirstScanPerforemed)) THEN
        xBusScanBusy:=TRUE; 
        MissingCounter:=0;
        xFirstScanPerforemed:=TRUE;
        FOR j:=1 TO GVL_MB.MD_COUNT DO
        (* MD_Calibrate is main calibration program.
         Identifiers - is array of State machines mentioned above
         Phase_Faulted is a state of Identifiers where I'm sure device is missing on the bus
        *)
            IF MD_Calibrate.Identifiers[j].state=eStateMDIdentifier.Phase_Faulted THEN
                MD_Calibrate.Identifiers[j].Rescan();
                MissingCounter:=MissingCounter+1;
            END_IF
        END_FOR
    END_IF
    tBusScanPauser(IN:=tBusScanDelayer.Q AND (MissingCounter>0),PT:=tBusScanDelay*MissingCounter);
    xBusScanBusy:=tBusScanPauser.Q; 
    xFirstScanPerforemed:=xFirstScanPerforemed OR tBusScanPauser.ET>=tBusScanPauser.PT;
    

    Also the GUI have buttons for each address possible that re-enables the device if required.

     

    Last edit: risele 2026-02-13

Log in to post a comment.