This project implements a touchless mouse.
The Bitcraze flow breakout contains an optical flow sensor that is able to sense how things are moving in front of it and a ranging sensor to sense the distance to the nearest object. The flow sensor is essentially an optical mouse sensor fitted with a lens focused to track objects far away.
The touchless mouse can detect that a hand is approaching and detect how it is moving, the movements are translated into mouse movements by an Arduino.
By using an Arduino Leonardo (or any other USB device-compatible Arduino) this project is seen as a regular mouse so it works out of the box on any computer.
Hardware setupThe flow deck is connected to two busses of the Arduino:
- The PMW3901 optical tracking sensor is connected to the SPI bus
- The VL53 ranging sensor is connected to the i2C bus
We also need to power the flow deck, this is done by connecting it to the 5V and GND pin of the Arduino. Note that on Arduino Leonardo, the SPI bus is only accessible on the ICSP pin header.
Required libraryThe two sensors require libraries to work. Using the Arduino IDE Library manager we load the two libraries:
- VL53L0x for the ranging sensor
- Bitcraze_pmw3901 for the optical flow sensor
The code is adapted from the Flow breakout getting started, we have simply added the mouse part:
#include "Bitcraze_PMW3901.h"
#include <Wire.h>
#include <VL53L0X.h>
#include <Mouse.h>
VL53L0X rangeSensor;
// Using digital pin 10 for chip select
Bitcraze_PMW3901 flow(10);
void setup() {
Serial.begin(9600);
// Initialize flow sensor
if (!flow.begin()) {
Serial.println("Initialization of the flow sensor failed");
while(1) { }
}
// Initialize range sensor
Wire.begin();
rangeSensor.init();
rangeSensor.setTimeout(500);
// Initialize Mouse
Mouse.begin();
}
int16_t deltaX,deltaY;
void loop() {
// Get motion count since last call
flow.readMotionCount(&deltaX, &deltaY);
// Get single range measurement
float range = rangeSensor.readRangeSingleMillimeters();
// Send motion as mouse movement when the hand is between 80 and 200mm
if (range < 200 && range > 80) {
Mouse.move(deltaX, -deltaY, 0);
}
// Press the left mouse button when the hand is bellow 50mm
if (range < 50) {
Mouse.press();
} else {
Mouse.release();
}
}
When an object is detected by the ranging sensor, at a distance between 80mm and 200mm, the movement measured by the flow sensor is sent as mouse movement. When the detected object is below 50mm we press the mouse button. The reason to keep 50mm to 80mm without motion detection and click is to make sure that the mouse is clicking without any movement: without this gap the mouse was always moving a bit when the hand goes down to click.
DemoNow for the mandatory video:
Comments