Generated reference › RPM Frequency Map — Control Systems/Vibration
kind: generated#block#control-systems-vibration

RPM Frequency Map — Control Systems/Vibration

Control_Systems/Vibration/RPM_Frequency_Map · 2 input / 3 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

RPM-Frequency Map

Control Systems / Vibration

The frequency map versus speed of a machine that is running up or down – MATLAB's rpmfreqmap, one column at a time. Every hop samples the block takes the last L samples, windows them and publishes the one-sided spectrum of that frame together with the shaft speed at the frame's centre, so a recorder builds the whole map over the run:

columnj[m] = c(m)·|Σn w[n]·x[j·hop+n]·e−i2πmn/N|,   m = 0 … N/2,   N = max(256, L),

with the window normalized to sum 1 and c the one-sided fold: 1 at DC and at Nyquist, √2 between. The window length L is not a parameter – it follows from the resolution asked for.

Ports

  • u – the sampled signal, scalar: one channel and its own window.
  • rpm – the shaft speed in revolutions per minute at the same instant, scalar and positive. It is a signal, not a parameter, because it is what the map is drawn against.
  • map – the current column, [N/2+1, 1], one-sided with DC first and Nyquist last; bin m is at m·fs/N hertz. It changes only on a frame sample and holds in between.
  • rpm – scalar: the speed at that column's centre, the map's horizontal axis. Interpolated between the two samples either side of the centre when the window is odd.
  • t – scalar: the time of that centre in seconds from the run's first sample, (j·hop + L/2)/fs.

Parameters

  • Sample Rate (Hz) – fs, the rate the signal was sampled at: the resolution, the window length and the output bins are all in hertz through it. Positive; defaults to 1000.
  • Resolution (Hz) – the frequency resolution asked for, which is what sets the window length: L is the length whose equivalent noise bandwidth gives that resolution, found by the same iteration rpmfreqmap uses. A finer resolution means a longer window and a slower map. Defaults to 7.8125, which is rpmfreqmap's own default of fs/128 at the default rate, and gives L = 193 with a Hann window. A resolution too fine for a window of 1024 samples, or too coarse for one of 4, is clamped to that window rather than refused – as rpmfreqmap clamps it to the record.
  • Window – the shape the frame is multiplied by, normalized to sum 1:
    • Hann – rpmfreqmap's default.
    • Hamming – a lower first sidelobe, a wider main lobe.
    • Flat Top – amplitude-accurate on a line that falls between bins, and the widest of the four; rpmordermap's default.
    • Rectangular – no window at all.
    rpmfreqmap also takes Kaiser and Chebyshev windows, which need a second parameter each; those two are not offered here.
  • Overlap Percent – how much of one frame the next one repeats, 0 to 100. The overlap in samples is min(ceil(percent/100·L), L−1) and the hop is L minus that, exactly as in rpmfreqmap. Defaults to 50.
  • Amplitude – what a bin carries:
    • RMS – the root-mean-square amplitude of that line: the default.
    • Peak – the peak amplitude, √2 times the RMS one (and at Nyquist, √2 times the unfolded magnitude).
    • Power – the square of the RMS value.
  • Scale – Linear, or dB: 20·log10 of an amplitude, 10·log10 of a power. A bin that is exactly zero is −∞ in dB, as it is in MATLAB.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Frames and timing

The first column is published when the window first fills – at sample L−1, counting from 0 – and then every hop samples, so the output at sample L−1+j·hop is column j of rpmfreqmap over the same record. Between columns all three outputs hold; before the first they are zero. The block is exactly rpmfreqmap here: a column depends on L samples and on nothing else, so nothing about it needs the rest of the record.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The window is computed once at export time and carried as numbers; the transform, the fold and the scaling run as loops in the core, so the emitted program does not grow with the number of bins. Every parameter is structural – re-export after changing one.

⚠ The three HDL targets run those loops in simulation-only real arithmetic, quantizing only at the port boundaries: a transform of a 1024-sample window and a square root do not belong in a Q16.16 datapath. They are not offered as synthesizable.

Simulink bridge

None (Support::None). rpmfreqmap is a Signal Processing Toolbox function and that toolbox ships no Simulink library, so there is no path a diagram could name. The bridge reports this block rather than dropping it silently, and it therefore has no parity testbench; code export verification still covers it across all ten languages.

Notes

  • Stateful, and discrete by nature (setDiscreteOnlyBlock(true)): two shift registers of L samples, a frame counter and the held column.
  • The speed axis is a signal, not a parameter. Feed rpm from a tachometer block (Tacho Pulse RPM) or from a recorded speed channel; the map is only as good as that speed.
  • Not Spectrogram. That block publishes |X| at a transform length equal to its window; this one follows rpmfreqmap – the window length comes from a resolution, the transform is at least 256 long, the window sums to 1, and the speed and time of each column come out beside it.
  • No state space. A magnitude is not linear in the window, so model reduction correctly declines to merge it.

Code facts#

FactValue
registered typeControl_Systems/Vibration/RPM_Frequency_Map
familyControl_Systems/Vibration
solver environment classICoreBlock_0_Control_Systems_1_Vibration_2_RPM_Frequency_Map
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Vibration/RPM_Frequency_Map/ICoreBlock_0_Control_Systems_1_Vibration_2_RPM_Frequency_Map.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Vibration/RPM_Frequency_Map/ICoreBlock_0_Control_Systems_1_Vibration_2_RPM_Frequency_Map.h
default size on canvas150 × 90 px
ports at insert2 in, 3 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2inICoreDoublerpm
3outICoreDoublemap
4outICoreDoublerpm
5outICoreDoublet

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Sample Rate (Hz)1000—
Resolution (Hz)7.8125—
WindowRM::WIN_HANN%~%RM::WIN_HAMMING%~%RM::WIN_FLATTOP%~%RM::WI…—
Overlap Percent50—
AmplitudeRM::AMP_RMS%~%RM::AMP_PEAK%~%RM::AMP_POWER~~RM::AMP_RMS—
ScaleRM::SCALE_LINEAR%~%RM::SCALE_DB~~RM::SCALE_LINEAR—

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::None
Simulink path—
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): rpmfreqmap is a Signal Processing Toolbox function, not a Simulink library block -- that toolbox ships no Simulink library at all -- so there is no path a diagram could name; the block is reported rather than dropped when a model crosses

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

RPM-Frequency Map -- MATLAB's rpmfreqmap, one column at a time A machine that runs up or down in speed writes its story in a map whose rows are FREQUENCY and whose columns are the speed the shaft had while that column was measured. This block publishes that map one column at a time:

L <- the window length the RESOLUTION asks for (rpmmap.m's ENBW iteration) hop <- L - min(ceil(OverlapPercent/100*L), L-1) nfft <- max(256, L) column j <- |DFT(w .* x[j*hop .. j*hop+L-1], nfft)| over bins 0 .. nfft/2, with the window normalized to sum 1, every bin but DC and Nyquist multiplied by sqrt(2), and the Amplitude and Scale rules on top of that rpm j <- the speed at the column's CENTRE, sample j*hop + L/2 t j <- (j*hop + L/2) / fs

⚠ THE FRAMING AND THE SCALING WERE READ OUT OF R2026a's rpmmap.m AND THEN MEASURED, not guessed. On a 600-sample record at fs = 1000 with the speed ramping 1500 -> 3000 rpm, the default configuration (resolution fs/128, Hann, 50 % overlap, rms, linear) gives a 129 x 5 map; the five columns of this block's framing -- a frame at sample L-1 and every hop after -- reproduce rpmfreqmap's five columns at max |error| = 0 (bit for bit, the same FFT), and the interpolated speeds at the column centres reproduce its rpm axis at max |error| = 0. What that pinned, each one a silent wrong answer if guessed:

  • THE WINDOW LENGTH IS NOT ceil(ENBW*fs/resolution) BUT A FIXED POINT OF IT. The ENBW

depends on the length being chosen, so rpmmap iterates and, when the iteration cycles, takes the length whose resolution is closest. At fs = 1000 and resolution fs/128 with a Hann window that is 193 samples, not 192.

  • nfft IS max(256, L), so the map has at least 129 rows however short the window is, and

the frequency axis is k*fs/nfft rather than k*fs/L.

  • THE WINDOW IS NORMALIZED TO SUM 1, which is what makes a bin read as an amplitude.
  • 'peak' MULTIPLIES BY sqrt(2) TWICE (once in the one-sided fold, once more) rather than

by 2 -- and the two are not the same double. The Nyquist bin gets the second factor and not the first.

Support::None: rpmfreqmap is a Signal Processing Toolbox FUNCTION and that toolbox ships no Simulink library, so there is no counterpart to bridge to or run a parity testbench against.

Sample results#

RPM Frequency Map — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleRPM Frequency Map — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0 [129x1] entry 0out ICoreDouble-Out-1out ICoreDouble-Out-2
tin ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0 [129x1] entry 0out ICoreDouble-Out-1out ICoreDouble-Out-2
0-2-2[0, 0, 0, 0]…00
0.40.50.5[0, 0, 0, 0]…00
0.8-2-2[0, 0, 0, 0]…00
1.20.50.5[0, 0, 0, 0]…00
1.6-2-2[0, 0, 0, 0]…00
20.50.5[0, 0, 0, 0]…00
2.4-2-2[0, 0, 0, 0]…00
2.80.50.5[0, 0, 0, 0]…00
3.2-2-2[0, 0, 0, 0]…00
3.60.50.5[0, 0, 0, 0]…00
4-2-2[0, 0, 0, 0]…00
4.40.50.5[0, 0, 0, 0]…00
4.8-2-2[0, 0, 0, 0]…00
5.20.50.5[0, 0, 0, 0]…00

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 0
rampRamp: slope 1 from t = 00 … 0
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias0 … 0
stepStep: 0 -> 1 at t = 1 s0 … 0

Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample

Category static · sample time 0.1 · 60 steps · commit 6b0471a23bd6163d7d7f33f764df08a614c2b6b8 · produced by docsSample --out <folder> --blocks Scalar_Root_Find Scalar_Bounded_Minimization Order_Waveform Order_Track RPM_Frequency_Map RPM_Order_Map --steps 60 · data docs/generated/samples/Control_Systems__Vibration__RPM_Frequency_Map.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).