Namespaces

Variants
Actions

BayleAdvancedProject-p6a

From Cycling '74 Wiki
(Difference between revisions)
Jump to: navigation, search
m (Ddg@cycling74.com moved page BayleAdvancedProject-p7 to BayleAdvancedProject-p6a: rename)
Line 9: Line 9:
 
Debouncing is a common technique used with digital input initially.
 
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: http://arduino.cc/en/Tutorial/Debounce and you can also find this in my book, obviously.
+
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: [http://arduino.cc/en/Tutorial/Debounce] 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.
+
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.
 
+
It produces that: you push it without releasiDon’t forget the whole schematic. Here it is below.
+
 
+
In this design, I also saved some money by not using 2 Arduino because I only needed to read data (and I could have been able to send some too) using the XBee module on the computer side. In this case, the only XBee explorer interface was enough !
+
 
+
I saw too much projects like that using 2 boards (and even sometimes BIG boards). Please don’t use too much components if you don’t need them!
+
 
+
 
+
+
'''<image here>
+
Basic design
+
'''
+
 
+
 
+
Continuing the firmware description, I created a function named setupAccelerometer() , this is only for a better vision of my code. I could have included the whole content of this function inside setup().
+
 
+
This function define and setup the whole ADXL345 behavior from the Arduino Fio’s firwmare point of view.
+
 
+
We define some threshold in order to track 5 events using one interrupt on the ADXL345 board:
+
 
+
- activity detection
+
 
+
- inactivity detection (which I defined as the lack of activity here)
+
 
+
- tap detection
+
 
+
- double tap detection
+
 
+
- freefall detection
+
 
+
Interrupt concept is quite well explain in my book. Basically, this is a way to interrupt the main flow of the global code and to trigger some action. These are very useful in our case. Why?
+
 
+
One of the best way to understand what they are is the mouse case.
+
 
+
The mouse on our computer (or the trackpad in my case) uses interrupt. Why would our operating system check everytime a day if I touched the track pad ? It would loose time and wouldn’t be really available for anything else (actually, it would, but it would loose time, anyway)
+
 
+
There is another architecture providing a way to handle what is done on the trackpad only when I’m using it. It is called interrupt.
+
 
+
I touch it, then release it, the operating system is informed something happens and is able to handle this then continue what he was doing.
+
 
+
This is a briefly and a bit simple explanation of what an interrupt provide.
+
 
+
In loop(), which is the main part of our firmware and is running continuously at runtime, I first grab interrupt source and put his in interrupts byte type variable.
+
 
+
There are then some conditional piece of code.
+
 
+
In our case, if no event is detected amongst those 5 described above, the main part of our firmware run by looping quietly.
+
 
+
If i let the accelerometer and the arduino Fio (and the battery) falling down, an interrupt is sent and the part of code testing the particular case ADXL345_FREE_FALL is suddenly verified.
+
 
+
If I put something special inside this case, it will only be triggered if the device freely falls.
+
 
+
So, I currently only have some message written to the serial port, i.e to the XBee module. This latter pushes this message to the other XBee connected to the computer and my Max6’s patch is able to grab it :)
+
 
+
I used this code for testing purpose only.
+
 
+
You probably check this part of the code, all commented.
+
 
+
// measuring Accelerometer on 3-axis
+
 
+
+
 
+
//int x,y,z; 
+
 
+
//adxl.readAccel(&x, &y, &z); //read accelerometer values store them in x,y,z
+
 
+
//Serial.print(x);
+
 
+
//Serial.print(y);
+
 
+
//Serial.println(z);
+
 
+
If we uncomment the 4 last rows, at each loop() execution, we read each value of the acceleration measured by the ADC (Indeed, an Analog to Digital Converter samples values measured by the sensor component) and we store them in some variable as integer.
+
 
+
Then, we are writing them to the serial for sending them, in fine, to Max6’s patch.
+
 
+
This is done at each turn.
+
 
+
Because I only wanted to track a fast movement, I decided to use only accelerometer values and put a small and cheap software filter also called debouncer.
+
 
+
Let’s check how I handled that.
+
 
+
ng 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.
 
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()
+
* ''Here is the pseudo code involving my filter in loop()''
 
+
* ''I read x acceleration value.''
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.''
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.
+
* ''Store the current value to be able to keep it to be compared to the next one.''
 
+
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.
 
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.
  
 +
<pre>
 
#include <Wire.h>
 
#include <Wire.h>
 
 
#include <ADXL345.h>
 
#include <ADXL345.h>
  
Line 117: Line 30:
  
 
int currentState;
 
int currentState;
 
 
long lastDebounceTime = 0;    // init the debounce
 
long lastDebounceTime = 0;    // init the debounce
 
 
long debounceDelay = 120;      // debounce delay for filtering
 
long debounceDelay = 120;      // debounce delay for filtering
 
 
int accelerationThreshold = 170;  // acceleration threshold to trigger a message
 
int accelerationThreshold = 170;  // acceleration threshold to trigger a message
 
 
boolean trigger = false;
 
boolean trigger = false;
  
 
void setup(){
 
void setup(){
 
 
  // init the serial communication between the Arduino Fio and XBee module
 
  // init the serial communication between the Arduino Fio and XBee module
 
 
  Serial.begin(57600);
 
  Serial.begin(57600);
 
 
  // accelerometer setup
 
  // accelerometer setup
 
 
  adxl.powerOn();
 
  adxl.powerOn();
 
 
}
 
}
  
 
void loop(){
 
void loop(){
 
 
  // measuring Accelerometer on 3-axis
 
  // measuring Accelerometer on 3-axis
 
 
  int x,y,z;   
 
  int x,y,z;   
 
 
  adxl.readAccel(&x, &y, &z); //read the accelerometer values and store them in 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 a threshold is reached
 
 
  if ( abs(abs(currentState) - abs(x)) > accelerationThreshold )   
 
  if ( abs(abs(currentState) - abs(x)) > accelerationThreshold )   
 
 
  {
 
  {
 
 
   // reset timer
 
   // reset timer
 
 
   lastDebounceTime = millis();
 
   lastDebounceTime = millis();
 
 
  // notify the program to fire a message at some point     
 
  // notify the program to fire a message at some point     
 
 
   trigger = true;                             
 
   trigger = true;                             
 
 
  }
 
  }
  
 
  // if the debouncer time is bigger than our delay
 
  // if the debouncer time is bigger than our delay
 
 
  if ((millis() - lastDebounceTime) > debounceDelay) {
 
  if ((millis() - lastDebounceTime) > debounceDelay) {
 
 
    
 
    
 
 
   // if the program has been notified to send something
 
   // if the program has been notified to send something
 
 
   if (trigger) {
 
   if (trigger) {
 
 
      
 
      
 
 
     // send the message to XBee and in fine to Max6
 
     // send the message to XBee and in fine to Max6
 
 
     Serial.println("movement");
 
     Serial.println("movement");
 
 
      
 
      
 
 
     // notify the program to not send something til next detection
 
     // notify the program to not send something til next detection
 
 
     trigger=false;
 
     trigger=false;
 
 
   }
 
   }
 
 
  }
 
  }
 
 
   
 
   
 
 
  // store the current state for next turn comparison
 
  // store the current state for next turn comparison
 
 
  currentState = x;
 
  currentState = x;
 
 
}
 
}
 +
</pre>
  
The code is quite explicitely commented and fits with the previously written pseudo-code.
+
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 ?
 
+
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.
 
I tested. This is the only way. You can analyze, calculate, at some point you have to make.
Line 210: Line 83:
 
For accelerationThreshold, I tried multiple values by replacing the whole loop by:
 
For accelerationThreshold, I tried multiple values by replacing the whole loop by:
  
 +
<pre>
 
void loop(){
 
void loop(){
 
 
  // measuring Accelerometer on 3-axis
 
  // measuring Accelerometer on 3-axis
 
 
  int x,y,z;   
 
  int x,y,z;   
 
 
  adxl.readAccel(&x, &y, &z); //read the accelerometer values and store them in 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 )  {
  if ( abs(abs(currentState) - abs(x)) > accelerationThreshold )
+
    Serial.println("movement");  
 
+
}
  {
+
 
+
Serial.println("movement");
+
 
+
}
+
 
+
 
  currentState = x;
 
  currentState = x;
 
 
}
 
}
 +
</pre>
  
 
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.
 
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.
+
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.
 
+
If there are 2 or 3, that is fine.
+
 
+
Then I found these values and I kept them.
+
 
+
  
 
So I achieved it.
 
So I achieved it.
Line 245: Line 105:
 
In the final release, I plugged my data source (coming from the device) to Openframeworks which can now react according to device’s movements.
 
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 th whole work there quite soon:
+
Keep connected to my website and my blog especially, I’ll post the whole work there quite soon:
  
http://julienbayle.net
+
[http://julienbayle.net]
  
 
I’m inviting you to follow me on twitter, facebook and everywhere else.
 
I’m inviting you to follow me on twitter, facebook and everywhere else.
  
 +
[[File:jb-arduino-TheWholeStuff.jpg]]
 +
'''The real big picture of everything working fine'''
  
The real big picture of everything working fine
+
[[BayleAdvancedProject-p5|Previous: Data Management]] --- [[BayleAdvancedProject-p7a|Conclusion]]
  
 
[[Category: Bayle Advanced Project]]
 
[[Category: Bayle Advanced Project]]

Revision as of 05:48, 12 June 2013

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:

[2]

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 --- Conclusion