2

I really need some help. I have absolutely no experience with accelerometers and have a project that would work great if I could integrate one into it. I am not hinting to have some write me a code, just get me looking in the right direction.

My code (below) was written to work with 2 buttons and an LED. Basically, its nothing but a reaction timer using an RGB liquid crystal display.

Sequence of events...

  1. power on
  2. displays “push button to start”
  3. when panel button is pushed, the loop begins by randomly selecting a “FIRE” time when “fire” button is pressed, it echoes the time it took
  4. my FOR statement, allows it to loop three times before returning to the begin.

This was all what I set out to accomplish, originally. My sister has been using it at a retirement home for some of the patients to play with. Lately she asked if instead of a “fire” button it could be programmed to simply, tap the whole unit, push the unit, or even use a tether of some sort. I figured an accelerometer was the ticket.

I purchased an ADXL345, I tried playing with several sketches from GitHub. What I find is the accelerometer is ALWAYS giving out information. I thought it would actually “rest” when not being physically moved.

How can I use my ADXL345 to be at complete standstill, until it is “moved,” that it would activate a WHILE statement???

#include <Wire.h>
#include <LiquidCrystal.h>
#include <SparkFun_ADXL345.h>

ADXL345 adxl = ADXL345();
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int lcdRedPWMPin = 17;
int lcdGreenPWMPin = 16;
int lcdBluePWMPin = 15;

void setDisplayRGB(int r, int g, int b)

{
  analogWrite(lcdRedPWMPin,   r);
  analogWrite(lcdGreenPWMPin, g);
  analogWrite(lcdBluePWMPin,  b);
}

void setup()
{
  lcd.begin(16, 2);
  lcd.clear();
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  adxl.powerOn();
  adxl.setRangeSetting(2);    // Accepted values are 2g, 4g, 8g or 16g
  //adxl.setSpiBit(0);
  adxl.setActivityXYZ(1, 1, 1);
  adxl.setActivityThreshold(70);
  adxl.ActivityINT(1);
  pinMode(13, INPUT);
  digitalWrite(13, LOW);

  pinMode(9, INPUT); //panel button
  digitalWrite(9, HIGH);

  pinMode(8, INPUT); //FIRE button
  digitalWrite(8, HIGH);

  pinMode(10, OUTPUT); //FIRE led
  digitalWrite(10, LOW);

  // int    fireButton = digitalRead(8);
  int    panelButton = digitalRead(9);
  lcd.clear();
  setDisplayRGB(100, 100, 75);
  lcd.setCursor(1, 0);
  lcd.print("Let's see what");
  lcd.setCursor(1, 1);
  lcd.print("what you got!");
  delay(2000);
}
double timeToFire = 0; //time it took to (fire-trigger)
double fireTimerStarts = millis(); //fire (timer starts)
double triggerTimerStops ; //trigger (timer stops)
int ran; //random


void loop()
{

  int x, y, z;
  adxl.readAccel(&x, &y, &z);
  // byte interrupts = adxl.getInterruptSource();
  int average = (x + y + z);

  while (digitalRead(9) == HIGH)
  {
    lcd.clear();
    setDisplayRGB(40, 200, 75); //purple 40,200,75
    lcd.setCursor(0, 0);
    lcd.print("Press Button");
    lcd.setCursor(0, 1);
    lcd.print("to Start ...");
    delay(50);
  }
  for (int panelButton = 0; panelButton < 3; panelButton++)

  {
    lcd.clear();
    lcd.setCursor(0, 0);
    setDisplayRGB(255, 255, 0); //blue
    lcd.print("  ---READY---");
    delay((int)random(1000, 5000));
    {
      ran = random(1, 3);
      Serial.println(ran);
      if ( ran == 1)
        lcd.clear();
      lcd.setCursor(0, 0);
      setDisplayRGB( 0, 155, 155 );  //red
      lcd.print("     <FIRE>   ");
      lcd.setCursor(0, 1);
      lcd.print(average);
      fireTimerStarts = millis();
      digitalWrite(10, HIGH);

      // if(adxl.triggered>activityThreshold)

      while (adxl.triggered(13, HIGH))

        //while (digitalRead(8) == HIGH)
      {
        triggerTimerStops = millis();
      }
      digitalWrite (13, LOW);
      digitalWrite(10, LOW);

      setDisplayRGB(100, 100, 225); //green
    }
    timeToFire = (triggerTimerStops - fireTimerStarts) / 1000;

    delay(500);
    {
      lcd.clear();
      setDisplayRGB(0, 255, 0);
      lcd.setCursor(0, 1);
      lcd.print(timeToFire);
      lcd.setCursor(11, 1);
      lcd.print("Sec's");
      lcd.setCursor(0, 0);
      lcd.print("Your time was ...");
      delay(1500);
    }
  }

}

3 Answers 3

1

An alternative to using an accelerometer is a simple Vibration Sensor Switch. Adafruit has a Fast Vibration Sensor Switch: https://www.adafruit.com/product/1766, Medium Vibration Sensor Switch: https://www.adafruit.com/product/2384 and a Slow Vibration Sensor Switch: https://www.adafruit.com/product/1767, each costing 1 USD.

Edit 1:

If you look for "ADXL345_ACTIVITY" in the SparkFun_ADXL345_Example.ino sketch, there is a comment that says "add code here to do when activity is sensed".

My suggestion is to get the ADXL345 working with this sketch first, then start removing the excess code from it that you don't need. Once you have the bare minimum code required to accomplish your goal, try to integrate that with you current sketch.

There are several "sensitivity adjustments" you can make under the "Configure ADXL345 Settings" section of the code.

1
  • 1
    Honestly VE7JRO, until you posted this response, I didn't know these things even existed. Of course going to the Adafruit website, I didn't know lots of that stuff existed. Your idea would work great, but I am at war with this accelerometer right now and not giving up quite yet.
    – Bender
    Commented Feb 11, 2018 at 0:40
0

I purchased an ADXL345, I tried playing with several sketches from GitHub. What I find is the accelerometer is ALWAYS giving out information. I thought it would actually “rest” when not being physically moved.

The accelerometer reports its current acceleration on each axis at all times, whether that acceleration is changing or not. When at rest and upright, it will report close to 1.0 g on the Z axis; when rotated to some other direction and held steady, the vector magnitude of the accelerations on the three axes will be close to 1.0. The vector magnitude is computed as the square root of the sum of the squares of the elements, so rather than averaging, you'll want to do this:

int x, y, z;
adxl.readAccel(&x, &y, &z);


float mag = sqrt( x*x + y*y + z*z ); 

This mag value should change only slightly if you gently rotate the accelerometer. That baseline value represents 1.0g of acceleration from Earth's gravity.

A rapid motion of the accelerometer will produce some higher or lower value, briefly. Figure out what threshold makes sense for your application and do something like:

if (mag > (BASELINE_GRAVITY * 1.2f))
{
    lcd.setCursor(0, 0);
    lcd.print("You moved!");
}
2
  • Thank-you for your response Russell. What would "BASELINE_GRAVITY" be defined as?
    – Bender
    Commented Feb 11, 2018 at 0:36
  • I wasn't able to determine that from a glance at the documentation -- it's unclear to me what units are returned by the adxl library.. It's whatever mag averages when the accelerometer is stationary. Commented Feb 11, 2018 at 0:38
0

According to the datasheet of adxl345, this chip (so the module) has single-tap, double-tap functionality. As described in the datasheet, you can configure the chip as you want it to operate. The chip has 2 interrupt pins. When it is configured to operate one of the tap modes and senses the tap, it gives an interrupt signal. You can check that signal and process the information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.