Question abount Arduino gesture sensor

Hello,

I am a beginner in Arduinos and I hope someone can help me out.

I have a Sparkfun Gesture Sensor which can read movement (left, right, up and down). I want to create a project, something like this:

Rule1 - When the sensor detects 3 "left" moves within 5 seconds, it will set LED1 to high Rule2 - When the sensor detects 2 "right" moves within 5 seconds, it will set LED2 to high Rule3 - When the sensor detects 2 "up" and then 2 "down" moves within 5 seconds, it will set LED3 to high

I also want that Rule 2 will become available only when Rule 1 is finished, and rules 3 will only become available when Rule 2 is finished.

In the example code with this sensor I see switch/ case statements, but I really don't know how I can use these for my above wishes ;) I am not sure if this is possible but I hope someone can push me in the right direction.

Thanks a lot! Mark

Make a circular buffer with each gesture stored as it is made along with a time stamp from the millis counter. Then look at he buffer to see if any of your conditions have been met.

Hi Grumpy_Mike,

Thanks for the answer. Can you help me along with circular buffers? And how te store the gesture?

For now I just played a little with some sensor, and never heard of circular buffers. Are there any manuals online to help me out?

Can you help me along with circular buffers?

Google is your friend https://en.wikipedia.org/wiki/Circular_buffer

And how te store the gesture?

Your sensor gives you results in the form of numbers. Store those numbers in memory as a variable.

I bought the Sparkfun gestore sensor, this one: https://www.sparkfun.com/products/12787

I uploaded the code to my arduino and tested it via the serial port. Al the 6 movements (left, right, far, near, up and down) are recognized and working. When I open the serial port, I see the corresponding lines...right, left, far, near, up and down. So far, so good.

But now I want to make my own movement, for example left, left, right. As I understand well, I have to record and store this gesture, so I need the number which the sensor gives me when I swipe left, left, right. I have no idea how I should do that....? Is this even possible with this sensor? Because I uploaded the sparkfun example, and the code is working with a switch, with cases.

Maybe this is to complex for a beginner but I definitely want to learn this.

Please read this:-
How to use this forum
It will help you ask a question.

Post the code you want help with correctly. The link to the example code on the SparkFun page is broken for me.

Below the code,
In this code a switch is made with 6 cases…
I am wondering how I can change the cases, for example:
case DIR_LEFT:
Serial.println(“LEFT”);
break;

I want to change that to:
case DIR_LEFT, DIR_RIGHT, DIR_LEFT: (so first a left swipe, then a right swipe, then a left swipe)
Serial.println(“LEFT, RIGHT, LEFT”);
break;

#include <Wire.h>
#include <SparkFun_APDS9960.h>

// Pins
#define APDS9960_INT    2 // Needs to be an interrupt pin

// Constants

// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;

void setup() {

 // Set interrupt pin as input
 pinMode(APDS9960_INT, INPUT);

 // Initialize Serial port
 Serial.begin(9600);
 Serial.println();
 Serial.println(F("--------------------------------"));
 Serial.println(F("SparkFun APDS-9960 - GestureTest"));
 Serial.println(F("--------------------------------"));
 
 // Initialize interrupt service routine
 attachInterrupt(0, interruptRoutine, FALLING);

 // Initialize APDS-9960 (configure I2C and initial values)
 if ( apds.init() ) {
   Serial.println(F("APDS-9960 initialization complete"));
 } else {
   Serial.println(F("Something went wrong during APDS-9960 init!"));
 }
 
 // Start running the APDS-9960 gesture sensor engine
 if ( apds.enableGestureSensor(true) ) {
   Serial.println(F("Gesture sensor is now running"));
 } else {
   Serial.println(F("Something went wrong during gesture sensor init!"));
 }
}

void loop() {
 if( isr_flag == 1 ) {
   detachInterrupt(0);
   handleGesture();
   isr_flag = 0;
   attachInterrupt(0, interruptRoutine, FALLING);
 }
}

void interruptRoutine() {
 isr_flag = 1;
}

void handleGesture() {
   if ( apds.isGestureAvailable() ) {
   switch ( apds.readGesture() ) {
     case DIR_UP:
       Serial.println("UP");
       break;
     case DIR_DOWN:
       Serial.println("DOWN");
       break;
     case DIR_LEFT:
       Serial.println("LEFT");
       break;
     case DIR_RIGHT:
       Serial.println("RIGHT");
       break;
     case DIR_NEAR:
       Serial.println("NEAR");
       break;
     case DIR_FAR:
       Serial.println("FAR");
       break;
     default:
       Serial.println("NONE");
   }
 }
}

So did you read How to use this forum, the answer is if you did then you did not pay attention to what you read. Read the bit about posting code. If you can't be bothered to read the rules why should I be bothered to help you?

Edit that last post of yours and add the code tags.

The call apds.readGesture() reads a number which is the gesture if there is a gesture to be read. The call apds.isGestureAvailable() tells you if there is one to read.

This number is what you must store in an array, then you look at the last 3 values in the array to see if you have these numbers. The variables DIR_UP, DIR_DOWN and so on contain the numbers corresponding to each gesture.

My apologies, I changed my previous post with the code tags.

So if I understand well, I first have to find out which numbers correspondents with the 6 gestures. I have done this via:

void handleGesture() {
    if ( apds.isGestureAvailable() ) {
    switch ( apds.readGesture() ) {
      case DIR_UP:
        Serial.print ("UP Decimaal is...   ");
        Serial.println(DIR_UP,DEC);
        break;
      case DIR_DOWN:
        Serial.print ("DOWN Decimaal is...   ");
        Serial.println(DIR_DOWN,DEC);
         break;
      case DIR_LEFT:
        Serial.print ("LEFT Decimaal is...   ");
        Serial.println(DIR_LEFT,DEC);
        break;
      case DIR_RIGHT:
       Serial.print ("RIGHT Decimaal is...   ");
        Serial.println(DIR_RIGHT,DEC);
        break;
      case DIR_NEAR:
        Serial.print ("NEAR Decimaal is...   ");
        Serial.println(DIR_NEAR,DEC);
        break;
      case DIR_FAR:
        Serial.print ("FAR Decimaal is...   ");
        Serial.println(DIR_FAR,DEC);
        break;
      default:
        Serial.println("NONE");

The outcome is: DIR_LEFT = 1 DIR_RIGHT = 2 DIR_UP = 3 DIR_DOWN = 4 DIR_NEAR = 5 DIR_FAR = 6

Have I done this correct?

Then I suppose I have to create this kind of array: int myArray[6] = {1,2,3,4,5,6};

Have I done this correct?

Looks right.

Then I suppose I have to create this kind of array: int myArray[6] = {1,2,3,4,5,6};

Well just int myArray[6] will do, you fill it in with numbers you get from your sensor. Remember to implement the filling of it like a circular buffer I told you about before.

I understand the sensor values 1 to 6, which corresponds to Down/Up/Right/Left/Near/Far. I also understand that if I want an action to take place when LEFT, LEFT, RIGHT is measured by the sensor, then I have to tell Arduino to look for value 1,1,2.

But I don't understand the part of Circular buffers/ Arrays. I never worked with it...

I am feeling like I am almost at the end of this project, but this last items (circular buffering and arrays) are really hard for me to understand.

And yes, I searched on my friend google, but still don't understand it. I am not a programmer, but I would really like to finish this project.

Can I please ask you for some more help?

To implement a circular list you need the concept of an input pointer. That is just a variable that points to the next free item in the array. Every time a gesture comes in you store it in the array with the index of the input pointer and then increment the input pointer. When ever you increment the input pointer you check to see it has not exceeded the size of the array ( that is the maximum index value which is one less than the size of the array - called buffer below ) , if it has you set the input pointer back to zero.

The simplest way for your project would be to have three output pointers all separated by one. Each time you increment the input pointer and check for wrap round you do the same for all three output pointers. Then to check the last three gestures you just use the three output pointers. If you start all these pointers off as:-

int out2 = 0, out1= 1, out0 = 2, inPoint = 3;

Then they should all keep the same distance. You can check for a sequence of gestures with something like this:-

if(buffer[out2] == DIR_LEFT && buffer[out1] == DIR_DOWN && buffer[out0] == DIR_FAR ) {
// then do stuff for a left / down / far sequence of gestures.
}

I really appreciate your explanation. Thank you for taking the time.

The problem is that I have never worked with circular lists, input/ output pointers and arrays. So it is impossible for me to understand how this works... Even after reading your answer 10 times and googling around, I still have no idea from what I should do...and what code I have to write (and yes, I know that is my problem, because I haven't got the knowledge of programming)

I am just a newbie to Arduino, and I can write (and understand) codes like the one I have right now, but going much further is a problem because I simply haven't got the knowledge...

So I think I cannot ask you for more help, because my knowledge is to less....what do you think?

The problem is that I have never worked with circular lists, input/ output pointers and arrays. So it is impossible for me to understand how this works.

You don't have to have experience working with something to understand it. I had no experience when I "invented" the technique. Others too interdependently invented it too. You have it easy, I am telling you what to do.

So I think I cannot ask you for more help

Up to you but I am willing to give it a go.

Break down what I told you into bits. Write the three lines of code that increments and wraps round a pointer and then post it here for comment.