2

I have a drivetrain setup where I have a ~3Hz vibration which I can feel quite strongly in the seat of my pants, but can't seem to see in accelerometer data.

Below is a diagram of the system. There is a 4-cycle 4-cylinder Rotax 914 engine which drives a 2.45:1 gearbox which in turn drives a driveshaft which in turn drives another 1.1:1 belt drive which finally drives the three-bladed propeller:

enter image description here

The engine spins around 5600rpm at max speed, and at this point the prop is around 2100RPM (~2.6:1 overall reduction). At a range of engine speeds from 4200-5400rpm I feel a sharp 3-4Hz impulse through the seat of my pants. Via a series of tests we have conclusively demonstrated that the impulse is tied to engine RPM, and nothing else. However, there is absolutely nothing which spins at 3-4Hz, or anywhere close to that. And the vibration completely smooths out below 4200rpm and above 5400 rpm I can no longer feel it (although there's a lot of broadband vibration at that rpm).

This impulse's band-limited nature points toward some kind of poorly damped constructive resonance between the various spinning elements. But before concluding that, I'd like to make sure that the data supports the theory. I have hooked up an accelerometer near the seatpan, another accelerometer on the gearbox, and a tachometer to measure engine position (which can be used to get RPM). I'd like to see if the signal is tied to some order of rpm.

I have done some basic spectrometer work (with Matlab), and I cannot see any discernible low-speed signal. In the accelerometer data I can make out the propeller RPM, the engine RPM, and (I think) even the driveshaft RPM. And, yet, this signal I can so easily feel in my body I cannot see in my data. Investigating the lower frequencies shows just noise.

What is a recommended approach to extracting this low speed signal in a noisy environment?

P.S. I am using two GY-521 accelerometers, which are the knock-off versions of the MPU-6050. I measure them at 1000Hz, using interrupts so I am sure that the data is read in a timely manner.


Update

Thanks to the people who answered, I learned that it's a beat frequency I'm feeling. The equation for a beat frequency is simply $f_{beat} = |f_2 - f_1|$. So since the driveshaft is 10% faster than the propeller, if the propeller spins at 2000rpm, then |(2000/60*1.1 - 2000/60)| = 3.3Hz. That's precisely what I feel.

Interestingly, that means there are two other beat frequencies as well, between the prop/engine and the driveshaft/engine. These frequencies are seen in the analysis presented in https://dsp.stackexchange.com/a/88983. My guess is that the 7.5Hz and 11Hz peak have to do with beat frequencies between cylinder-level vibration events, which occur at half engine speed, and the propeller and driveshaft, respectively.

Kenn Sebesta
  • 123
  • 5
  • Are you in the seat when performing the test? Resonance frequency is inversely related to mass and could be localized to a response of the chair. – Ash Aug 01 '23 at 01:03
  • @Ash that's an excellent point. I am in the seat when I feel it. Someone sitting in the other seat can also feel it at the same time, so it's not localized to just the one seat pan. It's also worth mentioning that this is a very reclined seat, and not set up like a chair: https://th.bing.com/th/id/OIP.AIsDMmdi7r9NP5FreiJn1wHaE7?pid=ImgDet&rs=1. The bottom of the seat pan is an integral part of the airframe, so it is not shock-absorbed or otherwise isolated. – Kenn Sebesta Aug 01 '23 at 14:38
  • Should the takeaway be that I would stand a better chance of detecting the low-frequency vibration if I were to attach a second accelerometer to the seat pan? – Kenn Sebesta Aug 01 '23 at 14:39
  • I'm just verifying that when you take measurements with the accelerometer, you are recreating the conditions in which you experience the vibration (e.g., by sitting in the seat you may apply a specific loading to the airframe). If you feel the vibration, your sensor almost certainly does as well. Low frequencies are somewhat agnostic to mounting material (wax vs. epoxy). It could be beneficial to post the 3 channel (one for each accelerometer axis) to let us else play around with it. Have you verified that the sensor works as expected outside of your test setup? – Ash Aug 01 '23 at 15:18
  • @Ash I have some data, but based on what you're saying there's a good chance that my measurement points where wrong. I will go for another flight with one sensor in my seat pan and the other one on the gearbox. – Kenn Sebesta Aug 01 '23 at 18:15
  • @Ash I collected some more data today, but no joy in terms of readily seeing the 3-4Hz impulse. How do I upload the data to SE.DSP? Or do I just share a link from a cloud storage account? – Kenn Sebesta Aug 03 '23 at 02:02
  • A link to cloud storage would be fine. – Ash Aug 03 '23 at 15:19
  • @Ash, this data is from a brief collection at 5100 engine rpm, when I could very clearly feel the impulse through the seat pan: https://drive.google.com/file/d/1khQ8QTifsWwhJ33XSjedggzJnQRBXgkC/view?usp=sharing. It's a .mat file, let me know if you would like another format. The struct's accelerometer fields are identified as longitudinal, lateral, and vertical. Presumably, there would be minimal rotational vibration along the longitudinal direction. – Kenn Sebesta Aug 03 '23 at 18:37
  • from MPU-60X0 manual: "Accelerometer measurements are passed through a configurable digital high pass filter (DHPF) in order to eliminate bias due to gravity." Are you sure your sensor is giving good readings at ~3 Hz? Either a high pass filter or low sensitivity at low frequencies could be a problem. Maybe just take a recording while you shake the sensor and see if you can get meaningfull values from that to prove that low frequency measurements work. – Matthias La Aug 08 '23 at 07:17
  • @MatthiasLa I think that HP filter is only accessible for the wake-on-motion feature. It's a relatively undocumented feature, without the register map even explaining how to set it. Anecdotally, I've been using this sensor for a decade and never noticed it high-pass filtering gravity. – Kenn Sebesta Aug 08 '23 at 10:51
  • As you say, I indeed found the acceleration in vertical direction to average out at ~9.8m/s^2, so obviously no low pass filtering. – Matthias La Aug 10 '23 at 06:18

3 Answers3

2

I've done a FFT analysis of the seatpan vertical acceleration data: seatpan vertical acceleration

After zooming in on the lower frequencies it seems that higher amplitudes occur closer to 0 Hz but not at 4 Hz: seatpan vertical acceleration

However the two increased frequencies at ~34 Hz and ~39 Hz together with the frequency at ~46 Hz should lead to some beating phenomena at low frequencies due to modulation which might be perceived as low frequency vibration.

Calculating a modulation spectrum vs time shows this: Modulation spectrum of seatpan vertical acceleration

Averaging of the modulation spectra gives: averaged modulation speactra of seattrack vertical accelerations

Further reading about the metrics used: Modulation Analysis Vibration Analysis of Rotating Machinery (Matlab)

Edit

As I have not done the analysis with matlab I can't simply post the code. But I can briefly say what would be needed. For the FFT colorplot, given y is the data and t the time vector:

FFTlen=1; % FFT length in seconds
[~,b]=min(abs(t-FFTlen));
if rem(b, 2) ~= 0
    b=b-1;
end
FrameSize = b;
Fs = 1/(t(2)-t(1));

hannEstimator = dsp.SpectrumEstimator('PowerUnits',"dBm",... 'Window',"Hann",'FrequencyRange',"onesided",... 'SpectralAverages',numAvgs,'SampleRate',Fs);

step=round(0.1*FrameSize); FFT=[]; i=0;

while (istep+FrameSize)<=length(y) x=y((istep+1):(istep+FrameSize)); Pse_hann = hannEstimator(x); tf(i+1)=t(istep+1); FFT(:,i+1)=Pse_hann; i=i+1 end

pFFT=pcolor(tf,[0:((Fs/2)/(size(FFT,1)-1)):(Fs/2)],FFT); shading interp xlabel('Seconds') ylabel('Frequency (Hz)') title('FFT') colormap(jet(256)); colorbar zMin=min(min(FFT)); zMax=max(max(FFT)); caxis([zMax-40, zMax]);

For the modulation analysis you need to similiarly calculate a FFT at fixed timestaps, but then from the envelope of the time signal. For calculating the envelope first you probably can use the Matlab envelope() function. Matlab envelope function

Lastly for the analysis of your beating frequencies I made this table:OrderFrequencies

It's very interesting that the 1/2 engine order seems to be the cause for the 2 higher beating frequencies. I think you are right that it has to do with between cylinder variations. I once had an issue with a high half order at a vehicle engine and changing the injectors to ones with lower tolerances helped significantly. It's also interesting that you don't feel the ~8 and ~11Hz but the ~3.5Hz. So maybe it would be possible to improve that ~3.5Hz beating issue by changing the distribution of the transmission ratio from 2.45&1.1 to something like 2.25&1.2. That way the overall ratio of 2.45*1.1=~2.7 would be kept (1.2*2.25=~2.7), but the resulting beating frequency would increase to |(2000/60*1.2 - 2000/60)| = 6.7Hz which might be enough to not be felt that much anymore.

Matthias La
  • 380
  • 2
  • 9
  • Fascinating! The 3.3Hz signal has got to be what I was feeling. What's so interesting here is that there're stronger peaks at 7.5 and 11Hz. I don't feel those, but that might be because they're too fast to individually sense. – Kenn Sebesta Aug 08 '23 at 13:49
  • I'll read those links, but for completeness would you mind posting the matlab code you used? – Kenn Sebesta Aug 08 '23 at 13:49
  • 1
    With some further thought, and looking at my graph from https://engineering.stackexchange.com/questions/55917/what-are-the-unknown-sources-of-vibration-in-this-rotax-914-propulsion-system/, I think the 7.5Hz and 11Hz signals are coming from the half-speed of the engine, which is the individual cylinder firing speed. (There's possibly a cylinder which is not firing as well as it should.) When this beat frequency is calculated for the propeller and driveshaft, it winds up in the ~8 and ~11Hz, respectively. – Kenn Sebesta Aug 08 '23 at 17:34
1

I performed some analysis on the data you provided. The first plot is the 3-axis acceleration magnitude for both the seatpan and gearbox, sampled at 1 kHz. Both accelerations follow each other fairly consistently and, assuming the units are accurate, there are some substantial oscillations at low frequencies - so you likely aren't crazy! Note that the large oscillations at the beginning are a transient artifact of the IIR butterworth filter and should just be ignored. The stable region after about 12 seconds looks more trustworthy, so focus on that for the three plots.

The second and third plots are the instantaneous frequency estimates using the Hilbert transform about the bandpassed engine and propeller rotational frequencies, respectively. It looks like there might be some resonances closer to 5175 RPM that are leading to your seatpan vibration. It's difficult to make many conclusions from this data about where the vibration is propagating from, but hopefully this helps you track it down.

I've included the code down below if you want to play around with it. Though it's in Python, the MATLAB code would look very similar.

enter image description here

from scipy.io import loadmat
from matplotlib import pyplot as plt
from scipy.signal import butter, sosfilt, hilbert
import numpy as np

mat = loadmat('se_dsp.mat')

Load the gearbox and seatpan acceleration data

gb = mat['accel_gearbox'][0][0][0] sp = mat['accel_seatpan'][0][0][0]

Sample rate (Hz)

fs = 1000

Calculate magnitude of 3 axes of acceleration

gb_mag = np.sqrt(np.sum(gb[:, 1:]2, axis=1)) sp_mag = np.sqrt(np.sum(sp[:, 1:]2, axis=1))

Create two plots that have a linked x-axis

fig, axes = plt.subplots(3, 1, sharex='all')

Define a nominal engine frequency to bandpass filter

engine_RPM = 5100

Convert RPM to Hz for engine and prop

engine_Hz = engine_RPM / 60 prop_Hz = engine_Hz / 2.6

Plot magnitude of 3-4 Hz Acceleration

Perform a 10th order butterworth bandpass about 2-5 Hz

sos = butter(10, (2, 5), 'bandpass', fs=fs, output='sos') gb_bandpass = sosfilt(sos, gb_mag) sp_bandpass = sosfilt(sos, sp_mag)

Get time vectors for each since they are of different lengths

t_gb = np.arange(0, len(gb_bandpass)) / fs t_sp = np.arange(0, len(sp_bandpass)) / fs

Plot it

axes[0].plot(t_sp, sp_bandpass, label='Seatpan', alpha=0.5) axes[0].plot(t_gb, gb_bandpass, label='Gearbox', alpha=0.5) axes[0].set_title('Acceleration near 3-4 Hz') axes[0].set_ylabel('3-Axis Acceleration\nMagnitude (G's?)') axes[0].set_ylim(-0.75, 0.75) axes[0].legend()

Plot instantaneous frequency of engine

Filter acceleration +/- 2.5 Hz about 5100 RPM (85 Hz) using 10th order butterworth bandpass

bandwidth = 5 sos = butter(10, (engine_Hz - bandwidth/2, engine_Hz + bandwidth/2), 'bandpass', fs=fs, output='sos') gb_engine_bandpass = sosfilt(sos, gb_mag)

Get analytical signal of filtered data using hilbert transform, perform window to attempt to manage edge effects

gb_engine_analytical = hilbert(gb_engine_bandpass*np.hanning(len(gb_engine_bandpass)))

Instantaneous frequency is the derivative of the unwrapped phase of the analytical signal

gb_engine_RPM = np.diff(np.unwrap(np.angle(gb_engine_analytical))/(2np.pi)fs*60, prepend=0)

Plot it

axes[1].plot(t_gb, gb_engine_RPM) axes[1].set_ylim(60(engine_Hz - 2.5bandwidth/2), 60(engine_Hz + 2.5bandwidth/2)) axes[1].set_title('Gearbox Instantaneous Frequency') axes[1].set_ylabel('Est. Engine RPM') axes[1].set_ylim(5050, 5275)

Plot instantaneous frequency of prop, should follow engine frequency relatively closely

Filter acceleration +/- 1 Hz about geared-down engine frequency using 10th order butterworth bandpass

bandwidth = 2 sos = butter(10, (prop_Hz - bandwidth/2, prop_Hz + bandwidth/2), 'bandpass', fs=fs, output='sos') gb_prop_bandpass = sosfilt(sos, gb_mag)

Get analytical signal of filtered data using hilbert transform, perform window to attempt to manage edge effects

gb_prop_analytical = hilbert(gb_prop_bandpass*np.hanning(len(gb_prop_bandpass)))

Instantaneous frequency is the derivative of the unwrapped phase of the analytical signal

gb_prop_RPM = np.diff(np.unwrap(np.angle(gb_prop_analytical))/(2np.pi)fs*60, prepend=0)

Plot it

axes[2].plot(t_gb, gb_prop_RPM) axes[2].set_ylim(60(prop_Hz - 2.5bandwidth/2), 60(prop_Hz + 2.5bandwidth/2)) axes[2].set_title('Gearbox Instantaneous Frequency') axes[2].set_ylabel('Est. Prop RPM') axes[2].set_xlabel('Time (sec)') axes[2].set_ylim(1900, 1960) plt.show()

Ash
  • 895
  • 2
  • 6
  • Fantastic! I'll give it a good look. I also noticed that I felt the pulse the most strongly in my seatback, so I'll maybe move the sensor there and rerun your code. – Kenn Sebesta Aug 08 '23 at 03:24
0

For your case of low frequency exploration, I would suggest to use autocorrelation (better than FFT for low-frequencies).

Some python examples can be found here:

https://www.geeksforgeeks.org/how-to-calculate-autocorrelation-in-python/

Filipe Pinto
  • 721
  • 4
  • 11
  • That's a neat idea. As a heavy Matlab user for control systems, I have a certain familiar with cross-correlation methods, although I must admit I don't see how they would apply here. Could you expand the answer with some strategies to apply to the real-world noisy data? – Kenn Sebesta Aug 01 '23 at 14:42
  • I'm also interested in the comment about "low frequencies". What defines "low" in this context? Is it something like a rule of thumb that if you have a strong signal at X frequency, then, e.g., two orders of magnitude slower would be hard to see with an FFT? – Kenn Sebesta Aug 01 '23 at 14:44
  • When you are working with low frequencies, i.e. working near the origin in the FFT frequency domain, it can be difficult to exactly identify peaks due to a lack of resolution. For these cases, I usually rely on autocorrelation. In Matlab you can use the xcorr function. – Filipe Pinto Aug 01 '23 at 15:07
  • I use xcorr for determining phase delays, but haven't used it to identify peaks in noisy data. Would you be willing to flesh out the answer to demonstrate this technique? I can play around with xcorr, but I don't have a sense as to TLAR and TLAW for real-world vibration data. – Kenn Sebesta Aug 01 '23 at 15:12
  • I could add some code but it would be exactly as the examples since I don't know your signals. XCORR multiplies the signal by itslef with a given lag corresponding to Ts=1/Fs. When you calculate autorcorrelation you will usually find a very high peak at 0 (lag). The next peak will be the first "hidden" periodocity. To find the peaks you can use FINDPEAKS. – Filipe Pinto Aug 01 '23 at 22:46
  • @KennSebesta also please see this similar post and code to recreate – Jdip Aug 08 '23 at 09:19