Post Go back to editing

Self Test fails intermittently fails

Thread Summary

The user is experiencing ADXL367 self-test failures (diff > max or diff < min) in an embedded design. The final answer suggests adding a 100ms delay after entering Measure mode and averaging multiple samples to reduce noise. The user confirmed the issue persists with diff = 0 (x_axis_1 = 0xFFFF, x_axis_2 = 0xFFFF) and will verify if this is due to communication issues or other environmental factors. The ADXL367 is used in the design, and the self-test function is based on the Analog Devices reference code.
AI Generated Content
Category: Hardware
Product Number: ADXL367

Hello,

We are using ADXL367 in our design interfacing to our embedded microcontroller.

We have implented ADXL367 Self Test during initialization, but have seen cases where the test fails (diff > max OR diff < min). We have followed the Analog devices reference source code here, https://github.com/analogdevicesinc/no-OS/blob/main/drivers/accel/adxl367/adxl367.c


Max = 1080
Min = 360
Dif = ~700-800 (Happy Case)
Dif = 1678 (Failure Case, only failure data point I have for now)

Questions:

  1. Do you have any insight on what could cause these types of failures?


Our Self Test Function:

/***************************************************************************//**
 * @brief Performs self test.
 *
 * @param dev - The device structure.
 *
 * @return 0 in case of success, negative error code otherwise.
*******************************************************************************/
int adxl367_self_test(struct adxl367_dev *dev, int16_t* p_result)
{
	int ret;
	int16_t x_axis_1, x_axis_2, dif, min, max;
	uint8_t read_val;
	uint32_t st_delay_ms;

	// 4 / ODR value in ms
	/* TO give sensor enoug warm up time giving 500 ms delay. with 80 ms 
         * delay self test failing all time.
         */
        st_delay_ms = 500;
        /*
        switch (dev->odr) {
	case ADXL367_ODR_12P5HZ:
		st_delay_ms = 320;
	case ADXL367_ODR_25HZ:
		st_delay_ms = 160;
	case ADXL367_ODR_50HZ:
		st_delay_ms = 80;
	case ADXL367_ODR_100HZ:
		st_delay_ms = 40;
	case ADXL367_ODR_200HZ:
		st_delay_ms = 20;
	case ADXL367_ODR_400HZ:
		st_delay_ms = 10;
                break;
	default:
		return -EINVAL;
	}
        */

	ret = adxl367_set_power_mode(dev, ADXL367_OP_MEASURE);
	if (ret)
		return ret;

	ret = adxl367_reg_write_msk(dev, ADXL367_REG_SELF_TEST, ADXL367_SELF_TEST_ST,
				    ADXL367_SELF_TEST_ST);
	if (ret)
		return ret;
	// 4 / ODR delay
	OsDelayMs(st_delay_ms, OS_OPT_TIME_DLY);
	ret = adxl367_get_register_value(dev, &read_val, ADXL367_REG_XDATA_H, 1);
	if (ret)
		return ret;
	x_axis_1 = read_val << 6;
	ret = adxl367_get_register_value(dev, &read_val, ADXL367_REG_XDATA_L, 1);
	if (ret)
		return ret;
	x_axis_1 += read_val >> 2;
	// extend sign to 16 bits
	if (x_axis_1 & NO_OS_BIT(13))
		x_axis_1 |= NO_OS_GENMASK(15, 14);

	ret = adxl367_reg_write_msk(dev, ADXL367_REG_SELF_TEST,
				    ADXL367_SELF_TEST_ST_FORCE, ADXL367_SELF_TEST_ST_FORCE);
	if (ret)
		return ret;
	// 4 / ODR delay

	OsDelayMs(st_delay_ms, OS_OPT_TIME_DLY);
	ret = adxl367_get_register_value(dev, &read_val, ADXL367_REG_XDATA_H, 1);
	if (ret)
		return ret;
	x_axis_2 = read_val << 6;
	ret = adxl367_get_register_value(dev, &read_val, ADXL367_REG_XDATA_L, 1);
	if (ret)
		return ret;
	x_axis_2 += read_val >> 2;
	// extend sign to 16 bits
	if (x_axis_2 & NO_OS_BIT(13))
		x_axis_2 |= NO_OS_GENMASK(15, 14);

	ret = adxl367_set_power_mode(dev, ADXL367_OP_STANDBY);
	if (ret)
		return ret;

	ret = adxl367_reg_write_msk(dev, ADXL367_REG_SELF_TEST, 0,
				    ADXL367_SELF_TEST_ST_FORCE | ADXL367_SELF_TEST_ST);
	if (ret)
		return ret;

	dif = x_axis_2 - x_axis_1;
	min = ADXL367_SELF_TEST_MIN * adxl367_scale_mul[dev->range];
	max = ADXL367_SELF_TEST_MAX * adxl367_scale_mul[dev->range];
#if RTT_XL_DEBUG_OUTPUT
        SEGGER_RTT_printf(0, "  dif: %d\n", dif);
        SEGGER_RTT_printf(0, "  min: %d\n", min);
        SEGGER_RTT_printf(0, "  max: %d\n", max);
#endif

    // Copy result to output parameter
	*p_result = dif;

	if ((dif >= min) && (dif <= max)) {
		return  0;
	} else {
		return -1;
	}
}

Parents
  • Hello  

    Could you check the output value while the sensor stands still in a table maybe it is a calibration/offset matter.

    I will also allocate some time to review your code,

    regards,

    Mario SM

  • Hi Mario,

    The results are obtained while the device is sitting flat on a desk.

    Was able to reproduce the issue two more times recently where diff = 1678 and diff = 0

  • Hi  

    right after entering to Measure mode, could you please try adding a 100ms delay as recommended in the DS?

    Can you please also share the values that you read on x_axis_2 and x_axis_1? that might give us an idea what is going on. 

    Tip: we usually recommend averaging several data points to reduce the noise on the self test measurement. So on the DS self test routine steps 4 and 7 I would read something like 10 samples from x-axis and get the average value out of those 10 samples as your x_axis_1 and x_axis_2. 

    I hope this helps, 

    Pablo. 

     

  • Regarding 100ms delay, this already exists as part of set_power_mode function.

    /***************************************************************************//**
     * @brief Places the device into standby/measure mode.
     *
     * @param dev      - The device structure.
     * @param mode     - Power mode.
     *                   Accepted values: 	ADXL367_OP_STANDBY = 0,
     *										ADXL367_OP_MEASURE = 2
     *
     * @return 0 in case of success, negative error code otherwise.
    *******************************************************************************/
    int adxl367_set_power_mode(struct adxl367_dev *dev,
    			   enum adxl367_op_mode mode)
    {
    	int ret;
    
    	ret = adxl367_reg_write_msk(dev,
    				    ADXL367_REG_POWER_CTL,
    				    field_prep(ADXL367_POWER_CTL_MEASURE_MSK, mode),
    				    ADXL367_POWER_CTL_MEASURE_MSK);
    	if (ret)
    		return ret;
    
    	//100 ms wait time before reading acceleration data.
    	if (mode == ADXL367_OP_MEASURE)
    		OsDelayMs(100, OS_OPT_TIME_DLY);
    
    	dev->op_mode = mode;
    
    	return 0;
    }


    Reagrding recording data from multiple axis, we will obtain this and report back. Unfortuantely do not have this data from previous failures as FW logs only report the diff.

  • Hello  hope you are doing well, any news on this?

  • Hi Mario, appreciate the follow-up. We still need to obtain the data referenced above to provide to you. I will push to get this done in next couple of days.

    Karl

Reply Children
No Data