I've been working on this for days, and have spent hours googling, but keep coming up short. I would like to detect tap gestures from different directions (left side, right, top, etc) to navigate a menu. I'm using the Adafruit Sense board, which has the LSM6DS33 onboard, via I2C. And the Adafruit library. From what I've read, this is a power chip, and has tap detection built in, & ST.com has a library for it in C, but I haven't seen it implemented in any arduino code.
I'm just self taught in the Arduino Language, so it's all over my head.
But it seems my approach SHOULD work, but it isn't... I am watching for a big change in any of the accel values, and then note that as a tap. I use a time stamp of 100ms for debouncing, and int diff as my difference threshold.
This code kinda works, but not enough to be usable. 5 tap to the top may produce results like 4 top taps, and one right tap... I know my code isn't very good, but here it is. I've tried to trim away anything unneeded for this debugging, and I commented everything. Any help would be appreciated. Thanks.
#include <Adafruit_LSM6DS33.h>
Adafruit_LSM6DS33 lsm6ds33; // accelerometer, gyroscope
float accel_x, accel_y, accel_z;
void setup(void) {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Feather Sense Tap detection Test");
lsm6ds33.begin_I2C();
testsettings(); //I tried changing the accell rate and the range here
}
float dif = 50; //this much difference is detected as a tap
float prevX; //the last accel x reading
float prevY; //the last accel y reading
float prevZ; //the last accel z reading
unsigned long prevTime; //previous time we detected a tap
void loop(void) {
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
lsm6ds33.getEvent(&accel, &gyro, &temp);
accel_x = accel.acceleration.x;
accel_y = accel.acceleration.y;
accel_z = accel.acceleration.z;
float xVal = abs(accel_x - prevX); //difference from last reading, as positive number
float yVal = abs(accel_y - prevY);
float zVal = abs(accel_z - prevZ);
if (millis() - prevTime > 100) { //it hasn't been long enough for a new tap
if (xVal > yVal && xVal > zVal) { //xVal had the most change
if (xVal > dif) { //tap detected
if (accel_x > prevX) {
Serial.print(" RIGHT");
Serial.print("\t");
Serial.print(xVal);
Serial.print("\t");
Serial.print(yVal);
Serial.print("\t");
Serial.print(zVal);
Serial.println();
}
else {
Serial.print(" LEFT");
Serial.print("\t");
Serial.print(xVal);
Serial.print("\t");
Serial.print(yVal);
Serial.print("\t");
Serial.print(zVal);
Serial.println();
}
prevTime = millis(); //a tap was detected
}
}
if (yVal > zVal && yVal > xVal) { //xVal had the most change
if (yVal > dif) { //tap detected
if (accel_y > prevY) {
Serial.print(" TOP");
Serial.print("\t");
Serial.print(xVal);
Serial.print("\t");
Serial.print(yVal);
Serial.print("\t");
Serial.print(zVal);
Serial.println();
}
else {
Serial.print(" BOTTOM");
Serial.print("\t");
Serial.print(xVal);
Serial.print("\t");
Serial.print(yVal);
Serial.print("\t");
Serial.print(zVal);
Serial.println();
}
prevTime = millis(); //a tap was detected
}
}
}
prevX = accel_x;
prevY = accel_y;
prevZ = accel_z;
}
void testsettings() {
//I've tried different combinations of these settings
lsm6ds33.setAccelRange(LSM6DS_ACCEL_RANGE_4_G);
Serial.print("Accelerometer range set to: ");
switch (lsm6ds33.getAccelRange()) {
case LSM6DS_ACCEL_RANGE_2_G:
Serial.println("+-2G");
break;
case LSM6DS_ACCEL_RANGE_4_G:
Serial.println("+-4G");
break;
case LSM6DS_ACCEL_RANGE_8_G:
Serial.println("+-8G");
break;
case LSM6DS_ACCEL_RANGE_16_G:
Serial.println("+-16G");
break;
}
lsm6ds33.setAccelDataRate(LSM6DS_RATE_6_66K_HZ);
Serial.print("Accelerometer data rate set to: ");
switch (lsm6ds33.getAccelDataRate()) {
case LSM6DS_RATE_SHUTDOWN:
Serial.println("0 Hz");
break;
case LSM6DS_RATE_12_5_HZ:
Serial.println("12.5 Hz");
break;
case LSM6DS_RATE_26_HZ:
Serial.println("26 Hz");
break;
case LSM6DS_RATE_52_HZ:
Serial.println("52 Hz");
break;
case LSM6DS_RATE_104_HZ:
Serial.println("104 Hz");
break;
case LSM6DS_RATE_208_HZ:
Serial.println("208 Hz");
break;
case LSM6DS_RATE_416_HZ:
Serial.println("416 Hz");
break;
case LSM6DS_RATE_833_HZ:
Serial.println("833 Hz");
break;
case LSM6DS_RATE_1_66K_HZ:
Serial.println("1.66 KHz");
break;
case LSM6DS_RATE_3_33K_HZ:
Serial.println("3.33 KHz");
break;
case LSM6DS_RATE_6_66K_HZ:
Serial.println("6.66 KHz");
break;
}
//I'm not sure what the following line does
lsm6ds33.configInt1(false, false, true); // accelerometer DRDY on INT1
}