Anyone been using the MEMS Sensor Eval Board from Xtrinsic (specifically the MMA8491Q 3-axis accelerometer) with a RPi using the supplied python scripts or derivatives?
After a period (of about 1600 read iterations) it appears to cause a constant series of failures which look like memory allocation failures in the virtual memory mapper of the bcm2835 starting with the BCS0 (used for I2C) and then immediately thereafter the ST (System Timer) and for all subsequent (accelerometer read) function calls (both with an error string that implies bcm2835_init is doing the call to mmap).
I'm not sure why the bcm2835_init: would be repeatedly called (as this seems to be the case) when using the read function which forms part of the getAccelerometer function, but there doesn't appear to be any source around for the sensor.so library object which is the interface in the python examples.
Is this an expected quirk of the evaluation source... as I wish to create a prototype 'acceleration logger' to ensure accelerometer sensing will be a suitable product response for a marine application, so need to be able to log at least a days worth of relatively high-speed data acquisition (all 3-axes every 20ms or better, for a whole day)... or do I need to rewrite the interface to the RPi myself just to prove the capability of the sensor for my application?
I can't believe the problem is in the (very widely used since 2011) bcm2835 driver from Mike McCauley, so have to presume the sensor.so library object is repeatedly attempting to re-initialise the hardware every time I read the accelerometer... and causes a memory leak.
I haven't tried the other sensors on the board, but presume the constructs would be the same and get a similar answer.
Any help would be welcome, as the prototype goes in front of the customer as part of system requirement gathering next week!
Thanks,
Stuart
解決済! 解決策の投稿を見る。
Same Problem here :-( it's unreliable. I want to use it in a ballooning project. I try to re-spawn the program so no data will be lost. Not sure whether that works or not...
Thanks for any help
Bruno
Bruno,
I turned the bcm2835 debug switch on and reverse engineered the calls, and reconstructed the equivalent locally, removing the unnecessary bits!
I've gone back to manhandling the bcm2835 directly to the original interface and using RPi.GPIO to handle the board's enable pin... assuming sensor.so still incorporates all the bcm2835 calls... and it seems to work for me... It also now respects the enable/disable specification (which needs best part of 1ms settle each way). I've also tried it at 400KHz, and it works, but makes little difference to performance.
Ignore my _target flags which allow me some off-target/host testing against a simulated input file, for remaining logic.
Regards,
Stuart
e.g.
if _target == True:
sensor = CDLL("./sensor.so")
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(22, GPIO.OUT)
class MMA8491Q_DATA(Structure):
_fields_ = [("Stat", c_int8),
("XH", c_int8), ("XL", c_int8),
("YH", c_int8), ("YL", c_int8),
("ZH", c_int8), ("ZL", c_int8)]
if _target == True:
class mma8491q:
def __init__(self):
# sensor.bcm2835_set_debug(1)
if (0 == sensor.bcm2835_init()):
print ("bcm2835 driver init failed.")
return
def init(self):
# sensor.MMA8491Q_Init()
# set up GPIO pins for Alt0 (i.e. I2C)
sensor.bcm2835_i2c_begin()
# set I2C clock at 100KHz (use 2500 for 100KHz, 625 for 400KHz)
sensor.bcm2835_i2c_setClockDivider(2500)
# set Accelerometer slave address (0x55 or 85D)
sensor.bcm2835_i2c_setSlaveAddress(85)
def enable(self):
# sensor.MMA8491Q_Enable()
GPIO.output(22, GPIO.HIGH)
# wait for data ready
time.sleep(t_on)
def disEnable(self):
# sensor.MMA8491Q_DisEnable()
GPIO.output(22, GPIO.LOW)
# wait for reset
time.sleep(t_reset)
def read(self, data):
# sensor.MMA8491_Read(data)
sensor.bcm2835_i2c_read(data, 7)
# first byte is status,
# data as per register access (i.e. sign in bit 15, data in bits 14 to bit 2)
def getAccelerometer(self):
data = MMA8491Q_DATA()
pdata = pointer(data)
self.read(pdata)
# re-align data to equivalent 16 bit signed integer
# print(data.Stat, data.XH, data.XL, data.YH, data.YL, data.ZH, data.ZL)
if (data.XH & 0x80) == 0x80:
x = ~(((data.XH << 8) + data.XL) >> 2) + 1
else:
x = (((data.XH << 8) + data.XL) >> 2)
if (data.YH & 0x80) == 0x80:
y = ~(((data.YH << 8) + data.YL) >> 2) + 1
else:
y = (((data.YH << 8) + data.YL) >> 2)
if (data.ZH & 0x80) == 0x80:
z = ~(((data.ZH << 8) + data.ZL) >> 2) + 1
else:
z = (((data.ZH << 8) + data.ZL) >> 2)
# print(x, y, z)
return (x, y, z);
Thanks a lot Stuart
I tried your approach and it seems to work (The error showed up very irregularly though, so lets see how it works for a longer period)
Thanks again
Bruno