Hi David! Thanks again!,
this is my code, the only thing it do is wait for a TAP and after 18 seconds it go to sleep. In WAKE mode I read about 500 uA, when it go to sleep current down to 350 uA aprox, but never so low as the data sheet says, arround 20 uA:
CODE:
#include "i2c.h"
#include <VirtualWire.h>
#include "LowPower.h"
// The SparkFun breakout board defaults to 1, set to 0 if SA0 jumper on the bottom of the board is set
#define SA0 1
#if SA0
#define MMA8452_ADDRESS 0x1D // SA0 is high, 0x1C if low
#else
#define MMA8452_ADDRESS 0x1C
#endif
#define SYSMOD 0x0B
#define INT_SOURCE 0x0C
#define FF_MT_CFG 0x15
#define FF_MT_SRC 0x16
#define FF_MT_THS 0x17
#define FF_MT_COUNT 0x18
#define CTRL_REG1 0x2A
#define CTRL_REG2 0x2B
#define CTRL_REG3 0x2C
#define CTRL_REG4 0x2D
#define CTRL_REG5 0x2E
bool sleepMode = false;
int count = 0;
const char *msg = "Mentita";
// Set the scale below either 2, 4 or 8
const byte SCALE = 2; // Sets full-scale range to +/-2, 4, or 8g. Used to calc real g values.
// Set the output data rate below. Value should be between 0 and 7
const byte dataRate = 0; // 0=800Hz, 1=400, 2=200, 3=100, 4=50, 5=12.5, 6=6.25, 7=1.56
// Pin definitions
int int1Pin = 2; // These can be changed, 2 and 3 are the Arduinos ext int pins
int int2Pin = 3;
const int wakeUpPin = 3; //Pin para despertar cuando hay TAP
int PinVccTransmisor = 9;
int PinDatosTransmisor = 10;
int VoltajeBateria = 11;
int accelCount[3]; // Stores the 12-bit signed value
float accelG[3]; // Stores the real accel value in g's
void setup()
{
byte c;
Serial.begin(9600);
// Set up the interrupt pins, they're set as active high, push-pull
pinMode(int1Pin, INPUT);
digitalWrite(int1Pin, LOW);
pinMode(int2Pin, INPUT);
digitalWrite(int2Pin, LOW);
pinMode(PinVccTransmisor, OUTPUT);
pinMode(PinDatosTransmisor, OUTPUT);
pinMode(VoltajeBateria, INPUT);
//Define velocidad de envio datos al receptor
{
vw_setup(2000); // Bits per sec
vw_set_tx_pin(PinDatosTransmisor);
}
// Read the WHO_AM_I register, this is a good test of communication
c = readRegister(0x0D); // Read WHO_AM_I register
if (c == 0x2A) // WHO_AM_I should always be 0x2A
{
initMMA8452(SCALE, dataRate); // init the accelerometer if communication is OK
Serial.println("MMA8452Q is online...");
}
else
{
Serial.print("Could not connect to MMA8452Q: 0x");
Serial.println(c, HEX);
while(1) ; // Loop forever if communication doesn't happen
}
}
// Initialize the MMA8452 registers
// See the many application notes for more info on setting all of these registers:
// http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA8452Q
// Feel free to modify any values, these are settings that work well for me.
void initMMA8452(byte fsr, byte dataRate)
{
MMA8452Standby(); // Must be in standby to change registers
// Set up the full scale range to 2, 4, or 8g.
if ((fsr==2)||(fsr==4)||(fsr==8))
writeRegister(0x0E, fsr >> 2);
else
writeRegister(0x0E, 0);
// Setup the 3 data rate bits, from 0 to 7
writeRegister(0x2A, readRegister(0x2A) & ~(0x38));
if (dataRate <= 7)
writeRegister(0x2A, readRegister(0x2A) | (dataRate << 3));
// Set up portrait/landscap registers - 4 steps:
// 1. Enable P/L
// 2. Set the back/front angle trigger points (z-lock)
// 3. Set the threshold/hysteresis angle
// 4. Set the debouce rate
// For more info check out this app note: http://cache.freescale.com/files/sensors/doc/app_note/AN4068.pdf
writeRegister(0x11, 0x40); // 1. Enable P/L
writeRegister(0x13, 0x44); // 2. 29deg z-lock (don't think this register is actually writable)
writeRegister(0x14, 0x84); // 3. 45deg thresh, 14deg hyst (don't think this register is writable either)
writeRegister(0x12, 0x50); // 4. debounce counter at 100ms (at 800 hz)
/* Set up single and double tap - 5 steps:
1. Set up single and/or double tap detection on each axis individually.
2. Set the threshold - minimum required acceleration to cause a tap.
3. Set the time limit - the maximum time that a tap can be above the threshold
4. Set the pulse latency - the minimum required time between one pulse and the next
5. Set the second pulse window - maximum allowed time between end of latency and start of second pulse
for more info check out this app note: http://cache.freescale.com/files/sensors/doc/app_note/AN4072.pdf */
// writeRegister(0x21, 0x7F); // 1. enable single/double taps on all axes
writeRegister(0x21, 0x55); // 1. single taps only on all axes
// writeRegister(0x21, 0x6A); // 1. double taps only on all axes
writeRegister(0x23, 0x04); // 2. x thresh at .5g, multiply the value by 0.0625g/LSB to get the threshold
writeRegister(0x24, 0x04); // 2. y thresh at .5g, multiply the value by 0.0625g/LSB to get the threshold
writeRegister(0x25, 0x04); // 2. z thresh at .5g, multiply the value by 0.0625g/LSB to get the threshold
writeRegister(0x26, 0x30); // 3. 30ms time limit at 800Hz odr, this is very dependent on data rate, see the app note
writeRegister(0x27, 0xA0); // 4. 200ms (at 800Hz odr) between taps min, this also depends on the data rate
writeRegister(0x28, 0xFF); // 5. 318ms (max value) between taps max
// Set up interrupt 1 and 2
writeRegister(0x2C, 0x02); // Active high, push-pull interrupts
writeRegister(0x2D, 0x08); // Interrupción sólo con TAP (Pulse)
writeRegister(0x2E, 0x01); // DRDY on INT1, P/L and taps on INT2
// These settings have to do with setting up the sleep mode and should probably be broken up into a separate function
// set Auto-WAKE sample frequency when the device is in sleep mode
writeRegister(0x29, 0x20 ); // sleep after ~36 seconds of inactivity at 6.25 Hz ODR
// Set Wake Oversampling mode to High resolutio (10 y Sleep Oversamplin to Low Power (11), SLPE=1
writeRegister(CTRL_REG2, readRegister(CTRL_REG2) & (0xE4)|(0x1A));
// set sleep mode interrupt scheme,// select wake on transient, orientation change, pulse, or freefall/motion detect
writeRegister(CTRL_REG3, readRegister(CTRL_REG3) & ~(0x3E)|(0x3E)); // clear bits 3, 4, 5, and 6, "Decia 3C"
// Enable Auto-SLEEP/WAKE interrupt
writeRegister(CTRL_REG4, readRegister(CTRL_REG4) & ~(0x88)|(0x88)); // clear bit 7 and select Auto-SLEEP/WAKE interrupt enable"Decia 80, se activa bit 3, PULSE"
MMA8452Active(); // Set to active to start reading
}
// Sets the MMA8452 to standby mode.
// It must be in standby to change most register settings
void MMA8452Standby()
{
byte c = readRegister(0x2A);
writeRegister(0x2A, c & ~(0x01));
}
// Sets the MMA8452 to active mode.
// Needs to be in this mode to output data
void MMA8452Active()
{
byte c = readRegister(0x2A);
writeRegister(0x2A, c | 0x01);
}
// Read i registers sequentially, starting at address into the dest byte array
void readRegisters(byte address, int i, byte * dest)
{
i2cSendStart();
i2cWaitForComplete();
i2cSendByte((MMA8452_ADDRESS<<1)); // write 0xB4
i2cWaitForComplete();
i2cSendByte(address); // write register address
i2cWaitForComplete();
i2cSendStart();
i2cSendByte((MMA8452_ADDRESS<<1)|0x01); // write 0xB5
i2cWaitForComplete();
for (int j=0; j<i; j++)
{
i2cReceiveByte(TRUE);
i2cWaitForComplete();
dest[j] = i2cGetReceivedByte(); // Get MSB result
}
i2cWaitForComplete();
i2cSendStop();
cbi(TWCR, TWEN); // Disable TWI
sbi(TWCR, TWEN); // Enable TWI
}
// Read a single byte from address and return it as a byte
byte readRegister(uint8_t address)
{
byte data;
i2cSendStart();
i2cWaitForComplete();
i2cSendByte((MMA8452_ADDRESS<<1)); // Write 0xB4
i2cWaitForComplete();
i2cSendByte(address); // Write register address
i2cWaitForComplete();
i2cSendStart();
i2cSendByte((MMA8452_ADDRESS<<1)|0x01); // Write 0xB5
i2cWaitForComplete();
i2cReceiveByte(TRUE);
i2cWaitForComplete();
data = i2cGetReceivedByte(); // Get MSB result
i2cWaitForComplete();
i2cSendStop();
cbi(TWCR, TWEN); // Disable TWI
sbi(TWCR, TWEN); // Enable TWI
return data;
}
// Writes a single byte (data) into address
void writeRegister(unsigned char address, unsigned char data)
{
i2cSendStart();
i2cWaitForComplete();
i2cSendByte((MMA8452_ADDRESS<<1)); // Write 0xB4
i2cWaitForComplete();
i2cSendByte(address); // Write register address
i2cWaitForComplete();
i2cSendByte(data);
i2cWaitForComplete();
i2cSendStop();
}
void tapHandler()
{
byte source = readRegister(0x22); // Reads the PULSE_SRC register
if (((source & 0x10)==0x10) || ((source & 0x20)==0x20) || ((source & 0x40)==0x40)) // If X o Y o Z bit is set
{
digitalWrite(PinVccTransmisor, HIGH); // Activa emisor
Serial.println("TAP Enviando Datos ");
vw_send((uint8_t *)msg, strlen(msg)); //Envia datos
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(PinVccTransmisor, LOW); //Apaga emisor
}
}
void loop()
{
static byte source;
source = readRegister(0x0C); // Read the interrupt source reg.
if ((source & 0x08)==0x08) // Otherwise, if tap register is set go check that
{
tapHandler();
}
// Manage sleep/wake interrupts
if((readRegister(INT_SOURCE) & 0x80) == 0x80) { // Check if interrupt source is sleep/wake interrupt
if(!sleepMode) {
Serial.println("entering sleep mode");
sleepMode = TRUE;
// attachInterrupt(0, wakeUp, HIGH);
// LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
// detachInterrupt(0);
}
else {
Serial.println("exiting sleep mode");
sleepMode = FALSE;
}
readRegister(SYSMOD); // clear sleep interrupt
}
delay(10); // Delay here for visibility
}
Thanks for your comments!