MMA8452 high quiescent current consumption

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

MMA8452 high quiescent current consumption

892 Views
Soumyaind80
Contributor II

Hi,

I have designed a PCB where I am using the MMA8452Q accelerometer. Because it is a battery powered device, we want to ensure that we are using the lowest sleep current states of all the components on board. However, while testing we noted that the accelerometer, even though FW has put it in low power mode with ODR of 12.5Hz, it is still consuming ~30uA of current in system sleep state. In our application, we just use INT1 to identify any interrupt and convey it to the MCU whenever set orientation threshold is crossed.

Infact, my issue is quite similar to this thread:

https://community.nxp.com/t5/Sensors/MMA8451Q-Exhibits-Excessive-Iq-In-Sleep-Mode/m-p/1176002

 

BLE_Debug3.PNG

I have a couple of queries:

1. I have decoupled pin 14 i.e. VDD pin with 0.1uF and pin 1 i.e. VDDIO with 4.7uF. Datasheet suggests the opposite. Can that be a reason for the heightened current in low power mode ?

2. SA0 pin is hard wired to GND. Is this affecting the quiescent current in low power state? Maybe an internal connection in the chip to some power rail which is creating a current flow path.

Any help would be appreciated !

0 Kudos
4 Replies

869 Views
Soumyaind80
Contributor II

Hi @TomasVaverka ,

Thanks for replying. I am attaching my code herewith:

Main code:

while (1)
{
switch (system_state)
{
case SYSTEM_INIT:
// System Init tings
timers_init ();
leds_init ();
// Internal Peripheral Power Up
// SAADC
saadc_init ();
saadc_sampling_event_init ();
saadc_sampling_event_enable ();
// User Timer
start_timer ();
// I2C
twi_init ();
enableAcclMOtionDetection ();
// External Device Power Up
ledInit ();
nrf_gpio_pin_write (LED_BLUE, RESET);
system_state = SYSTEM_RUNNING;

case SYSTEM_RUNNING:
watch_accl ();
sd_app_evt_wait ();
if (system_sleep_counter) break;

case SYSTEM_BROADCAST_START:
// BLE Stack Enable
ble_stack_init ();
HX711_power_up ();
HX711_begin (128);
HX711_set_offset (HX711_VALUE_OFFSET);
advertising_activeate ();
system_sleep_counter = SYSTEM_DATA_SEND_DURATION;
system_state = SYSTEM_BROADCAST;
break;

case SYSTEM_BROADCAST:
adv_active_machine ();
if (system_sleep_counter) break;

case SYSTEM_DEINIT:
// External Device Power Down
HX711_power_down ();
nrf_gpio_pin_write (LED_BLUE, SET);
ledPinsLow ();
// Internal Peripheral Power Down
timers_deinit ();
timerStop ();
twi_disable ();
saadc_deinit ();
// BLE Power Down
advertising_stop ();
sd_power_system_off ();
system_state = SYSTEM_SLEEP;

case SYSTEM_SLEEP:
nrf_pwr_mgmt_shutdown (NRF_PWR_MGMT_SHUTDOWN_STAY_IN_SYSOFF);
while (1)
{
nrf_pwr_mgmt_run();
watch_accl ();
if (system_sleep_counter) break;
}

default:
system_state = SYSTEM_INIT;
}
}

Here is the accelerometer C file:

#include "i2c_control.h"

#include "nrf_drv_gpiote.h"
#include "sdk_macros.h"
#include "boards.h"
#include "common_decl.h"
#include "timer_user.h"

extern uint32_t system_sleep_counter; /**< System sleep counter used in main for power managment */

// Accl related flags
uint8_t accl_int1_flag = RESET; /**< Accl intterupt flag */
uint8_t accl_read_flag = RESET; /**< Flag to tell it's time to read Accl */


/**@brief Accelerometer Interupt handler.
*
* @details This gets called when accelerometer raises hardware interrupt
*
* @param pin Which pin raised interrupr
*
* @param action Polarity of the Pin
*/
void acclIntHandler (nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
// Clear interrupt flags
NRF_GPIOTE->EVENTS_PORT = RESET;
NRF_GPIOTE->EVENTS_IN[0] = RESET;
NRF_GPIOTE->EVENTS_IN[1] = RESET;
NRF_GPIOTE->EVENTS_IN[2] = RESET;
NRF_GPIOTE->EVENTS_IN[3] = RESET;

accl_int1_flag = SET;
return;
}


/**@brief Chec if motion happening in Accelerometer
*
* @details Reads Accelerometer and gets the flags in Accelerometer
* which tells wether acceleration is crossing threhhold
*
* @return 1: Acceleration is crossing threhhold, 0: Acceleration not crossing threhhold
*
*/
uint8_t accl_check_motion_happening (void)
{
uint8_t sub_addr_data[2];
sub_addr_data[0] = 0x16;
/*ret_code_t twi_write_read(uint8_t addr, uint8_t subaddr[],
uint8_t subaddr_len, uint8_t data_read[],
uint8_t data_len)
*/
twi_write_read (ACCL_SLAVE_ADDR, &sub_addr_data[0], 1, &sub_addr_data[1], 1);
return (sub_addr_data[1] & 0x80);
}


/**@brief Watch Accelerometer
*
* @details Controls the main program by using *system_sleep_counter*
* according to status of *accl_int1_flag* *accl_read_flag* and *system_sleep_counter*
*
*/
void watch_accl (void)
{
/*
When system_sleep_counter is 0, and interrupt is rasied by accelerometer
system_sleep_counter will be set to SYSTEM_UP_DURATION which will wake up
the system. If system_sleep_counter goes to 0 the system goes to sleep
*/
if (accl_int1_flag && (!system_sleep_counter))
{
accl_int1_flag = RESET;
system_sleep_counter = SYSTEM_UP_DURATION;
}
/*
When is wakeup mode system_sleep_counter will be non zero.
In wakeup mode at every ACCL_READ_FREQ the accelerometer's register will be read
and if motion is going on, the system_sleep_counter will be set to SYSTEM_UP_DURATION
*/
if (system_sleep_counter)
{
if ((accl_read_flag) && (accl_check_motion_happening()))
{
accl_read_flag = RESET;
system_sleep_counter = SYSTEM_UP_DURATION;
}
}
return;
}


/**@brief Enable external interupt used by Accelerometer
*
* @details Enable external interupt used by Accelerometer and the callback function
*
* @return 32-bit success/error code
*
*/
uint32_t enableAcclExtInt (void)
{
uint32_t err_code;
// Configure the device INT1 Pin Input as Interrupt
nrf_drv_gpiote_init ();
nrf_drv_gpiote_in_config_t config = GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(false);
config.pull = NRF_GPIO_PIN_PULLUP;
config.skip_gpio_setup = false;
err_code = nrf_drv_gpiote_in_init(ACCL_INT_1_PIN, &config, acclIntHandler);
VERIFY_SUCCESS(err_code);
nrf_drv_gpiote_in_event_enable (ACCL_INT_1_PIN, true);
return err_code;
}


/**@brief Enable motion detection in Accelerometer
*
* @details Enable motion detection and configure Accelerometer for power saving
* by wrting into it's registers over I2C.
*
* @return 32-bit success/error code
*
*/
uint32_t enableAcclMOtionDetection (void)
{
uint8_t send_array [3];
uint32_t err_code;

// Put Module in Standby mode do the settings
// And set Data Rate and auto_sleep to 12.5 Hz
// Auto Wakeup Sleep frrequency to 12.5 Hz
// Normal mode for LNOis and Fast Read
send_array[0] = 0x2A; // Register adress CTRL_REG1
send_array[1] = 0xF8; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);


// Auto Sleep counter
send_array[0] = 0x29; // Register adress FF_MT_CFG
send_array[1] = 0x00; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);


// Setting to detect motion, X and Y axis will be considered
// only X and Y is considered beacause Z will always be 1g
// and status registers will reset after event is over
send_array[0] = 0x15; // Register adress FF_MT_CFG
send_array[1] = 0xD8; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

// Setting to set threshhold to 1.25g
// The step count is 0.063g/ count• 1.25/0.063g = 19.4; //Round up to 20
// DBCNTM bit is a logic ‘1’, the debounce counter is cleared to 0
// whenever the inertial event of interest is no longer true
send_array[0] = 0x17; // Register adress FF_MT_THS
send_array[1] = 0x82; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

// Debouce counter to avoid false reading
// Set to 10 Counts
send_array[0] = 0x18; // Register adress FF_MT_COUNT
send_array[1] = 0x0A; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

// Enable Motion Interrupt Function in the System
send_array[0] = 0x2D; // Register adress CTRL_REG4
send_array[1] = 0x04; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

// Route the Motion Interrupt Function to INT1 hardware pin
send_array[0] = 0x2E; // Register adress CTRL_REG5
send_array[1] = 0x04; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

// Activate the device aftr settings are done
// And set Data Rate to 12.5 Hz
// Auto Wakeup Sleep frrequency to 12.5 Hz
// Normal mode for LNOis and Fast Read
send_array[0] = 0x2A; // Register adress CTRL_REG1
send_array[1] = 0xF9; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

// Self test disabled, Reset at 0
// Sleep mode and normal mode power profile is se to Low power
// Auto sleep enabled
send_array[0] = 0x2B; // Register adress CTRL_REG2
send_array[1] = 0x1F; // Data to be written in the register
err_code = twi_write (ACCL_SLAVE_ADDR, send_array, 2);
VERIFY_SUCCESS(err_code);

err_code = enableAcclExtInt ();

return err_code;
}

Can you please have a look at it and let us know if we are missing anything ?

0 Kudos

876 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Soumya,

 

1. No.

2. No, this also does not affect the current consumption.

 

When you change the (S)MODS bits to 0b11, is the MMA8452Q in Standby mode?

 

Most, although not quite all changes to the registers must be done while the MMA8452Q is in Standby mode. Current consumption in Standby mode should be ~ 2μA.

 

Best regards,

Tomas

0 Kudos

837 Views
Soumyaind80
Contributor II

Hi @TomasVaverka ,

I did notice that we are setting the low power mode ( SMOD bits ) after putting the device into active mode. I guess it has to before that ? If we write to the registers after setting it in active mode, it doesn't get executed ?

0 Kudos

831 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Soumya,

 

Yes, the (S)MODS bits need to be changed in Standby mode.

Please refer to the AN4076 (chapter 3.1) or the datasheet where note #4 under table 11 says: Modification of this register’s content can only occur when device is in STANDBY mode, except CTRL_REG1 ACTIVE bit and CTRL_REG2 RST bit.

 

Best regards,

Tomas

0 Kudos