Namespaces

Variants
Actions

BayleAdvancedProject-p6a

From Cycling '74 Wiki
Jump to: navigation, search

Handling fast movement for dedicated purpose

As I decided, I didn’t really need to track all 3 axis value. I tested that by prototyping.

Moving the device fast in any direction alters any of the axis so, I decide to test (and finally use) only the x-axis.

Why use a debouncer?

Debouncing is a common technique used with digital input initially.

Indeed, it basically involves a timer in order to filter mechanical artifacts happening when you push a button and read a digital input value with a microcontroller. Check this article about the debouncing: [1] and you can also find this in my book, obviously.

When you push a button, it bounces. This happens really fast, but you can have jumping (bouncing) values if you measure it continuously. This saves my protodeck in the past and even if you have very good quality buttons/switches, it occurs. It produces that: you push it without releasing it, and the value read should be 1. But it is 1, then 0, then 1 etc... several times, then 1 finally.

If you put a timer involving a right and subtly found delay time during which NO value is read, you can filter (we also used to say smooth) the value read.

Here is the pseudo code involving my filter in loop():

  • I read x acceleration value.
  • If the difference between this current value and the last one (at the previous loop) is bigger than a threshold, reset the timer and say to the program to fire a message on next time.
  • If the delay between the last detection and now is higher than the debouncing delay AND the program has to fire a message then fire the message AND say to the program not to send anything till the next detection occurs.
  • Store the current value to be able to keep it to be compared to the next one.

Here is now ... the code implementing this behavior. I put the whole code and I removed all unuseful parts in order to make it ... simpler & clearer.

#include <Wire.h>
#include <ADXL345.h>

ADXL345 adxl; //variable adxl is an instance of the ADXL345 library

int currentState;
long lastDebounceTime = 0;     // init the debounce
long debounceDelay = 120;      // debounce delay for filtering
int accelerationThreshold = 170;  // acceleration threshold to trigger a message
boolean trigger = false;

void setup(){
 // init the serial communication between the Arduino Fio and XBee module
 Serial.begin(57600);
 // accelerometer setup
 adxl.powerOn();
}

void loop(){
 // measuring Accelerometer on 3-axis
 int x,y,z;  
 adxl.readAccel(&x, &y, &z); //read the accelerometer values and store them in x,y,z
 
 // if a threshold is reached
 if ( abs(abs(currentState) - abs(x)) > accelerationThreshold )  
 {
   // reset timer
   lastDebounceTime = millis();
 // notify the program to fire a message at some point    
   trigger = true;                             
 }

 // if the debouncer time is bigger than our delay
 if ((millis() - lastDebounceTime) > debounceDelay) {
   
   // if the program has been notified to send something
   if (trigger) {
     
     // send the message to XBee and in fine to Max6
     Serial.println("movement");
     
     // notify the program to not send something til next detection
     trigger=false;
   }
 }
 
 // store the current state for next turn comparison
 currentState = x;
}

The code is quite explicitely commented and fits with the previously written pseudo-code. The only thing I want to explain here is the debounceDelay and accelerationThreshold. Indeed, how I found the perfect fitting value ?

I tested. This is the only way. You can analyze, calculate, at some point you have to make.

120 ms make people able to make a big breadth movement.

For accelerationThreshold, I tried multiple values by replacing the whole loop by:

void loop(){
 // measuring Accelerometer on 3-axis
 int x,y,z;  
 adxl.readAccel(&x, &y, &z); //read the accelerometer values and store them in x,y,z
 if ( abs(abs(currentState) - abs(x)) > accelerationThreshold )  {
    Serial.println("movement"); 
 }
 currentState = x;
}

Monitoring values looking at the Max6 patch, I tried some values until, while I was still moving almost permanently the device prototype making my daughter laughing at me very lound, I had only very few triggering while moving.

Ideally, it would send only one message for each movement. If there are 2 or 3, that is fine. Then I found these values and I kept them.

So I achieved it.

It worked.

In the final release, I plugged my data source (coming from the device) to Openframeworks which can now react according to device’s movements.

Keep connected to my website and my blog especially, I’ll post the whole work there quite soon.

I’m inviting you to follow me on twitter, facebook and everywhere else.


jb-arduino-TheWholeStuff.jpg

The real big picture of everything working fine

Previous: Data Management --- Next: Conclusion