Below are my ADXL357 accelerometer reading when calculating vibrations of a engine. I have a feeling that the g is being calculated wrong

Hi
I am using ADXL357 accelerometer, and i am trying to record sensitivity in terms of g.
here is the algorithm for taking out raw value and calculation of g through it

int sensitivity = 19.5  

float convert_to_g(raw_reading, sensitivity)
{
     // Convert raw readings to acceleration in g
     return (raw_reading * sensitivity) / 1000000;
}

// Split data
                xdata = (xdata1 >> 4) + (xdata2 << 4) + (xdata3 << 12);
                ydata = (ydata1 >> 4) + (ydata2 << 4) + (ydata3 << 12);
                zdata = (zdata1 >> 4) + (zdata2 << 4) + (zdata3 << 12);
   
                // Apply two complement
                if (xdata >= 0x80000)
                    xdata = ~xdata + 1 ;
                if (ydata >= 0x80000)
                    ydata = ~ydata + 1;
                if (zdata >= 0x80000)
                    zdata = ~zdata + 1;

 // Convert raw readings to acceleration in g
                acc_x = convert_to_g(xdata, sensitivity_X);
                acc_y = convert_to_g(ydata, sensitivity_Y);
                acc_z = convert_to_g(zdata, sensitivity_Z);

and on using this algorithm
AccToTime_adxl357EngTopMount-X
AccToTime_adxl357EngTopMount-Y
AccToTime_adxl357EngTopMount-Z
FFT_adxl357EngTopMount-Y
FFT_adxl357EngTopMount-Z
, here is the plot of the acceleration in terms of FFT, RMS and with time. The mounting position of the sensor is Z-axis is perpendicular to g and X axis is aligned with the earth's gravity.
So i want to know that is this the right way, or am i doing something wrong?

Hello Sonofgod123

Perform some data logging and analyses to see what happens.

1 Like

Should be float, not int.

1 Like
float convert_to_g(raw_reading, sensitivity)
{
     // Convert raw readings to acceleration in g
     return (raw_reading * sensitivity) / 1000000;
}

What datatypes are raw_reading and sensitivity here? I'm surprised this even compiles if you don't name your datatypes.

1 Like

What format is the incoming data that requires this "Apply two compliment" transformation?

The datasheet

ETA: looking at your graphs, I'm surprised that the noisy Y and Z values don't go below zero.

Please post all the code.

1 Like

Hi so basically now i am coding in PYTHON on pi and got similar results.

import spidev
import time
import csv
from datetime import datetime
    # SPI setup

SPI_MAX_CLOCK_HZ = 10000000
SPI_MODE = 0b00
SPI_BUS = 0
SPI_DEVICE = 0
spi = spidev.SpiDev()
spi.open(SPI_BUS, SPI_DEVICE)
spi.max_speed_hz = SPI_MAX_CLOCK_HZ
spi.mode = SPI_MODE

    # Memory register addresses
XDATA3 = 0x08
XDATA2 = 0x09
XDATA1 = 0x0A
YDATA3 = 0x0B
YDATA2 = 0x0C
YDATA1 = 0x0D
ZDATA3 = 0x0E
ZDATA2 = 0x0F
ZDATA1 = 0x10
RANGE = 0x2C
POWER_CTL = 0x2D
REG_RESET = 0x2F
REG_DEVID_AD = 0x00
REG_DEVID_MST = 0x01
REG_PART_ID = 0x02
REG_REVID = 0x03
REG_STATUS = 0x04

    # Device values
RANGE_10G = 0x01
RANGE_20G = 0x02
RANGE_40G = 0x03
MEASURE_MODE = 0x06  # Only accelerometer

    # Operations
READ_BYTE = 0x01
WRITE_BYTE = 0x00

sensitivity_X = 19.5  
sensitivity_Y = 19.5
sensitivity_Z = 19.5

def write_register(this_register, this_value):
    data_to_send = (this_register << 1) | WRITE_BYTE
    spi.xfer2([data_to_send, this_value])

def read_register(this_register):
    data_to_send = (this_register << 1) | READ_BYTE
    result = spi.xfer2([data_to_send, 0x00])
    return result[1]

def read_multiple_data(addresses, data_size, read_data):
    spi.writebytes([addresses[i] << 1 | READ_BYTE for i in range(data_size)])
    read_data[:] = spi.readbytes(data_size)
    
def set_Frequency_range():
    write_register(FILTER_CTL, frequency)
    
def set_measure_range(measure_range):
    write_register(RANGE, measure_range)    


def enable_measure_mode():
    write_register(POWER_CTL, MEASURE_MODE)

def convert_to_g(raw_reading, sensitivity):
     # Convert raw readings to acceleration in g
     return (raw_reading * sensitivity) / 1000000

def main():
    spi.max_speed_hz = 100000  # Set SPI speed to match the sensor requirements
    write_register(RANGE, RANGE_2G)  # 2G
    write_register(POWER_CTL, MEASURE_MODE)  # Enable measure mode
    time.sleep(1)
    
set_measure_range(RANGE_10G)
#set_Frequency_range()
enable_measure_mode()        
timestamp_str = datetime.now().strftime("%Y%m%d%H%M%S")
csv_filename_X = f'adxl357X_{timestamp_str}.csv'
csv_filename_Y = f'adxl357Y_{timestamp_str}.csv'
csv_filename_Z = f'adxl357Z_{timestamp_str}.csv'
start_time = time.time()

while True:
                elapsed_microseconds = ((time.time() - start_time))  # converting time to microseconds
                range_value = read_register(RANGE)
                power_ctrl = read_register(POWER_CTL)
                analog_id = read_register(REG_DEVID_AD)
                mst_id = read_register(REG_DEVID_MST)
                part_id = read_register(REG_PART_ID)
                rev_id = read_register(REG_REVID)
                status = read_register(REG_STATUS)
                xdata1 = read_register(XDATA1)
                xdata2 = read_register(XDATA2)
                xdata3 = read_register(XDATA3)
                ydata1 = read_register(YDATA1)
                ydata2 = read_register(YDATA2)
                ydata3 = read_register(YDATA3)
                zdata1 = read_register(ZDATA1)
                zdata2 = read_register(ZDATA2)
                zdata3 = read_register(ZDATA3)

                # Split data
                xdata = (xdata1 >> 4) + (xdata2 << 4) + (xdata3 << 12)
                ydata = (ydata1 >> 4) + (ydata2 << 4) + (ydata3 << 12)
                zdata = (zdata1 >> 4) + (zdata2 << 4) + (zdata3 << 12)
   
                # Apply two complement
                if xdata >= 0x80000:
                    xdata = ~xdata + 1
                if ydata >= 0x80000:
                    ydata = ~ydata + 1
                if zdata >= 0x80000:
                    zdata = ~zdata + 1

                # Convert raw readings to acceleration in g
                acc_x = convert_to_g(xdata, sensitivity_X)
                acc_y = convert_to_g(ydata, sensitivity_Y)
                acc_z = convert_to_g(zdata, sensitivity_Z)

    
                #print(range_value)
                print(f"{elapsed_microseconds}, X:{acc_x:.6f}g, Y:{acc_y:.6f}g, Z: {acc_z:.6f}g")
                with open(csv_filename_X,'a') as log:
                        output = "{},{}\n".format(elapsed_microseconds,acc_x)
                        log.write(output)
                
                with open(csv_filename_Y,'a') as log:
                        output = "{},{}\n".format(elapsed_microseconds,acc_y)
                        log.write(output)
                        
                with open(csv_filename_Z,'a') as log:
                        output = "{},{}\n".format(elapsed_microseconds,acc_z)
                        log.write(output)
                        
                        

this is the complete python script.
I have mounted the sensor on a diesel engine using magnetic mounting. I am trying to calculate the rpm using vibrations in a engine but i feel my FFT values are wrong as when i measure peak of FFT its similar for all rpm.

700RPM
1500RPM


2000RPM

Its in the form of left-biased 2's complement

actually the code was in python, i just changed it into C. I have posted the complete python script. I forgot to put their data types. both of them are integer type.

i performed data logging but i am getting same graphs for different data recorded at different rpm's of the engine

Instead of:

why not:

long xdata = (xdata1 << 4) + (xdata2 << 8) + (xdata3 << 16);

...then it's in a nice microgQ28.4 which you convert to g with xdata/16000000.0

Something definitely looks wrong with the sign handling, since your Y & Z graphs look like the readings have been abs(??) -filtered, and your X graph looks like it's centered around -19.5.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.