1""" EtherCAT network status diagnostic utility for real-time monitoring.
2
3 This utility displays the overall network status from the MotionController and
4 the individual status of each network node. It provides visibility into:
5
6 Network Status (MotionController level):
7 - ActiveNodeCount: Number of nodes actively responding on the network
8 - AlStatus: Logical OR of AL Status registers from all nodes (0x0130)
9 - MissedCyclicFrameCount: Cumulative count of missed cyclic EtherCAT frames
10 - CyclicFramePeriodUs: Most recent cyclic frame period in microseconds
11 - SynchronizationErrorNs: Distributed Clock synchronization error in nanoseconds
12
13 Node Status (per RapidCodeNetworkNode):
14 - AlStatus: EtherCAT AL Status register (0x0130) value for this specific node
15 - AlStatusCode: EtherCAT AL Status Code register value (error details)
16 - CoeEmergencyMessage: CANopen over EtherCAT emergency message (if any)
17 - CoeEmergencyMessageNetworkCounter: Network counter when emergency was received
18 - SdoReadCount / SdoWriteCount: Service channel requests (CoE SDO transfers and also
19 register access, index below 0x1000) the network firmware serviced for this node,
20 cumulative since the network started
21 - SdoReadFailCount / SdoWriteFailCount: How many of those requests failed (an SDO abort
22 or other error status, or no answer within the firmware's one second wait). Register
23 writes are fire and forget, so they never count as failures
24 - AkdAsciiCount / AkdAsciiFailCount: Kollmorgen AKD ASCII commands serviced for this
25 node, and how many of them failed (shown only where the node accepts them, see
26 RapidCodeNetworkNode.IsAKDASCIICommandSupported)
27
28 AL Status Register (0x0130) Decoding:
29 Bits 0-3 indicate Device State Machine state:
30 - 1 = Init (initialization)
31 - 2 = PreOp (pre-operational, mailbox communication only)
32 - 3 = Bootstrap (firmware update mode)
33 - 4 = SafeOp (safe-operational, inputs active, outputs safe)
34 - 8 = Operational (full operation, inputs and outputs active)
35 Bit 4 is the Error Flag - when set, check AlStatusCode for details.
36
37 When to Use This Diagnostic Tool:
38 - Verify all nodes are in OPERATIONAL state after network startup
39 - Check for nodes reporting errors (Bit 4 set in AlStatus)
40 - Monitor missed cyclic frame counts for network quality issues
41 - Check DC synchronization error for timing accuracy
42 - Diagnose CoE emergency messages from drives or devices
43
44 Practical Examples of Output to Diagnose Network Issues:
45 Example 1: A cable or power failure.
46 - Active Node Count: 2 (7 discovered)
47 Example 2: A node fell out of Operational state. Look up 1A in the manual.
48 - 0 | Mitsubishi MR-J5-TM | 0x14 (SAFEOP+ERR) | 0x001A | 0x000000000000 | 0
49"""
50
51from _imports import RapidCode, helpers
52
53
54
55
56
57
58MAX_STATE_WIDTH = max(len(s) for s in helpers.AL_STATUS_STATES.values()) + len(helpers.AL_STATUS_ERROR_SUFFIX)
59AL_STATUS_COL_WIDTH = 7 + MAX_STATE_WIDTH
60
61
62def display_network_status(controller: RapidCode.MotionController):
63 """Display the overall network status and per-node status."""
64
65
66 network_status = controller.NetworkStatusGet()
67
68
69 nodes = []
70 max_name_len = 10
71 for i in range(controller.NetworkNodeCountGet()):
72 node = controller.NetworkNodeGet(i)
73 helpers.check_errors(node)
74 if node.Exists():
75 nodes.append(node)
76 max_name_len = max(max_name_len, len(node.NameGet()))
77
78
79 width = 80
80 print("\n" + "=" * width)
81 print("NETWORK STATUS")
82 print("=" * width)
83
84
85 network_state = helpers.get_enum_name("RSINetworkState_RSINetworkState", controller.NetworkStateGet())
86 al_status_str = f"0x{network_status.AlStatus:02X} ({helpers.decode_al_status_ored(network_status.AlStatus)})"
87 sync_sign = "+" if network_status.SynchronizationErrorNs >= 0 else ""
88
89 print(f" Network State: {network_state}")
90 print(f" Active Node Count: {network_status.ActiveNodeCount} ({controller.NetworkNodeCountGet()} discovered)")
91 print(f" AL Status: {al_status_str}")
92 print(f" Missed Cyclic Frames: {network_status.MissedCyclicFrameCount}")
93 print(f" Cyclic Frame Period: {network_status.CyclicFramePeriodUs} us")
94 print(f" Synchronization Error: {sync_sign}{network_status.SynchronizationErrorNs} ns")
95
96
97 print("\n" + "=" * width)
98 print("NODE STATUS (with each node's service channel request counts)")
99 print("=" * width)
100
101
102 header = f"{'Node':>4} | {'Name':<{max_name_len}} | {'AL Status':^{AL_STATUS_COL_WIDTH}} | {'AL Code':^8} | {'CoE Emergency':^16} | {'Counter':>8}"
103 print(header)
104 print("-" * len(header))
105
106
107 for node in nodes:
108 node_index = node.NumberGet()
109 node_name = node.NameGet()[:max_name_len]
110
111
112 status = node.StatusGet()
113
114
115 al_status_str = f"0x{status.AlStatus:02X} ({helpers.decode_al_status(status.AlStatus):^{MAX_STATE_WIDTH}})"
116 al_code_str = f"0x{status.AlStatusCode:04X}"
117 coe_emergency_str = f"0x{status.CoeEmergencyMessage:012X}"
118 counter_str = f"{status.CoeEmergencyMessageNetworkCounter:8d}"
119
120 print(f"{node_index:>4} | {node_name:<{max_name_len}} | {al_status_str:^{AL_STATUS_COL_WIDTH}} | {al_code_str:^8} | {coe_emergency_str:^16} | {counter_str}")
121
122
123
124
125
126 service_channel = (f" service channel: SDO r/w {status.SdoReadCount}/{status.SdoWriteCount} "
127 f"(fail {status.SdoReadFailCount}/{status.SdoWriteFailCount})")
128
129 if node.IsAKDASCIICommandSupported():
130 service_channel += f", AKD ASCII {status.AkdAsciiCount} (fail {status.AkdAsciiFailCount})"
131 print(service_channel)
132
133 print("=" * width)
134
135
136
137print("Network Status Diagnostic")
138print("-" * 40)
139
140
141creation_params: RapidCode.CreationParameters = helpers.get_creation_parameters()
142motion_controller: RapidCode.MotionController = RapidCode.MotionController.Create(creation_params)
143
144
145print(f"MotionController creation error count: {motion_controller.ErrorLogCountGet()}")
146helpers.check_errors(motion_controller)
147
148
149print(f"RapidCode Version: {motion_controller.VersionGet()}")
150print(f"Serial Number: {motion_controller.SerialNumberGet()}")
151
152
153display_network_status(motion_controller)
154
155
156motion_controller.Delete()