Skip to content

Axioline F Hot Reload

Hey All,

Understand its not electrically supported, but we would like to automatically reload our C++ runtime whenever the modules on an Axioline F are swapped.

I'm currently looking at https://api.plcnext.help/api_docs_2020-3/classArp_1_1Io_1_1Axioline_1_1Services_1_1IAxioMasterService.html as the class that we will need to use to perform this.

Our current CPP code is more or less:

- ArpPlcGds_BeginRead for Arp.Io.AxlC/AXIO_DIAG_STATUS_REG
- Check If it equals 0xE010 (i.e. F_BD_BIT - Bus Different) is set (This will be fleshed out more past proof of concept)
- If it does, then call
axioMasterService->ResetMaster();
axioMasterService->CreateConfiguration(0x0001);
axioMasterService->ActivateConfiguration(0x0001);

This currently produces logging like such (Noting endianess of what I'm logging is inverted from what the manual indicates):
13.12.21 06:44:09.995 root INFO - AXIO Status Changed from FFFF to E000 <-- Initialised & working
13.12.21 06:45:35.016 root INFO - AXIO Status Changed from E000 to C400 <-- Remove a DI16 module
13.12.21 06:45:46.019 root INFO - AXIO Status Changed from C400 to C410 <--- Remove another DI16 module
13.12.21 06:45:49.521 root INFO - AXIO Status Changed from C410 to E010 <--- Swap position of two removed modules (in an SE6)
13.12.21 06:45:49.521 root INFO - AXIO Status indicates a different bus configuration, hot reloading
13.12.21 06:45:49.814 root INFO - AXIO Status reload successful <-- Written after the reset/create/activate code above
13.12.21 06:45:50.314 root INFO - AXIO Status Changed from E010 to C000 <--- Result after code above

Some of this code is gathered from the plcNext Bus Conductor example, however, I am sure I am just missing some crucial final step. We are essentially trying to automate "sudo /etc/init.d/plcnext restart" whenever the bus configuration changes (As currently, if I "hot-swap" two modules and run the restart it works perfectly). Please note that the module types are not changing here, purely for replacement if a module dies.

Cheers,

Joseph

Comments

  • Hello Joseph,
    please note that the module types are not changing here, purely for replacement if a module dies.
    if you do not introduce new modules and only replace faulty modules with identical modules.
    I do not understand what the purpose of the application is.
    The PLC should automatically accept those modules already,
    without any manual AxioMasterService implementation.

    What exactly is unsatisfactory in your usecase with the current implementation?

    kind regards,
    Oliver
  • edited December 2021
    Hey Oliver,

    Site scenario is:
    PLC is running, fully powered up
    Say a DI16 module in an SE6 fails
    Without removing power, swap faulty DI16 with a new DI16, whilst SE6 remains fully powered
    After performing this swap, the SE6 LED's indicate solid green on all sub-modules except for the one that is swapped, which remains flashing green
    A check of the diagnostic register at this point indicates that F_BD_BIT is set
    IO at this point can be read/written to all SE6 modules except for the one that has been interchanged
    A restart of the PLC C++ application via `sudo /etc/init.d/plcnext restart` at this point will result in it coming back online and the F_BD_BIT clearing and data can then be read/written to the swapped module as if no swap had occurred.

    In our test environment, we are simulating this "site fault" by swapping two modules around (Both DI16) rather than removing a single module and replacing with a new module.

    The issue we are trying to avoid is the restart of the entire PLC runtime, as numerous things start up and this means the reload time after swapping a module is potentially on the order of 1 minute. Whereas if we can re-initialise the entire Axioline F bus from within the C++ runtime on its own, we are hoping to achieve something closer to the sub-10 second region.

    Cheers,

    Joseph
  • edited December 2021
    Managed to get it working, having a more careful read through the BusConductor C++ example. Below was the implementation used to successfully (Sub 1 second) hot reload when swapping two identical DI16 modules.
    if (axioStatus == 0xE010) {
        Log::Info("AXIO Status indicates a different bus configuration, hot reloading");
        // Reset driver
        //axioMasterService->ResetMaster(); ???
        send[0] = 0x1703;
        send[1] = 0x0000;
        uint16_t response =axioMasterService->AxioControl(send, receive);
        if (response != 0) {
            Log::Error("AXIO reset failed");
        } else {
            Log::Info("AXIO reset successful");
        }
    
        // Create configuration
        //axioMasterService->CreateConfiguration(0x0001); ???
        send[0] = 0x0710;
        send[1] = 0x0001;
        send[2] = 0x0001;
        response =axioMasterService->AxioControl(send, receive);
        if (response != 0) {
            Log::Error("AXIO configuration create failed");
        } else {
            Log::Info("AXIO configuration create successful");
        }
    
        // Read configuration
        //axioMasterService->ReadConfiguration(); ???
        send[0] = 0x030B;
        send[1] = 0x0001;
        send[2] = 0x0003;
        response =axioMasterService->AxioControl(send, receive);
        if (response != 0) {
            Log::Error("AXIO configuration read failed");
        } else {
            Log::Info("AXIO configuration read successful");
        }
    
        // Start local IO?
        //axioMasterService->ActivateConfiguration(0x0001); ???
        send[0] = 0x0728;
        send[1] = 0x0004;
        send[2] = 0x3000;
        send[3] = 0x0001;
        send[4] = 0x0021;
        send[5] = 0x0000;
        receive.clear();
        response = axioMasterService->AxioControl(send, receive);
        if (response != 0) {
            Log::Error("AXIO configuration load failed");
        } else {
            Log::Info("AXIO configuration load successful");
        }
    
        // Start data transfer
        //axioMasterService->????(); ???
        send[0] = 0x0701;
        send[1] = 0x0001;
        send[2] = 0x0001;
        send[3] = 0x0001;
        send[4] = 0x0021;
        send[5] = 0x0000;
        receive.clear();
        response = axioMasterService->AxioControl(send, receive);
        if (response != 0) {
            Log::Error("AXIO data output enable failed");
        } else {
            Log::Info("AXIO data output enable successful");
        }
    }
    
    14.12.21 03:48:58.258 root                      INFO    - AXIO Status Changed from E000 to C400
    14.12.21 03:49:11.261 root                      INFO    - AXIO Status Changed from C400 to C410
    14.12.21 03:49:18.763 root                      INFO    - AXIO Status Changed from C410 to E010
    14.12.21 03:49:18.880 root                      INFO    - AXIO Status indicates a different bus configuration, hot reloading
    14.12.21 03:49:18.909 root                      INFO    - AXIO reset successful
    14.12.21 03:49:19.143 root                      INFO    - AXIO configuration create successful
    14.12.21 03:49:19.172 root                      INFO    - AXIO configuration read successful
    14.12.21 03:49:19.188 root                      INFO    - AXIO configuration load successful
    14.12.21 03:49:19.192 root                      INFO    - AXIO data output enable successful
    14.12.21 03:49:19.693 root                      INFO    - AXIO Status Changed from E010 to E000
    

    Only potential request would be that the "random" hex codes I've used be more publicly documented (Current ones there are pulled "magically" from the BusConductor file") and/or that the functions above be confirmed and/or added to IAxioMasterService as a single (or set of) named commands as this is likely a very useful bit of functionality for people to utilise.
  • A note on my previous posts, I incorrectly identified it as the F_BD_BIT, however, it is in fact the F_PARA_REQ (Module requesting parameters) that is set, which makes more sense, since the bus is probably the same, however the modules are requesting initialisation, which is what I am doing in my code above.
This discussion has been closed.