Sunday, March 20, 2016

Linux - Python driver for the MMA8451 accelerometer

The mma8451 is another accelerometer available for $5 that was the model for the fiendishly complex mc3610.  This must be 'west coast' and the adxl345 is 'east coast'.  Anyway, the tests put it at the same discrimination as the mc3610, but not as good as two adxl345's.  However, the calibration the $5 board is infinitely better than the cheap Chinese $2 adxl's.  If my new shipment from China is as bad as the last one, I may go with these for my dream el cheapo accelerometer.  I'm still waiting for the raspi zero to become available in volume before I move on much.  The basic idea is too have an open design that people can do themselves and then set them up in the richer houses of Oklahoma.  You'll need 'unlimited' Internet (you use Netflix a lot) and a big hunk of space in Google Drive.  I hope to get it to something like $20 of parts and an hour of labour.  It'll be fun!

Here's the main Python driver for 2g and 200 Hz.  The program samples at 100 Hz.  Once again, the spec sheet is crap and I had to fool around.  I suppose they do that to allow people to keep secrets.  I never keep secrets.  Go ahead, busgus, outdo me!

Python Driver



#This is a Python driver for the mma8451

import pigpio
from time import sleep



# mma constants

MODE_REG = 0X2a


MODE_STANDBY = 0x14
MODE_CWAKE = 0x15

pi = pigpio.pi()



#initial sequence

start = pi.bb_i2c_open(2, 3, 50000)



#Start by sending it into Standby mode, and wait a bit


#cmd_readreg =
cmd_standby = [4, 0x1d, 2, 7, 2, MODE_REG, MODE_STANDBY, 3, 0]
(count,data)  =  pi.bb_i2c_zip(2,cmd_standby)
sleep(0.004)
print "have started standby"

#This also gives a sampling of 200
#range of 2 g is default

#Finally, set mode to cwake, for readings

cmd_cwake = [4, 0x1d, 2, 7, 2,MODE_REG , 0x15, 3, 0]
(count,data)  =  pi.bb_i2c_zip(2,cmd_cwake)
sleep(0.004)

class MMA8451:
#The msb and lsb order are reversed from the adxl345 and mc3610
    def getAxes(self):
adata = [0]*6
scale_factor = 16383.0
cmd_read = [4, 0x1d, 2, 7, 1,0x1 , 2,6,6,3, 0]
(count,adata)  =  pi.bb_i2c_zip(2,cmd_read)


        x = adata[1] | (adata[0] << 8)
        if(x & (1 << 16 - 1)):
            x = x - (1<<16 p="">

        y = adata[3] | (adata[2] << 8)
        if(y & (1 << 16 - 1)):
            y = y - (1<<16 p="">

        z = adata[5] | (adata[4] << 8)
        if(z & (1 << 16 - 1)):
            z = z - (1<<16 p="">


xf = x  / scale_factor
yf= y  / scale_factor
zf= z  / scale_factor

        return {"x": xf, "y": yf, "z": zf}




if __name__ == "__main__":
    # if run directly we'll just create an instance of the class and output
    # the current readings
mma8451 = MMA8451()
 
axes = mma8451.getAxes()
print "   x = %.5fG" % ( axes['x'] )
print "   y = %.5fG" % ( axes['y'] )
print "   z = %.5fG" % ( axes['z'] )
sleep(0.01)



#close after running - pigs BI2CC 2

****************************************

The 'average' application

#!/usr/bin/python

import time
#import graphics
from mmadriv import MMA8451

from time import sleep


mma8451=MMA8451()

dt = 0.01



accxsum = 0
accysum = 0
acczsum = 0

for a in range(4,250):
axes = mma8451.getAxes()
accy = axes['y']
accz = axes['z']
accx = axes['x']
print "   accx = %.5fG" % ( accx )
print "   accy = %.5fG" % ( accy )
print "   accz = %.5G" % ( accz )

accxsum = accxsum + accx
accysum = accysum + accy
acczsum = acczsum + accz
sleep(dt)

accxavg = accxsum / 250
accyavg = accysum / 250
acczavg = acczsum / 250

print "   accxavg = %.5f" % ( accxavg )
print "   accyavg = %.5f" % ( accyavg )
print "   acczavg = %.5f" % ( acczavg )

************************************

ps. I've ordered 4 from China (cheap as the adxl345) to see if they are seconds, like my first batch.

No comments: