Friday, December 8, 2017

Lightmouse

While surfing over the internet I stumbled upon the Leap Motion Controller and I was flabbergasted. It was something that that really amazed me. Controlling your computer with your hands instead of a mouse. I wanted one.

Then I started thinking. Wouldn't it be possible to make something like this by myself. Well not actually tracking the movement of your fingers. That would be to complicated. But tracking the movement of a hand should be possible.

The general idea was that when your hand moves over a surface the place where the hand is, is in the shade and the rest would be in the light. And that is something you can easily measure by using LDR's (Light Dependend Resistors). So I made a simple setup.



I used two small breadboards next to eachother. This makes it possible to put the LDR's on the breadboard at a certain distance. I attached the LDR's to the analog ports of the Arduino Pro Micro.

Mind you: for this project you really need an Arduino Pro Micro as this has a real USB interface and not a USB-serial interface. We will be needing the USB interface for simulating a mouse.

The LDR's have a pull down resistor for more accurate measuring. To calculate which value the pull-down resistor needs in your particular case use the formula described in this article.
If you do not use the right pull-down resistors the setup will not function  as intended and react poorly at your movements.
In my setup I am using 10K resistors because my setup is intended to work in full light. However if you are using this in more ambient circumstances make sure you alter the values of the resistors using the described formula in the formentioned article.

The first tests were done by just reading the values the LDR's would give when I moved my hand above it. And the results were very satisfying.

Now I had to find the right formula for making something usefull out of this.

Let us look at the following simplified setup.





The square represents the total setup and the black dots represent the LDR's.

If I want to go left my hand has to cover LDR A and C.
For going right it has to cover B and D
Up means covering A and B
Going down can be achieved by covering C and D

By covering the individual leds I indicate that I want to go diagonal.

This can be easily represented in a formula.
Think about this.
If I cover LDR A and C they will get less light as LDR B and D.

X direction =  (A+C) - (B +D)

If the outcome is negative I am moving left. If the outcome is positive I am moving right. Remember that the LDR's give a higher value where there is more light.

Y direction = (A+B) - (C+D)

Same drill as the X direction.

The individual leds are even easier.

If the Value of LDR A drops then I am covering the LDR and want to move UP-LEFT.

And this is really all that is to it.

The only thing I need to test is wether I am actually moving my hand above the setup.
That can easily be done by the following test:

  x = ((A+C) -(B+D));
  y = ((A+B )- (C+D));
  axy = (abs(abs(x)-abs(y)));
 
  if ((abs(x)>25) && (abs(y)>25))

Look at this formula. It just tests if the difference between X and Y is bigger as 25 and that indicates that something is going on above the LDR's. I have substituted the formula in my program by using the variables s1 to s3 which represent the analog lines A0 to A3.

Now we only have to tell the Arduino Pro Micro that it has to act as a mouse by the following command:

void setup()
{
  Mouse.begin();
}

And here we get at a more difficult part of the program. Look at the following lines:

  if ((x<0) && ((abs(x))>(abs(y))) && (y>0) && (axy>100))
    {
      //going left
      Mouse.move(-10, 0, 0);
    }


Let's examine it in detail.

 if ((x<0) && ((abs(x))>(abs(y))) && (y>0)

The first part just tests if  X = smaller as 0. If that is true then this means you want to move left.
As a safety measure I also test if the X value is really bigger as the Y value. That indicates that there is indeed less light on the X LDR's.

&& (axy>100))

This last part tests wether there is a significant difference between the X and Y values. That is to make sure it is my hand moving above the LDR's and not just some shade of a cloud passing by.

Just one last thing to do:

Mouse.move(-10, 0, 0);

And that is why you need to use the Arduino Pro Micro.
This command actually moves the mousepointer of your PC (or Raspberry) to the left by 10 pixels. The 0 following the -10 makes sure that the mouse stays on the same line (Y-coordinate( and just the X moves. The second 0 indicates that the scroll wheel of the mouse should do nothing.

So here is the full listing:



/*Light Mouse
  Luc Volders

Decides on which way the mouse will go by checking
which LDR's get light on and which do not

using 4 LDR's put in a square form
top:    A1, A3
bottom: A0, A2
*/


int s1, s2, s3, s4, x ,y, axy;


void setup()
{
  Mouse.begin();
}

void loop() {
  
  s1 = analogRead(A0);
  s2 = analogRead(A1);
  s3 = analogRead(A2);
  s4 = analogRead(A3);

  x=((s3+s4) -(s1+s2));
  y=((s1+s3)-(s4+s2));
  axy = (abs(abs(x)-abs(y)));
  
  if ((abs(x)>25) && (abs(y)>25)) // test for action
  {
  if ((x<0) && ((abs(x))>(abs(y))) && (y>0) && (axy>100))
    {
      //going left
      Mouse.move(-10, 0, 0);
    }
  if (((x>0) && (y>0)) && (axy>100))
    {
      //going right
      Mouse.move(10, 0, 0);
    }
  if (x<0 && y<0 && axy>100)
    {
      //going up
      Mouse.move(0, -10, 0);
    }
  if (x<0 && (abs(x)<abs(y))&& y>0 && axy>100)
    {  
      //going down
       Mouse.move(0, 10, 0);
    }
  // -------------------------------------------------------
  // schuin
  // -------------------------------------------------------
    if (((x<0) && (y<0)) && (axy<100))
    {
     // moving left-up
      Mouse.move(-10, -10, 0);
    }
    if (((x>0) && (y<0)) && (axy<100))
    {
      //moving right-up
      Mouse.move(10, -10, 0);
    }
    if (((x<0) && (y>0)) && (axy<100))
    {
      //moving left-down
      Mouse.move(-10, 10, 0);
    }
    if (((x>0) && (y>0)) && (axy<100))
    {
      //moving right-down
      Mouse.move(10, 10, 0);
    }
  }
  
  delay(50);
}


After I was sure everything worked fine on the breadboard setup I made an experimental setup using a cardboard.


And after thorough testing I sat behind my computer and designed a casing. This was done in Tinkercad. This design proves that Tinkercad is quite capable.








And this is how it looks in real life.



And man does it work !!!!



I am sorry the video is of such a bad quality but it is the best I could do in my crammed man/cave. I had to make the video using one hand and using the other hand to operate the device.

It also works on my Raspberry Pi and using a USB/OTG adapter it also works on an Android device. I tried it on my Phone and on a tablet with great results.

A lot of possibilities come to my mind for this device. Using it as a joystick for games is obvious. How about adapting the hardware and making a remote for a model boat or car. Gesture controlling a Power-point presentation is another option. Use your imagination.

You can as always find all files on my Github repositry.
https://github.com/Lucvolders/Light-Mouse

So try this for yourselves and have fun.
Till next time

Luc Volders