mma7660 accelerometer

I was trying to port a MMA7660 library but when I it onto the core, it just started flashing 8 red blinks then restarted. It looks like it should be a simple port but I can not figure out why it is failing on the core. Any help will be greatly appreciated. Below is the github files.

Hmm, I think 8 blinks is an out of heap memory ( https://community.spark.io/t/core-firmware-sos-panic-codes/4337 ). We should be releasing an update very soon that frees up a bunch of RAM that should help!

But, just eyeing this code, I don’t see any major memory use, maybe I’m missing something?

Thanks,
David

@wesner0019, I will take a shot at the port and see if I have better luck :smile:

PS: Can you please post your test code? - NEVER MIND, I just found the library you used :smile:

@wesner0019, the library you are using has some “issues” that could cause the code wild. I found a more recent and robust library by seeedstudio that I ported and is available here. It compiled fine using Spark CLI. Give it a shot with your device and let me know how it goes. :smile:

1 Like

Thanks! I’ll give it try.

This code is working good! Thanks for your help.

1 Like

After getting it set-up and running, the code does not appear to be outputting or using negative numbers. When the z should be -1 is actually 2. There is something going on with the use of negative numbers somewhere. Do you have any ideas?

@wesner0019, I am not convinced the x,y,z conversion from 2’s complement in MMA7660.cpp was correctly done using the (char) type cast. I have changed this to (int8_t) instead and hopefully, it will work. I posted the change on the github files. :smile:

That worked.

Hopefully one last question. When I leave the accelerometer stable, it stops outputting. I think the accelerometer, once stable, goes into a sleep mode but does not wake up when moved again. I was reading through the datasheet (http://cache.freescale.com/files/sensors/doc/data_sheet/MMA7660FC.pdf) and could not determine exactly how to activate the auto wake feature (if this is the cause). I believe it is in the 0x07 register and or 0x08. I also wasn’t sure if any of the interrupts had to be activated also. Any ideas?

Thanks a lot for you input.

I will take a look and let you know:)

@wesner0019, actually the datasheet is as clear as mud on the auto-wake feature so I’ve got to dig some more :smile:

To simplify trouble shooting. I just used the below code. Im connected to CoolTerm (termial for serial connection) and any where from 30second to 6minutes the i2c stops working and the serial also stops. The breathing cyan light keeps working though. I dont know what is causing the i2c to freeze. I am using 2.2k pull-ups on the lines. Other i2c device such as the adafruit ssd1306 work fine and do not freeze.

I re-looked through the data sheet and it looks like the auto wake and sleep are disabled so this should not affect the i2c to freeze 0x07 register is only 0x01 auto wake/sleep enabled would be 00011001 (0x19).

Any thoughts why this library is causing the serial and i2c to freeze?

#include "MMA7660.h"

MMA7660 accelemeter;
void setup()
{
    Serial.begin(9600);
//    while(!Serial.available())  // Wait here until the user presses ENTER 
  //  SPARK_WLAN_Loop();        // in the Serial Terminal. Call the BG Tasks
                              // while we are hanging around doing nothing.
    accelemeter.init();
}
void loop()
{
    int8_t x;
    int8_t y;
    int8_t z;
    float ax,ay,az;
    accelemeter.getAcceleration(&ax,&ay,&az);
    Serial.print(az);
    Serial.print(" g   ");
    delay(500);
}

@wesner0019, the code sets the sampling rate to "AUTO_SLEEP_32" which according to the specs, sets 32 Samples/Second Active and Auto-Sleep Mode. However (!), the MODE register is written such that:

Active Mode enabled
Auto-Wake is disabled
Auto-Sleep is disabled

So, the device should never sleep and sample at 32 samples/sec.

Looking at the code, accelemeter.getXYZ(&x,&y,&z) is not a blocking call so it should not hang the code. I ran the demo code with NO I2C device connected and it looped without stopping. I did make a minor fix on the MMA7660.cpp file that adds "(float)" casts to the acceleration values. You may want to grab the latest version.

You can also try moving the variable declarations above setup() to make them globals:

int8_t x;
int8_t y;
int8_t z;
float ax,ay,az;

Try the update I made plus the global vars and see if that makes a difference. :smile:

Before making the above changes, I changed the sample rate to AUTO_SLEEP_4    0X05. Did a hard reset and reloaded the code. So far its been working normally. Not really sure why its working at lower sample rate but from my use this is fast enough.

Ill incorporate the above changes at the next upload.

1 Like

After testing this did not end up fixing the problem. It ran form 1820 seconds then stopped, after reset ran for 879 seconds then stopped, then reset and ran for 550 seconds then stopped. I’ll try these changes now.

@wesner0019, how are you powering the module?

I am powering through the usb. Currently this has now been running for 3600 second. I do have a 3.3 boost converter on my board (http://www.ti.com/lit/ds/symlink/tps61020.pdf) TPS61025 with the power save enabled. The power save may be giving me some issues when running on 2AAA but I’ve seen the issue using both power supplies.

@wesner0019, can you try running the sensor using the Spark 3.3V line and not use the boost converter? Strip the system down to just the Spark and the MMA7660 if possible and power it via USB.

It doesnt look like the code i posted is coming in correctly. It is all in the link I gave though.

I have bypassed the boost converter and am only using the spark ldo to power via it's 3.3V line.

After reading more, it looks like this accelerometer uses a repeated start condition. Could this repeated start condition be causing issues? I ran into the below thread that suggested a fix for the Due.
https://code.google.com/p/arduino/issues/detail?id=28

The sendStop parameter does fix the problem. The following routines demonstrate how Wire can be used to implement the write addr then read or write data protocol. These code snippets were tested on a i2c digital 3 axis accelerometer, so I recommend that this bug be closed as fixed.

unsigned char I2c::writeAddrWriteData(unsigned char deviceAddress, unsigned char addr, const unsigned char* buf, int length)
{
Wire.beginTransmission(deviceAddress);
Wire.write(addr);
for (int i=0;i<length;i++) Wire.write(buf[i]);
Wire.endTransmission();
return length;
}

unsigned char I2c::writeAddrReadData(unsigned char deviceAddress, unsigned char addr, unsigned char* buf, int length)
{
//Wire.requestFromAt((unsigned char)deviceAddress,(unsigned char)addr,(unsigned char)length);
Wire.beginTransmission(deviceAddress);
Wire.write(addr);
Wire.endTransmission(false); // Don't issue a stop because we need to read the value.
Wire.requestFrom((uint8_t) deviceAddress, (uint8_t) length, (uint8_t) false);
for (int i=0;i<length;i++,buf++) *buf = Wire.read();
Wire.endTransmission(true); // Now issue the stop
return length;
}
*/

@wesner0019, nice catch! I wasn't even looking for that. DOH! :blush:

I created branch of the code on my github and did a couple of changes. First, the read and write functions were calling Wire.begin() on every call. The Spark documentation says:

Initiate the Wire library and join the I2C bus as a master or slave. This should normally be called only once.

So this may be part of the problem. I moved Wire.begin() to the init() functon. I also modified the existing code to do the start/restart as per the code link you included above. I included the (commented out) code in MMA7660.cpp for comparison. I don't like the way the while(Wire.available()) works in read() but give the code a shot and see if it works correctly now. You branched code is here. :smile: