Incorrect calculated data from MMA8452 accelerometers? (MMA8452-Accelerometer-Library-Spark-Core)

Hi,

I’m working on a prototype to prevent bad posture, and I’m using two MMA8452 accelerometers. However, I got some trouble with the calculated values when using the MMA8452-Accelerometer-Library-Spark-Core library. The not calculated values is working fine, or at least I get different values when moving the accelerometers, but when I change to the calculated values I only get the value 0 or 3.

Hope you guys can help me out…

Regards Mads Svendsen

My code looks like this: (It’s mainly the PublishVal function that’s interesting)

// This #include statement was automatically added by the Spark IDE.
#include "SparkTime/SparkTime.h"

// This #include statement was automatically added by the Spark IDE.
#include "MMA8452-Accelerometer-Library-Spark-Core/MMA8452-Accelerometer-Library-Spark-Core.h"
//******************************************************************************

MMA8452Q accel1(0x1D);
MMA8452Q accel2(0x1C);

int PublishTime;
int Posturevalue;
int x;
int y;
int z;
long Timer;

int ButtonPin = D4;
int VibratorPin = D5;

#define ONE_HOUR_MILLIS (60 * 60 * 1000)
#define POSTUREVAL_INTERVAL (5 * 1000)
unsigned long lastSync = millis();

void setup()
{
    accel1.init(); //initialise accelerometer1
    accel2.init(); //initialise accelerometer2
    
    pinMode(ButtonPin, INPUT_PULLUP);
    pinMode(VibratorPin, OUTPUT);
    
    Timer = millis();
}

void loop()
{
    Vibrator();
    PublishVal();
    UpdateTime();
}

void Vibrator() {
    if (digitalRead(ButtonPin) == LOW) {
    digitalWrite(VibratorPin, HIGH);
    }
    else {
    digitalWrite(VibratorPin, LOW);
    }
}

void PublishVal() {
        if (accel1.available() && accel2.available() && millis()-Timer >= POSTUREVAL_INTERVAL){
    accel1.read();
    accel2.read();
    PublishTime = Time.now();
    
    if (PublishTime != NULL) {
    
    x = accel1.cx;
    y = accel1.cy;
    z = accel1.cz;
    
    if (x != NULL && y != NULL && z != NULL) {
    Spark.variable("x", &x, INT);
    Spark.variable("y", &y, INT);
    Spark.variable("z", &z, INT);
    }
    
    x = accel2.cx;
    y = accel2.cy;
    z = accel2.cz;
    
    if (x != NULL && y != NULL && z != NULL) {
    Spark.variable("x", &x, INT);
    Spark.variable("y", &y, INT);
    Spark.variable("z", &z, INT);
    }
   
   
    Spark.variable("Time", &PublishTime, INT);
   }
    
    Timer = millis();
    }
}

void UpdateTime() {
      if (millis() - lastSync > ONE_HOUR_MILLIS) {
    // Request time synchronization from the Particle Cloud
    Spark.syncTime();
    lastSync = millis();
  }
}

@svendsen2032, what a cool project! I believe the issues your are having are related to the way you use Spark.variable() in your code. The idea of Spark.variable() is to make a (global) variable in your code visible to the cloud. The “declaration” (ie the call to Spark.variable()) only needs to be done once in setup(). Afterwards, you simply change the value of the referred variable and it gets automagically (as @wgbartley would say) updated in the Cloud.

I notice in your code you are trying to use the same set of Spark.variables() for the two accelerometer data sets. You can have up to 10 Spark.variables() declared on the Core so I suggest you create unique x,y,z variables for each accelerometer.

So, in your code, move/copy this code to setup:

    Spark.variable("x", &x, INT);
    Spark.variable("y", &y, INT);
    Spark.variable("z", &z, INT);

to create 2 sets of variables .

    Spark.variable("x1", &x, INT);
    Spark.variable("y1", &y, INT);
    Spark.variable("z1", &z, INT);
    Spark.variable("x2", &x, INT);
    Spark.variable("y2", &y, INT);
    Spark.variable("z2", &z, INT);

Then, update your PublishVal() code to set all 6 variables. You can remove the if() statements associated to these since the variables are automatically updated in the Cloud.

The same thing applies to the Time SparkVariable(), that is, move it to setup().

BTW, you may want to consider debouncing the ButtonPin in Vibrator() with a timer (lots of examples in other topics if you do a search)
:smile:

1 Like

Thanks peekay123 - that’s is very useful answer. I have fixed the Spark.variables(). Had no idea that is how to implement the Spark.variables :smile: I might have a look at the “timer” later on. I did read about it briefly while looking for a solution to my timer problem, but ended not using it, cause I did not want another library implementet.

However, I’m still not getting the correct data when using accel.cx, accel.cy and accel.cz - can you explain why that is?

@svendsen2032, can you please post your updated code?

Here goes: (im just reading data from one accelerometer right now, as it is easier while figuring out why im not getting the correct data)

// This #include statement was automatically added by the Spark IDE.
#include "SparkTime/SparkTime.h"

// This #include statement was automatically added by the Spark IDE.
#include "MMA8452-Accelerometer-Library-Spark-Core/MMA8452-Accelerometer-Library-Spark-Core.h"
//******************************************************************************

MMA8452Q accel(0x1D);

int PublishTime;
int Posturevalue;
int x;
int y;
int z;
unsigned long Timer;
unsigned long lastSync = millis();

int ButtonPin = D4;
int VibratorPin = D5;

#define ONE_HOUR_MILLIS (60 * 60 * 1000)
#define POSTUREVAL_INTERVAL (5 * 1000)


void setup()
{
    
    Spark.variable("x", &x, INT);
    Spark.variable("y", &y, INT);
    Spark.variable("z", &z, INT);
    Spark.variable("Time", &PublishTime, INT);
    
    accel.init(SCALE_8G, ODR_50); //initialise accelerometer
    
    pinMode(ButtonPin, INPUT_PULLUP);
    pinMode(VibratorPin, OUTPUT);
    
    Timer = millis();
}

void loop()
{
    Vibrator();
    PublishVal();
    UpdateTime();
}

void Vibrator() {
    if (digitalRead(ButtonPin) == LOW) {
    digitalWrite(VibratorPin, HIGH);
    }
    else {
    digitalWrite(VibratorPin, LOW);
    }
}

void PublishVal() {
        if (accel.available() && millis()-Timer >= POSTUREVAL_INTERVAL){
    accel.read();

    PublishTime = Time.now();
    
    if (accel.cx != NULL && accel.cy != NULL && accel.cz != NULL) {
        x = accel.cx;
        y = accel.cy;
        z = accel.cz;
    }
    
    Timer = millis();
    }
}

void UpdateTime() {
      if (millis() - lastSync > ONE_HOUR_MILLIS) {
    // Request time synchronization from the Particle Cloud
    Spark.syncTime();
    lastSync = millis();
  }
}

@svendsen2032, you don’t need the SparkTime library since it is built into the firmware Time library.

Also, can I ask if you are using an MMA8452 breakout and if so, which one?

When you say “not getting the correct data”, is it zero or just not correct in your estimation?

You may want to simplify your PublishVal() code by removing the Timer delay code and just reading the accelerometer if accel.available() is true. Use a dumb delay() for timing. This is just for testing purposes.

Ahh, alright. Then I might implement it :smile:

Yes, I am using the breakout (Link to accelerometer)

My x and z values are 0 and my y values are 15, and they do not change, when changing the position of the accelerometer.

Thanks.

@svendsen2032, how are you powering the breakout. More specifically, how it is connected to your Core (describe wiring)? Do you have any other I2C devices connected?

Also, and because I have to ask, did you run the basic demo that comes with the IDE library?

I’m powering the particle core either with my computer (USB) or a battery pack (1000 mAh). See picture for wiring.

I startet out by setting it all up with Arduino and tried it, everything worked fine. I have not tried just to do the example on the particle core. I startet with the arduino, cause it has the Serial Monitor, which I find easy when monitering data :+1:

@svendsen2032, here are a few observations:

  1. Powering the vibration motor directly from a GPIO pin is not a good idea. The pins are rated for 20ma max and motors are known for their inrush current. They will also have inductive kickback which can cause damage to the Core. Ideally, you would drive the motor via a small transistor and put a diode accross the motor (in reverse to the applied polarity) for protection. Perhaps the unit you are using has this built-in?

  2. There is no need for pull-up resistors are they are already on the Sparkfun boards. Adding more will just lower the effective pull-up resistance.

The Core has serial over USB and you can use any terminal application (eg. Putty) to see any Serial.print() output from your code. Just make sure you have the windows drivers installed.

Can you run the demo code on the IDE as a start. If that works, we can go from there. :smiley:

1 Like

@peekay123 think I might have found the problem :smile:

  1. A few words I did not know (inrush current and inductive kickback) - so I tried to figure out what you are saying. I understand that the inductive kickback can be dangerous to the electronic circuit, and that I should fix it. However, as my deadline is tonight and as I have already done the soldering, I do not have time to change it. But I will certainly change it later on - thanks a lot. And I’m pretty sure the vibration motor does not come with it built in (link)

  2. You are refering to the resistors connected to the two accelerometers, right? I used them, cause they are used in similar circuits I found on the internet and in the library. Again, the circuit is already soldered, so I can’t fix it before my deadline, but I’ll do it later on.

  3. I already had CoolTerm on my MacBook, so I took around 2 seconds to get all the data from the Particle core shown on my screen. Sooo nice - really missed that.

  4. I could run the demo and in the terminal it was clear that the calculated values worked perfect. I think that my problem is that the calculated values are returned as floats, while the non calculated values are returned as integers and I assigned both valuestypes to an integer variable.

Thanks so much for the help, it has been really useful :+1:

1 Like