mma8451 Motion Detection and RaspberryPi 2b+

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

mma8451 Motion Detection and RaspberryPi 2b+

1,285 Views
luigi5hd
Contributor II

Goodmornig,

This is my main code:

##############################"

xOffset = -0.400 # m/s^2
yOffset =  0.200 # m/s^2
zOffset =  9.400 # m/s^2
while True:
    while sensor.Motion():
        x, y, z = sensor.acceleration
        time_now = datetime.datetime.now()
        Calcx = -xOffset
        Calcy = -yOffset
        Calcz = -zOffset
        X = x + Calcx
        Y = y + Calcy
        Z = z + Calcz
    
        sensor.MotionRegister()    
                
        print('Time={0}   X={1:0.3f} m/s^2  Y:{2:0.3f} m/s^2  Z:{3:0.3f} m/s^2'.format(time_now, X, Y, Z))
        time.sleep(0)
            
    IntSourceMFF = sensor.MotionRegister()

#####################"

And I have setup my MMA8451 into a class like this:

###################""

    def Motion (self): #, IntSourceSystem,IntSourceMFF):
        reg1 = self._read_u8(_MMA8451_REG_CTRL_REG1)
        reg1 &= 0xFE #clear active bit (standby)
        self._write_u8(_MMA8451_REG_CTRL_REG1, reg1)
        self._write_u8(REG_FF_MT_CONFIG, 0x48) #Moto detection X axe after the debounce time (100)ms is reached
        self._write_u8(REG_FF_MT_THS, 0x10)    #threshold 1g: es 1g/0.063g = 16 counts = 10 (hexadecimal)
        self._write_u8(REG_FF_MT_COUNT, 0x0A) #Debounce counter, set at 12.5ms timer for 800 output data rate
        self._write_u8(_MMA8451_REG_CTRL_REG4, 0x04)
        self._write_u8(_MMA8451_REG_CTRL_REG5, 0x04)
        # self._write_u8(_MMA8451_REG_CTRL_REG3, 0x04)
        reg1 = self._read_u8(_MMA8451_REG_CTRL_REG1)
        self._write_u8(_MMA8451_REG_CTRL_REG1, reg1 | 0x01) #activated
        print("It will work")
        IntSourceSystem = self._read_u8(_MMA8451_INT_SOURCE)
        if ((IntSourceSystem & 0x04) == 0x04):
            print("You are into if")
            return True
        else:
            print("You are into else")
            return False

    def MotionRegister (self):
        return self._read_u8(REG_MT_SRC)

##################"

Something strange happens, it works properly only if I print something in my setup module (in this case "It will work").

Why it does it? I don't want that print.

Maybe it is a problem with the Count register setup..I didn't well realized how to use it, I want to use a 100ms timer for 800 ODR but with 0x50 didn't works..

Can someone help me pls?

Labels (1)
8 Replies

876 Views
luigi5hd
Contributor II

Hey Tomas,

Firstly best wishes!!

I still have the same problem with the autocalibration..

But I want to change my question:

If the device is stationary on a "flat" desktop, and the measures are

X= 0.201 m/s2

Y= 0.220 m/s2

Z= 9.409 m/s2

Which is the best way to gain:

X= 0 m/s2

Y= 0 m/s2

Z= 9.81 m/s2   ?

I'm also available to use the simple method calibration, but how can I be able to delete the noise? 

Am I forced to use the High pass filter or can I use the offset registers?

What do you think? And can you suggest me how to do it?

Thank you, best regards.

0 Kudos

876 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Luigi,

First off... Happy New Year and sorry for my late response.

Everything you described in your post from Dec 21st is correct for 8g mode.

In order to reduce noise, our recommendation is using lowest possible ODR and High Resolution Mode as shown in the AN4075 (page 7).

Best regards,

Tomas 

0 Kudos

875 Views
luigi5hd
Contributor II

ok I have solved the print problem; it was just a bad use of the class module; I just have the reg count problem, can someone explain it to me?

0 Kudos

876 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Luigi,

As I do not fully understand what you are asking, I would refer to the AN4070 where you may find useful information related to the embedded motion detection function. If you need to know anything specific, please elaborate it a bit more.

Best regards,

Tomas

876 Views
luigi5hd
Contributor II

Hi Tomas,

Yes I have already read the AN4070 note,

so, my problem was to how to calculate correctly the value to write into the FF_MT_THS register (0x17), and it is just "Threshold/0.063" ;

and how to calculate correctly the value to write into the FF_MT_COUNT register (0x18), and it is just  "DebounceTime/TimeStep".

Forget about them.

Now I have another problem:

I'm trying to doing the Aut-Calibration Procedure of the device.

yes, I have already read the AN4069 note :smileyhappy:

On page 6 of the note there is an example using a flow chart.

I didn't understand the 3th box:

pastedImage_2.png

Have I to read, (and so print?) the acceleration on X,Y, and Z using firstly the register OUT_X_MSB?

After that have I to read the acceleration on X,Y, and Z using the register OUT_X_LSB?

After that have I to read the acceleration on X,Y, and Z using the register OUT_Y_MSB? etc?

0 Kudos

876 Views
luigi5hd
Contributor II

I've tried to do as I mentioned and my Acceleration values are these:

pastedImage_5.png

first line X,Y,Z using OUT_X_MSB

second X,Y,Z using OUT_X_LSB

third X,Y,Z using OUT_Y_MSB

fourth X,Y,Z using OUT_Y_LSB

etc.

Are these the values that I need to use in the next step, for the 2's complement?

pastedImage_3.png

Thank you.

0 Kudos

876 Views
TomasVaverka
NXP TechSupport
NXP TechSupport

Hi Luigi,

Sorry for my late response. I would recommend you to take a look at my simple example code for the MMA8451Q where I illustrate offset calibration based on the AN4069.

You should use something like this:

I2C_ReadMultiRegisters(MMA845x_I2C_ADDRESS, OUT_X_MSB_REG, 6, AccData);           // Read data output registers 0x01-0x06

                                          

Xout_14_bit = ((short) (AccData[0]<<8 | AccData[1])) >> 2;           // Compute 14-bit X-axis output value

Yout_14_bit = ((short) (AccData[2]<<8 | AccData[3])) >> 2;           // Compute 14-bit Y-axis output value

Zout_14_bit = ((short) (AccData[4]<<8 | AccData[5])) >> 2;           // Compute 14-bit Z-axis output value

                                   

Xoffset = Xout_14_bit / 8 * (-1);        // Compute X-axis offset correction value

Yoffset = Yout_14_bit / 8 * (-1);        // Compute Y-axis offset correction value

Zoffset = (Zout_14_bit - SENSITIVITY_2G) / 8 * (-1);          // Compute Z-axis offset correction value

                                   

I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG1, 0x00);             // Standby mode to allow writing to the offset registers 

I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_X_REG, Xoffset);        

I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_Y_REG, Yoffset); 

I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_Z_REG, Zoffset); 

Hope it helps!

Best regards,

Tomas

0 Kudos

876 Views
luigi5hd
Contributor II

Yes, I was just following your metal bare example but I still have some problem.

Firstly: I'm in 14 bit, ODR 800, 8g mode.

 

Here:

Xout_14_bit = ((short) (AccData[0]<<8 | AccData[1])) >> 2;           // Compute 14-bit X-axis output value

Yout_14_bit = ((short) (AccData[2]<<8 | AccData[3])) >> 2;           // Compute 14-bit Y-axis output value

Zout_14_bit = ((short) (AccData[4]<<8 | AccData[5])) >> 2;           // Compute 14-bit Z-axis output value

 

What are you doing with this shifting?

Is this equivalent to a 2's complement for XYZ no?

And are they approximated as integers no? ("short" operator)

 

Now I've calculated the  Offset like this:

Xoffset = Xout_14_bit / 2 * (-1);        // Compute X-axis offset correction value

Yoffset = Yout_14_bit / 2 * (-1);        // Compute Y-axis offset correction value

Zoffset = (Zout_14_bit - 1024) / 2 * (-1);          // Compute Z-axis offset correction value with 8g sensitivity

It looks correct to me..

 

After that I convert them as hexadecimal (ok?) and I put them into the Offset registers:

 

I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG1, 0x00);             // Standby mode to allow writing to the offset registers 

I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_X_REG, Xoffset);        

I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_Y_REG, Yoffset); 

I2C_WriteRegister(MMA845x_I2C_ADDRESS, OFF_Z_REG, Zoffset); 

I2C_WriteRegister(MMA845x_I2C_ADDRESS, CTRL_REG1, 0x01);             // Active mode

 

 

And it doesn't work properly anyway :/

The y and z acceleration doesn't change enough, and  X acceleration doesn't change at all.

NB my stationary target is:

X=0g

Y=0g

Z=1g

Obvious my device is properly oriented.

I'm sorry if I'm annoying you too much, I'm a bit noob.

Thank you and merry Christmas.

0 Kudos