This project is submitted for

Description

A computer running a program written in Python and using the libraries, Numpy, Scipy, Matplotlib, and Pyserial is the FFT spectrum analyzer. An Arduino Nano is used as the data acquisition system for reading acceleration form a ADXL335 accelerometer.
This combination makes an effective, simple and low cost FFT spectrum analyzer for machinery vibration analysis.

Details

Overview

Machinery vibration is usually the best indicator of overall mechanical condition. It is used in preventive and corrective maintenance.

It can be measured using displacement and velocity transducers, and accelerometers. You can get an overall reading indicating the maximum value of vibration, but the most useful information is obtained with a FFT spectrum analysis of a time period reading.

Machinery vibration analyzers are usually expensive and complicated and many small and medium sized industries can't afford this instruments, particularly in my country (Bolivia).

Open source hardware and software tools are very accessible this days, and a simple, inexpensive and open source FFT spectrum analyzer can be easily built using some of this tools.

Description

For this project, an Arduino Nano is used as the data acquisition system, it contains an USB to serial converter and ADC channels. A common accelerometer, the ADXL335 is used as the transducer for vibration measurement, and a computer is the FFT analyzer, using Python and Numy, Scipy and Matplotlib libraries.

A system diagram is shown below.

The Arduino Nano listens for an incoming command from the computer, that tells it to start or stop sending ADC readings. The ADC reads the accelerometer vibration channels on a given sampling frequency (5000 Hz), controlled by one of the micro controller timers. This readings are sent on the serial port at a speed of 0.5 Mbps.

The Arduino Nano program (adxl335_01.c ) is compiled with Avr gcc, and programmed using Avrdude and the Arduino Bootloader installed in the atMega328 microcontroller. The Arduino libraries and IDE are not used.

The ADXL335 is a small, thin, low power, complete 3-axis accelerometer with signal conditioned voltage outputs. Maximum bandwidth is selected for the application, with a range of 1600 Hz for the X and Y axes. The Z axis maximum range is 550Hz, and is not used because the limited range, but it is wired to the micro controller in case it is used in the future.

A circuit diagram is shown next.

The computer controls the data acquisition sending commands to start or stop the transmission of samples. The program counts the amount of data received and the amount of data it needs (sample size). When the necessary amount of data has been taken, a command to stop is send to the microcontroller. Pyserial is the python library used to control the serial communication.

The serial communication is binary based and a mechanism to mark the end of packages is necessary. A PPP type byte stuffing algorithm is used for this. In PPP frame boundaries are marked with a reserved byte value 0x7E. This reserved value is not permitted to occur in any other place than frame boundary. In a case the reserved value should occur in data packet, an escape sequence is used to transfer 0x7E into byte sequence of 0x7D, 0x5E. The byte value 0x7D means that a possible escape follows and is called a Control Escape value. Also the Control Escape itself needs to be escaped and becomes to byte sequence of 0x7D, 0x5D.

This PPP framing algorithm is used in the Arduino Nano and on the python program for the computer.

There are two python programs, one for data acquisition from the serial port and saving that data, and the second for file opening, plotting of data and FFT spectrum calculation and plotting.

Program serial_avr_01.py sends commands to the Arduino and reads data from the serial port. Once the desired amount of data has been acquired, it is saved on a file, as text, separated by comas and delimited by tags.

Program acel_file_plot_02.py waits for a file name introduced on console, opens the file and plots the signal from the accelerometer. It is shown on the next picture.

Then, the FFT spectrum is calculated and plotted. It can be seen in the next picture.

This
images correspond to a motor running at 1450 rpm (24.17 Hz). It can
be seen that the peaks in the FFT spectrum are multiples of this
frequency (24.17, 48.33,
72.5, 95.67, 120.83 and so on).

A program with a GUI has been developed (fft_spectrum_gui.py). It uses the Tkinter library, basically because it is the one included with Python, and no additional programs are needed. Also, it integrates very well with matplotlib.

The new program combines the programs acel_file_plot_03.py and serial_avr_01.py. This new interface lets you scan serial ports, select the serial port, save the sampled data to file, and open files with sampled data previously saved. It also has a scrolled textbox where messages are displayed (the ones printed on the previous programs).

Window functions are used to avoid signal leakage, that can hide low amplitude level signals when their frequency is close to high amplitude level ones. To avoid this leakage, the input samples are multiplied to a mathematical function, so the samples at the center of the sampled time are favored while the values of the samples at the extremes, are lowered. Usually Hann and Flattop windows are applied. Using Python and Scipy, applying window functions is very simple.

First, you have to import the signal module

from scipy import signal

Then create the window function coefficients. For the Hann window use

w = signal.hann(N, sym=False)

For the Flattop window use

w = signal.flattop(N, sym=False)

N is the length of the signal (number of samples).

Finally apply the FFT to the signal weighted with the window
function.

yf = fftpack.fft(y*w)

Program acel_file_plot_win_01.py plots the FFT spectrum using the window functions.

After applying the window functions, no much change is visible in the signal frequency separation and only the amplitude is reduced. Apparently, signal leakage is low for the sampled data used, and further testing would be required to validate this functions.

Three measurements on the same rotating machine were taken for testing the instrument response. The first measurement was taken without modifying the machine.

The second test was taken adding weight to a certain place on the machine, for creating an imbalance. It can be clearly seen an increase in the magnitude of the acceleration, both in time domain and frequency domain.

Finally, more weight was added to increase the imbalance and a third
measurement was made. Again, an increase in the acceleration
amplitude is observed.

From the test results, it can be seen that the instrument can detect the imbalance variations, and seems to be working properly.

The original program was not properly scaled. The signals were plotted using the ADC values and the number of samples obtained.

The signal size has been scaled to g. The ADXL335 has an output from -3g to +3g, for a voltage range from 0 to 3.3 V, that is converted by the ADC to values from 0 to 1023. The original signal is multiplied by 3.0/512, and then the DC offset is determined, taking the average of all the readings. This approach assumes that the average value of the vibration signal is 0.

A correction to the time scale has also been done, considering the sampling rate and the number of samples taken. Frequency range has been limited to 1500 Hz, the maximum frequency that the ADXL335 con provide on the X and Y axes.

The corrected program is acel_file_plot_03.py, and the resulting plots are now properly scaled.

The accelerometer and the Arduino Nano fit together inside a plastic
probe (camera film canister). A strong magnet is also included
inside, so the probe can be attached very firmly to different parts
of a rotating machine and measure its vibration.

The accelerometer breakout board is soldered to a perforated board and three capacitors are connected and soldered, one to every analog output form the ADXL335. Header pins are placed at the sides of the board and arranged so this pins fit inside single line sockets soldered on the Arduino Nano, instead of the regular connector headers.

Discussions

Become a member

Hi Ariel. a last question: I want to use your script also on other PC but not every has a python installed. so i tried to create EXE file but struggled. I have tried py2exe successless. Do you have experience with this tool ?

Hi Ole, It is possible to compile using the Arduino IDE, but you have to use its structure (setup and loop). If you use the IDE, you can use the Serial class to manage the serial port. I wrote the program for Arduino IDE and it´s included with the project files. To configure the timer and ADC it writes directly in the configuration registers. Regards, Ariel.

Hi Ariel.thx so much. compiling and downloading works, but the read out values are just 0-values. Now i am not quite sure if my breakout is working or not (although it is a new one). Are the external capacitors (3x3.3nF) necessary?

Ole, did you connect the 3.3V to the Aref input in the Arduino? The capacitors (2X 3.3nF, 1X10nF) are used to limit the signal bandwidth, and avoid aliasing problems due to sampling. Probably you can skip them because the bandwidth is limited in the adxl335, but I prefer to be sure.

Hi Ole. Sorry, I have no experience with py2exe. I think that the problem could be with the numerical libraries, Numpy and Scipy, that use compiled code for optimization. I would rather work with the Python interpreter and install the required modules.

Hello Ariel, I heve project about vibration Analyzer and I want to try make same this one. I have Question for you. Can you explain to me how to upload your arduino program to the arduino boart. thanks

Hi, I am sorry I didn´t see your message before. I did not use the Arduino IDE for previous versions, but I rewrote the program to work with the Arduino IDE (setup, loop and serial). The program is adxl335_3chan_01.ino and it is inculded with the project files. If you use the previous version (.c file) you have to compile it using GGG end download it using AVRDUDE.

Yes Ariel. thanks so much for your respon. Now i have a finish running your python program and uploading adxl335_3chan_01.ino to my Arduino nano. Your project is very cool. I have tested your vibration analyzer on drilling machine and I got the result is very well. But i heve Question about this project, I see the data graphic will update if I click button read serial data and is not real time update on the graphic.

I need your help, can you explain to me how to make the graphic is realtime update the data. Thanks

Hi, I don't think the system can run fast enough to be real time. Maybe it can run in continuous mode, starting a new reading immediately after the previous reading finishes, not waiting for a button press. You nedd a certain amout of data to run the FFT.

You created an infinite loop that continuously will read the serial port, but I never ends. You have to make a call to read_serial(), the function called when you press the button to read data. This function should be called after it finishes reading data. Use a flag (boolean) to control start and stop reading. You can use a button to start/stop the readings also.

Hi, I think the problem is in the incoming data (communication channel or microcontroller). The list 'valores' is formed when you receive a 0x7E byte, that marks the end of a data block, so when you analyze a block of data, you should alwas have either a 0x5D or 0x5E after a 0x7D byte. If not, there is an error in the data block received. Which OS are you working with? Which UART to USB chip are you using? I had problems with data loss when using a CH340 and Debian Linux. Regards.

You are right, the "while conta_datos_rx < datos_a_leer:" will create an infinite loop if the total amount of data expected is not received or if it is not foratted correctly (not enought 0x7E markers). I think that a timeout should be added to this loop. This is one thing that has to be added to the program. Thank you for noticing it.

Hi, I added a timeout to the loop "while (conta_datos_rx < datos_a_leer)". I am checking the elapsed time since the loop started, and if it is longer than 8 seconds (defined in t_timeout), the loop will terminate.

Hi, this is a very useful industrial application, I'm very interested in replicate it by myself! But, is any practical improvement (sensibility, range, etc.) in changing the adxl335 for the "new" adxl345 or even for a piezoelectric vibration sensor? thanks!

Hi, I don't know why I missed your message, very sorry. I think the adxl345 is a good replacement, and you can select between many sensitivities. 2g to 16g. Interfacing shoud also be easier, no badwith limiting capacitors nor sampling needed. Also the lowest resolution seems to be 10 bits, that is the same in the atMega328 ADC. A piezo sensor should work fine, but maybe you would need some extra signal conditioning.

I really like this, I've often wondered if such an analysis would be beneficial in domestic cars. Given the low cost of the components it must be getting closer to a time when such analysis is practical for every day mechanics, the issue then becomes the interpretation rather than the tools.