mcp-server-mcsa 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_server_mcsa/__init__.py +37 -37
- mcp_server_mcsa/__main__.py +5 -5
- mcp_server_mcsa/analysis/__init__.py +19 -19
- mcp_server_mcsa/analysis/bearing.py +147 -147
- mcp_server_mcsa/analysis/envelope.py +96 -97
- mcp_server_mcsa/analysis/fault_detection.py +424 -425
- mcp_server_mcsa/analysis/file_io.py +429 -428
- mcp_server_mcsa/analysis/motor.py +147 -145
- mcp_server_mcsa/analysis/preprocessing.py +180 -180
- mcp_server_mcsa/analysis/spectral.py +171 -172
- mcp_server_mcsa/analysis/test_signal.py +232 -232
- mcp_server_mcsa/analysis/timefreq.py +132 -132
- mcp_server_mcsa/server.py +954 -955
- {mcp_server_mcsa-0.1.0.dist-info → mcp_server_mcsa-0.1.1.dist-info}/METADATA +3 -1
- mcp_server_mcsa-0.1.1.dist-info/RECORD +18 -0
- {mcp_server_mcsa-0.1.0.dist-info → mcp_server_mcsa-0.1.1.dist-info}/licenses/LICENSE +21 -21
- mcp_server_mcsa-0.1.0.dist-info/RECORD +0 -18
- {mcp_server_mcsa-0.1.0.dist-info → mcp_server_mcsa-0.1.1.dist-info}/WHEEL +0 -0
- {mcp_server_mcsa-0.1.0.dist-info → mcp_server_mcsa-0.1.1.dist-info}/entry_points.txt +0 -0
|
@@ -1,232 +1,232 @@
|
|
|
1
|
-
"""Synthetic test‑signal generator for MCSA.
|
|
2
|
-
|
|
3
|
-
Generates simulated stator‑current waveforms with optional fault
|
|
4
|
-
signatures for testing, validation, and demonstration purposes.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import numpy as np
|
|
10
|
-
from numpy.typing import NDArray
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def generate_healthy_signal(
|
|
14
|
-
duration_s: float,
|
|
15
|
-
fs_sample: float,
|
|
16
|
-
supply_freq_hz: float = 50.0,
|
|
17
|
-
amplitude: float = 1.0,
|
|
18
|
-
noise_std: float = 0.01,
|
|
19
|
-
harmonics: list[tuple[int, float]] | None = None,
|
|
20
|
-
) -> tuple[NDArray[np.floating], NDArray[np.floating]]:
|
|
21
|
-
"""Generate a clean (healthy) motor‑current signal.
|
|
22
|
-
|
|
23
|
-
Args:
|
|
24
|
-
duration_s: Signal duration in seconds.
|
|
25
|
-
fs_sample: Sampling frequency in Hz.
|
|
26
|
-
supply_freq_hz: Supply fundamental frequency in Hz.
|
|
27
|
-
amplitude: Peak amplitude of the fundamental.
|
|
28
|
-
noise_std: Standard deviation of additive Gaussian noise.
|
|
29
|
-
harmonics: Optional list of (harmonic_number, relative_amplitude)
|
|
30
|
-
to add supply harmonics (e.g. [(3, 0.05), (5, 0.03)]).
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
(time, signal) — 1‑D arrays.
|
|
34
|
-
"""
|
|
35
|
-
n_samples = int(duration_s * fs_sample)
|
|
36
|
-
t = np.arange(n_samples) / fs_sample
|
|
37
|
-
|
|
38
|
-
x = amplitude * np.sin(2.0 * np.pi * supply_freq_hz * t)
|
|
39
|
-
|
|
40
|
-
if harmonics:
|
|
41
|
-
for h_num, h_amp in harmonics:
|
|
42
|
-
x += h_amp * amplitude * np.sin(2.0 * np.pi * h_num * supply_freq_hz * t)
|
|
43
|
-
|
|
44
|
-
if noise_std > 0:
|
|
45
|
-
x += np.random.default_rng(42).normal(0, noise_std, n_samples)
|
|
46
|
-
|
|
47
|
-
return t, x
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def inject_brb_fault(
|
|
51
|
-
t: NDArray[np.floating],
|
|
52
|
-
x: NDArray[np.floating],
|
|
53
|
-
supply_freq_hz: float,
|
|
54
|
-
slip: float,
|
|
55
|
-
sideband_amplitude: float = 0.02,
|
|
56
|
-
n_harmonics: int = 1,
|
|
57
|
-
) -> NDArray[np.floating]:
|
|
58
|
-
"""Inject broken‑rotor‑bar sidebands into a current signal.
|
|
59
|
-
|
|
60
|
-
Adds components at (1 ± 2ks)·f_s for k = 1 … n_harmonics.
|
|
61
|
-
|
|
62
|
-
Args:
|
|
63
|
-
t: Time axis.
|
|
64
|
-
x: Original signal.
|
|
65
|
-
supply_freq_hz: Supply frequency (Hz).
|
|
66
|
-
slip: Motor slip (per‑unit).
|
|
67
|
-
sideband_amplitude: Amplitude of each sideband component.
|
|
68
|
-
n_harmonics: Number of sideband pairs.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Signal with BRB fault injected.
|
|
72
|
-
"""
|
|
73
|
-
y = x.copy()
|
|
74
|
-
fs = supply_freq_hz
|
|
75
|
-
|
|
76
|
-
for k in range(1, n_harmonics + 1):
|
|
77
|
-
f_lower = (1 - 2 * k * slip) * fs
|
|
78
|
-
f_upper = (1 + 2 * k * slip) * fs
|
|
79
|
-
y += sideband_amplitude * np.sin(2.0 * np.pi * f_lower * t)
|
|
80
|
-
y += sideband_amplitude * np.sin(2.0 * np.pi * f_upper * t)
|
|
81
|
-
|
|
82
|
-
return y
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def inject_eccentricity_fault(
|
|
86
|
-
t: NDArray[np.floating],
|
|
87
|
-
x: NDArray[np.floating],
|
|
88
|
-
supply_freq_hz: float,
|
|
89
|
-
rotor_freq_hz: float,
|
|
90
|
-
sideband_amplitude: float = 0.015,
|
|
91
|
-
n_harmonics: int = 2,
|
|
92
|
-
) -> NDArray[np.floating]:
|
|
93
|
-
"""Inject eccentricity sidebands at f_s ± k·f_r.
|
|
94
|
-
|
|
95
|
-
Args:
|
|
96
|
-
t: Time axis.
|
|
97
|
-
x: Original signal.
|
|
98
|
-
supply_freq_hz: Supply frequency (Hz).
|
|
99
|
-
rotor_freq_hz: Rotor mechanical frequency (Hz).
|
|
100
|
-
sideband_amplitude: Amplitude per sideband.
|
|
101
|
-
n_harmonics: Number of sideband pairs.
|
|
102
|
-
|
|
103
|
-
Returns:
|
|
104
|
-
Signal with eccentricity fault injected.
|
|
105
|
-
"""
|
|
106
|
-
y = x.copy()
|
|
107
|
-
|
|
108
|
-
for k in range(1, n_harmonics + 1):
|
|
109
|
-
f_lo = supply_freq_hz - k * rotor_freq_hz
|
|
110
|
-
f_hi = supply_freq_hz + k * rotor_freq_hz
|
|
111
|
-
y += sideband_amplitude * np.sin(2.0 * np.pi * f_lo * t)
|
|
112
|
-
y += sideband_amplitude * np.sin(2.0 * np.pi * f_hi * t)
|
|
113
|
-
|
|
114
|
-
return y
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def inject_bearing_fault(
|
|
118
|
-
t: NDArray[np.floating],
|
|
119
|
-
x: NDArray[np.floating],
|
|
120
|
-
supply_freq_hz: float,
|
|
121
|
-
defect_freq_hz: float,
|
|
122
|
-
modulation_depth: float = 0.01,
|
|
123
|
-
n_harmonics: int = 2,
|
|
124
|
-
) -> NDArray[np.floating]:
|
|
125
|
-
"""Inject bearing defect modulation into a current signal.
|
|
126
|
-
|
|
127
|
-
Bearing faults produce torque oscillations that amplitude‑modulate
|
|
128
|
-
the stator current, creating sidebands at f_s ± k·f_defect.
|
|
129
|
-
|
|
130
|
-
Args:
|
|
131
|
-
t: Time axis.
|
|
132
|
-
x: Original signal.
|
|
133
|
-
supply_freq_hz: Supply frequency (Hz).
|
|
134
|
-
defect_freq_hz: Bearing characteristic defect frequency (Hz).
|
|
135
|
-
modulation_depth: Modulation amplitude.
|
|
136
|
-
n_harmonics: Number of sideband pairs.
|
|
137
|
-
|
|
138
|
-
Returns:
|
|
139
|
-
Signal with bearing fault injected.
|
|
140
|
-
"""
|
|
141
|
-
y = x.copy()
|
|
142
|
-
|
|
143
|
-
for k in range(1, n_harmonics + 1):
|
|
144
|
-
f_lo = supply_freq_hz - k * defect_freq_hz
|
|
145
|
-
f_hi = supply_freq_hz + k * defect_freq_hz
|
|
146
|
-
y += modulation_depth * np.sin(2.0 * np.pi * f_lo * t)
|
|
147
|
-
y += modulation_depth * np.sin(2.0 * np.pi * f_hi * t)
|
|
148
|
-
|
|
149
|
-
return y
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def generate_test_signal(
|
|
153
|
-
duration_s: float = 10.0,
|
|
154
|
-
fs_sample: float = 5000.0,
|
|
155
|
-
supply_freq_hz: float = 50.0,
|
|
156
|
-
poles: int = 4,
|
|
157
|
-
rotor_speed_rpm: float = 1470.0,
|
|
158
|
-
amplitude: float = 1.0,
|
|
159
|
-
noise_std: float = 0.01,
|
|
160
|
-
faults: list[str] | None = None,
|
|
161
|
-
fault_severity: float = 0.02,
|
|
162
|
-
bearing_defect_freq_hz: float | None = None,
|
|
163
|
-
) -> dict:
|
|
164
|
-
"""Generate a complete synthetic motor‑current test signal.
|
|
165
|
-
|
|
166
|
-
Convenience function that creates a healthy baseline and optionally
|
|
167
|
-
injects one or more fault types.
|
|
168
|
-
|
|
169
|
-
Args:
|
|
170
|
-
duration_s: Signal duration in seconds.
|
|
171
|
-
fs_sample: Sampling frequency in Hz.
|
|
172
|
-
supply_freq_hz: Supply frequency in Hz.
|
|
173
|
-
poles: Number of poles.
|
|
174
|
-
rotor_speed_rpm: Rotor speed in RPM.
|
|
175
|
-
amplitude: Fundamental amplitude.
|
|
176
|
-
noise_std: Noise level.
|
|
177
|
-
faults: List of fault types to inject. Options:
|
|
178
|
-
``"brb"`` — broken rotor bars,
|
|
179
|
-
``"eccentricity"`` — air‑gap eccentricity,
|
|
180
|
-
``"bearing"`` — bearing defect.
|
|
181
|
-
fault_severity: Amplitude of fault components (0–1 relative).
|
|
182
|
-
bearing_defect_freq_hz: Bearing defect frequency (Hz). Required
|
|
183
|
-
if ``"bearing"`` is in faults.
|
|
184
|
-
|
|
185
|
-
Returns:
|
|
186
|
-
Dictionary with ``time_s``, ``signal``, ``sampling_freq_hz``,
|
|
187
|
-
``motor_params``, ``faults_injected``.
|
|
188
|
-
"""
|
|
189
|
-
sync_speed = 120.0 * supply_freq_hz / poles
|
|
190
|
-
slip = (sync_speed - rotor_speed_rpm) / sync_speed
|
|
191
|
-
rotor_freq = rotor_speed_rpm / 60.0
|
|
192
|
-
|
|
193
|
-
t, x = generate_healthy_signal(
|
|
194
|
-
duration_s, fs_sample, supply_freq_hz, amplitude, noise_std,
|
|
195
|
-
harmonics=[(3, 0.03), (5, 0.015)],
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
injected = []
|
|
199
|
-
|
|
200
|
-
if faults:
|
|
201
|
-
for fault in faults:
|
|
202
|
-
fault = fault.lower().strip()
|
|
203
|
-
if fault == "brb":
|
|
204
|
-
x = inject_brb_fault(t, x, supply_freq_hz, slip, fault_severity)
|
|
205
|
-
injected.append("broken_rotor_bars")
|
|
206
|
-
elif fault == "eccentricity":
|
|
207
|
-
x = inject_eccentricity_fault(
|
|
208
|
-
t, x, supply_freq_hz, rotor_freq, fault_severity
|
|
209
|
-
)
|
|
210
|
-
injected.append("eccentricity")
|
|
211
|
-
elif fault == "bearing":
|
|
212
|
-
bdf = bearing_defect_freq_hz or (3.5 * rotor_freq)
|
|
213
|
-
x = inject_bearing_fault(t, x, supply_freq_hz, bdf, fault_severity)
|
|
214
|
-
injected.append("bearing")
|
|
215
|
-
|
|
216
|
-
return {
|
|
217
|
-
"time_s": t.tolist(),
|
|
218
|
-
"signal": x.tolist(),
|
|
219
|
-
"sampling_freq_hz": fs_sample,
|
|
220
|
-
"duration_s": duration_s,
|
|
221
|
-
"n_samples": len(t),
|
|
222
|
-
"motor_params": {
|
|
223
|
-
"supply_freq_hz": supply_freq_hz,
|
|
224
|
-
"poles": poles,
|
|
225
|
-
"sync_speed_rpm": sync_speed,
|
|
226
|
-
"rotor_speed_rpm": rotor_speed_rpm,
|
|
227
|
-
"slip": slip,
|
|
228
|
-
"rotor_freq_hz": rotor_freq,
|
|
229
|
-
},
|
|
230
|
-
"faults_injected": injected,
|
|
231
|
-
"fault_severity": fault_severity,
|
|
232
|
-
}
|
|
1
|
+
"""Synthetic test‑signal generator for MCSA.
|
|
2
|
+
|
|
3
|
+
Generates simulated stator‑current waveforms with optional fault
|
|
4
|
+
signatures for testing, validation, and demonstration purposes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from numpy.typing import NDArray
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def generate_healthy_signal(
|
|
14
|
+
duration_s: float,
|
|
15
|
+
fs_sample: float,
|
|
16
|
+
supply_freq_hz: float = 50.0,
|
|
17
|
+
amplitude: float = 1.0,
|
|
18
|
+
noise_std: float = 0.01,
|
|
19
|
+
harmonics: list[tuple[int, float]] | None = None,
|
|
20
|
+
) -> tuple[NDArray[np.floating], NDArray[np.floating]]:
|
|
21
|
+
"""Generate a clean (healthy) motor‑current signal.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
duration_s: Signal duration in seconds.
|
|
25
|
+
fs_sample: Sampling frequency in Hz.
|
|
26
|
+
supply_freq_hz: Supply fundamental frequency in Hz.
|
|
27
|
+
amplitude: Peak amplitude of the fundamental.
|
|
28
|
+
noise_std: Standard deviation of additive Gaussian noise.
|
|
29
|
+
harmonics: Optional list of (harmonic_number, relative_amplitude)
|
|
30
|
+
to add supply harmonics (e.g. [(3, 0.05), (5, 0.03)]).
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
(time, signal) — 1‑D arrays.
|
|
34
|
+
"""
|
|
35
|
+
n_samples = int(duration_s * fs_sample)
|
|
36
|
+
t = np.arange(n_samples) / fs_sample
|
|
37
|
+
|
|
38
|
+
x = amplitude * np.sin(2.0 * np.pi * supply_freq_hz * t)
|
|
39
|
+
|
|
40
|
+
if harmonics:
|
|
41
|
+
for h_num, h_amp in harmonics:
|
|
42
|
+
x += h_amp * amplitude * np.sin(2.0 * np.pi * h_num * supply_freq_hz * t)
|
|
43
|
+
|
|
44
|
+
if noise_std > 0:
|
|
45
|
+
x += np.random.default_rng(42).normal(0, noise_std, n_samples)
|
|
46
|
+
|
|
47
|
+
return t, x
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def inject_brb_fault(
|
|
51
|
+
t: NDArray[np.floating],
|
|
52
|
+
x: NDArray[np.floating],
|
|
53
|
+
supply_freq_hz: float,
|
|
54
|
+
slip: float,
|
|
55
|
+
sideband_amplitude: float = 0.02,
|
|
56
|
+
n_harmonics: int = 1,
|
|
57
|
+
) -> NDArray[np.floating]:
|
|
58
|
+
"""Inject broken‑rotor‑bar sidebands into a current signal.
|
|
59
|
+
|
|
60
|
+
Adds components at (1 ± 2ks)·f_s for k = 1 … n_harmonics.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
t: Time axis.
|
|
64
|
+
x: Original signal.
|
|
65
|
+
supply_freq_hz: Supply frequency (Hz).
|
|
66
|
+
slip: Motor slip (per‑unit).
|
|
67
|
+
sideband_amplitude: Amplitude of each sideband component.
|
|
68
|
+
n_harmonics: Number of sideband pairs.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Signal with BRB fault injected.
|
|
72
|
+
"""
|
|
73
|
+
y = x.copy()
|
|
74
|
+
fs = supply_freq_hz
|
|
75
|
+
|
|
76
|
+
for k in range(1, n_harmonics + 1):
|
|
77
|
+
f_lower = (1 - 2 * k * slip) * fs
|
|
78
|
+
f_upper = (1 + 2 * k * slip) * fs
|
|
79
|
+
y += sideband_amplitude * np.sin(2.0 * np.pi * f_lower * t)
|
|
80
|
+
y += sideband_amplitude * np.sin(2.0 * np.pi * f_upper * t)
|
|
81
|
+
|
|
82
|
+
return y
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def inject_eccentricity_fault(
|
|
86
|
+
t: NDArray[np.floating],
|
|
87
|
+
x: NDArray[np.floating],
|
|
88
|
+
supply_freq_hz: float,
|
|
89
|
+
rotor_freq_hz: float,
|
|
90
|
+
sideband_amplitude: float = 0.015,
|
|
91
|
+
n_harmonics: int = 2,
|
|
92
|
+
) -> NDArray[np.floating]:
|
|
93
|
+
"""Inject eccentricity sidebands at f_s ± k·f_r.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
t: Time axis.
|
|
97
|
+
x: Original signal.
|
|
98
|
+
supply_freq_hz: Supply frequency (Hz).
|
|
99
|
+
rotor_freq_hz: Rotor mechanical frequency (Hz).
|
|
100
|
+
sideband_amplitude: Amplitude per sideband.
|
|
101
|
+
n_harmonics: Number of sideband pairs.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
Signal with eccentricity fault injected.
|
|
105
|
+
"""
|
|
106
|
+
y = x.copy()
|
|
107
|
+
|
|
108
|
+
for k in range(1, n_harmonics + 1):
|
|
109
|
+
f_lo = supply_freq_hz - k * rotor_freq_hz
|
|
110
|
+
f_hi = supply_freq_hz + k * rotor_freq_hz
|
|
111
|
+
y += sideband_amplitude * np.sin(2.0 * np.pi * f_lo * t)
|
|
112
|
+
y += sideband_amplitude * np.sin(2.0 * np.pi * f_hi * t)
|
|
113
|
+
|
|
114
|
+
return y
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def inject_bearing_fault(
|
|
118
|
+
t: NDArray[np.floating],
|
|
119
|
+
x: NDArray[np.floating],
|
|
120
|
+
supply_freq_hz: float,
|
|
121
|
+
defect_freq_hz: float,
|
|
122
|
+
modulation_depth: float = 0.01,
|
|
123
|
+
n_harmonics: int = 2,
|
|
124
|
+
) -> NDArray[np.floating]:
|
|
125
|
+
"""Inject bearing defect modulation into a current signal.
|
|
126
|
+
|
|
127
|
+
Bearing faults produce torque oscillations that amplitude‑modulate
|
|
128
|
+
the stator current, creating sidebands at f_s ± k·f_defect.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
t: Time axis.
|
|
132
|
+
x: Original signal.
|
|
133
|
+
supply_freq_hz: Supply frequency (Hz).
|
|
134
|
+
defect_freq_hz: Bearing characteristic defect frequency (Hz).
|
|
135
|
+
modulation_depth: Modulation amplitude.
|
|
136
|
+
n_harmonics: Number of sideband pairs.
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Signal with bearing fault injected.
|
|
140
|
+
"""
|
|
141
|
+
y = x.copy()
|
|
142
|
+
|
|
143
|
+
for k in range(1, n_harmonics + 1):
|
|
144
|
+
f_lo = supply_freq_hz - k * defect_freq_hz
|
|
145
|
+
f_hi = supply_freq_hz + k * defect_freq_hz
|
|
146
|
+
y += modulation_depth * np.sin(2.0 * np.pi * f_lo * t)
|
|
147
|
+
y += modulation_depth * np.sin(2.0 * np.pi * f_hi * t)
|
|
148
|
+
|
|
149
|
+
return y
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def generate_test_signal(
|
|
153
|
+
duration_s: float = 10.0,
|
|
154
|
+
fs_sample: float = 5000.0,
|
|
155
|
+
supply_freq_hz: float = 50.0,
|
|
156
|
+
poles: int = 4,
|
|
157
|
+
rotor_speed_rpm: float = 1470.0,
|
|
158
|
+
amplitude: float = 1.0,
|
|
159
|
+
noise_std: float = 0.01,
|
|
160
|
+
faults: list[str] | None = None,
|
|
161
|
+
fault_severity: float = 0.02,
|
|
162
|
+
bearing_defect_freq_hz: float | None = None,
|
|
163
|
+
) -> dict:
|
|
164
|
+
"""Generate a complete synthetic motor‑current test signal.
|
|
165
|
+
|
|
166
|
+
Convenience function that creates a healthy baseline and optionally
|
|
167
|
+
injects one or more fault types.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
duration_s: Signal duration in seconds.
|
|
171
|
+
fs_sample: Sampling frequency in Hz.
|
|
172
|
+
supply_freq_hz: Supply frequency in Hz.
|
|
173
|
+
poles: Number of poles.
|
|
174
|
+
rotor_speed_rpm: Rotor speed in RPM.
|
|
175
|
+
amplitude: Fundamental amplitude.
|
|
176
|
+
noise_std: Noise level.
|
|
177
|
+
faults: List of fault types to inject. Options:
|
|
178
|
+
``"brb"`` — broken rotor bars,
|
|
179
|
+
``"eccentricity"`` — air‑gap eccentricity,
|
|
180
|
+
``"bearing"`` — bearing defect.
|
|
181
|
+
fault_severity: Amplitude of fault components (0–1 relative).
|
|
182
|
+
bearing_defect_freq_hz: Bearing defect frequency (Hz). Required
|
|
183
|
+
if ``"bearing"`` is in faults.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Dictionary with ``time_s``, ``signal``, ``sampling_freq_hz``,
|
|
187
|
+
``motor_params``, ``faults_injected``.
|
|
188
|
+
"""
|
|
189
|
+
sync_speed = 120.0 * supply_freq_hz / poles
|
|
190
|
+
slip = (sync_speed - rotor_speed_rpm) / sync_speed
|
|
191
|
+
rotor_freq = rotor_speed_rpm / 60.0
|
|
192
|
+
|
|
193
|
+
t, x = generate_healthy_signal(
|
|
194
|
+
duration_s, fs_sample, supply_freq_hz, amplitude, noise_std,
|
|
195
|
+
harmonics=[(3, 0.03), (5, 0.015)],
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
injected = []
|
|
199
|
+
|
|
200
|
+
if faults:
|
|
201
|
+
for fault in faults:
|
|
202
|
+
fault = fault.lower().strip()
|
|
203
|
+
if fault == "brb":
|
|
204
|
+
x = inject_brb_fault(t, x, supply_freq_hz, slip, fault_severity)
|
|
205
|
+
injected.append("broken_rotor_bars")
|
|
206
|
+
elif fault == "eccentricity":
|
|
207
|
+
x = inject_eccentricity_fault(
|
|
208
|
+
t, x, supply_freq_hz, rotor_freq, fault_severity
|
|
209
|
+
)
|
|
210
|
+
injected.append("eccentricity")
|
|
211
|
+
elif fault == "bearing":
|
|
212
|
+
bdf = bearing_defect_freq_hz or (3.5 * rotor_freq)
|
|
213
|
+
x = inject_bearing_fault(t, x, supply_freq_hz, bdf, fault_severity)
|
|
214
|
+
injected.append("bearing")
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
"time_s": t.tolist(),
|
|
218
|
+
"signal": x.tolist(),
|
|
219
|
+
"sampling_freq_hz": fs_sample,
|
|
220
|
+
"duration_s": duration_s,
|
|
221
|
+
"n_samples": len(t),
|
|
222
|
+
"motor_params": {
|
|
223
|
+
"supply_freq_hz": supply_freq_hz,
|
|
224
|
+
"poles": poles,
|
|
225
|
+
"sync_speed_rpm": sync_speed,
|
|
226
|
+
"rotor_speed_rpm": rotor_speed_rpm,
|
|
227
|
+
"slip": slip,
|
|
228
|
+
"rotor_freq_hz": rotor_freq,
|
|
229
|
+
},
|
|
230
|
+
"faults_injected": injected,
|
|
231
|
+
"fault_severity": fault_severity,
|
|
232
|
+
}
|