Added Plugin for Gesture Sensor APDS9960 (#409)

* First draft

* Work release

* work release

* Working release

Known BUG: While performing a gesture the reader function blocks rest of ESPEasy processing!!! (Feel free to fix...)
This commit is contained in:
Jochen Krapf
2017-07-05 11:55:12 +02:00
committed by DatuX
parent 9a88269e28
commit c95d04aa6b
13 changed files with 3605 additions and 2 deletions
@@ -0,0 +1,9 @@
License Information
-------------------
The hardware is released under [Creative Commons Share-alike 3.0](http://creativecommons.org/licenses/by-sa/3.0/).
All other code is open source so please feel free to do anything you want with it; you buy me a beer if you use this and we meet someday ([Beerware license](http://en.wikipedia.org/wiki/Beerware)).
@@ -0,0 +1,82 @@
SparkFun APDS9960 RGB and Gesture Sensor Arduino Library
=========================================================
![Avago APDS-9960 Breakout Board - SEN-12787 ](https://cdn.sparkfun.com/r/92-92/assets/parts/9/6/0/3/12787-01.jpg)
[*Avago APDS-9960 Breakout Board (SEN-12787)*](https://www.sparkfun.com/products/12787)
Getting Started
---------------
* Download the Git repository as a ZIP ("Download ZIP" button)
* Unzip
* Copy the entire library directory (APDS-9960_RGB_and_Gesture_Sensor_Arduino_Library
) to \<Arduino installation directory\>/libraries
* Open the Arduino program
* Select File -> Examples -> SparkFun_APDS9960 -> GestureTest
* Plug in your Arduino and APDS-9960 with the following connections
*-OR-*
* Use the library manager
| Arduino Pin | APDS-9960 Board | Function |
|---|---|---|
| 3.3V | VCC | Power |
| GND | GND | Ground |
| A4 | SDA | I2C Data |
| A5 | SCL | I2C Clock |
| 2 | INT | Interrupt |
* Go to Tools -> Board and select your Arduino board
* Go to Tools -> Serial Port and select the COM port of your Arduino board
* Click "Upload"
* Go to Tools -> Serial Monitor
* Ensure the baud rate is set at 9600 baud
* Swipe your hand over the sensor in various directions!
Repository Contents
-------------------
* **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE.
* **/src** - Source files for the library (.cpp, .h).
* **library.properties** - General library properties for the Arduino package manager.
Documentation
--------------
* **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library.
* **[Product Repository](https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor)** - Main repository (including hardware files) for the SparkFun_APDS9960 RGB and Gesture Sensor.
* **[Hookup Guide](https://learn.sparkfun.com/tutorials/apds-9960-rgb-and-gesture-sensor-hookup-guide)** - Basic hookup guide for the sensor.
Products that use this Library
---------------------------------
* [SEN-12787](https://www.sparkfun.com/products/12787)- Avago APDS-9960
Version History
---------------
* [V_1.4.1](https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library/tree/V_1.4.1) - Removing blank files, updating library.properties file.
* [V_1.4.0](https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor_Arduino_Library/tree/V_1.4.0) - Updated to new library structure
* V_1.3.0 - Implemented disableProximitySensor(). Thanks to jmg5150 for catching that!
* V_1.2.0 - Added pinMode line to GestureTest demo to fix interrupt bug with some Arduinos
* V_1.1.0 - Updated GestureTest demo to not freeze with fast swipes
* V_1.0.0: Initial release
* Ambient and RGB light sensing implemented
* Ambient light interrupts working
* Proximity sensing implemented
* Proximity interrupts working
* Gesture (UP, DOWN, LEFT, RIGHT, NEAR, FAR) sensing implemented
License Information
-------------------
This product is _**open source**_!
The **code** is beerware; if you see me (or any other SparkFun employee) at the local, and you've found our code helpful, please buy us a round!
Please use, reuse, and modify these files as you see fit. Please maintain attribution to SparkFun Electronics and release anything derivative under the same license.
Distributed as-is; no warranty is given.
- Your friends at SparkFun.
@@ -0,0 +1,161 @@
/****************************************************************
AmbientLightInterrupt.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
October 24, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the ambient light interrupt abilities of the APDS-9960.
Configures the APDS-9960 over I2C and waits for an external
interrupt based on high or low light conditions. Try covering
the sensor with your hand or bringing the sensor close to a
bright light source. You might need to adjust the LIGHT_INT_HIGH
and LIGHT_INT_LOW values to get the interrupt to work correctly.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
2 INT Interrupt
13 - LED
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
// Pins
#define APDS9960_INT 2 // Needs to be an interrupt pin
#define LED_PIN 13 // LED for showing interrupt
// Constants
#define LIGHT_INT_HIGH 1000 // High light level for interrupt
#define LIGHT_INT_LOW 10 // Low light level for interrupt
// 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;
int isr_flag = 0;
uint16_t threshold = 0;
void setup() {
// Set LED as output
pinMode(LED_PIN, OUTPUT);
pinMode(APDS9960_INT, INPUT);
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("-------------------------------------"));
Serial.println(F("SparkFun APDS-9960 - Light Interrupts"));
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!"));
}
// Set high and low interrupt thresholds
if ( !apds.setLightIntLowThreshold(LIGHT_INT_LOW) ) {
Serial.println(F("Error writing low threshold"));
}
if ( !apds.setLightIntHighThreshold(LIGHT_INT_HIGH) ) {
Serial.println(F("Error writing high threshold"));
}
// 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!"));
}
// Read high and low interrupt thresholds
if ( !apds.getLightIntLowThreshold(threshold) ) {
Serial.println(F("Error reading low threshold"));
} else {
Serial.print(F("Low Threshold: "));
Serial.println(threshold);
}
if ( !apds.getLightIntHighThreshold(threshold) ) {
Serial.println(F("Error reading high threshold"));
} else {
Serial.print(F("High Threshold: "));
Serial.println(threshold);
}
// Enable interrupts
if ( !apds.setAmbientLightIntEnable(1) ) {
Serial.println(F("Error enabling interrupts"));
}
// Wait for initialization and calibration to finish
delay(500);
}
void loop() {
// If interrupt occurs, print out the light levels
if ( isr_flag == 1 ) {
// Read the light levels (ambient, red, green, blue) and print
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("Interrupt! Ambient: ");
Serial.print(ambient_light);
Serial.print(" R: ");
Serial.print(red_light);
Serial.print(" G: ");
Serial.print(green_light);
Serial.print(" B: ");
Serial.println(blue_light);
}
// Turn on LED for a half a second
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
// Reset flag and clear APDS-9960 interrupt (IMPORTANT!)
isr_flag = 0;
if ( !apds.clearAmbientLightInt() ) {
Serial.println("Error clearing interrupt");
}
}
}
void interruptRoutine() {
isr_flag = 1;
}
@@ -0,0 +1,96 @@
/****************************************************************
ColorSensor.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
October 15, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the color and ambient light sensing abilities of the
APDS-9960. Configures APDS-9960 over I2C and polls the sensor for
ambient light and color levels, which are displayed over the
serial console.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
// 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;
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() {
// 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);
}
// Wait 1 second before next reading
delay(1000);
}
@@ -0,0 +1,128 @@
/****************************************************************
GestureTest.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
May 30, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the gesture sensing abilities of the APDS-9960. Configures
APDS-9960 over I2C and waits for gesture events. Calculates the
direction of the swipe (up, down, left, right) and displays it
on a serial console.
To perform a NEAR gesture, hold your hand
far above the sensor and move it close to the sensor (within 2
inches). Hold your hand there for at least 1 second and move it
away.
To perform a FAR gesture, hold your hand within 2 inches of the
sensor for at least 1 second and then move it above (out of
range) of the sensor.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
2 INT Interrupt
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#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");
}
}
}
@@ -0,0 +1,129 @@
/****************************************************************
ProximityInterrupt.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
October 24, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the proximity interrupt abilities of the APDS-9960.
Configures the APDS-9960 over I2C and waits for an external
interrupt based on high or low proximity conditions. Move your
hand near the sensor and watch the LED on pin 13.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
2 INT Interrupt
13 - LED
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
// Pins
#define APDS9960_INT 2 // Needs to be an interrupt pin
#define LED_PIN 13 // LED for showing interrupt
// Constants
#define PROX_INT_HIGH 50 // Proximity level for interrupt
#define PROX_INT_LOW 0 // No far interrupt
// Global variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint8_t proximity_data = 0;
int isr_flag = 0;
void setup() {
// Set LED as output
pinMode(LED_PIN, OUTPUT);
pinMode(APDS9960_INT, INPUT);
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("---------------------------------------"));
Serial.println(F("SparkFun APDS-9960 - ProximityInterrupt"));
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!"));
}
// Adjust the Proximity sensor gain
if ( !apds.setProximityGain(PGAIN_2X) ) {
Serial.println(F("Something went wrong trying to set PGAIN"));
}
// Set proximity interrupt thresholds
if ( !apds.setProximityIntLowThreshold(PROX_INT_LOW) ) {
Serial.println(F("Error writing low threshold"));
}
if ( !apds.setProximityIntHighThreshold(PROX_INT_HIGH) ) {
Serial.println(F("Error writing high threshold"));
}
// Start running the APDS-9960 proximity sensor (interrupts)
if ( apds.enableProximitySensor(true) ) {
Serial.println(F("Proximity sensor is now running"));
} else {
Serial.println(F("Something went wrong during sensor init!"));
}
}
void loop() {
// If interrupt occurs, print out the proximity level
if ( isr_flag == 1 ) {
// Read proximity level and print it out
if ( !apds.readProximity(proximity_data) ) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity detected! Level: ");
Serial.println(proximity_data);
}
// Turn on LED for a half a second
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
// Reset flag and clear APDS-9960 interrupt (IMPORTANT!)
isr_flag = 0;
if ( !apds.clearProximityInt() ) {
Serial.println("Error clearing interrupt");
}
}
}
void interruptRoutine() {
isr_flag = 1;
}
@@ -0,0 +1,85 @@
/****************************************************************
ProximityTest.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
October 28, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the proximity sensing abilities of the APDS-9960.
Configures the APDS-9960 over I2C and polls for the distance to
the object nearest the sensor.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint8_t proximity_data = 0;
void setup() {
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("------------------------------------"));
Serial.println(F("SparkFun APDS-9960 - ProximitySensor"));
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!"));
}
// Adjust the Proximity sensor gain
if ( !apds.setProximityGain(PGAIN_2X) ) {
Serial.println(F("Something went wrong trying to set PGAIN"));
}
// Start running the APDS-9960 proximity sensor (no interrupts)
if ( apds.enableProximitySensor(false) ) {
Serial.println(F("Proximity sensor is now running"));
} else {
Serial.println(F("Something went wrong during sensor init!"));
}
}
void loop() {
// Read the proximity value
if ( !apds.readProximity(proximity_data) ) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity: ");
Serial.println(proximity_data);
}
// Wait 250 ms before next reading
delay(250);
}
@@ -0,0 +1,9 @@
name=SparkFun APDS9960 RGB and Gesture Sensor
version=1.4.2
author=SparkFun Electronics <techsupport@sparkfun.com>
maintainer=SparkFun Electronics <sparkfun.com>
sentence=Library for the Avago APDS-9960 sensor
paragraph=This library works with the SparkFun Breakout board for the Avago APDS-9960 proximity, light, RGB, and gesture sensor, made by SparkFun Electronics.
category=Sensors
url=https://github.com/sparkfun/SparkFun_APDS-9960_Sensor_Arduino_Library
architectures=*
@@ -0,0 +1,5 @@
This folder should contain the .cpp and .h files for the library.
If backward compatibility is needed, source code should be placed in the library root folder and in a "utilyt" folder.
Check out the [library specification](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification) for more details.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,349 @@
/**
* @file SparkFun_APDS-9960.h
* @brief Library for the SparkFun APDS-9960 breakout board
* @author Shawn Hymel (SparkFun Electronics)
*
* @copyright This code is public domain but you buy me a beer if you use
* this and we meet someday (Beerware license).
*
* This library interfaces the Avago APDS-9960 to Arduino over I2C. The library
* relies on the Arduino Wire (I2C) library. to use the library, instantiate an
* APDS9960 object, call init(), and call the appropriate functions.
*/
#ifndef SparkFun_APDS9960_H
#define SparkFun_APDS9960_H
#include <Arduino.h>
/* Debug */
#define DEBUG 0
/* APDS-9960 I2C address */
#define APDS9960_I2C_ADDR 0x39
/* Gesture parameters */
#define GESTURE_THRESHOLD_OUT 10
#define GESTURE_SENSITIVITY_1 50
#define GESTURE_SENSITIVITY_2 20
/* Error code for returned values */
#define ERROR 0xFF
/* Acceptable device IDs */
#define APDS9960_ID_1 0xAB
#define APDS9960_ID_2 0x9C
/* Misc parameters */
#define FIFO_PAUSE_TIME 30 // Wait period (ms) between FIFO reads
/* APDS-9960 register addresses */
#define APDS9960_ENABLE 0x80
#define APDS9960_ATIME 0x81
#define APDS9960_WTIME 0x83
#define APDS9960_AILTL 0x84
#define APDS9960_AILTH 0x85
#define APDS9960_AIHTL 0x86
#define APDS9960_AIHTH 0x87
#define APDS9960_PILT 0x89
#define APDS9960_PIHT 0x8B
#define APDS9960_PERS 0x8C
#define APDS9960_CONFIG1 0x8D
#define APDS9960_PPULSE 0x8E
#define APDS9960_CONTROL 0x8F
#define APDS9960_CONFIG2 0x90
#define APDS9960_ID 0x92
#define APDS9960_STATUS 0x93
#define APDS9960_CDATAL 0x94
#define APDS9960_CDATAH 0x95
#define APDS9960_RDATAL 0x96
#define APDS9960_RDATAH 0x97
#define APDS9960_GDATAL 0x98
#define APDS9960_GDATAH 0x99
#define APDS9960_BDATAL 0x9A
#define APDS9960_BDATAH 0x9B
#define APDS9960_PDATA 0x9C
#define APDS9960_POFFSET_UR 0x9D
#define APDS9960_POFFSET_DL 0x9E
#define APDS9960_CONFIG3 0x9F
#define APDS9960_GPENTH 0xA0
#define APDS9960_GEXTH 0xA1
#define APDS9960_GCONF1 0xA2
#define APDS9960_GCONF2 0xA3
#define APDS9960_GOFFSET_U 0xA4
#define APDS9960_GOFFSET_D 0xA5
#define APDS9960_GOFFSET_L 0xA7
#define APDS9960_GOFFSET_R 0xA9
#define APDS9960_GPULSE 0xA6
#define APDS9960_GCONF3 0xAA
#define APDS9960_GCONF4 0xAB
#define APDS9960_GFLVL 0xAE
#define APDS9960_GSTATUS 0xAF
#define APDS9960_IFORCE 0xE4
#define APDS9960_PICLEAR 0xE5
#define APDS9960_CICLEAR 0xE6
#define APDS9960_AICLEAR 0xE7
#define APDS9960_GFIFO_U 0xFC
#define APDS9960_GFIFO_D 0xFD
#define APDS9960_GFIFO_L 0xFE
#define APDS9960_GFIFO_R 0xFF
/* Bit fields */
#define APDS9960_PON 0b00000001
#define APDS9960_AEN 0b00000010
#define APDS9960_PEN 0b00000100
#define APDS9960_WEN 0b00001000
#define APSD9960_AIEN 0b00010000
#define APDS9960_PIEN 0b00100000
#define APDS9960_GEN 0b01000000
#define APDS9960_GVALID 0b00000001
/* On/Off definitions */
#define OFF 0
#define ON 1
/* Acceptable parameters for setMode */
#define POWER 0
#define AMBIENT_LIGHT 1
#define PROXIMITY 2
#define WAIT 3
#define AMBIENT_LIGHT_INT 4
#define PROXIMITY_INT 5
#define GESTURE 6
#define ALL 7
/* LED Drive values */
#define LED_DRIVE_100MA 0
#define LED_DRIVE_50MA 1
#define LED_DRIVE_25MA 2
#define LED_DRIVE_12_5MA 3
/* Proximity Gain (PGAIN) values */
#define PGAIN_1X 0
#define PGAIN_2X 1
#define PGAIN_4X 2
#define PGAIN_8X 3
/* ALS Gain (AGAIN) values */
#define AGAIN_1X 0
#define AGAIN_4X 1
#define AGAIN_16X 2
#define AGAIN_64X 3
/* Gesture Gain (GGAIN) values */
#define GGAIN_1X 0
#define GGAIN_2X 1
#define GGAIN_4X 2
#define GGAIN_8X 3
/* LED Boost values */
#define LED_BOOST_100 0
#define LED_BOOST_150 1
#define LED_BOOST_200 2
#define LED_BOOST_300 3
/* Gesture wait time values */
#define GWTIME_0MS 0
#define GWTIME_2_8MS 1
#define GWTIME_5_6MS 2
#define GWTIME_8_4MS 3
#define GWTIME_14_0MS 4
#define GWTIME_22_4MS 5
#define GWTIME_30_8MS 6
#define GWTIME_39_2MS 7
/* Default values */
#define DEFAULT_ATIME 219 // 103ms
#define DEFAULT_WTIME 246 // 27ms
#define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses
#define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses
#define DEFAULT_POFFSET_UR 0 // 0 offset
#define DEFAULT_POFFSET_DL 0 // 0 offset
#define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor
#define DEFAULT_LDRIVE LED_DRIVE_100MA
#define DEFAULT_PGAIN PGAIN_4X
#define DEFAULT_AGAIN AGAIN_4X
#define DEFAULT_PILT 0 // Low proximity threshold
#define DEFAULT_PIHT 50 // High proximity threshold
#define DEFAULT_AILT 0xFFFF // Force interrupt for calibration
#define DEFAULT_AIHT 0
#define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int.
#define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost
#define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI
#define DEFAULT_GPENTH 40 // Threshold for entering gesture mode
#define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode
#define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit
#define DEFAULT_GGAIN GGAIN_4X
#define DEFAULT_GLDRIVE LED_DRIVE_100MA
#define DEFAULT_GWTIME GWTIME_2_8MS
#define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode
#define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses
#define DEFAULT_GCONF3 0 // All photodiodes active during gesture
#define DEFAULT_GIEN 0 // Disable gesture interrupts
/* Direction definitions */
enum {
DIR_NONE,
DIR_LEFT,
DIR_RIGHT,
DIR_UP,
DIR_DOWN,
DIR_NEAR,
DIR_FAR,
DIR_ALL
};
/* State definitions */
enum {
N_A_STATE, // NA_STATE - collision with ESP8266WiFi.h
NEAR_STATE,
FAR_STATE,
ALL_STATE
};
/* Container for gesture data */
typedef struct gesture_data_type {
uint8_t u_data[32];
uint8_t d_data[32];
uint8_t l_data[32];
uint8_t r_data[32];
uint8_t index;
uint8_t total_gestures;
uint8_t in_threshold;
uint8_t out_threshold;
} gesture_data_type;
/* APDS9960 Class */
class SparkFun_APDS9960 {
public:
/* Initialization methods */
SparkFun_APDS9960();
~SparkFun_APDS9960();
bool init();
uint8_t getMode();
bool setMode(uint8_t mode, uint8_t enable);
/* Turn the APDS-9960 on and off */
bool enablePower();
bool disablePower();
/* Enable or disable specific sensors */
bool enableLightSensor(bool interrupts = false);
bool disableLightSensor();
bool enableProximitySensor(bool interrupts = false);
bool disableProximitySensor();
bool enableGestureSensor(bool interrupts = true);
bool disableGestureSensor();
/* LED drive strength control */
uint8_t getLEDDrive();
bool setLEDDrive(uint8_t drive);
uint8_t getGestureLEDDrive();
bool setGestureLEDDrive(uint8_t drive);
/* Gain control */
uint8_t getAmbientLightGain();
bool setAmbientLightGain(uint8_t gain);
uint8_t getProximityGain();
bool setProximityGain(uint8_t gain);
uint8_t getGestureGain();
bool setGestureGain(uint8_t gain);
/* Get and set light interrupt thresholds */
bool getLightIntLowThreshold(uint16_t &threshold);
bool setLightIntLowThreshold(uint16_t threshold);
bool getLightIntHighThreshold(uint16_t &threshold);
bool setLightIntHighThreshold(uint16_t threshold);
/* Get and set proximity interrupt thresholds */
bool getProximityIntLowThreshold(uint8_t &threshold);
bool setProximityIntLowThreshold(uint8_t threshold);
bool getProximityIntHighThreshold(uint8_t &threshold);
bool setProximityIntHighThreshold(uint8_t threshold);
/* Get and set interrupt enables */
uint8_t getAmbientLightIntEnable();
bool setAmbientLightIntEnable(uint8_t enable);
uint8_t getProximityIntEnable();
bool setProximityIntEnable(uint8_t enable);
uint8_t getGestureIntEnable();
bool setGestureIntEnable(uint8_t enable);
/* Clear interrupts */
bool clearAmbientLightInt();
bool clearProximityInt();
/* Ambient light methods */
bool readAmbientLight(uint16_t &val);
bool readRedLight(uint16_t &val);
bool readGreenLight(uint16_t &val);
bool readBlueLight(uint16_t &val);
/* Proximity methods */
bool readProximity(uint8_t &val);
/* Gesture methods */
bool isGestureAvailable();
int readGesture();
int readGestureNonBlocking();
private:
/* Gesture processing */
void resetGestureParameters();
bool processGestureData();
bool decodeGesture();
/* Proximity Interrupt Threshold */
uint8_t getProxIntLowThresh();
bool setProxIntLowThresh(uint8_t threshold);
uint8_t getProxIntHighThresh();
bool setProxIntHighThresh(uint8_t threshold);
/* LED Boost Control */
uint8_t getLEDBoost();
bool setLEDBoost(uint8_t boost);
/* Proximity photodiode select */
uint8_t getProxGainCompEnable();
bool setProxGainCompEnable(uint8_t enable);
uint8_t getProxPhotoMask();
bool setProxPhotoMask(uint8_t mask);
/* Gesture threshold control */
uint8_t getGestureEnterThresh();
bool setGestureEnterThresh(uint8_t threshold);
uint8_t getGestureExitThresh();
bool setGestureExitThresh(uint8_t threshold);
/* Gesture LED, gain, and time control */
uint8_t getGestureWaitTime();
bool setGestureWaitTime(uint8_t time);
/* Gesture mode */
uint8_t getGestureMode();
bool setGestureMode(uint8_t mode);
/* Raw I2C Commands */
bool wireWriteByte(uint8_t val);
bool wireWriteDataByte(uint8_t reg, uint8_t val);
bool wireWriteDataBlock(uint8_t reg, uint8_t *val, unsigned int len);
bool wireReadDataByte(uint8_t reg, uint8_t &val);
int wireReadDataBlock(uint8_t reg, uint8_t *val, unsigned int len);
/* Members */
gesture_data_type gesture_data_;
int gesture_ud_delta_;
int gesture_lr_delta_;
int gesture_ud_count_;
int gesture_lr_count_;
int gesture_near_count_;
int gesture_far_count_;
int gesture_state_;
int gesture_motion_;
};
#endif
+2 -2
View File
@@ -2632,7 +2632,7 @@ void handle_i2cscanner() {
reply += F("PCF8574A");
break;
case 0x39:
reply += F("PCF8574A<BR>TSL2561");
reply += F("PCF8574A<BR>TSL2561<BR>APDS9960");
break;
case 0x3C:
case 0x3D:
@@ -3560,7 +3560,7 @@ void handle_rules() {
String reply = "";
checkRAM(F("handle_rules"));
addHeader(true, reply);
if (WebServer.args() > 0)
+217
View File
@@ -0,0 +1,217 @@
//#######################################################################################################
//#################################### Plugin 064: APDS9960 Gesture ##############################
//#######################################################################################################
// ESPEasy Plugin to scan a gesture, proximity and light chip APDS9960
// written by Jochen Krapf (jk@nerd2nerd.org)
// A new gesture is send immediately to controllers.
// Proximity and Light are scanned frequently by given 'Delay' setting.
// RGB is not scanned because there are only 4 vars per task.
// Known BUG: While performing a gesture the reader function blocks rest of ESPEasy processing!!! (Feel free to fix...)
// Note: The chip has a wide view-of-angle. If housing is in this angle the chip blocks!
#ifdef PLUGIN_BUILD_DEV
#define PLUGIN_064
#define PLUGIN_ID_064 64
#define PLUGIN_NAME_064 "Gesture - APDS9960 [DEV]"
#define PLUGIN_VALUENAME1_064 "Gesture"
#define PLUGIN_VALUENAME2_064 "Proximity"
#define PLUGIN_VALUENAME3_064 "Light"
/*
#define PLUGIN_VALUENAME4_064 "R"
#define PLUGIN_VALUENAME5_064 "G"
#define PLUGIN_VALUENAME6_064 "B"
*/
#include <SparkFun_APDS9960.h> //Lib is modified to work with ESP
#ifndef CONFIG
#define CONFIG(n) (Settings.TaskDevicePluginConfig[event->TaskIndex][n])
#endif
SparkFun_APDS9960* PLUGIN_064_pds = NULL;
boolean Plugin_064(byte function, struct EventStruct *event, String& string)
{
boolean success = false;
switch (function)
{
case PLUGIN_DEVICE_ADD:
{
Device[++deviceCount].Number = PLUGIN_ID_064;
Device[deviceCount].Type = DEVICE_TYPE_I2C;
Device[deviceCount].Ports = 0;
Device[deviceCount].VType = SENSOR_TYPE_SWITCH;
Device[deviceCount].PullUpOption = false;
Device[deviceCount].InverseLogicOption = false;
Device[deviceCount].FormulaOption = false;
Device[deviceCount].ValueCount = 3;
Device[deviceCount].SendDataOption = true;
Device[deviceCount].TimerOption = true;
Device[deviceCount].TimerOptional = true;
Device[deviceCount].GlobalSyncOption = true;
break;
}
case PLUGIN_GET_DEVICENAME:
{
string = F(PLUGIN_NAME_064);
break;
}
case PLUGIN_GET_DEVICEVALUENAMES:
{
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_064));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_064));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_064));
/*
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_064));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[4], PSTR(PLUGIN_VALUENAME5_064));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[5], PSTR(PLUGIN_VALUENAME6_064));
*/
break;
}
case PLUGIN_WEBFORM_LOAD:
{
byte addr = 0x39; // CONFIG(0); chip has only 1 address
int optionValues[1] = { 0x39 };
addFormSelectorI2C(string, F("i2c_addr"), 1, optionValues, addr); //Only for display I2C address
success = true;
break;
}
case PLUGIN_WEBFORM_SAVE:
{
//CONFIG(0) = getFormItemInt(F("i2c_addr"));
success = true;
break;
}
case PLUGIN_INIT:
{
if (PLUGIN_064_pds)
delete PLUGIN_064_pds;
PLUGIN_064_pds = new SparkFun_APDS9960();
String log = F("APDS : ");
if ( PLUGIN_064_pds->init() )
{
log += F("Init");
PLUGIN_064_pds->enablePower();
if (! PLUGIN_064_pds->enableLightSensor(false))
log += F(" - Error during light sensor init!");
if (! PLUGIN_064_pds->enableProximitySensor(false))
log += F(" - Error during proximity sensor init!");
if (! PLUGIN_064_pds->enableGestureSensor(false))
log += F(" - Error during gesture sensor init!");
}
else
{
log += F("Error during APDS-9960 init!");
}
addLog(LOG_LEVEL_INFO, log);
success = true;
break;
}
case PLUGIN_FIFTY_PER_SECOND:
{
if (!PLUGIN_064_pds)
break;
if ( !PLUGIN_064_pds->isGestureAvailable() )
break;
int gesture = PLUGIN_064_pds->readGesture();
//int gesture = PLUGIN_064_pds->readGestureNonBlocking();
//if (gesture == -1) Serial.print(".");
//if (gesture == -2) Serial.print(":");
//if (gesture == -3) Serial.print("|");
//if ( 0 && PLUGIN_064_pds->isGestureAvailable() )
if (gesture >= 0)
{
String log = F("APDS : Gesture=");
switch ( gesture )
{
case DIR_UP: log += F("UP"); break;
case DIR_DOWN: log += F("DOWN"); break;
case DIR_LEFT: log += F("LEFT"); break;
case DIR_RIGHT: log += F("RIGHT"); break;
case DIR_NEAR: log += F("NEAR"); break;
case DIR_FAR: log += F("FAR"); break;
default: log += F("NONE"); break;
}
log += F(" (");
log += gesture;
log += F(")");
UserVar[event->BaseVarIndex] = (float)gesture;
event->sensorType = SENSOR_TYPE_SWITCH;
sendData(event);
addLog(LOG_LEVEL_INFO, log);
}
success = true;
break;
}
case PLUGIN_READ:
{
if (!PLUGIN_064_pds)
break;
// Gesture - work is done in PLUGIN_FIFTY_PER_SECOND
if (1)
{
uint8_t proximity_data = 0;
PLUGIN_064_pds->readProximity(proximity_data);
UserVar[event->BaseVarIndex + 1] = (float)proximity_data;
uint16_t ambient_light = 0;
PLUGIN_064_pds->readAmbientLight(ambient_light);
UserVar[event->BaseVarIndex + 2] = (float)ambient_light;
/*
uint16_t red_light = 0;
uint16_t green_light = 0;
uint16_t blue_light = 0;
PLUGIN_064_pds->readRedLight(red_light);
PLUGIN_064_pds->readGreenLight(green_light);
PLUGIN_064_pds->readBlueLight(blue_light);
UserVar[event->BaseVarIndex + 3] = (float)red_light;
UserVar[event->BaseVarIndex + 4] = (float)green_light;
UserVar[event->BaseVarIndex + 5] = (float)blue_light;
*/
}
success = true;
break;
}
}
return success;
}
#endif