Hello Community, One of the main features of the NXP accelerometers is the Auto-WAKE/SLEEP mode. I would like to share this project in order to demonstrate the feasibility of using the Low-power and auto-WAKE/SLEEP modes for reducing current consumption in the different NXP accelerometers such as the MMA845x and MMA865x series. I created this project using the FRDM-KL25Z platform and the MMA8652FC accelerometer (You may find the breakout board files here). The complete source code is written in CodeWarrior v10.x IDE. This document gives you an introduction of the MMA8652FC accelerometer as well as the different power consumptions and guides you through the initialization process and how to appreciate the demonstration: Initialization of the MKL25Z128 MCU. Initialization of the MMA8652FC. Auto-WAKE/SLEEP mode. MMA8652FC Embedded functions. Interrupt handlers. Evaluation of the interrupt source. Summarizing the application and Macros definition. Visualization of the current consumption. 1. As you can see in the FRDM-KL25Z schematic and the image below, the I2C signals are routed to the I2C1 module (PTC1 and PTC2 pins) of the KL25Z MCU and the INT1 and INT2 outputs are connected to the PTD5 and PTA5 pins. The INT1 and INT2 outputs of the MMA8652FC are configured as a push-pull active-low outputs, so the corresponding PTD5 and PTA5 pins configuration are GPIOs with an interrupt on falling edge. The MCU is, therefore, configured as follows: /* I2C1 module initialization */ SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK; // Turn on clock to I2C1 module SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK; // Turn on clock to Port C module PORTC_PCR1 |= PORT_PCR_MUX(0x2); // PTC1 pin is I2C1 SCL line PORTC_PCR2 |= PORT_PCR_MUX(0x2); // PTC2 pin is I2C1 SDA line I2C1_F |= I2C_F_ICR(0x14); // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us I2C1_C1 |= I2C_C1_IICEN_MASK; // Enable I2C1 module /*Configure the PTD5 and PTA5 pin (connected to the INT1 and INT2 of the MMA8652FC) for falling edge interrupts */ SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; // Turn on clock to Port D module PORTD_PCR5 |= (0|PORT_PCR_ISF_MASK| // Clear the interrupt flag PORT_PCR_MUX(0x1)| // PTD5 is configured as GPIO PORT_PCR_IRQC(0xA));// PTD5 is configured for falling edge interrupts SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK; // Turn on clock to Port A module PORTA_PCR5 |= (0|PORT_PCR_ISF_MASK| // Clear the interrupt flag PORT_PCR_MUX(0x1)| // PTA5 is configured as GPIO PORT_PCR_IRQC(0xA));// PTA5 is configured for falling edge interrupts /* Enable PORTD interrupt on NVIC */ NVIC_ICPR |= 1 << ((INT_PORTD - 16)%32); NVIC_ISER |= 1 << ((INT_PORTD - 16)%32); /* Enable PORTA interrupt on NVIC */ NVIC_ICPR |= 1 << ((INT_PORTA - 16)%32); NVIC_ISER |= 1 << ((INT_PORTA - 16)%32); 2. The MMA8652FC is an intelligent, low-power, three-axis, capacitive micromachined accelerometer with 12 bits of resolution. At the beginning of the initialization, all registers are reset to their default values by setting the RST bit of the CTRL_REG2 register. The Normal and Low Power modes are set in the same register. The MODS[1:0] bits select which Oversampling mode is to be used. The Oversampling modes are available in both WAKE Mode MOD[1:0] and also in the SLEEP Mode SMOD[1:0]. Then the MMA8652FC is initialized as shown below: I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2, 0x40); // Reset all registers to POR values Pause(0x631); // ~1ms delay I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, XYZ_DATA_CFG_REG, 0x00); // +/-2g range with ~0.977mg/LSB /* Power Mode Configuration */ If LOW power mode is selected: I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2, 0x1B); // Low Power mode If NORMAL power mode is selected: I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2, 0x00); // Normal mode 3. As I mentioned, one of the main features of the MMA8652FC is the Auto-WAKE/SLEEP mode. The advantage of using the Auto-WAKE/SLEEP is that the system can automatically transition to a higher sample rate (higher current consumption) when needed, but spends the majority of the time in the SLEEP mode (lower current) when the device does not require higher sampling rates. • Auto-WAKE refers to the device being triggered by one of the interrupt functions to transition to a higher sample rate. This may also interrupt the processor to transition from a SLEEP mode to a higher power mode. • SLEEP mode occurs after the accelerometer has not detected an interrupt for longer than the user-definable timeout period. At the ASLP_COUNT register, you can set the minimum time period of inactivity required to switch the part between Wake and Sleep status, in this case, 5 seconds. The Auto-WAKE/SLEEP mode, therefore, is configured as follow: read_reg = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2); I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG2, read_reg|0x04); // Auto-SLEEP enable I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, ASLP_COUNT_REG, 0x10); // 5 seconds (16 * 320ms) read_reg = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG4); I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG4, read_reg|0x80); // Enable AutoSleep interrupt, INT2 - PTD5 I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG1, 0xC1); // ODR=800Hz and Sleep mode ODR=1.56Hz, Active mode 4. The device can be configured to generate inertial wake-up interrupt signals from any combination of the configurable embedded functions, enabling the MMA8652FC to monitor inertial events while remaining in a low-power mode during periods of inactivity. The Interrupts that can WAKE the device from SLEEP are: Tap Detection, Orientation Detection, Motion/Freefall, and Transient Detection. In this project, the TAP (Pulse) or Transient interrupts are used to wake up the device from the SLEEP. In order to get more information about the TAP detection, please click here. The MMA8652FC is configured as below: If Transient interrupt is selected: I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, TRANSIENT_THS_REG, 0x84); // Set threshold to 252mg (4 x 63mg ) I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, TRANSIENT_COUNT_REG, 0x02); // Set debounce timer period to 40ms (low power mode) / 2.5ms (normal mode)-Table 66 I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, TRANSIENT_CFG_REG, 0x17); // Enable transient detection for X and Y axis, latch enabled I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG3, 0x40); // Wake from Transient interrupt, Push-pull, active low interrupt I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG4, 0x20); // Enable Transient detection interrupt I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG5, 0x20); // Transient interrupt routed to INT1 - PTA5 If TAP interrupt is selected: I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, PULSE_CFG_REG, 0x15); // Enable X, Y and Z Single Pulse I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, PULSE_THSX_REG, 0x20); // Set X Threshold to 2.016g I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, PULSE_THSY_REG, 0x20); // Set Y Threshold to 2.016g I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, PULSE_THSZ_REG, 0x2A); // Set Z Threshold to 2.646g I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, PULSE_TMLT_REG, 0x28); // Set Time Limit for Tap Detection to 25 ms I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, PULSE_LTCY_REG, 0x28); // Set Latency Time to 50 ms. During this time interval, all pulses are ignored I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG3, 0x10); // Wake from Pulse interrupt, Push-pull, active low interrupt I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG4, 0x08); // Pulse detection interrupt enabled I2C_WriteRegister(MMA8652FC_I2C_ADDRESS, CTRL_REG5, 0x08); // Pulse interrupt routed to INT1 - PTA5 5. As I mentioned above, the TAP (Pulse) or Transient interrupts are used to wake up the device from the SLEEP. Besides, if Auto-SLEEP interrupt is enabled, then transitioning from ACTIVE mode to Auto-SLEEP mode (or vice versa) generates an interrupt. In this project, the Auto-SLEEP, the TAP (Pulse) or the Transient interrupts are enable. The MKL25Z128 responds to these interrupts reading the INT_SOURCE (0x0C) register, in order to determine the appropriate sources of the interrupt. Every source of interrupt has its own way to clear the interrupt flag. Please refer to the comments of each ISR: Transient interrupt handler void PORTA_IRQHandler() { PORTA_PCR5 |= PORT_PCR_ISF_MASK; // Clear the PTC interrupt int_source = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, INT_SOURCE_REG); // Clear interrupt Source Register if(int_source&0x20) // Transient interrupt ? { i = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, TRANSIENT_SRC_REG); // Read the TRANSIENT_SRC register to clear the SRC_TRANS flag in the INT_SOURCE register transient_int = 1; } } TAP interrupt handler void PORTA_IRQHandler() { PORTA_PCR5 |= PORT_PCR_ISF_MASK; // Clear the PTC interrupt flag int_source = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, INT_SOURCE_REG); // Clear interrupt Source Register if(int_source&0x08) // Pulse interrupt ? { i = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, PULSE_SRC_REG); // Read the PULSE_SRC register to clear the SRC_TRANS flag in the INT_SOURCE register pulse_int = 1; } } Auto WAKE/SLEEP interrupt handler void PORTD_IRQHandler() { PORTD_PCR5 |= PORT_PCR_ISF_MASK; // Clear the PTD interrupt flag int_source = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, INT_SOURCE_REG); // Clear interrupt Source Register if (int_source&0x80) // Auto Sleep/Wake interrupt ? { i = I2C_ReadRegister(MMA8652FC_I2C_ADDRESS, SYSMOD_REG); // Read the SYSMOD register to clear the SRC_ASLP flag in the INT_SOURCE register sleep_int = 1; } } 6. At this point, the configuration of the MCU and the accelerometer is done. The RGB LED contained on the FRDM-KL25Z board is configured in order to help showing the behavior of the application. This behavior is configured as follow: #if TRANSIENT_DETECTION if (transient_int){ transient_int = 0; TURN_BLUE_ON(); TURN_RED_OFF();} #elif TAP_DETECTION if (pulse_int){ pulse_int = 0; TURN_BLUE_ON(); TURN_RED_OFF();} #endif if (sleep_int){ sleep_int = 0; TURN_RED_ON(); TURN_BLUE_OFF();} 7. In summary, the FRDM-KL25Z will be interfacing with the MMA8652FC. The power mode will be set and the interrupts will be enabled. The macros at the top of the source code will allow us to select between the different power modes, the different embedded functions and to select the Auto-WAKE/SLEEP function. If the Auto-WAKE/SLEEP function is enabled, the MMA8652FC will go into the SLEEP mode (ODR=1.56Hz) after 5 seconds of inactivity. The RED LED will be set. When an interrupt from the embedded functions is generated, the MMA8652FC will be awakened (ODR=800Hz) and so on. The BLUE LED will be set. /* Select the Power Mode - Table 101 from datasheet */ #define NORMAL_MODE 1 #define LOW_POWER_MODE 0 /* Select the Embedded Function */ #define TRANSIENT_DETECTION 1 #define TAP_DETECTION 0 /* Auto-WAKE/SLEEP Function */ #define AUTO_SLEEP 1 8. The Table 5 from the datasheet shows the expected current consumption in regard with the power mode and ODR selected: As I mentioned before, the Sleep mode allow us to change between different Output Data Rates (ODR) dynamically so we can reduce the current consumption. In order to verify if the accelerometer is consuming the current mentioned on the datasheet, I measured the MMA8652FC current consumption using the project mentioned. Please refer to the results below: 9. The advantage of using the Auto-WAKE/SLEEP mode is that the system can automatically transition to a higher sample rate (higher current consumption) when needed, but spends the majority of the time in the SLEEP mode (lower current) when the device does not require higher sampling rates. In the manner we have come to expect of the MMA8652FC, the current consumption decreases when the ODR is changed from 800Hz to 1.56Hz, in both normal and low power mode. The information mentioned on the datasheet is now confirmed. Please find attached the complete source code. I hope you find useful and funny this sample project. Any suggestion will be appreciated. You are invited to take part of the NXP community where you can post all your questions and you may find useful material for your projects. Best Regards, David
View full article