Friday, March 18, 2016

Linux - Pyrrhic Victory in reading the MC3610

I've been trying to get the mc3610 to work *forever*.  Now, I have finally written the Python programs to get this to work.  It doesn't help that their sample driver for Arduino is crap, or their spec sheet is inconsistent.  These guys make the Dementors look like buffoons.

So, for the Raspberry Pi, you install pigpio library.

This allows you to directly bit-bang the stupid thing.  Here's the Python driver.  I only have 2 options, and I just changed the sampling to 200 Hz without commenting, because that's where the spec is bad at 100 Hz.

#This is a Python driver for the MC3610

import pigpio
from time import sleep



# mc3610 constants

MODE_REG = 0X10
SAMPLE_RATE_1_REG = 0x11
SAMPLE_RATE_2_REG = 0x12
RANGE_RES_REG = 0x15
I2CSET_REG = 0x13

MODE_STANDBY = 0x1
MODE_CWAKE = 0x5

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, 0x6c, 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"
#read to confirm
#(count, rdata) =  pi.bb_i2c_zip(2,cmd_standby)


#You must then send a command to choose i2c only (it also does spi on the same pins)
cmd_i2c = [4, 0x6c, 2, 7, 2, I2CSET_REG , 0x80, 3, 0]
(count,data)  =  pi.bb_i2c_zip(2,cmd_i2c)


#The sample rate is set by two registers (100 Hz)

cmd_sam1 = [4, 0x6c, 2, 7, 2,SAMPLE_RATE_1_REG , 0x09, 3, 0]
#cmd_sam2 = [4, 0x6c, 2, 7, 2,SAMPLE_RATE_2_REG , 0xe0, 3, 0]
(count,data)  =  pi.bb_i2c_zip(2,cmd_sam1)
#(count,data)  =  pi.bb_i2c_zip(2,cmd_sam2)

#Set range and resolution (16g, 14 bits)
#cmd_rres = [4, 0x6c, 2, 7, 2,RANGE_RES_REG , 0x25, 3, 0]

#This is 2g with 14 bits, the scale factor changes each time
cmd_rres = [4, 0x6c, 2, 7, 2,RANGE_RES_REG , 0x05, 3, 0]
(count,data)  =  pi.bb_i2c_zip(2,cmd_rres)

#Finally, set mode to cwake, for readings

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

class MC3610:

    def getAxes(self):
adata = [0]*6
scale_factor = 16383 / 2.0
cmd_read = [4, 0x6c, 2, 7, 1,0x2 , 2,6,6,3, 0]
(count,adata)  =  pi.bb_i2c_zip(2,cmd_read)


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

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

        z = adata[4] | (adata[5] << 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
mc3610 = MC3610()
 
axes = mc3610.getAxes()
print "   x = %.5fG" % ( axes['x'] )
print "   y = %.5fG" % ( axes['y'] )
print "   z = %.5fG" % ( axes['z'] )
sleep(0.01)
axes = mc3610.getAxes()
print "   x = %.5fG" % ( axes['x'] )
print "   y = %.5fG" % ( axes['y'] )
print "   z = %.5fG" % ( axes['z'] )


#mc3610 and pigpiod stay open after this, restart everything manually

END OF FIRST BLOOD SWEAT TEARS

Now you can run a python program doing things like plotting or here, calculating the average.

#!/usr/bin/python

import time
#import graphics
from mc3610driv import MC3610

from time import sleep


mc3610=MC3610()

dt = 0.01



accxsum = 0
accysum = 0
acczsum = 0

for a in range(4,250):
axes = mc3610.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 )

END OF THIS CRAP

This accelerometer is marginally better than the adxl345, but not as good as two of them chained together.  The adxl345 is $2 from China, but I had difficulty buying good ones.  My second attempt is taking over a month to ship, and I pray to get them soon.  If you can find working versions then you chain a lot together for one $16 mc3610.  DON'T BUY FROM THESE CRAZY PEOPLE!

I learned that c++ is horrible, and I like Python.  The Raspberry Pi is fantastic with all the support.

ps.  The pigs library was a great thing because I can now make a second i2c from the other lines.  No need to go that 'mysterious' underneath second i2c.

No comments: