narrowing fidelity for MMA8451 accelerometer

Hi all,

I have developed a necklace that senses the rise and fall of your chest as you breathe using the MMA8451 digital accelerometer, and outputs the information into a responsive fading light. All movement at the moment is sensed on the x-axis.

It works with the code that I have so far, however I am trying to improve the fidelity so that the light responds to a very small window of movement. It is currently responding to an arc movement of about 2 inches, but I would like to minimize it to 1" or even 1/2".

I’m not sure how to do this. I’ve coded it by watching the x-axis movements in the serial monitor and setting the parameters that way, but as I narrow the parameters it doesn’t seem to respond as well as when they are more open. My experience with coding Arduino is purely hacking together and modifying example code / existing code from projects with similar actions, so my ability to be creative is limited. Any help or advice would be greatly appreciated.

*note that there is a “guide” LED as well in the code, and that is unrelated to the problem (I think). This is an LED that fades in and out at a constant rate. I am having a separate issue coding that fade to hold at 255 and 16 for a second and then resuming the fade in/out process, but this is a less important issue.

**using millis

#include <Wire.h>
#include <Adafruit_MMA8451.h>
#include <Adafruit_Sensor.h>
Adafruit_MMA8451 mma = Adafruit_MMA8451();

//milli code
// each "event" (LED) gets their own tracking variable
unsigned long previousMillisLED3=0;
unsigned long previousMillisLED9=0;

// different intervals for each LED
int intervalLED3 = 100; //accellerometer output
int intervalLED9 = 60; // guide output


// determine if LED is to fade in or out
boolean LEDrun = false;

// Accelerometer Constants

const int analogOutPin = 3; // Analog output pin that the LED is attached to
int led=3;              //led at pin 3=
int ledValue;           //value of led
int ledFadeAmount = 5;  //value when led is fading

// Guide Constants
int ledPin = 9;   
int fadeValue = 0; // guidefade

//#define ondelay 30
//#define offdelay 60
 
void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
  
  pinMode(led, OUTPUT);                //led specified as output
  Serial.begin(2400);                   //starting serial at 2400 baud
  mma.begin();                          //initialize accel board

  mma.setRange(MMA8451_RANGE_2_G);

  mma.read();  
  sensors_event_t event;                //collect data 
}

void ledFadeIn(){                     //function of fade from 16 to 255

  sensors_event_t event;              //collect data
  mma.getEvent(&event);               // read dataw
  


  //   Read the 'raw' data in 14-bit counts

  if (event.acceleration.x > 0.00 | event.acceleration.x < -10.50){  //if x position is greater than 0 or x is smaller than -10.00 
    ledValue = ledValue + ledFadeAmount;                              //set led value to the sum of led value and fade amount
    if(ledValue > 255)                                                //if led value is greather than 255
     ledValue = 255;                                                  //set led value to 255. Stops looping between led value 16 and 255. Thanks PaulS!
    analogWrite(led, ledValue);                                       //analog write of led value to led (pin 9)
    //delay(1000);                                                        //delay of 30 ms then start the ledfadein again
    }

}

void ledFadeOut(){                    //function of fade from 255 to 16

  sensors_event_t event;              //collect data 
  mma.getEvent(&event);               // read data 

  if (event.acceleration.x < 0.00 | event.acceleration.x > -10.50){  //if x position is smaller than 0 or x is larger than -10.00
    ledValue = ledValue - ledFadeAmount;                              //set led value to the sum of led value minus the fade amount
    if(ledValue < 16)                                                 //if led value is smaller than 255
      ledValue = 16;                                                  //set led value to 16. Stops looping between led value 255 and 16. Thanks PaulS!
    analogWrite(led, ledValue);                                       //analog write of led value to led (pin 9)
    //delay(1000);                                                        //delay of 30 ms then start the ledfadeout again
    } 
    
}

void loop() {

//BREATH CODE
    unsigned long currentMillis = millis();
   
   if ((unsigned long)(currentMillis - previousMillisLED3) >= intervalLED3) {
   sensors_event_t event;              //collect data
  mma.getEvent(&event);
  
  //float pos = event.acceleration.x;   //test purpose for determining position of x. Future use.
  Serial.println(ledValue);           //print value of led in the Serial Monitor

  if (event.acceleration.x > 0.00 | event.acceleration.x < -10.50)    //if x position is greater than 0 or x is smaller than -10.00
    ledFadeIn();                                                      //goto the ledFadeIn function
  else                                                                 
    ledFadeOut();                                                      //goto the ledFadeIn function
  
        }

  // print the results to the Serial Monitor:
//  Serial.print("sensor = ");
//  Serial.print(sensorValue);
//  Serial.print("\t output = ");
//  Serial.println(outputValue);
//Serial.print("MillisX "); Serial.print(currentMillis); Serial.println("\t");
// Serial.print("prevMillisX "); Serial.print(previousMillisLED3); Serial.println("\t");

//GUIDE CODE [from fading] 
// fade in from min to max in increments of 5 points:
   if ((unsigned long)(currentMillis - previousMillisLED9) >= intervalLED9) {
    if (LEDrun == false) {
      fadeValue = fadeValue + 5;
      analogWrite(ledPin, fadeValue);
      if (fadeValue == 255) {
        LEDrun = !LEDrun;
      }
      }
    if (LEDrun == true) {
      fadeValue = fadeValue - 5;
      analogWrite(ledPin, fadeValue);
      if (fadeValue == 0) {
        LEDrun = !LEDrun;
      }
      }
    previousMillisLED9 = currentMillis;
    }
}

The logical OR operator is ‘||’ not ‘|’. You are doing a binary or’ing of the two values and if that result happens to be non-zero, you if() statement is true.

Also, why are you reading the accelerometer in the main loop() and then again in the fadein() and fadeout(). It would seem more logical to just read it in the main loop() and then determine if you want to fade in or fade out and call the function. Or you could just call a fade() function which determines which way it should be going (up or down).

You also were not updating previousMillisLED3 with the currentMillis

#include <Wire.h>
#include <Adafruit_MMA8451.h>
#include <Adafruit_Sensor.h>
Adafruit_MMA8451 mma = Adafruit_MMA8451();

//milli code
// each "event" (LED) gets their own tracking variable
unsigned long previousMillisLED3 = 0;
unsigned long previousMillisLED9 = 0;

// different intervals for each LED
int intervalLED3 = 100; //accellerometer output
int intervalLED9 = 60; // guide output


// determine if LED is to fade in or out
boolean LEDrun = false;

// Accelerometer Constants

const int analogOutPin = 3; // Analog output pin that the LED is attached to
int led = 3;            //led at pin 3=
int ledValue;           //value of led
int ledFadeAmount = 5;  //value when led is fading

// Guide Constants
int ledPin = 9;
int fadeValue = 0; // guidefade

//#define ondelay 30
//#define offdelay 60

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);

  pinMode(led, OUTPUT);                //led specified as output
  Serial.begin(2400);                   //starting serial at 2400 baud
  mma.begin();                          //initialize accel board

  mma.setRange(MMA8451_RANGE_2_G);

  //mma.read();
  //  sensors_event_t event;                //collect data
}

void ledFadeIn() {                    //function of fade from 16 to 255

  ledValue += ledFadeAmount;                              //set led value to the sum of led value and fade amount
  if (ledValue > 255) {                                               //if led value is greather than 255
    ledValue = 255;                                                  //set led value to 255. Stops looping between led value 16 and 255. Thanks PaulS!
  }
  analogWrite(led, ledValue);                                       //analog write of led value to led (pin 9)
  //delay(1000);                                                        //delay of 30 ms then start the ledfadein again
}

void ledFadeOut() {                   //function of fade from 255 to 16

  ledValue -= ledFadeAmount;                              //set led value to the sum of led value minus the fade amount
  if (ledValue < 16) {                                               //if led value is smaller than 255
    ledValue = 16;                                                  //set led value to 16. Stops looping between led value 255 and 16. Thanks PaulS!
  }
  analogWrite(led, ledValue);                                       //analog write of led value to led (pin 9)
  //delay(1000);                                                        //delay of 30 ms then start the ledfadeout again
}

void loop() {

  //BREATH CODE
  unsigned long currentMillis = millis();
  sensors_event_t event;              //collect data

  if (currentMillis - previousMillisLED3 >= intervalLED3) {
    mma.getEvent(&event);

    //float pos = event.acceleration.x;   //test purpose for determining position of x. Future use.
    Serial.println(ledValue);           //print value of led in the Serial Monitor

    if (event.acceleration.x > 0.00 || event.acceleration.x < -10.50)    //if x position is greater than 0 or x is smaller than -10.00
      ledFadeIn();                                                      //goto the ledFadeIn function
    else
      ledFadeOut();                                                      //goto the ledFadeIn function
    previousMillisLED3 = currentMillis;
  }

  // print the results to the Serial Monitor:
  //  Serial.print("sensor = ");
  //  Serial.print(sensorValue);
  //  Serial.print("\t output = ");
  //  Serial.println(outputValue);
  //Serial.print("MillisX "); Serial.print(currentMillis); Serial.println("\t");
  // Serial.print("prevMillisX "); Serial.print(previousMillisLED3); Serial.println("\t");

  //GUIDE CODE [from fading]
  // fade in from min to max in increments of 5 points:
  if (currentMillis - previousMillisLED9 >= intervalLED9) {
    if (LEDrun == false) {
      fadeValue += 5;
    } else {
      fadeValue -= 5;
    }
    fadeValue = constrain( fadeValue, 0, 255 ); // keep it in range
    analogWrite(ledPin, fadeValue);
    if (fadeValue == 255 || fadeValue == 0) {
      LEDrun = !LEDrun;
    }
    previousMillisLED9 = currentMillis;
  }
}