Browse Source

Refactor sensor interface with extra files and function pointer

That makes it easier to enable/disable sensors.

Also added support for APDS9930
Florian Eitel 1 year ago
parent
commit
be334245ff
No account linked to committer's email address

+ 5
- 1
firmware/config_user.h.example View File

@@ -10,6 +10,11 @@
10 10
 // Enable/Disable features
11 11
 //#define WEBUPDATER_FEATURE
12 12
 #define BATTERY_POWERED
13
+#define SENSOR_WIND
14
+#define SENSOR_APDS9960
15
+//#define SENSOR_APDS9930
16
+#define SENSOR_BME280
17
+#define SENSOR_BATTERY
13 18
 
14 19
 const float HUMIDITY_FACTOR = 1.0;
15 20
 const float LIGHT_FACTOR    = 1.0;
@@ -27,4 +32,3 @@ const char     *INFLUXDB_PASS = "password";
27 32
 String          DEVICE_NAME   = "devicename";
28 33
 
29 34
 #endif
30
-

+ 44
- 61
firmware/firmware.ino View File

@@ -18,8 +18,6 @@
18 18
 #include <WiFiClient.h>          // WiFiClient
19 19
 #include <WiFiManager.h>         // WiFiManager
20 20
 #include <ESP8266Influxdb.h>     // https://github.com/hwwong/ESP8266Influxdb auchecken und den ordner in das arduino\library verzeichnis kopieren
21
-#include <Adafruit_APDS9960.h>   // Adafruit APDS9960 - https://www.makerfabs.com/index.php?route=product/product&product_id=281
22
-#include <Adafruit_BME280.h>     // BME280 - https://www.roboter-bausatz.de/1704/bmp280-barometer-luftdrucksensor?gclid=EAIaIQobChMIlpumj8Hp2wIVFWYbCh01PgmFEAQYAyABEgIwBvD_BwE
23 21
 
24 22
 // Project includes
25 23
 #include "config.h"
@@ -49,18 +47,15 @@
49 47
 
50 48
 //*************************************************************************//
51 49
 
52
-float currentSensorData[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
50
+const uint8_t VALUES = 8;
51
+float currentSensorData[VALUES] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
52
+float (*sensors[VALUES])() = {};
53 53
 
54 54
 uint16_t update_sensor_cnt      = 0;
55 55
 uint16_t update_webserver_cnt   = 0;
56
-uint16_t energySavingIterations = 0;
57 56
 
58 57
 WiFiManager wifiManager;
59 58
 Influxdb influxdb(INFLUXDB_HOST, INFLUXDB_PORT);
60
-Adafruit_APDS9960 apds;
61
-Adafruit_BME280 bme;
62
-
63
-bool apds_connected = false;
64 59
 
65 60
 #ifdef WEBUPDATER_FEATURE
66 61
 String localIP = "127.0.0.1";
@@ -117,21 +112,36 @@ void setup() {
117 112
   influxdb.opendb(INFLUXDB_DB, INFLUXDB_USER, INFLUXDB_PASS);
118 113
 
119 114
   // Initialize and configure the sensors
120
-  //Light Sensor
121
-  if (apds.begin()) {
122
-    apds_connected = true;
123
-    apds.enableColor(true);
115
+#ifdef SENSOR_APDS9930
116
+  if (sensor_apds9930_begin()) {
117
+    sensors[SENSOR_LIGHT] = &apds9930_light;
124 118
   }
119
+#endif
125 120
 
126
-  debug("APDS Connected!");
121
+#ifdef SENSOR_APDS9960
122
+  if (sensor_apds9960_begin()) {
123
+    sensors[SENSOR_LIGHT] = &apds9930_light;
124
+  }
125
+#endif
127 126
 
127
+#ifdef SENSOR_BME280
128 128
   //Temperature + pressure
129
-  bool status = bme.begin(BME_ADDRESS);
130
-  if (!status) {
131
-    debug("Could not find a valid BME280 sensor, check wiring!");
132
-   //#warning TODO: FIXME while (1);
129
+  if (sensor_bme280_begin(BME_ADDRESS)) {
130
+    sensors[SENSOR_TEMPERATURE] = &bme280_temperature;
131
+    sensors[SENSOR_HUMIDITY] = &bme280_humidity;
132
+    sensors[SENSOR_PRESSURE] = &bme280_pressure;
133 133
   }
134
-  debug("BME Connected!");
134
+#endif
135
+
136
+#ifdef SENSOR_WIND
137
+  sensors[SENSOR_WINDSPEED] = &wind_speed;
138
+#endif
139
+
140
+#ifdef SENSOR_BATTERY
141
+  sensors[SENSOR_BAT_VOLTAGE] = &battery_voltage;
142
+  sensors[SENSOR_BATCHARGESTATE] = &battery_charging;
143
+  sensors[SENSOR_ESAVEMODE] = &isEnergySavingMode;
144
+#endif
135 145
 
136 146
 #ifdef WEBUPDATER_FEATURE
137 147
 #ifndef BATTERY_POWERED
@@ -166,7 +176,7 @@ void setup() {
166 176
 
167 177
 #ifdef BATTERY_POWERED
168 178
 void criticalBatCheck() {
169
-  float volt = getBatteryVoltage();
179
+  float volt = battery_voltage();
170 180
   if (volt <= BAT_EMERGENCY_DEEPSLEEP_VOLTAGE) {
171 181
     debug("Bat Voltage: " + String(volt) + " V");
172 182
     debug("Low battery, going into deep sleep.");
@@ -177,26 +187,6 @@ void criticalBatCheck() {
177 187
 }
178 188
 #endif
179 189
 
180
-#ifdef BATTERY_POWERED
181
-int energySavingMode() {
182
-  // Give the solar panel some time to load the cell to prevent
183
-  // flapping.
184
-  if (energySavingIterations > 0) {
185
-    energySavingIterations--;
186
-    return 1;
187
-  }
188
-
189
-  // Is the battery low?
190
-  if (currentSensorData[SENSOR_BAT_VOLTAGE] <= BAT_LOW_VOLTAGE) {
191
-    // Entering energy saving
192
-    energySavingIterations = ENERGY_SAVING_ITERATIONS;
193
-
194
-    return 1;
195
-  }
196
-
197
-  return 0;
198
-}
199
-#endif
200 190
 
201 191
 void loop() {
202 192
 #ifdef BATTERY_POWERED
@@ -232,32 +222,25 @@ void _loop() {
232 222
   }
233 223
 #endif
234 224
 
235
-    update_sensor_cnt = 0;
236
-    currentSensorData[SENSOR_TEMPERATURE] = fetchTemperature();
237
-    currentSensorData[SENSOR_HUMIDITY]    = fetchHumidity();
238
-    if (apds_connected) {
239
-      currentSensorData[SENSOR_LIGHT]       = fetchLight();
240
-    }
241
-    currentSensorData[SENSOR_PRESSURE]    = fetchPressure();
242
-#ifdef BATTERY_POWERED
243
-    currentSensorData[SENSOR_BAT_VOLTAGE]    = getBatteryVoltage();
244
-    currentSensorData[SENSOR_BATCHARGESTATE] = isBatCharging();
245
-#else
246
-    currentSensorData[SENSOR_BAT_VOLTAGE]    = 0xFFFFFFFF;
247
-    currentSensorData[SENSOR_BATCHARGESTATE] = 0xFFFFFFFF;
248
-#endif
249
-#ifdef BATTERY_POWERED
225
+
226
+#ifdef defined(BATTERY_POWERED) && defined(SENSOR_WIND)
227
+  if (energySavingMode() == 1) {
250 228
     // Disable expensive tasks
251
-    if (energySavingMode() == 0) {
229
+    sensors[SENSOR_WINDSPEED] = 0;
230
+  } else {
231
+    sensors[SENSOR_WINDSPEED] = &wind_speed;
232
+  }
252 233
 #endif
253
-      currentSensorData[SENSOR_WINDSPEED] = fetchWindspeed();
254
-      currentSensorData[SENSOR_ESAVEMODE] = ENERGY_SAVE_MODE_DISABLED;
255
-#ifdef BATTERY_POWERED
234
+
235
+  update_sensor_cnt = 0;
236
+
237
+  for (uint8_t i = 0; i < VALUES; i++) {
238
+    if (sensors[i]) {
239
+      currentSensorData[i] = sensors[i]();
256 240
     } else {
257
-      currentSensorData[SENSOR_WINDSPEED] = 0xFFFFFFFF;
258
-      currentSensorData[SENSOR_ESAVEMODE] = ENERGY_SAVE_MODE_ENABLED;
241
+      currentSensorData[i] = 0xFFFFFFFF;
259 242
     }
260
-#endif
243
+  }
261 244
 
262 245
     debug("");
263 246
     debug("Current readings:");

+ 22
- 0
firmware/libraries/APDS9930-master/.gitattributes View File

@@ -0,0 +1,22 @@
1
+# Auto detect text files and perform LF normalization
2
+* text=auto
3
+
4
+# Custom for Visual Studio
5
+*.cs     diff=csharp
6
+*.sln    merge=union
7
+*.csproj merge=union
8
+*.vbproj merge=union
9
+*.fsproj merge=union
10
+*.dbproj merge=union
11
+
12
+# Standard to msysgit
13
+*.doc	 diff=astextplain
14
+*.DOC	 diff=astextplain
15
+*.docx diff=astextplain
16
+*.DOCX diff=astextplain
17
+*.dot  diff=astextplain
18
+*.DOT  diff=astextplain
19
+*.pdf  diff=astextplain
20
+*.PDF	 diff=astextplain
21
+*.rtf	 diff=astextplain
22
+*.RTF	 diff=astextplain

+ 192
- 0
firmware/libraries/APDS9930-master/.gitignore View File

@@ -0,0 +1,192 @@
1
+#################
2
+## SparkFun Useful stuff
3
+#################
4
+
5
+## AVR Development
6
+*.eep
7
+*.elf
8
+*.lst
9
+*.lss
10
+*.sym
11
+*.d
12
+*.o
13
+*.srec
14
+*.map
15
+
16
+## Notepad++ backup files
17
+*.bak
18
+
19
+## BOM files
20
+*bom*
21
+
22
+#################
23
+## Eclipse
24
+#################
25
+
26
+*.pydevproject
27
+.project
28
+.metadata
29
+bin/
30
+tmp/
31
+*.tmp
32
+*.bak
33
+*.swp
34
+*~.nib
35
+local.properties
36
+.classpath
37
+.settings/
38
+.loadpath
39
+
40
+# External tool builders
41
+.externalToolBuilders/
42
+
43
+# Locally stored "Eclipse launch configurations"
44
+*.launch
45
+
46
+# CDT-specific
47
+.cproject
48
+
49
+# PDT-specific
50
+.buildpath
51
+
52
+
53
+#############
54
+## Eagle
55
+#############
56
+
57
+# Ignore the board and schematic backup files
58
+*.b#?
59
+*.s#?
60
+
61
+
62
+#################
63
+## Visual Studio
64
+#################
65
+
66
+## Ignore Visual Studio temporary files, build results, and
67
+## files generated by popular Visual Studio add-ons.
68
+
69
+# User-specific files
70
+*.suo
71
+*.user
72
+*.sln.docstates
73
+
74
+# Build results
75
+[Dd]ebug/
76
+[Rr]elease/
77
+*_i.c
78
+*_p.c
79
+*.ilk
80
+*.meta
81
+*.obj
82
+*.pch
83
+*.pdb
84
+*.pgc
85
+*.pgd
86
+*.rsp
87
+*.sbr
88
+*.tlb
89
+*.tli
90
+*.tlh
91
+*.tmp
92
+*.vspscc
93
+.builds
94
+*.dotCover
95
+
96
+## TODO: If you have NuGet Package Restore enabled, uncomment this
97
+#packages/
98
+
99
+# Visual C++ cache files
100
+ipch/
101
+*.aps
102
+*.ncb
103
+*.opensdf
104
+*.sdf
105
+
106
+# Visual Studio profiler
107
+*.psess
108
+*.vsp
109
+
110
+# ReSharper is a .NET coding add-in
111
+_ReSharper*
112
+
113
+# Installshield output folder
114
+[Ee]xpress
115
+
116
+# DocProject is a documentation generator add-in
117
+DocProject/buildhelp/
118
+DocProject/Help/*.HxT
119
+DocProject/Help/*.HxC
120
+DocProject/Help/*.hhc
121
+DocProject/Help/*.hhk
122
+DocProject/Help/*.hhp
123
+DocProject/Help/Html2
124
+DocProject/Help/html
125
+
126
+# Click-Once directory
127
+publish
128
+
129
+# Others
130
+[Bb]in
131
+[Oo]bj
132
+sql
133
+TestResults
134
+*.Cache
135
+ClientBin
136
+stylecop.*
137
+~$*
138
+*.dbmdl
139
+Generated_Code #added for RIA/Silverlight projects
140
+
141
+# Backup & report files from converting an old project file to a newer
142
+# Visual Studio version. Backup files are not needed, because we have git ;-)
143
+_UpgradeReport_Files/
144
+Backup*/
145
+UpgradeLog*.XML
146
+
147
+
148
+############
149
+## Windows
150
+############
151
+
152
+# Windows image file caches
153
+Thumbs.db
154
+
155
+# Folder config file
156
+Desktop.ini
157
+
158
+
159
+#############
160
+## Python
161
+#############
162
+
163
+*.py[co]
164
+
165
+# Packages
166
+*.egg
167
+*.egg-info
168
+dist
169
+build
170
+eggs
171
+parts
172
+bin
173
+var
174
+sdist
175
+develop-eggs
176
+.installed.cfg
177
+
178
+# Installer logs
179
+pip-log.txt
180
+
181
+# Unit test / coverage reports
182
+.coverage
183
+.tox
184
+
185
+#Translations
186
+*.mo
187
+
188
+#Mr Developer
189
+.mr.developer.cfg
190
+
191
+# Mac crap
192
+.DS_Store

+ 22
- 0
firmware/libraries/APDS9930-master/LICENSE View File

@@ -0,0 +1,22 @@
1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2015 Davide Depau
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.
22
+

+ 92
- 0
firmware/libraries/APDS9930-master/README.md View File

@@ -0,0 +1,92 @@
1
+APDS9930 Ambient Light and Proximity sensor
2
+===========================================
3
+
4
+This is a fork of the [library from Sparkfun for the APDS-9960 sensor](https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor). It has been adapted to read values from this other model.
5
+
6
+[**Quick-start guide available here**](https://web.archive.org/web/20151224052223/http://davideddu.org/blog/posts/apds-9930-arduino-quickstart/)
7
+
8
+[**Purchase an Avago APDS-9930 Breakout Board here**](http://www.dx.com/p/384037?Utm_rid=14976370&Utm_source=affiliate)
9
+
10
+
11
+# DO NOT EMAIL ME IF YOU HAVE AN ISSUE
12
+It will be deleted without reading. If you have an issue, [create an issue](https://github.com/Depau/APDS9930/issues) here on GitHub.
13
+
14
+# Unmaintained
15
+I'm not going to maintain this library any more. I will merge pull requests, though. Contributions are welcome. Just don't expect anything from me.
16
+
17
+![Avago APDS-9930 Breakout Board](http://img.dxcdn.com/productimages/sku_384037_1.jpg)
18
+
19
+**Note:** even though it says APDS-9960, it's an APDS-9930. That's how I ended up getting one of those. I wanted the RGB sensor. I found this crap in my mailbox. But I decided to write a library for it anyways ;)
20
+
21
+Getting Started
22
+---------------
23
+
24
+* Download the Git repository as a ZIP ("Download ZIP" button)
25
+* Unzip
26
+* Copy the entire library directory (APDS-9930) to
27
+\<Arduino installation directory\>/libraries
28
+* Open the Arduino program
29
+* Select File -> Examples -> APDS9930 -> GestureTest
30
+* Plug in your Arduino and APDS-9930 with the following connections
31
+
32
+*-OR-*
33
+
34
+* Use the library manager
35
+
36
+| Arduino Pin | APDS-9930 Board | Function |
37
+|---|---|---| 
38
+| 3.3V | VCC | Power |
39
+| GND | GND | Ground |
40
+| A4 | SDA | I²C Data |
41
+| A5 | SCL | I²C Clock |
42
+| 2 | INT | Interrupt |
43
+
44
+*P.S.: you already know you can't use this purple little thing with your 5V Arduino without a level shifter, right? :) In case you don't have a level shifter, you can detach the microcontroller from an Arduino Uno, reconnect the oscillator pins, the RX and TX pins, the reset and the LED/SCK pins back to the board with some jumper wires. You can then power the microcontroller from a 3.3V source (the 3V3 output on the board should work) and connect the sensor directly to the MCU. Look up "Arduino on Breadboard".*
45
+
46
+* Go to Tools -> Board and select your Arduino board
47
+* Go to Tools -> Serial Port and select the COM port of your Arduino board
48
+* Click "Upload"
49
+* Go to Tools -> Serial Monitor
50
+* Ensure the baud rate is set at 9600 baud
51
+* Swipe your hand over the sensor in various directions!
52
+
53
+Repository Contents
54
+-------------------
55
+
56
+* **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 
57
+* **/extras** - Additional documentation for the user. These files are ignored by the IDE. 
58
+* **/src** - Source files for the library (.cpp, .h).
59
+* **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 
60
+* **library.properties** - General library properties for the Arduino package manager. 
61
+
62
+Documentation
63
+--------------
64
+
65
+* **[Quickstart Guide](https://web.archive.org/web/20151224052223/http://davideddu.org/blog/posts/apds-9930-arduino-quickstart/)** - Basic hookup guide for the sensor.
66
+* **[Product Repository](https://github.com/Davideddu/APDS9930)** - Main repository (including hardware files) for the APDS9930 ambient light and proximity sensor.
67
+* **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library.
68
+
69
+
70
+Version History
71
+---------------
72
+* master - Adapted for use with APDS-9930
73
+* [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
74
+* V_1.3.0 - Implemented disableProximitySensor(). Thanks to jmg5150 for catching that!
75
+* V_1.2.0 - Added pinMode line to GestureTest demo to fix interrupt bug with some Arduinos
76
+* V_1.1.0 - Updated GestureTest demo to not freeze with fast swipes
77
+* V_1.0.0: Initial release
78
+* Ambient and RGB light sensing implemented
79
+* Ambient light interrupts working
80
+* Proximity sensing implemented
81
+* Proximity interrupts working
82
+
83
+License Information
84
+-------------------
85
+
86
+This product is _**open source**_! 
87
+
88
+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.
89
+
90
+Distributed as-is; no warranty is given.
91
+
92
+- Your friends at SparkFun. And Davide Depau :*

+ 180
- 0
firmware/libraries/APDS9930-master/examples/AmbientLightInterrupt/AmbientLightInterrupt.ino View File

@@ -0,0 +1,180 @@
1
+/****************************************************************
2
+AmbientLightInterrupt.ino
3
+APDS-9930 RGB and Gesture Sensor
4
+Shawn Hymel @ SparkFun Electronics
5
+October 24, 2014
6
+https://github.com/sparkfun/APDS-9930_RGB_and_Gesture_Sensor
7
+
8
+Tests the ambient light interrupt abilities of the APDS-9930.
9
+Configures the APDS-9930 over I2C and waits for an external
10
+interrupt based on high or low light conditions. Try covering
11
+the sensor with your hand or bringing the sensor close to a
12
+bright light source. You might need to adjust the LIGHT_INT_HIGH
13
+and LIGHT_INT_LOW values to get the interrupt to work correctly.
14
+
15
+Hardware Connections:
16
+
17
+IMPORTANT: The APDS-9930 can only accept 3.3V!
18
+ 
19
+ Arduino Pin  APDS-9930 Board  Function
20
+ 
21
+ 3.3V         VCC              Power
22
+ GND          GND              Ground
23
+ A4           SDA              I2C Data
24
+ A5           SCL              I2C Clock
25
+ 2            INT              Interrupt
26
+ 13           -                LED
27
+
28
+Resources:
29
+Include Wire.h and APDS9930.h
30
+
31
+Development environment specifics:
32
+Written in Arduino 1.0.5
33
+Tested with SparkFun Arduino Pro Mini 3.3V
34
+
35
+This code is beerware; if you see me (or any other SparkFun 
36
+employee) at the local, and you've found our code helpful, please
37
+buy us a round!
38
+
39
+Distributed as-is; no warranty is given.
40
+****************************************************************/
41
+
42
+#define DUMP_REGS
43
+
44
+#include <Wire.h>
45
+#include <APDS9930.h>
46
+
47
+// Pins
48
+#define APDS9930_INT    2  // Needs to be an interrupt pin
49
+#define LED_PIN         13 // LED for showing interrupt
50
+
51
+// Constants
52
+#define LIGHT_INT_HIGH  1000 // High light level for interrupt
53
+#define LIGHT_INT_LOW   10   // Low light level for interrupt
54
+
55
+// Global variables
56
+APDS9930 apds = APDS9930();
57
+float ambient_light = 0;
58
+uint16_t ch0 = 0;
59
+uint16_t ch1 = 1;
60
+volatile bool isr_flag = false;
61
+uint16_t threshold = 0;
62
+
63
+void setup() {
64
+  
65
+  // Set LED as output
66
+  pinMode(LED_PIN, OUTPUT);
67
+  pinMode(APDS9930_INT, INPUT);
68
+  
69
+  // Initialize Serial port
70
+  Serial.begin(9600);
71
+  Serial.println();
72
+  Serial.println(F("----------------------------"));
73
+  Serial.println(F("APDS-9930 - Light Interrupts"));
74
+  Serial.println(F("----------------------------"));
75
+  
76
+  // Initialize interrupt service routine
77
+  attachInterrupt(0, interruptRoutine, FALLING);
78
+  
79
+  // Initialize APDS-9930 (configure I2C and initial values)
80
+  if ( apds.init() ) {
81
+    Serial.println(F("APDS-9930 initialization complete"));
82
+  } else {
83
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
84
+  }
85
+  
86
+  // Set high and low interrupt thresholds
87
+  if ( !apds.setLightIntLowThreshold(LIGHT_INT_LOW) ) {
88
+    Serial.println(F("Error writing low threshold"));
89
+  }
90
+  if ( !apds.setLightIntHighThreshold(LIGHT_INT_HIGH) ) {
91
+    Serial.println(F("Error writing high threshold"));
92
+  }
93
+  
94
+  // Start running the APDS-9930 light sensor (no interrupts)
95
+  if ( apds.enableLightSensor(false) ) {
96
+    Serial.println(F("Light sensor is now running"));
97
+  } else {
98
+    Serial.println(F("Something went wrong during light sensor init!"));
99
+  }
100
+  
101
+  // Read high and low interrupt thresholds
102
+  if ( !apds.getLightIntLowThreshold(threshold) ) {
103
+    Serial.println(F("Error reading low threshold"));
104
+  } else {
105
+    Serial.print(F("Low Threshold: "));
106
+    Serial.println(threshold);
107
+  }
108
+  if ( !apds.getLightIntHighThreshold(threshold) ) {
109
+    Serial.println(F("Error reading high threshold"));
110
+  } else {
111
+    Serial.print(F("High Threshold: "));
112
+    Serial.println(threshold);
113
+  }
114
+  
115
+  // Enable interrupts
116
+  if ( !apds.setAmbientLightIntEnable(1) ) {
117
+    Serial.println(F("Error enabling interrupts"));
118
+  }
119
+
120
+#ifdef DUMP_REGS
121
+  /* Register dump */
122
+  uint8_t reg;
123
+  uint8_t val;
124
+
125
+  for(reg = 0x00; reg <= 0x19; reg++) {
126
+    if( (reg != 0x10) && \
127
+        (reg != 0x11) )
128
+    {
129
+      apds.wireReadDataByte(reg, val);
130
+      Serial.print(reg, HEX);
131
+      Serial.print(": 0x");
132
+      Serial.println(val, HEX);
133
+    }
134
+  }
135
+  apds.wireReadDataByte(0x1E, val);
136
+  Serial.print(0x1E, HEX);
137
+  Serial.print(": 0x");
138
+  Serial.println(val, HEX);
139
+#endif
140
+
141
+  // Wait for initialization and calibration to finish
142
+  delay(500);
143
+}
144
+
145
+void loop() {
146
+  
147
+  // If interrupt occurs, print out the light levels
148
+  if ( isr_flag ) {
149
+    
150
+    // Read the light levels (ambient, red, green, blue) and print
151
+    if ( !apds.readAmbientLightLux(ambient_light) ||
152
+         !apds.readCh0Light(ch0) || 
153
+         !apds.readCh1Light(ch1) ) {
154
+      Serial.println("Error reading light values");
155
+    } else {
156
+      Serial.print("Interrupt! Ambient: ");
157
+      Serial.print(ambient_light);
158
+      Serial.print(F("  Ch0: "));
159
+      Serial.print(ch0);
160
+      Serial.print(F("  Ch1: "));
161
+      Serial.println(ch1);
162
+    }
163
+    
164
+    // Turn on LED for a half a second
165
+    digitalWrite(LED_PIN, HIGH);
166
+    delay(500);
167
+    digitalWrite(LED_PIN, LOW);
168
+    
169
+    // Reset flag and clear APDS-9930 interrupt (IMPORTANT!)
170
+    isr_flag = false;
171
+    if ( !apds.clearAmbientLightInt() ) {
172
+      Serial.println("Error clearing interrupt");
173
+    }
174
+    
175
+  }
176
+}
177
+
178
+void interruptRoutine() {
179
+  isr_flag = true;
180
+}

+ 113
- 0
firmware/libraries/APDS9930-master/examples/AmbientLightLED/AmbientLightLED.ino View File

@@ -0,0 +1,113 @@
1
+/****************************************************************
2
+AmbientLightLED.ino
3
+
4
+Tests the ambient light sensing abilities of the 
5
+APDS-9930. Configures APDS-9930 over I2C and polls the sensor for
6
+ambient light levels, which are displayed over the 
7
+serial console.
8
+
9
+Hardware Connections:
10
+
11
+IMPORTANT: The APDS-9930 can only accept 3.3V!
12
+ 
13
+ Arduino Pin  APDS-9930 Board  Function
14
+ 
15
+ 3.3V         VCC              Power
16
+ GND          GND              Ground
17
+ A4           SDA              I2C Data
18
+ A5           SCL              I2C Clock
19
+
20
+ 10 (pwm)     LED anode
21
+
22
+Distributed as-is; no warranty is given.
23
+****************************************************************/
24
+
25
+#define PWM_LED_PIN       10
26
+#define DUMP_REGS
27
+
28
+#include <Wire.h>
29
+#include <APDS9930.h>
30
+
31
+// Global Variables
32
+APDS9930 apds = APDS9930();
33
+float ambient_light = 0; // can also be an unsigned long
34
+uint16_t ch0 = 0;
35
+uint16_t ch1 = 1;
36
+float max_light = 0;
37
+
38
+void setup() {
39
+  //analogReference(EXTERNAL);
40
+  pinMode(PWM_LED_PIN, OUTPUT);
41
+  
42
+  // Initialize Serial port
43
+  Serial.begin(9600);
44
+  Serial.println();
45
+  Serial.println(F("--------------------------------"));
46
+  Serial.println(F("APDS-9930 - Ambient light sensor"));
47
+  Serial.println(F("--------------------------------"));
48
+  
49
+  // Initialize APDS-9930 (configure I2C and initial values)
50
+  if ( apds.init() ) {
51
+    Serial.println(F("APDS-9930 initialization complete"));
52
+  } else {
53
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
54
+  }
55
+  
56
+  // Start running the APDS-9930 light sensor (no interrupts)
57
+  if ( apds.enableLightSensor(false) ) {
58
+    Serial.println(F("Light sensor is now running"));
59
+  } else {
60
+    Serial.println(F("Something went wrong during light sensor init!"));
61
+  }
62
+
63
+#ifdef DUMP_REGS
64
+  /* Register dump */
65
+  uint8_t reg;
66
+  uint8_t val;
67
+
68
+  for(reg = 0x00; reg <= 0x19; reg++) {
69
+    if( (reg != 0x10) && \
70
+        (reg != 0x11) )
71
+    {
72
+      apds.wireReadDataByte(reg, val);
73
+      Serial.print(reg, HEX);
74
+      Serial.print(": 0x");
75
+      Serial.println(val, HEX);
76
+    }
77
+  }
78
+  apds.wireReadDataByte(0x1E, val);
79
+  Serial.print(0x1E, HEX);
80
+  Serial.print(": 0x");
81
+  Serial.println(val, HEX);
82
+#endif
83
+
84
+  // Wait for initialization and calibration to finish
85
+  delay(500);
86
+}
87
+
88
+void loop() {
89
+  
90
+  // Read the light levels (ambient, red, green, blue)
91
+  if (  !apds.readAmbientLightLux(ambient_light) ||
92
+        !apds.readCh0Light(ch0) || 
93
+        !apds.readCh1Light(ch1) ) {
94
+    Serial.println(F("Error reading light values"));
95
+  } else {
96
+    Serial.print(F("Ambient: "));
97
+    Serial.print(ambient_light);
98
+    Serial.print(F("  Ch0: "));
99
+    Serial.print(ch0);
100
+    Serial.print(F("  Ch1: "));
101
+    Serial.println(ch1);
102
+
103
+    if ( ambient_light > max_light ) {
104
+      max_light = ambient_light;
105
+    }
106
+    ambient_light = map(ambient_light, 0, max_light, 0, 1023);
107
+    analogWrite(PWM_LED_PIN, ambient_light);
108
+
109
+  }
110
+  
111
+  // Wait 1 second before next reading
112
+  delay(50);
113
+}

+ 120
- 0
firmware/libraries/APDS9930-master/examples/AmbientLightSensor/AmbientLightSensor.ino View File

@@ -0,0 +1,120 @@
1
+/****************************************************************
2
+AmbientLightSensor.ino
3
+APDS-9930 Ambient light and proximity sensor
4
+Davide Depau
5
+December 11, 2015
6
+https://github.com/Davideddu/APDS9930
7
+
8
+Shawn Hymel @ SparkFun Electronics
9
+October 15, 2014
10
+https://github.com/sparkfun/APDS-9930_RGB_and_Gesture_Sensor
11
+
12
+Tests thembient light sensing abilities of the 
13
+APDS-9930. Configures APDS-9930 over I2C and polls the sensor for
14
+ambient light levels, which are displayed over the 
15
+serial console.
16
+
17
+Hardware Connections:
18
+
19
+IMPORTANT: The APDS-9930 can only accept 3.3V!
20
+ 
21
+ Arduino Pin  APDS-9930 Board  Function
22
+ 
23
+ 3.3V         VCC              Power
24
+ GND          GND              Ground
25
+ A4           SDA              I2C Data
26
+ A5           SCL              I2C Clock
27
+
28
+Resources:
29
+Include Wire.h and APDS-9930.h
30
+
31
+Development environment specifics:
32
+Written in Arduino 1.6.5
33
+Tested with Arduino Uno and Mega.
34
+
35
+This code is beerware; if you see me (or any other SparkFun 
36
+employee) at the local, and you've found our code helpful, please
37
+buy us a round!
38
+
39
+Distributed as-is; no warranty is given.
40
+****************************************************************/
41
+
42
+#define DUMP_REGS
43
+
44
+#include <Wire.h>
45
+#include <APDS9930.h>
46
+
47
+// Global Variables
48
+APDS9930 apds = APDS9930();
49
+float ambient_light = 0; // can also be an unsigned long
50
+uint16_t ch0 = 0;
51
+uint16_t ch1 = 1;
52
+
53
+void setup() {
54
+  //analogReference(EXTERNAL);
55
+  
56
+  // Initialize Serial port
57
+  Serial.begin(9600);
58
+  Serial.println();
59
+  Serial.println(F("--------------------------------"));
60
+  Serial.println(F("APDS-9930 - Ambient light sensor"));
61
+  Serial.println(F("--------------------------------"));
62
+  
63
+  // Initialize APDS-9930 (configure I2C and initial values)
64
+  if ( apds.init() ) {
65
+    Serial.println(F("APDS-9930 initialization complete"));
66
+  } else {
67
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
68
+  }
69
+  
70
+  // Start running the APDS-9930 light sensor (no interrupts)
71
+  if ( apds.enableLightSensor(false) ) {
72
+    Serial.println(F("Light sensor is now running"));
73
+  } else {
74
+    Serial.println(F("Something went wrong during light sensor init!"));
75
+  }
76
+
77
+#ifdef DUMP_REGS
78
+  /* Register dump */
79
+  uint8_t reg;
80
+  uint8_t val;
81
+
82
+  for(reg = 0x00; reg <= 0x19; reg++) {
83
+    if( (reg != 0x10) && \
84
+        (reg != 0x11) )
85
+    {
86
+      apds.wireReadDataByte(reg, val);
87
+      Serial.print(reg, HEX);
88
+      Serial.print(": 0x");
89
+      Serial.println(val, HEX);
90
+    }
91
+  }
92
+  apds.wireReadDataByte(0x1E, val);
93
+  Serial.print(0x1E, HEX);
94
+  Serial.print(": 0x");
95
+  Serial.println(val, HEX);
96
+#endif
97
+
98
+  // Wait for initialization and calibration to finish
99
+  delay(500);
100
+}
101
+
102
+void loop() {
103
+  
104
+  // Read the light levels (ambient, red, green, blue)
105
+  if (  !apds.readAmbientLightLux(ambient_light) ||
106
+        !apds.readCh0Light(ch0) || 
107
+        !apds.readCh1Light(ch1) ) {
108
+    Serial.println(F("Error reading light values"));
109
+  } else {
110
+    Serial.print(F("Ambient: "));
111
+    Serial.print(ambient_light);
112
+    Serial.print(F("  Ch0: "));
113
+    Serial.print(ch0);
114
+    Serial.print(F("  Ch1: "));
115
+    Serial.println(ch1);
116
+  }
117
+  
118
+  // Wait 1 second before next reading
119
+  delay(1000);
120
+}

+ 108
- 0
firmware/libraries/APDS9930-master/examples/AmbientLightToneAC/AmbientLightToneAC.ino View File

@@ -0,0 +1,108 @@
1
+/****************************************************************
2
+AmbientLightToneAC.ino
3
+
4
+Tests the ambient light sensing abilities of the 
5
+APDS-9930. Configures APDS-9930 over I2C and polls the sensor for
6
+ambient light levels, which are displayed over the 
7
+serial console.
8
+
9
+Hardware Connections:
10
+
11
+IMPORTANT: The APDS-9930 can only accept 3.3V!
12
+ 
13
+ Arduino Pin  APDS-9930 Board  Function
14
+ 
15
+ 3.3V         VCC              Power
16
+ GND          GND              Ground
17
+ A4           SDA              I2C Data
18
+ A5           SCL              I2C Clock
19
+
20
+Connect speakers to the correct pins. Check toneAC.h for more info.
21
+
22
+Distributed as-is; no warranty is given.
23
+****************************************************************/
24
+
25
+#define DUMP_REGS
26
+
27
+#include <Wire.h>
28
+#include <APDS9930.h>
29
+#include <toneAC.h>
30
+
31
+// Global Variables
32
+APDS9930 apds = APDS9930();
33
+float ambient_light = 0; // can also be an unsigned long
34
+uint16_t ch0 = 0;
35
+uint16_t ch1 = 1;
36
+float max_light = 0;
37
+
38
+void setup() {
39
+  //analogReference(EXTERNAL);
40
+  
41
+  // Initialize Serial port
42
+  Serial.begin(9600);
43
+  Serial.println();
44
+  Serial.println(F("--------------------------------"));
45
+  Serial.println(F("APDS-9930 - Ambient light sensor"));
46
+  Serial.println(F("--------------------------------"));
47
+  
48
+  // Initialize APDS-9930 (configure I2C and initial values)
49
+  if ( apds.init() ) {
50
+    Serial.println(F("APDS-9930 initialization complete"));
51
+  } else {
52
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
53
+  }
54
+  
55
+  // Start running the APDS-9930 light sensor (no interrupts)
56
+  if ( apds.enableLightSensor(false) ) {
57
+    Serial.println(F("Light sensor is now running"));
58
+  } else {
59
+    Serial.println(F("Something went wrong during light sensor init!"));
60
+  }
61
+
62
+#ifdef DUMP_REGS
63
+  /* Register dump */
64
+  uint8_t reg;
65
+  uint8_t val;
66
+
67
+  for(reg = 0x00; reg <= 0x19; reg++) {
68
+    if( (reg != 0x10) && \
69
+        (reg != 0x11) )
70
+    {
71
+      apds.wireReadDataByte(reg, val);
72
+      Serial.print(reg, HEX);
73
+      Serial.print(": 0x");
74
+      Serial.println(val, HEX);
75
+    }
76
+  }
77
+  apds.wireReadDataByte(0x1E, val);
78
+  Serial.print(0x1E, HEX);
79
+  Serial.print(": 0x");
80
+  Serial.println(val, HEX);
81
+#endif
82
+
83
+  // Wait for initialization and calibration to finish
84
+  delay(500);
85
+}
86
+
87
+void loop() {
88
+  
89
+  // Read the light levels (ambient, red, green, blue)
90
+  if (  !apds.readAmbientLightLux(ambient_light) ||
91
+        !apds.readCh0Light(ch0) || 
92
+        !apds.readCh1Light(ch1) ) {
93
+    Serial.println(F("Error reading light values"));
94
+  } else {
95
+    Serial.print(F("Ambient: "));
96
+    Serial.print(ambient_light);
97
+    Serial.print(F("  Ch0: "));
98
+    Serial.print(ch0);
99
+    Serial.print(F("  Ch1: "));
100
+    Serial.println(ch1);
101
+
102
+    unsigned long freq = map(ch0, 0, 1024, 60, 16000);
103
+    toneAC(freq, 10, 50, true);
104
+  }
105
+  
106
+  // Wait 1 second before next reading
107
+  delay(50);
108
+}

+ 157
- 0
firmware/libraries/APDS9930-master/examples/ProximityInterrupt/ProximityInterrupt.ino View File

@@ -0,0 +1,157 @@
1
+/****************************************************************
2
+ProximityInterrupt.ino
3
+APDS-9930 Ambient light and proximity sensor
4
+Davide Depau
5
+December 11, 2015
6
+https://github.com/Davideddu/APDS9930
7
+
8
+Shawn Hymel @ SparkFun Electronics
9
+October 24, 2014
10
+https://github.com/sparkfun/APDS-9930_RGB_and_Gesture_Sensor
11
+
12
+Tests the proximity interrupt abilities of the APDS-9930.
13
+Configures the APDS-9930 over I2C and waits for an external
14
+interrupt based on high or low proximity conditions. Move your
15
+hand near the sensor and watch the LED on pin 13.
16
+
17
+Hardware Connections:
18
+
19
+IMPORTANT: The APDS-9930 can only accept 3.3V!
20
+ 
21
+ Arduino Pin  APDS-9930 Board  Function
22
+ 
23
+ 3.3V         VCC              Power
24
+ GND          GND              Ground
25
+ A4           SDA              I2C Data
26
+ A5           SCL              I2C Clock
27
+ 2            INT              Interrupt
28
+ 13           -                LED
29
+
30
+Resources:
31
+Include Wire.h and APDS9930.h
32
+
33
+Development environment specifics:
34
+Written in Arduino 1.6.5
35
+Tested with Arduino Uno and Mega
36
+
37
+This code is beerware; if you see me (or any other SparkFun 
38
+employee) at the local, and you've found our code helpful, please
39
+buy us a round!
40
+
41
+Distributed as-is; no warranty is given.
42
+****************************************************************/
43
+
44
+#define DUMP_REGS
45
+
46
+#include <Wire.h>
47
+#include <APDS9930.h>
48
+
49
+// Pins
50
+#define APDS9930_INT    2  // Needs to be an interrupt pin
51
+#define LED_PIN         13 // LED for showing interrupt
52
+
53
+// Constants
54
+#define PROX_INT_HIGH   600 // Proximity level for interrupt
55
+#define PROX_INT_LOW    0  // No far interrupt
56
+
57
+// Global variables
58
+APDS9930 apds = APDS9930();
59
+uint16_t proximity_data = 0;
60
+volatile bool isr_flag = false;
61
+
62
+void setup() {
63
+  
64
+  // Set LED as output
65
+  pinMode(LED_PIN, OUTPUT);
66
+  pinMode(APDS9930_INT, INPUT);
67
+  
68
+  // Initialize Serial port
69
+  Serial.begin(9600);
70
+  Serial.println();
71
+  Serial.println(F("------------------------------"));
72
+  Serial.println(F("APDS-9930 - ProximityInterrupt"));
73
+  Serial.println(F("------------------------------"));
74
+  
75
+  // Initialize interrupt service routine
76
+  attachInterrupt(0, interruptRoutine, FALLING);
77
+  
78
+  // Initialize APDS-9930 (configure I2C and initial values)
79
+  if ( apds.init() ) {
80
+    Serial.println(F("APDS-9930 initialization complete"));
81
+  } else {
82
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
83
+  }
84
+  
85
+  // Adjust the Proximity sensor gain
86
+  if ( !apds.setProximityGain(PGAIN_2X) ) {
87
+    Serial.println(F("Something went wrong trying to set PGAIN"));
88
+  }
89
+  
90
+  // Set proximity interrupt thresholds
91
+  if ( !apds.setProximityIntLowThreshold(PROX_INT_LOW) ) {
92
+    Serial.println(F("Error writing low threshold"));
93
+  }
94
+  if ( !apds.setProximityIntHighThreshold(PROX_INT_HIGH) ) {
95
+    Serial.println(F("Error writing high threshold"));
96
+  }
97
+  
98
+  // Start running the APDS-9930 proximity sensor (interrupts)
99
+  if ( apds.enableProximitySensor(true) ) {
100
+    Serial.println(F("Proximity sensor is now running"));
101
+  } else {
102
+    Serial.println(F("Something went wrong during sensor init!"));
103
+  }
104
+
105
+#ifdef DUMP_REGS
106
+  /* Register dump */
107
+  uint8_t reg;
108
+  uint8_t val;
109
+
110
+  for(reg = 0x00; reg <= 0x19; reg++) {
111
+    if( (reg != 0x10) && \
112
+        (reg != 0x11) )
113
+    {
114
+      apds.wireReadDataByte(reg, val);
115
+      Serial.print(reg, HEX);
116
+      Serial.print(": 0x");
117
+      Serial.println(val, HEX);
118
+    }
119
+  }
120
+  apds.wireReadDataByte(0x1E, val);
121
+  Serial.print(0x1E, HEX);
122
+  Serial.print(": 0x");
123
+  Serial.println(val, HEX);
124
+#endif
125
+
126
+}
127
+
128
+void loop() {
129
+  
130
+  // If interrupt occurs, print out the proximity level
131
+  if ( isr_flag ) {
132
+  
133
+    // Read proximity level and print it out
134
+    if ( !apds.readProximity(proximity_data) ) {
135
+      Serial.println("Error reading proximity value");
136
+    } else {
137
+      Serial.print("Proximity detected! Level: ");
138
+      Serial.println(proximity_data);
139
+    }
140
+    
141
+    // Turn on LED for a half a second
142
+    digitalWrite(LED_PIN, HIGH);
143
+    delay(500);
144
+    digitalWrite(LED_PIN, LOW);
145
+    
146
+    // Reset flag and clear APDS-9930 interrupt (IMPORTANT!)
147
+    isr_flag = false;
148
+    if ( !apds.clearProximityInt() ) {
149
+      Serial.println("Error clearing interrupt");
150
+    }
151
+    
152
+  }
153
+}
154
+
155
+void interruptRoutine() {
156
+  isr_flag = true;
157
+}

+ 131
- 0
firmware/libraries/APDS9930-master/examples/ProximityLED/ProximityLED.ino View File

@@ -0,0 +1,131 @@
1
+/****************************************************************
2
+ProximityLED.ino
3
+Davide Depau
4
+December 11, 2015
5
+https://github.com/Davideddu/APDS9930
6
+
7
+https://github.com/sparkfun/APDS-9930_RGB_and_Gesture_Sensor
8
+
9
+Tests the proximity sensing abilities of the APDS-9930.
10
+Configures the APDS-9930 over I2C and polls for the distance to
11
+the object nearest the sensor, then turns on an LED accordingly.
12
+
13
+Hardware Connections:
14
+
15
+IMPORTANT: The APDS-9930 can only accept 3.3V!
16
+ 
17
+ Arduino Pin  APDS-9930 Board  Function
18
+ 
19
+ 3.3V         VCC              Power
20
+ GND          GND              Ground
21
+ A4           SDA              I2C Data
22
+ A5           SCL              I2C Clock
23
+
24
+ 10 (PWM)     LED Anode
25
+
26
+Resources:
27
+Include Wire.h and APDS9930.h
28
+
29
+Development environment specifics:
30
+Written in Sublime Text + Stino + Arduino 1.7.2
31
+Tested with Arduino Uno + level shifter
32
+
33
+This code is chocolateware; if you see me at the grocery store,
34
+and you've found our code helpful, please buy us me a chocolate bar! :D
35
+
36
+Distributed as-is; no warranty is given.
37
+****************************************************************/
38
+
39
+#define DUMP_REGS
40
+#define PWM_LED_PIN       10
41
+
42
+#include <Wire.h>
43
+#include <APDS9930.h>
44
+
45
+// Global Variables
46
+APDS9930 apds = APDS9930();
47
+uint16_t proximity_data = 0;
48
+int proximity_max = 0;
49
+
50
+void setup() {
51
+  //analogReference(EXTERNAL);
52
+  pinMode(PWM_LED_PIN, OUTPUT);
53
+
54
+  // Initialize Serial port
55
+  Serial.begin(9600);
56
+  Serial.println();
57
+  Serial.println(F("------------------------"));
58
+  Serial.println(F("APDS-9930 - ProximityLED"));
59
+  Serial.println(F("------------------------"));
60
+  
61
+  // Initialize APDS-9930 (configure I2C and initial values)
62
+  if ( apds.init() ) {
63
+    Serial.println(F("APDS-9930 initialization complete"));
64
+  } else {
65
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
66
+  }
67
+  
68
+  // Adjust the Proximity sensor gain
69
+  if ( !apds.setProximityGain(PGAIN_1X) ) {
70
+    Serial.println(F("Something went wrong trying to set PGAIN"));
71
+  }
72
+  
73
+  // Start running the APDS-9930 proximity sensor (no interrupts)
74
+  if ( apds.enableProximitySensor(false) ) {
75
+    Serial.println(F("Proximity sensor is now running"));
76
+  } else {
77
+    Serial.println(F("Something went wrong during sensor init!"));
78
+  }
79
+
80
+#ifdef DUMP_REGS
81
+  /* Register dump */
82
+  uint8_t reg;
83
+  uint8_t val;
84
+
85
+  for(reg = 0x00; reg <= 0x19; reg++) {
86
+    if( (reg != 0x10) && \
87
+        (reg != 0x11) )
88
+    {
89
+      apds.wireReadDataByte(reg, val);
90
+      Serial.print(reg, HEX);
91
+      Serial.print(": 0x");
92
+      Serial.println(val, HEX);
93
+    }
94
+  }
95
+  apds.wireReadDataByte(0x1E, val);
96
+  Serial.print(0x1E, HEX);
97
+  Serial.print(": 0x");
98
+  Serial.println(val, HEX);
99
+#endif
100
+}
101
+
102
+void loop() {
103
+  
104
+  // Read the proximity value
105
+  if ( !apds.readProximity(proximity_data) ) {
106
+    Serial.println("Error reading proximity value");
107
+  } else {
108
+    Serial.print("Proximity: ");
109
+    Serial.print(proximity_data);
110
+
111
+    // This is an ugly hack to reduce sensor noise.
112
+    // You may want to adjust POFFSET instead.
113
+    /*
114
+    proximity_data -= 200;
115
+    if (proximity_data > 50000) {
116
+      proximity_data = 0;
117
+    }
118
+    if (proximity_data > proximity_max) {
119
+      proximity_max = proximity_data;
120
+    }
121
+    proximity_data = map(proximity_data, 0, proximity_max, 0, 1023);
122
+    */
123
+
124
+    Serial.print(F("  Remapped: "));
125
+    Serial.println(proximity_data);
126
+    analogWrite(PWM_LED_PIN, proximity_data);
127
+  }
128
+  
129
+  // Wait 250 ms before next reading
130
+  delay(10);
131
+}

+ 113
- 0
firmware/libraries/APDS9930-master/examples/ProximitySensor/ProximitySensor.ino View File

@@ -0,0 +1,113 @@
1
+/****************************************************************
2
+ProximitySensor.ino
3
+APDS-9930 ambient light and proximity sensor
4
+Davide Depau
5
+December 11, 2015
6
+https://github.com/Davideddu/APDS9930
7
+
8
+Shawn Hymel @ SparkFun Electronics
9
+October 28, 2014
10
+https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
11
+
12
+Tests the proximity sensing abilities of the APDS-9930.
13
+Configures the APDS-9930 over I2C and polls for the distance to
14
+the object nearest the sensor.
15
+
16
+Hardware Connections:
17
+
18
+IMPORTANT: The APDS-9930 can only accept 3.3V!
19
+ 
20
+ Arduino Pin  APDS-9930 Board  Function
21
+ 
22
+ 3.3V         VCC              Power
23
+ GND          GND              Ground
24
+ A4           SDA              I2C Data
25
+ A5           SCL              I2C Clock
26
+
27
+Resources:
28
+Include Wire.h and SparkFun_APDS-9930.h
29
+
30
+Development environment specifics:
31
+Written in Arduino 1.0.5
32
+Tested with SparkFun Arduino Pro Mini 3.3V
33
+
34
+This code is beerware; if you see me (or any other SparkFun 
35
+employee) at the local, and you've found our code helpful, please
36
+buy us a round!
37
+
38
+Distributed as-is; no warranty is given.
39
+****************************************************************/
40
+
41
+#define DUMP_REGS
42
+
43
+#include <Wire.h>
44
+#include <APDS9930.h>
45
+
46
+// Global Variables
47
+APDS9930 apds = APDS9930();
48
+uint16_t proximity_data = 0;
49
+
50
+void setup() {
51
+  //analogReference(EXTERNAL);
52
+
53
+  // Initialize Serial port
54
+  Serial.begin(9600);
55
+  Serial.println();
56
+  Serial.println(F("---------------------------"));
57
+  Serial.println(F("APDS-9930 - ProximitySensor"));
58
+  Serial.println(F("---------------------------"));
59
+  
60
+  // Initialize APDS-9930 (configure I2C and initial values)
61
+  if ( apds.init() ) {
62
+    Serial.println(F("APDS-9930 initialization complete"));
63
+  } else {
64
+    Serial.println(F("Something went wrong during APDS-9930 init!"));
65
+  }
66
+  
67
+  // // Adjust the Proximity sensor gain
68
+  // if ( !apds.setProximityGain(PGAIN_2X) ) {
69
+  //   Serial.println(F("Something went wrong trying to set PGAIN"));
70
+  // }
71
+  
72
+  // Start running the APDS-9930 proximity sensor (no interrupts)
73
+  if ( apds.enableProximitySensor(false) ) {
74
+    Serial.println(F("Proximity sensor is now running"));
75
+  } else {
76
+    Serial.println(F("Something went wrong during sensor init!"));
77
+  }
78
+
79
+#ifdef DUMP_REGS
80
+  /* Register dump */
81
+  uint8_t reg;
82
+  uint8_t val;
83
+
84
+  for(reg = 0x00; reg <= 0x19; reg++) {
85
+    if( (reg != 0x10) && \
86
+        (reg != 0x11) )
87
+    {
88
+      apds.wireReadDataByte(reg, val);
89
+      Serial.print(reg, HEX);
90
+      Serial.print(": 0x");
91
+      Serial.println(val, HEX);
92
+    }
93
+  }
94
+  apds.wireReadDataByte(0x1E, val);
95
+  Serial.print(0x1E, HEX);
96
+  Serial.print(": 0x");
97
+  Serial.println(val, HEX);
98
+#endif
99
+}
100
+
101
+void loop() {
102
+  
103
+  // Read the proximity value
104
+  if ( !apds.readProximity(proximity_data) ) {
105
+    Serial.println("Error reading proximity value");
106
+  } else {
107
+    Serial.print("Proximity: ");
108
+    Serial.println(proximity_data);
109
+  }
110
+  
111
+  // Wait 250 ms before next reading
112
+  delay(250);
113
+}

+ 0
- 0
firmware/libraries/APDS9930-master/keywords.txt View File


+ 9
- 0
firmware/libraries/APDS9930-master/library.properties View File

@@ -0,0 +1,9 @@
1
+name=APDS-9930 Ambient Light and Proximity Sensor
2
+version=1.5.1
3
+author=Davide Depau
4
+maintainer=Davide Depau
5
+sentence=Library for the Avago APDS-9930 sensor
6
+paragraph=This library works with the breakout board for the Avago APDS-9930 proximity and light sensor
7
+category=Sensors
8
+url=https://github.com/Davideddu/APDS9930
9
+architectures=*

+ 1147
- 0
firmware/libraries/APDS9930-master/src/APDS9930.cpp View File

@@ -0,0 +1,1147 @@
1
+/**
2
+ * @file    APDS-9930.cpp
3
+ * @brief   Library for the SparkFun APDS-9930 breakout board
4
+ * @author  Shawn Hymel (SparkFun Electronics)
5
+ *
6
+ * @copyright	This code is public domain but you buy me a beer if you use
7
+ * this and we meet someday (Beerware license).
8
+ *
9
+ * This library interfaces the Avago APDS-9930 to Arduino over I2C. The library
10
+ * relies on the Arduino Wire (I2C) library. to use the library, instantiate an
11
+ * APDS9930 object, call init(), and call the appropriate functions.
12
+ *
13
+ * APDS-9930 current draw tests (default parameters):
14
+ *   Off:                   1mA
15
+ *   Waiting for gesture:   14mA
16
+ *   Gesture in progress:   35mA
17
+ */
18
+ 
19
+ #include <Arduino.h>
20
+ #include <Wire.h>
21
+ 
22
+ #include "APDS9930.h"
23
+ 
24
+/**
25
+ * @brief Constructor - Instantiates APDS9930 object
26
+ */
27
+APDS9930::APDS9930()
28
+{
29
+
30
+}
31
+ 
32
+/**
33
+ * @brief Destructor
34
+ */
35
+APDS9930::~APDS9930()
36
+{
37
+
38
+}
39
+
40
+/**
41
+ * @brief Configures I2C communications and initializes registers to defaults
42
+ *
43
+ * @return True if initialized successfully. False otherwise.
44
+ */
45
+bool APDS9930::init()
46
+{
47
+    uint8_t id;
48
+
49
+    /* Initialize I2C */
50
+    Wire.begin();
51
+     
52
+    /* Read ID register and check against known values for APDS-9930 */
53
+    if( !wireReadDataByte(APDS9930_ID, id) ) {
54
+        Serial.println(F("ID read"));
55
+        return false;
56
+    }
57
+    if( !(id == APDS9930_ID_1 || id == APDS9930_ID_2) ) {
58
+        Serial.println(F("ID check"));
59
+        Serial.println(String("ID is ") + String(id, HEX));
60
+        //return false;
61
+    }
62
+     
63
+    /* Set ENABLE register to 0 (disable all features) */
64
+    if( !setMode(ALL, OFF) ) {
65
+        Serial.println(F("Regs off"));
66
+        return false;
67
+    }
68
+    
69
+    /* Set default values for ambient light and proximity registers */
70
+    if( !wireWriteDataByte(APDS9930_ATIME, DEFAULT_ATIME) ) {
71
+        return false;
72
+    }
73
+    if( !wireWriteDataByte(APDS9930_WTIME, DEFAULT_WTIME) ) {
74
+        return false;
75
+    }
76
+    if( !wireWriteDataByte(APDS9930_PPULSE, DEFAULT_PPULSE) ) {
77
+        return false;
78
+    }
79
+    if( !wireWriteDataByte(APDS9930_POFFSET, DEFAULT_POFFSET) ) {
80
+        return false;
81
+    }
82
+    if( !wireWriteDataByte(APDS9930_CONFIG, DEFAULT_CONFIG) ) {
83
+        return false;
84
+    }
85
+    if( !setLEDDrive(DEFAULT_PDRIVE) ) {
86
+        return false;
87
+    }
88
+    if( !setProximityGain(DEFAULT_PGAIN) ) {
89
+        return false;
90
+    }
91
+    if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
92
+        return false;
93
+    }
94
+    if( !setProximityDiode(DEFAULT_PDIODE) ) {
95
+        return false;
96
+    }
97
+    if( !setProximityIntLowThreshold(DEFAULT_PILT) ) {
98
+        return false;
99
+    }
100
+    if( !setProximityIntHighThreshold(DEFAULT_PIHT) ) {
101
+        return false;
102
+    }
103
+    if( !setLightIntLowThreshold(DEFAULT_AILT) ) {
104
+        return false;
105
+    }
106
+    if( !setLightIntHighThreshold(DEFAULT_AIHT) ) {
107
+        return false;
108
+    }
109
+    if( !wireWriteDataByte(APDS9930_PERS, DEFAULT_PERS) ) {
110
+        return false;
111
+    }
112
+
113
+    return true;
114
+}
115
+
116
+/*******************************************************************************
117
+ * Public methods for controlling the APDS-9930
118
+ ******************************************************************************/
119
+
120
+/**
121
+ * @brief Reads and returns the contents of the ENABLE register
122
+ *
123
+ * @return Contents of the ENABLE register. 0xFF if error.
124
+ */
125
+uint8_t APDS9930::getMode()
126
+{
127
+    uint8_t enable_value;
128
+    
129
+    /* Read current ENABLE register */
130
+    if( !wireReadDataByte(APDS9930_ENABLE, enable_value) ) {
131
+        return ERROR;
132
+    }
133
+    
134
+    return enable_value;
135
+}
136
+
137
+/**
138
+ * @brief Enables or disables a feature in the APDS-9930
139
+ *
140
+ * @param[in] mode which feature to enable
141
+ * @param[in] enable ON (1) or OFF (0)
142
+ * @return True if operation success. False otherwise.
143
+ */
144
+bool APDS9930::setMode(uint8_t mode, uint8_t enable)
145
+{
146
+    uint8_t reg_val;
147
+
148
+    /* Read current ENABLE register */
149
+    reg_val = getMode();
150
+    if( reg_val == ERROR ) {
151
+        return false;
152
+    }
153
+    
154
+    /* Change bit(s) in ENABLE register */
155
+    enable = enable & 0x01;
156
+    if( mode >= 0 && mode <= 6 ) {
157
+        if (enable) {
158
+            reg_val |= (1 << mode);
159
+        } else {
160
+            reg_val &= ~(1 << mode);
161
+        }
162
+    } else if( mode == ALL ) {
163
+        if (enable) {
164
+            reg_val = 0x7F;
165
+        } else {
166
+            reg_val = 0x00;
167
+        }
168
+    }
169
+        
170
+    /* Write value back to ENABLE register */
171
+    if( !wireWriteDataByte(APDS9930_ENABLE, reg_val) ) {
172
+        return false;
173
+    }
174
+        
175
+    return true;
176
+}
177
+
178
+/**
179
+ * @brief Starts the light (Ambient/IR) sensor on the APDS-9930
180
+ *
181
+ * @param[in] interrupts true to enable hardware interrupt on high or low light
182
+ * @return True if sensor enabled correctly. False on error.
183
+ */
184
+bool APDS9930::enableLightSensor(bool interrupts)
185
+{
186
+    
187
+    /* Set default gain, interrupts, enable power, and enable sensor */
188
+    if( !setAmbientLightGain(DEFAULT_AGAIN) ) {
189
+        return false;
190
+    }
191
+    if( interrupts ) {
192
+        if( !setAmbientLightIntEnable(1) ) {
193
+            return false;
194
+        }
195
+    } else {
196
+        if( !setAmbientLightIntEnable(0) ) {
197
+            return false;
198
+        }
199
+    }
200
+    if( !enablePower() ){
201
+        return false;
202
+    }
203
+    if( !setMode(AMBIENT_LIGHT, 1) ) {
204
+        return false;
205
+    }
206
+    
207
+    return true;
208
+
209
+}
210
+
211
+/**
212
+ * @brief Ends the light sensor on the APDS-9930
213
+ *
214
+ * @return True if sensor disabled correctly. False on error.
215
+ */
216
+bool APDS9930::disableLightSensor()
217
+{
218
+    if( !setAmbientLightIntEnable(0) ) {
219
+        return false;
220
+    }
221
+    if( !setMode(AMBIENT_LIGHT, 0) ) {
222
+        return false;
223
+    }
224
+    
225
+    return true;
226
+}
227
+
228
+/**
229
+ * @brief Starts the proximity sensor on the APDS-9930
230
+ *
231
+ * @param[in] interrupts true to enable hardware external interrupt on proximity
232
+ * @return True if sensor enabled correctly. False on error.
233
+ */
234
+bool APDS9930::enableProximitySensor(bool interrupts)
235
+{
236
+    /* Set default gain, LED, interrupts, enable power, and enable sensor */
237
+    if( !setProximityGain(DEFAULT_PGAIN) ) {
238
+        return false;
239
+    }
240
+    if( !setLEDDrive(DEFAULT_PDRIVE) ) {
241
+        return false;
242
+    }
243
+    if( interrupts ) {
244
+        if( !setProximityIntEnable(1) ) {
245
+            return false;
246
+        }
247
+    } else {
248
+        if( !setProximityIntEnable(0) ) {
249
+            return false;
250
+        }
251
+    }
252
+    if( !enablePower() ){
253
+        return false;
254
+    }
255
+    if( !setMode(PROXIMITY, 1) ) {
256
+        return false;
257
+    }
258
+    
259
+    return true;
260
+}
261
+
262
+/**
263
+ * @brief Ends the proximity sensor on the APDS-9930
264
+ *
265
+ * @return True if sensor disabled correctly. False on error.
266
+ */
267
+bool APDS9930::disableProximitySensor()
268
+{
269
+	if( !setProximityIntEnable(0) ) {
270
+		return false;
271
+	}
272
+	if( !setMode(PROXIMITY, 0) ) {
273
+		return false;
274
+	}
275
+
276
+	return true;
277
+}
278
+
279
+/**
280
+ * Turn the APDS-9930 on
281
+ *
282
+ * @return True if operation successful. False otherwise.
283
+ */
284
+bool APDS9930::enablePower()
285
+{
286
+    if( !setMode(POWER, 1) ) {
287
+        return false;
288
+    }
289
+    
290
+    return true;
291
+}
292
+
293
+/**
294
+ * Turn the APDS-9930 off
295
+ *
296
+ * @return True if operation successful. False otherwise.
297
+ */
298
+bool APDS9930::disablePower()
299
+{
300
+    if( !setMode(POWER, 0) ) {
301
+        return false;
302
+    }
303
+    
304
+    return true;
305
+}
306
+
307
+/*******************************************************************************
308
+ * Ambient light sensor controls
309
+ ******************************************************************************/
310
+
311
+/**
312
+ * @brief Reads the ambient (clear) light level as a 16-bit value
313
+ *
314
+ * @param[out] val value of the light sensor.
315
+ * @return True if operation successful. False otherwise.
316
+ */
317
+bool APDS9930::readAmbientLightLux(float &val)
318
+{
319
+    uint16_t Ch0;
320
+    uint16_t Ch1;
321
+    
322
+    /* Read value from channel 0 */
323
+    if( !readCh0Light(Ch0) ) {
324
+        return false;
325
+    }
326
+
327
+    /* Read value from channel 1 */
328
+    if( !readCh1Light(Ch1) ) {
329
+        return false;
330
+    }
331
+
332
+    val = floatAmbientToLux(Ch0, Ch1);
333
+    return true;
334
+}
335
+
336
+bool APDS9930::readAmbientLightLux(unsigned long &val)
337
+{
338
+    uint16_t Ch0;
339
+    uint16_t Ch1;
340
+    
341
+    /* Read value from channel 0 */
342
+    if( !readCh0Light(Ch0) ) {
343
+        return false;
344
+    }
345
+
346
+    /* Read value from channel 1 */
347
+    if( !readCh1Light(Ch1) ) {
348
+        return false;
349
+    }
350
+
351
+    val = ulongAmbientToLux(Ch0, Ch1);
352
+    return true;
353
+}
354
+
355
+float APDS9930::floatAmbientToLux(uint16_t Ch0, uint16_t Ch1)
356
+{
357
+	uint8_t x[4]={1,8,16,120};
358
+    float ALSIT = 2.73 * (256 - DEFAULT_ATIME);
359
+    float iac  = max(Ch0 - B * Ch1, C * Ch0 - D * Ch1);
360
+    if (iac < 0) iac = 0;
361
+	float lpc  = GA * DF / (ALSIT * x[getAmbientLightGain()]);
362
+    return iac * lpc;
363
+}
364
+
365
+unsigned long APDS9930::ulongAmbientToLux(uint16_t Ch0, uint16_t Ch1)
366
+{
367
+	uint8_t x[4]={1,8,16,120};
368
+    unsigned long ALSIT = 2.73 * (256 - DEFAULT_ATIME);
369
+    unsigned long iac  = max(Ch0 - B * Ch1, C * Ch0 - D * Ch1);
370
+	if (iac < 0) iac = 0;
371
+    unsigned long lpc  = GA * DF / (ALSIT * x[getAmbientLightGain()]);
372
+    return iac * lpc;
373
+}
374
+
375
+bool APDS9930::readCh0Light(uint16_t &val)
376
+{
377
+    uint8_t val_byte;
378
+    val = 0;
379
+    
380
+    /* Read value from channel 0 */
381
+    if( !wireReadDataByte(APDS9930_Ch0DATAL, val_byte) ) {
382
+        return false;
383
+    }
384
+    val = val_byte;
385
+    if( !wireReadDataByte(APDS9930_Ch0DATAH, val_byte) ) {
386
+        return false;
387
+    }
388
+    val += ((uint16_t)val_byte << 8);
389
+    return true;
390
+}
391
+
392
+bool APDS9930::readCh1Light(uint16_t &val)
393
+{
394
+    uint8_t val_byte;
395
+    val = 0;
396
+    
397
+    /* Read value from channel 0 */
398
+    if( !wireReadDataByte(APDS9930_Ch1DATAL, val_byte) ) {
399
+        return false;
400
+    }
401
+    val = val_byte;
402
+    if( !wireReadDataByte(APDS9930_Ch1DATAH, val_byte) ) {
403
+        return false;
404
+    }
405
+    val += ((uint16_t)val_byte << 8);
406
+    return true;
407
+}
408
+
409
+/*******************************************************************************
410
+ * Proximity sensor controls
411
+ ******************************************************************************/
412
+
413
+/**
414
+ * @brief Reads the proximity level as an 8-bit value
415
+ *
416
+ * @param[out] val value of the proximity sensor.
417
+ * @return True if operation successful. False otherwise.
418
+ */
419
+bool APDS9930::readProximity(uint16_t &val)
420
+{
421
+    val = 0;
422
+    uint8_t val_byte;
423
+
424
+    /* Read value from proximity data register */
425
+    if( !wireReadDataByte(APDS9930_PDATAL, val_byte) ) {
426
+        return false;
427
+    }
428
+    val = val_byte;
429
+    if( !wireReadDataByte(APDS9930_PDATAH, val_byte) ) {
430
+        return false;
431
+    }
432
+    val += ((uint16_t)val_byte << 8);
433
+    
434
+    return true;
435
+}
436
+
437
+/*******************************************************************************
438
+ * Getters and setters for register values
439
+ ******************************************************************************/
440
+
441
+/**
442
+ * @brief Returns the lower threshold for proximity detection
443
+ *
444
+ * @return lower threshold
445
+ */
446
+uint16_t APDS9930::getProximityIntLowThreshold()
447
+{
448
+    uint16_t val;
449
+    uint8_t val_byte;
450
+    
451
+    /* Read value from PILT register */
452
+    if( !wireReadDataByte(APDS9930_PILTL, val_byte) ) {
453
+        val = 0;
454
+    }
455
+    val = val_byte;
456
+    if( !wireReadDataByte(APDS9930_PILTH, val_byte) ) {
457
+        val = 0;
458
+    }
459
+    val |= ((uint16_t)val_byte << 8);    
460
+    
461
+    return val;
462
+}
463
+
464
+/**
465
+ * @brief Sets the lower threshold for proximity detection
466
+ *
467
+ * @param[in] threshold the lower proximity threshold
468
+ * @return True if operation successful. False otherwise.
469
+ */
470
+bool APDS9930::setProximityIntLowThreshold(uint16_t threshold)
471
+{
472
+    uint8_t lo;
473
+    uint8_t hi;
474
+    hi = threshold >> 8;
475
+    lo = threshold & 0x00FF;
476
+
477
+    if( !wireWriteDataByte(APDS9930_PILTL, lo) ) {
478
+        return false;
479
+    }
480
+    if( !wireWriteDataByte(APDS9930_PILTH, hi) ) {
481
+        return false;
482
+    }
483
+    
484
+    return true;
485
+}
486
+
487
+/**
488
+ * @brief Returns the high threshold for proximity detection
489
+ *
490
+ * @return high threshold
491
+ */
492
+uint16_t APDS9930::getProximityIntHighThreshold()
493
+{
494
+    uint16_t val;
495
+    uint8_t val_byte;
496
+    
497
+    /* Read value from PILT register */
498
+    if( !wireReadDataByte(APDS9930_PIHTL, val_byte) ) {
499
+        val = 0;
500
+    }
501
+    val = val_byte;
502
+    if( !wireReadDataByte(APDS9930_PIHTH, val_byte) ) {
503
+        val = 0;
504
+    }
505
+    val |= ((uint16_t)val_byte << 8);    
506
+    
507
+    return val;
508
+}
509
+
510
+/**
511
+ * @brief Sets the high threshold for proximity detection
512
+ *
513
+ * @param[in] threshold the high proximity threshold
514
+ * @return True if operation successful. False otherwise.
515
+ */
516
+bool APDS9930::setProximityIntHighThreshold(uint16_t threshold)
517
+{
518
+    uint8_t lo;
519
+    uint8_t hi;
520
+    hi = threshold >> 8;
521
+    lo = threshold & 0x00FF;
522
+
523
+    if( !wireWriteDataByte(APDS9930_PIHTL, lo) ) {
524
+        return false;
525
+    }
526
+    if( !wireWriteDataByte(APDS9930_PIHTH, hi) ) {
527
+        return false;
528
+    }
529
+    
530
+    return true;
531
+}
532
+
533
+/**
534
+ * @brief Returns LED drive strength for proximity and ALS
535
+ *
536
+ * Value    LED Current
537
+ *   0        100 mA
538
+ *   1         50 mA
539
+ *   2         25 mA
540
+ *   3         12.5 mA
541
+ *
542
+ * @return the value of the LED drive strength. 0xFF on failure.
543
+ */
544
+uint8_t APDS9930::getLEDDrive()
545
+{
546
+    uint8_t val;
547
+    
548
+    /* Read value from CONTROL register */
549
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
550
+        return ERROR;
551
+    }
552
+    
553
+    /* Shift and mask out LED drive bits */
554
+    val = (val >> 6) & 0b00000011;
555
+    
556
+    return val;
557
+}
558
+
559
+/**
560
+ * @brief Sets the LED drive strength for proximity and ALS
561
+ *
562
+ * Value    LED Current
563
+ *   0        100 mA
564
+ *   1         50 mA
565
+ *   2         25 mA
566
+ *   3         12.5 mA
567
+ *
568
+ * @param[in] drive the value (0-3) for the LED drive strength
569
+ * @return True if operation successful. False otherwise.
570
+ */
571
+bool APDS9930::setLEDDrive(uint8_t drive)
572
+{
573
+    uint8_t val;
574
+    
575
+    /* Read value from CONTROL register */
576
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
577
+        return false;
578
+    }
579
+    
580
+    /* Set bits in register to given value */
581
+    drive &= 0b00000011;
582
+    drive = drive << 6;
583
+    val &= 0b00111111;
584
+    val |= drive;
585
+    
586
+    /* Write register value back into CONTROL register */
587
+    if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
588
+        return false;
589
+    }
590
+    
591
+    return true;
592
+}
593
+
594
+/**
595
+ * @brief Returns receiver gain for proximity detection
596
+ *
597
+ * Value    Gain
598
+ *   0       1x
599
+ *   1       2x
600
+ *   2       4x
601
+ *   3       8x
602
+ *
603
+ * @return the value of the proximity gain. 0xFF on failure.
604
+ */
605
+uint8_t APDS9930::getProximityGain()
606
+{
607
+    uint8_t val;
608
+    
609
+    /* Read value from CONTROL register */
610
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
611
+        return ERROR;
612
+    }
613
+    
614
+    /* Shift and mask out PDRIVE bits */
615
+    val = (val >> 2) & 0b00000011;
616
+    
617
+    return val;
618
+}
619
+
620
+/**
621
+ * @brief Sets the receiver gain for proximity detection
622
+ *
623
+ * Value    Gain
624
+ *   0       1x
625
+ *   1       2x
626
+ *   2       4x
627
+ *   3       8x
628
+ *
629
+ * @param[in] drive the value (0-3) for the gain
630
+ * @return True if operation successful. False otherwise.
631
+ */
632
+bool APDS9930::setProximityGain(uint8_t drive)
633
+{
634
+    uint8_t val;
635
+    
636
+    /* Read value from CONTROL register */
637
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
638
+        return false;
639
+    }
640
+    
641
+    /* Set bits in register to given value */
642
+    drive &= 0b00000011;
643
+    drive = drive << 2;
644
+    val &= 0b11110011;
645
+    val |= drive;
646
+    
647
+    /* Write register value back into CONTROL register */
648
+    if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
649
+        return false;
650
+    }
651
+    
652
+    return true;
653
+}
654
+
655
+/**
656
+ * @brief Returns the proximity diode
657
+ *
658
+ * Value    Diode selection
659
+ *   0       Reserved
660
+ *   1       Reserved
661
+ *   2       Use Ch1 diode
662
+ *   3       Reserved
663
+ *
664
+ * @return the selected diode. 0xFF on failure.
665
+ */
666
+uint8_t APDS9930::getProximityDiode()
667
+{
668
+    uint8_t val;
669
+    
670
+    /* Read value from CONTROL register */
671
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
672
+        return ERROR;
673
+    }
674
+    
675
+    /* Shift and mask out PDRIVE bits */
676
+    val = (val >> 4) & 0b00000011;
677
+    
678
+    return val;
679
+}
680
+
681
+/**
682
+ * @brief Selects the proximity diode
683
+ *
684
+ * Value    Diode selection
685
+ *   0       Reserved
686
+ *   1       Reserved
687
+ *   2       Use Ch1 diode
688
+ *   3       Reserved
689
+ *
690
+ * @param[in] drive the value (0-3) for the diode
691
+ * @return True if operation successful. False otherwise.
692
+ */
693
+bool APDS9930::setProximityDiode(uint8_t drive)
694
+{
695
+    uint8_t val;
696
+    
697
+    /* Read value from CONTROL register */
698
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
699
+        return false;
700
+    }
701
+    
702
+    /* Set bits in register to given value */
703
+    drive &= 0b00000011;
704
+    drive = drive << 4;
705
+    val &= 0b11001111;
706
+    val |= drive;
707
+    
708
+    /* Write register value back into CONTROL register */
709
+    if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
710
+        return false;
711
+    }
712
+    
713
+    return true;
714
+}
715
+
716
+/**
717
+ * @brief Returns receiver gain for the ambient light sensor (ALS)
718
+ *
719
+ * Value    Gain
720
+ *   0        1x
721
+ *   1        4x
722
+ *   2       16x
723
+ *   3      120x
724
+ *
725
+ * @return the value of the ALS gain. 0xFF on failure.
726
+ */
727
+uint8_t APDS9930::getAmbientLightGain()
728
+{
729
+    uint8_t val;
730
+    
731
+    /* Read value from CONTROL register */
732
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
733
+        return ERROR;
734
+    }
735
+    
736
+    /* Shift and mask out ADRIVE bits */
737
+    val &= 0b00000011;
738
+	
739
+    return val;
740
+}
741
+
742
+/**
743
+ * @brief Sets the receiver gain for the ambient light sensor (ALS)
744
+ *
745
+ * Value    Gain
746
+ *   0        1x
747
+ *   1        4x
748
+ *   2       16x
749
+ *   3       64x
750
+ *
751
+ * @param[in] drive the value (0-3) for the gain
752
+ * @return True if operation successful. False otherwise.
753
+ */
754
+bool APDS9930::setAmbientLightGain(uint8_t drive)
755
+{
756
+    uint8_t val;
757
+    
758
+    /* Read value from CONTROL register */
759
+    if( !wireReadDataByte(APDS9930_CONTROL, val) ) {
760
+        return false;
761
+    }
762
+    
763
+    /* Set bits in register to given value */
764
+    drive &= 0b00000011;
765
+    val &= 0b11111100;
766
+    val |= drive;
767
+    
768
+    /* Write register value back into CONTROL register */
769
+    if( !wireWriteDataByte(APDS9930_CONTROL, val) ) {
770
+        return false;
771
+    }
772
+    
773
+    return true;
774
+}
775
+
776
+/**
777
+ * @brief Gets the low threshold for ambient light interrupts
778
+ *
779
+ * @param[out] threshold current low threshold stored on the APDS-9930
780
+ * @return True if operation successful. False otherwise.
781
+ */
782
+bool APDS9930::getLightIntLowThreshold(uint16_t &threshold)
783
+{
784
+    uint8_t val_byte;
785
+    threshold = 0;
786
+    
787
+    /* Read value from ambient light low threshold, low byte register */
788
+    if( !wireReadDataByte(APDS9930_AILTL, val_byte) ) {
789
+        return false;
790
+    }
791
+    threshold = val_byte;
792
+    
793
+    /* Read value from ambient light low threshold, high byte register */
794
+    if( !wireReadDataByte(APDS9930_AILTH, val_byte) ) {
795
+        return false;
796
+    }
797
+    threshold = threshold + ((uint16_t)val_byte << 8);
798
+    
799
+    return true;
800
+}
801
+
802
+/**
803
+ * @brief Sets the low threshold for ambient light interrupts
804
+ *
805
+ * @param[in] threshold low threshold value for interrupt to trigger
806
+ * @return True if operation successful. False otherwise.
807
+ */
808
+bool APDS9930::setLightIntLowThreshold(uint16_t threshold)
809
+{
810
+    uint8_t val_low;
811
+    uint8_t val_high;
812
+    
813
+    /* Break 16-bit threshold into 2 8-bit values */
814
+    val_low = threshold & 0x00FF;
815
+    val_high = (threshold & 0xFF00) >> 8;
816
+    
817
+    /* Write low byte */
818
+    if( !wireWriteDataByte(APDS9930_AILTL, val_low) ) {
819
+        return false;
820
+    }
821
+    
822
+    /* Write high byte */
823
+    if( !wireWriteDataByte(APDS9930_AILTH, val_high) ) {
824
+        return false;
825
+    }
826
+    
827
+    return true;
828
+}
829
+
830
+/**
831
+ * @brief Gets the high threshold for ambient light interrupts
832
+ *
833
+ * @param[out] threshold current low threshold stored on the APDS-9930
834
+ * @return True if operation successful. False otherwise.
835
+ */
836
+bool APDS9930::getLightIntHighThreshold(uint16_t &threshold)
837
+{
838
+    uint8_t val_byte;
839
+    threshold = 0;
840
+    
841
+    /* Read value from ambient light high threshold, low byte register */
842
+    if( !wireReadDataByte(APDS9930_AIHTL, val_byte) ) {
843
+        return false;
844
+    }
845
+    threshold = val_byte;
846
+    
847
+    /* Read value from ambient light high threshold, high byte register */
848
+    if( !wireReadDataByte(APDS9930_AIHTH, val_byte) ) {
849
+        return false;
850
+    }
851
+    threshold = threshold + ((uint16_t)val_byte << 8);
852
+    
853
+    return true;
854
+}
855
+
856
+/**
857
+ * @brief Sets the high threshold for ambient light interrupts
858
+ *
859
+ * @param[in] threshold high threshold value for interrupt to trigger
860
+ * @return True if operation successful. False otherwise.
861
+ */
862
+bool APDS9930::setLightIntHighThreshold(uint16_t threshold)
863
+{
864
+    uint8_t val_low;
865
+    uint8_t val_high;
866
+    
867
+    /* Break 16-bit threshold into 2 8-bit values */
868
+    val_low = threshold & 0x00FF;
869
+    val_high = (threshold & 0xFF00) >> 8;
870
+    
871
+    /* Write low byte */
872
+    if( !wireWriteDataByte(APDS9930_AIHTL, val_low) ) {
873
+        return false;
874
+    }
875
+    
876
+    /* Write high byte */
877
+    if( !wireWriteDataByte(APDS9930_AIHTH, val_high) ) {
878
+        return false;
879
+    }
880
+    
881
+    return true;
882
+}
883
+
884
+
885
+/**
886
+ * @brief Gets if ambient light interrupts are enabled or not
887
+ *
888
+ * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
889
+ */
890
+uint8_t APDS9930::getAmbientLightIntEnable()
891
+{
892
+    uint8_t val;
893
+    
894
+    /* Read value from ENABLE register */
895
+    if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
896
+        return ERROR;
897
+    }
898
+    
899
+    /* Shift and mask out AIEN bit */
900
+    val = (val >> 4) & 0b00000001;
901
+    
902
+    return val;
903
+}
904
+
905
+/**
906
+ * @brief Turns ambient light interrupts on or off
907
+ *
908
+ * @param[in] enable 1 to enable interrupts, 0 to turn them off
909
+ * @return True if operation successful. False otherwise.
910
+ */
911
+bool APDS9930::setAmbientLightIntEnable(uint8_t enable)
912
+{
913
+    uint8_t val;
914
+    
915
+    /* Read value from ENABLE register */
916
+    if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
917
+        return false;
918
+    }
919
+    
920
+    /* Set bits in register to given value */
921
+    enable &= 0b00000001;
922
+    enable = enable << 4;
923
+    val &= 0b11101111;
924
+    val |= enable;
925
+    
926
+    /* Write register value back into ENABLE register */
927
+    if( !wireWriteDataByte(APDS9930_ENABLE, val) ) {
928
+        return false;
929
+    }
930
+    
931
+    return true;
932
+}
933
+
934
+/**
935
+ * @brief Gets if proximity interrupts are enabled or not
936
+ *
937
+ * @return 1 if interrupts are enabled, 0 if not. 0xFF on error.
938
+ */
939
+uint8_t APDS9930::getProximityIntEnable()
940
+{
941
+    uint8_t val;
942
+    
943
+    /* Read value from ENABLE register */
944
+    if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
945
+        return ERROR;
946
+    }
947
+    
948
+    /* Shift and mask out PIEN bit */
949
+    val = (val >> 5) & 0b00000001;
950
+    
951
+    return val;
952
+}
953
+
954
+/**
955
+ * @brief Turns proximity interrupts on or off
956
+ *
957
+ * @param[in] enable 1 to enable interrupts, 0 to turn them off
958
+ * @return True if operation successful. False otherwise.
959
+ */
960
+bool APDS9930::setProximityIntEnable(uint8_t enable)
961
+{
962
+    uint8_t val;
963
+    
964
+    /* Read value from ENABLE register */
965
+    if( !wireReadDataByte(APDS9930_ENABLE, val) ) {
966
+        return false;
967
+    }
968
+    
969
+    /* Set bits in register to given value */
970
+    enable &= 0b00000001;
971
+    enable = enable << 5;
972
+    val &= 0b11011111;
973
+    val |= enable;
974
+    
975
+    /* Write register value back into ENABLE register */
976
+    if( !wireWriteDataByte(APDS9930_ENABLE, val) ) {
977
+        return false;
978
+    }
979
+    
980
+    return true;
981
+}
982
+
983
+/**
984
+ * @brief Clears the ambient light interrupt
985
+ *
986
+ * @return True if operation completed successfully. False otherwise.
987
+ */
988
+bool APDS9930::clearAmbientLightInt()
989
+{
990
+    if( !wireWriteByte(CLEAR_ALS_INT) ) {
991
+        return false;
992
+    }
993
+    
994
+    return true;
995
+}
996
+
997
+/**
998
+ * @brief Clears the proximity interrupt
999
+ *
1000
+ * @return True if operation completed successfully. False otherwise.
1001
+ */
1002
+bool APDS9930::clearProximityInt()
1003
+{
1004
+    if( !wireWriteByte(CLEAR_PROX_INT) ) {
1005
+        return false;
1006
+    }
1007
+    
1008
+    return true;
1009
+}
1010
+
1011
+/**
1012
+ * @brief Clears all interrupts
1013
+ *
1014
+ * @return True if operation completed successfully. False otherwise.
1015
+ */
1016
+bool APDS9930::clearAllInts()
1017
+{
1018
+    if( !wireWriteByte(CLEAR_ALL_INTS) ) {
1019
+        return false;
1020
+    }
1021
+    
1022
+    return true;
1023
+}
1024
+
1025
+/*******************************************************************************
1026
+ * Raw I2C Reads and Writes
1027
+ ******************************************************************************/
1028
+
1029
+/**
1030
+ * @brief Writes a single byte to the I2C device (no register)
1031
+ *
1032
+ * @param[in] val the 1-byte value to write to the I2C device
1033
+ * @return True if successful write operation. False otherwise.
1034
+ */
1035
+bool APDS9930::wireWriteByte(uint8_t val)
1036
+{
1037
+    Wire.beginTransmission(APDS9930_I2C_ADDR);
1038
+    Wire.write(val);
1039
+    if( Wire.endTransmission() != 0 ) {
1040
+        return false;
1041
+    }
1042
+    
1043
+    return true;
1044
+}
1045
+
1046
+/**
1047
+ * @brief Writes a single byte to the I2C device and specified register
1048
+ *
1049
+ * @param[in] reg the register in the I2C device to write to
1050
+ * @param[in] val the 1-byte value to write to the I2C device
1051
+ * @return True if successful write operation. False otherwise.
1052
+ */
1053
+bool APDS9930::wireWriteDataByte(uint8_t reg, uint8_t val)
1054
+{
1055
+    Wire.beginTransmission(APDS9930_I2C_ADDR);
1056
+    Wire.write(reg | AUTO_INCREMENT);
1057
+    Wire.write(val);
1058
+    if( Wire.endTransmission() != 0 ) {
1059
+        return false;
1060
+    }
1061
+
1062
+    return true;
1063
+}
1064
+
1065
+/**
1066
+ * @brief Writes a block (array) of bytes to the I2C device and register
1067
+ *
1068
+ * @param[in] reg the register in the I2C device to write to
1069
+ * @param[in] val pointer to the beginning of the data byte array
1070
+ * @param[in] len the length (in bytes) of the data to write
1071
+ * @return True if successful write operation. False otherwise.
1072
+ */
1073
+bool APDS9930::wireWriteDataBlock(  uint8_t reg, 
1074
+                                        uint8_t *val, 
1075
+                                        unsigned int len)
1076
+{
1077
+    unsigned int i;
1078
+
1079
+    Wire.beginTransmission(APDS9930_I2C_ADDR);
1080
+    Wire.write(reg | AUTO_INCREMENT);
1081
+    for(i = 0; i < len; i++) {
1082
+        Wire.beginTransmission(APDS9930_I2C_ADDR);
1083
+        Wire.write(val[i]);
1084
+    }
1085
+    if( Wire.endTransmission() != 0 ) {
1086
+        return false;
1087
+    }
1088
+
1089
+    return true;
1090
+}
1091
+
1092
+/**
1093
+ * @brief Reads a single byte from the I2C device and specified register
1094
+ *
1095
+ * @param[in] reg the register to read from
1096
+ * @param[out] the value returned from the register
1097
+ * @return True if successful read operation. False otherwise.
1098
+ */
1099
+bool APDS9930::wireReadDataByte(uint8_t reg, uint8_t &val)
1100
+{
1101
+    
1102
+    /* Indicate which register we want to read from */
1103
+    if (!wireWriteByte(reg | AUTO_INCREMENT)) {
1104
+        return false;
1105
+    }
1106
+    
1107
+    /* Read from register */
1108
+    Wire.requestFrom(APDS9930_I2C_ADDR, 1);
1109
+    while (Wire.available()) {
1110
+        val = Wire.read();
1111
+    }
1112
+
1113
+    return true;
1114
+}
1115
+
1116
+
1117
+/**
1118
+ * @brief Reads a block (array) of bytes from the I2C device and register
1119
+ *
1120
+ * @param[in] reg the register to read from
1121
+ * @param[out] val pointer to the beginning of the data
1122
+ * @param[in] len number of bytes to read
1123
+ * @return Number of bytes read. -1 on read error.
1124
+ */
1125
+int APDS9930::wireReadDataBlock(   uint8_t reg, 
1126
+                                        uint8_t *val, 
1127
+                                        unsigned int len)
1128
+{
1129
+    unsigned char i = 0;
1130
+    
1131
+    /* Indicate which register we want to read from */
1132
+    if (!wireWriteByte(reg | AUTO_INCREMENT)) {
1133
+        return -1;
1134
+    }
1135
+    
1136
+    /* Read block data */
1137
+    Wire.requestFrom(APDS9930_I2C_ADDR, len);
1138
+    while (Wire.available()) {
1139
+        if (i >= len) {
1140
+            return -1;
1141
+        }
1142
+        val[i] = Wire.read();
1143
+        i++;
1144
+    }
1145
+
1146
+    return i;
1147
+}

+ 231
- 0
firmware/libraries/APDS9930-master/src/APDS9930.h View File

@@ -0,0 +1,231 @@
1
+/**
2
+ * @file    APDS-9930.h
3
+ * @brief   Library for the SparkFun APDS-9930 breakout board
4
+ * @author  Shawn Hymel (SparkFun Electronics)
5
+ *
6
+ * @copyright	This code is public domain but you buy me a beer if you use
7
+ * this and we meet someday (Beerware license).
8
+ *
9
+ * This library interfaces the Avago APDS-9930 to Arduino over I2C. The library
10
+ * relies on the Arduino Wire (I2C) library. to use the library, instantiate an
11
+ * APDS9930 object, call init(), and call the appropriate functions.
12
+ */
13
+ 
14
+#ifndef APDS9930_H
15
+#define APDS9930_H
16
+
17
+#include <Arduino.h>
18
+
19
+/* Debug */
20
+#define DEBUG                   0
21
+
22
+/* APDS-9930 I2C address */
23
+#define APDS9930_I2C_ADDR       0x39
24
+
25
+/* Command register modes */
26
+#define REPEATED_BYTE           0x80
27
+#define AUTO_INCREMENT          0xA0
28
+#define SPECIAL_FN              0xE0
29
+
30
+/* Error code for returned values */
31
+#define ERROR                   0xFF
32
+
33
+/* Acceptable device IDs */
34
+#define APDS9930_ID_1           0x12
35
+#define APDS9930_ID_2           0x39
36
+
37
+/* Misc parameters */
38
+#define FIFO_PAUSE_TIME         30      // Wait period (ms) between FIFO reads
39
+
40
+/* APDS-9930 register addresses */
41
+#define APDS9930_ENABLE         0x00
42
+#define APDS9930_ATIME          0x01
43
+#define APDS9930_PTIME          0x02
44
+#define APDS9930_WTIME          0x03
45
+#define APDS9930_AILTL          0x04
46
+#define APDS9930_AILTH          0x05
47
+#define APDS9930_AIHTL          0x06
48
+#define APDS9930_AIHTH          0x07
49
+#define APDS9930_PILTL          0x08
50
+#define APDS9930_PILTH          0x09
51
+#define APDS9930_PIHTL          0x0A
52
+#define APDS9930_PIHTH          0x0B