Gesture detection using Particle Core and SparkFun Gesture Sensor

@indraastra I understand now.

I thought in the code you posed above you were just pointing out how Sparkfuns library was setup and pointing out how it can block the loop from running.

Are you saying this is your modified code does not block the loop from running? If so is all I need to do copy and paste it into my current sketch?

Thanks for taking the time to help me understand this.

Just prepend the "modifier" volatile to your current declaration of int Isr_flag = 0;

An explanation for what it's good can be found here
Example: Logging and graphing data from your Spark Core using Google - #177 by ScruffR

1 Like

@indraastra, to the contrary. In AUTOMATIC (without SYSTEM_THREAD(ENABLED)) if your code is blocking for more than 10sec the cloud connection will drop out and the Photon will stop executing your sketch until the connection is reestablished.
Hence long running processes should call Particle.process() on a regular basis to keep the cloud alive and the device responsive.
Another thing that can severly hang the device it the I2C bus when not wired correctly.

1 Like

@ScruffR Ah, I should have qualified that with ā€œon startupā€, since @RWB said it wouldnā€™t even connect to the cloud when the sensor was connected. Good to know that even AUTOMATIC mode can be brought down to a grind if things block long enough.

@RWB It seems like Iā€™m not communicating too clearly, so I apologize for confusing the issue. What you should do when you get the new board is just ensure your I2C lines are properly connected like @ScruffR suggests, and then get the examples working like you were already doing. Once you have an example running, try putting some action in your main loop() (print to serial, toggle an LED, whatever) and then see how your gestures affect this action. What I was pointing out is that in the vanilla SparkFun library, every interaction with the gesture sensor will steal time from your main loop. If you expect gestures to be quick, you shouldnā€™t even worry about this.

What motivated our nonblocking modification to the library (which was pretty trivial actually) is that we make use of a hold gesture which triggers after 5 seconds, but we canā€™t afford to be hung for those 5 seconds.

Hope that makes more sense!

2 Likes

@indraastra I received the new gesture sensor and itā€™s working perfectly now :smiley: So I did fry the other one by supplying it 5v :smile:

Iā€™m surprised at how well the gesture sensing works, even under low light itā€™s very accurate.

I also tried the color sensing abilities under not so great lighting and it seemed to work just fine also.

@ScruffR In the color reading mode it supplies RGB values of what color its seeing. I looked on the forum and documentation but didnā€™t find a clear cut way to use the Photonā€™s RGB LED. Iā€™m wanting to send the RGB values from the color sensor to the RGB led on the Photon so it represents the color the sensor is seeing at any time.

Is there a easy way to do this?

1 Like

Look at the docs for the RGB object
https://docs.particle.io/reference/firmware/photon/#rgb

This is also one of the hits when searching (in the ā€œ:mag: Searchā€ field) for RGB in the docs :wink:

@ScruffR Thank you! Itā€™s way easier to do than expected.

I didnā€™t search the documents but I did look over all the categories and didnā€™t find anything that rang a bell but your right I should have used the Search Function :spark:

1 Like

I guess you didnā€™t see it since itā€™s tucked away inside the > Libraries node - with a bunch of other useful libs :wink:

@ScruffR Quick question about using the RGB + Map function.

The Gesture sensor at max brightness is giving these readings:

Iā€™m trying to map this 0 -37889 to 0 - 255 by using this code:

void loop() {
    
RGB.control(true);
  
  // Read the light levels (ambient, red, green, blue)
  if (  !apds.readAmbientLight(ambient_light) ||
        !apds.readRedLight(red_light) ||
        !apds.readGreenLight(green_light) ||
        !apds.readBlueLight(blue_light) ) {
    Serial.println("Error reading light values");
  } else {
    Serial.print("Ambient: ");
    Serial.print(ambient_light);
    Serial.print(" Red: ");
    Serial.print(red_light);
    Serial.print(" Green: ");
    Serial.print(green_light);
    Serial.print(" Blue: ");
    Serial.println(blue_light);
    
    red = map(red_light, 0, 37889, 0, 255);
    green = map(green_light, 0, 37889, 0, 255);
    blue = map(blue_light, 0, 37889, 0, 255);
    
    
    RGB.color(red, green, blue);
  } 

I had to add this code above the Void Loop to get it to compile:

uint16_t red = 0;
uint16_t green = 0;
uint16_t blue = 0;

Here is the whole .ino file.

#define DEBUG
// This #include statement was automatically added by the Particle IDE.
#include "SparkFun_APDS9960.h"

// Interrupt Pin
#define APDS9960_INT    D3

// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint16_t ambient_light = 0;
uint16_t red_light = 0;
uint16_t green_light = 0;
uint16_t blue_light = 0;

uint16_t red = 0;
uint16_t green = 0;
uint16_t blue = 0;

void setup() {
  
  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("SparkFun APDS-9960 - ColorSensor"));
  Serial.println(F("--------------------------------"));
  
  // 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 light sensor (no interrupts)
  if ( apds.enableLightSensor(false) ) {
    Serial.println(F("Light sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during light sensor init!"));
  }
  
  // Wait for initialization and calibration to finish
  delay(500);
}

void loop() {
    
RGB.control(true);
  
  // Read the light levels (ambient, red, green, blue)
  if (  !apds.readAmbientLight(ambient_light) ||
        !apds.readRedLight(red_light) ||
        !apds.readGreenLight(green_light) ||
        !apds.readBlueLight(blue_light) ) {
    Serial.println("Error reading light values");
  } else {
    Serial.print("Ambient: ");
    Serial.print(ambient_light);
    Serial.print(" Red: ");
    Serial.print(red_light);
    Serial.print(" Green: ");
    Serial.print(green_light);
    Serial.print(" Blue: ");
    Serial.println(blue_light);
    
    red = map(red_light, 0, 37889, 0, 255);
    green = map(green_light, 0, 37889, 0, 255);
    blue = map(blue_light, 0, 37889, 0, 255);
    
    
    RGB.color(red, green, blue);
  }
  
  // Wait 1 second before next reading
  delay(1000);
}

The code runs and spits out the color readings over serial just fine but the RGB led just sits there OFF. So Iā€™m pretty sure my mapping setup is not right as far as converting the larger 37,889 max reading down to the 8 bit 0-255 range.

Itā€™s probably something simple but Iā€™m short on time at the moment so I figured i would ask incase itā€™s something that not so simple :smiley:

Just try to print out your mapped values too.

@ScruffR OK, did that and Iā€™m getting zeros.

I changed the numbers where I defined red, green, blue but the serial output for those numbers remain zero so Iā€™m assuming the problem has to do with one of the following:

Defining the red, green, blue values as uint16_t which I would think is fine since it covers up to 65535.

Or my Map function needs to be written differently due the size of the 37889 max sensor output. I did some quick google searching but found nothing helpful so far.

@ScruffR there was nothing wrong after more testing :spark:

It was reading zero because I was inside under low light and because the mapping rang is so large the low light readings fell within the 0-1 mapping range.

The LCD is not showing up so good, itā€™s dim, Iā€™m gonna try increasing the led brightness to see if that helps.

What pin can I use for the interrupt? I have D2 and D3 in use.

Have you seen this?
https://docs.particle.io/reference/firmware/core/#attachinterrupt-
There is a list of what pins can be used for interrupts.

1 Like

Yup so I was able to get it to work on a different Photon without the color OLED display that was connected with MISO. I think I am going to use a non color display with I2C.