Close

Glove 3- calibration and clicking

A project log for Wearable Computer Rig & Powerglove Mouse

Inspired by Martin Magnusson's wearable computer, I've refined the display, and modified a Nintendo Powerglove to be the complete interface!

scott-sScott S 05/15/2015 at 02:550 Comments

To start converting finger movement into mouse clicks, I set up some rough code to define a threshold of approximate finger joint bending that beyond which, would translate into a mouse click. Make sure to have the serial monitor open while running the code.

https://github.com/slicer364/powerglove-mouse/blob/master/powerglove_calibrate

Now, the values taken from bend sensors in the fingers are between 0 and 1023, as there are 1023 discrete steps that the A/D converter turns the 0-5 volts into. As the bend sensors in the fingers are bent more, the resistance increases, and the step value decreases with the voltage.

The code above asks the user to keep all of their fingers open for a few seconds, and then close them to get readings from each finger at each position.

The average, "avg" is then taken between those values, and will be later used as a threshold to define "mouse clicks". As the properties of the bend sensors tend to differ from sensor to sensor, you will have to get these values yourself.

My threshold results from the calibration code:

thumb: 45

index: 27

middle: 43

ring: 51

----------------------------------------

Now that we have the finger threshold values, let's actually use them as mouse clicks!

https://github.com/slicer364/powerglove-mouse/blob/master/powerglove_debounced_clicks

Please note- my code above will only work on an Arduino Leonardo or Arduino Micro as they have the ATmega32u4 microcontroller, IT WILL NOT WORK ON A STANDARD ARDUINO. This is because the ATmega32u4 appears to a connected computer as a keyboard and mouse, not just a USB port.

Now, I'll be honest, I am skipping a whole lot of my trial and error code, and efforts learning on my part about debouncing momentary switches/buttons. When I initially wrote the code to translate finger movements into mouse clicks, I had never heard of debouncing. Simply put, it is a methodology to only recognize input "if you mean it", and ignore noise.

Without debouncing, if I quickly bent a finger to click, the code would interpret a really large number of clicks in that small amount of time that my finger was bent. The only good thing that I discovered with a lack of debouncing that is that if I had opened 300 of the same window on my computer, I could quickly close all 300. Yay.

Please see the following tutorial link for more information:

http://www.arduino.cc/en/tutorial/debounce

As a side note, I initially used the mouse.click() command, but then quickly realized that only mouse.press() would allow holding down the mouse- for click&drag input.

http://www.arduino.cc/en/Reference/MouseClick

http://www.arduino.cc/en/Reference/MousePress

I've clumped together all of the pointer finger code below to make it easier to follow.

void loop() {
  fingbool2= (analogRead(FingerV2))/avg2;
   /*if the finger reading is larger than avg reading value (threshold) for that finger, 
   then the fraction is greater than 1, and the boolean fingbool BECOMES 1, and is true
   if the finger reading is smaller than the avg reading value (threshold)  for that finger, 
   then the fraction is less than 1, and the boolean fingbool BECOMES 0, and is false
   */
                         

  /* check to see if you just pressed the button 
  (i.e. the input went from 0 to 1),  and you've waited 
  long enough since the last press to ignore any noise: 
   If the switch changed, due to noise or pressing: */
  if (fingbool2 != lastfingerstate2) {
    fingerlastDebounceTime2 = millis();  // reset the debouncing timer
  } 


  //pointer finger = left click
    // whatever the current reading is, it's been there for longer
    // than the debounce delay,take it as the actual current state:
if ((millis() - fingerlastDebounceTime2) > fingerdebounceDelay) {

   // if the button state has changed:
   if (fingbool2 != fingerstate2) {
      fingerstate2 = fingbool2;

    if (fingbool2 == 0) {
         Mouse.press(MOUSE_LEFT);   
      }

      else  {
       Mouse.release(MOUSE_LEFT);
      }
    }
  }

  
lastfingerstate2 = fingbool2; //store the current values for the next loop of the code
}

Discussions