Proximity Detection with the Nano 33 BLE Sense
Learn how to control the built in RGB LED using the built in proximity sensor of the Nano 33 BLE Sense.
In this tutorial we will use an Arduino Nano 33 BLE Sense for proximity detection, made possible by the embedded APDS9960 sensor.
We will use the sensor to print out simple proximity detections and control the board's RGB LED accordingly. In addition, we will program our board to change the colors of the RGB LED according to the proximity of an object to the board.
Goals
The goals of this project are:
- Learn how the APDS9960 sensor works.
- Use the APDS9960 library.
- Learn how to output raw sensor data from the Arduino Nano 33 BLE Sense.
- Create your own proximity detection monitor.
- Learn how to control the RGB LED, through proximity values.
Hardware & Software Needed
- This project uses no external sensors or components.
- In this tutorial we will use the Arduino Web Editor to program the board.
APDS9960 Sensor
The APDS9960 sensor is a multipurpose device that features advanced gesture detection, proximity detection, digital ambient light sense (ALS) and color sense (RGBC).
The sensor's gesture detection utilizes four directional photodiodes to sense reflected infrared (IR) energy, sourced by the integrated LED, to convert physical motion information (i.e. velocity, direction and distance) into digital information.
It features:
- Four separate diodes sensitive to different directions.
- Ambient light rejection.
- Offset compensation.
- Programmable driver for IR LED current.
- 32 dataset storage FIFO.
- Interrupt driven I2C-bus communication.
If you want to read more about the APDS9960 sensor module see here.
The Library
The APDS9960 library allows us to use the sensor available on the board, to read gestures, color, light intensity and proximity. The library includes some of the following functions:
1begin()2end()3gestureAvailable()4readGesture()5colorAvailable()6readColor()7proximityAvailable()8readProximity()9setGestureSensitivity()10setInterruptPin()11setLEDBoost()
If you want a deeper understanding on any of the functions of the library, you can check the Arduino reference for more information.
For the purposes of this tutorial we will only focus on the proximity readings, which are based on the detection of an object over four photodiodes and then converted to millimeters inside the sensor for our usage.
Creating the Program
1. Setting up
Let's start by opening the Arduino Web Editor, click on the Libraries tab and search for the APDS9960 library. Then in > Examples, open the ProximitySensor sketch and once it opens, you could rename is as Proximity_LED.
2. Connecting the board
Now, connect the Arduino Nano 33 BLE Sense to the computer and make sure that the Web Editor recognizes it, if so, the board and port should appear as shown in the image below. If they don't appear, follow the instructions to install the plugin that will allow the Editor to recognize your board.
3. Blink patterns according to proximity
Now we will need to modify the code on the example, in order to change the color of the RGB LED according to the proximity.
After including the
Arduino_APDS9960.h
library, we will need to initialize some variables that will be used to control the blinking time of the RGB LED.1#include <Arduino_APDS9960.h>2
3int ledState = LOW;4
5unsigned long previousMillis = 0;6
7const long intervalLong = 1000;8const long intervalMed = 500;9const long intervalShort = 100;
Now, we need to configure the LED's pins at the end of the
setup()
section, to behave as OUTPUT
s and then we need to turn all the LEDs OFF, by adding the following statements:1// set the LEDs pins as outputs2 pinMode(LEDR, OUTPUT);3 pinMode(LEDG, OUTPUT);4 pinMode(LEDB, OUTPUT);5
6 // turn all the LEDs off7 digitalWrite(LEDR, HIGH);8 digitalWrite(LEDG, HIGH);9 digitalWrite(LEDB, HIGH);
In the
loop()
section, we need to initialize a new variable called currentMillis
where the time that the sketch has been running, will be stored. The if()
statement is checking that the gesture sensor is available and if it is, it reads for any incoming gesture detection.1unsigned long currentMillis = millis();2
3 // check if a proximity reading is available4 if (APDS.proximityAvailable()) {5 // read the proximity6 // - 0 => close7 // - 255 => far8 // - -1 => error9 int proximity = APDS.readProximity();
The next thing we need to do is create an
if
statement to check if the object is far. If it is, the green LED will blink slowly using the intervalLong
to set the blinking time.1if (proximity > 150) {2 if (currentMillis - previousMillis >= intervalLong) {3 previousMillis = currentMillis;4
5 // if the LED is off turn it on and vice-versa:6 if (ledState == LOW) {7 ledState = HIGH;8 } else {9 ledState = LOW;10 }11
12 // set the green LED with the ledState of the variable and turn off the rest13 digitalWrite(LEDG, ledState);14 digitalWrite(LEDR, HIGH);15 digitalWrite(LEDB, HIGH);16 }17 }
Now, we need to do the same to check if the object is in a medium distance from the board using an
else if
statement. If it is, the blue LED will blink faster than before due to the intervalMed
.1else if(proximity > 50 && proximity <= 150){2 if (currentMillis - previousMillis >= intervalMed) {3 previousMillis = currentMillis;4
5 // if the LED is off turn it on and vice-versa:6 if (ledState == LOW) {7 ledState = HIGH;8 } else {9 ledState = LOW;10 }11
12 // set the blue LED with the ledState of the variable and turn off the rest13 digitalWrite(LEDB, ledState);14 digitalWrite(LEDR, HIGH);15 digitalWrite(LEDG, HIGH);16 }17 }
Lastly, we use another
else
statement to check if the object is too close from the board. If it is, the red LED will blink fast thanks to the intervalShort
. Finally, we will use a Serial.println()
function to print out the proximity values to the Serial Monitor. Don't forget to delete the delay()
function since this could make us lose some data.1else {2 if (currentMillis - previousMillis >= intervalShort) {3 previousMillis = currentMillis;4
5 // if the LED is off turn it on and vice-versa:6 if (ledState == LOW) {7 ledState = HIGH;8 } else {9 ledState = LOW;10 }11
12 // set the blue LED with the ledState of the variable and turn off the rest13 digitalWrite(LEDR, ledState);14 digitalWrite(LEDB, HIGH);15 digitalWrite(LEDG, HIGH);16 }17 }18
19 // print value to the Serial Monitor20 Serial.println(proximity);21 }22}
Now the code is complete!
4. Complete code
If you choose to skip the code building section, the complete code can be found below:
1#include <Arduino_APDS9960.h>2
3int ledState = LOW;4
5unsigned long previousMillis = 0;6
7const long intervalLong = 1000;8const long intervalMed = 500;9const long intervalShort = 100;10
11void setup() {12 Serial.begin(9600);13 while (!Serial);14
15 if (!APDS.begin()) {16 Serial.println("Error initializing APDS9960 sensor!");17 }18
19 // set the LEDs pins as outputs20 pinMode(LEDR, OUTPUT);21 pinMode(LEDG, OUTPUT);22 pinMode(LEDB, OUTPUT);23
24 // turn all the LEDs off25 digitalWrite(LEDR, HIGH);26 digitalWrite(LEDG, HIGH);27 digitalWrite(LEDB, HIGH);28}29
30void loop() {31 unsigned long currentMillis = millis();32
33 // check if a proximity reading is available34 if (APDS.proximityAvailable()) {35 // read the proximity36 // - 0 => close37 // - 255 => far38 // - -1 => error39 int proximity = APDS.readProximity();40
41 if (proximity > 150) {42 if (currentMillis - previousMillis >= intervalLong) {43 previousMillis = currentMillis;44
45 // if the LED is off turn it on and vice-versa:46 if (ledState == LOW) {47 ledState = HIGH;48 } else {49 ledState = LOW;50 }51
52 // set the green LED with the ledState of the variable and turn off the rest53 digitalWrite(LEDG, ledState);54 digitalWrite(LEDR, HIGH);55 digitalWrite(LEDB, HIGH);56 }57 }58
59 else if(proximity > 50 && proximity <= 150){60 if (currentMillis - previousMillis >= intervalMed) {61 previousMillis = currentMillis;62
63 // if the LED is off turn it on and vice-versa:64 if (ledState == LOW) {65 ledState = HIGH;66 } else {67 ledState = LOW;68 }69
70 // set the blue LED with the ledState of the variable and turn off the rest71 digitalWrite(LEDB, ledState);72 digitalWrite(LEDR, HIGH);73 digitalWrite(LEDG, HIGH);74 }75 }76
77 else {78 if (currentMillis - previousMillis >= intervalShort) {79 previousMillis = currentMillis;80
81 // if the LED is off turn it on and vice-versa:82 if (ledState == LOW) {83 ledState = HIGH;84 } else {85 ledState = LOW;86 }87
88 // set the blue LED with the ledState of the variable and turn off the rest89 digitalWrite(LEDR, ledState);90 digitalWrite(LEDB, HIGH);91 digitalWrite(LEDG, HIGH);92 }93 }94
95 // print value to the Serial Monitor96 Serial.println(proximity);97 }98}
Testing It Out
After you have successfully verified and uploaded the sketch to the board, open the Serial Monitor from the menu on the left.
In order to test out the code, you could begin by stabilizing your board on a standing position in front of you (USB port facing down) and moving an object up and down close to the board. You will see the values on the Serial Monitor changing and changing the color of the RGB LED and the blinking time.
Here is a screenshot example of the sketch returning values through the Serial Monitor.
Troubleshoot
Sometimes errors occur, if the code is not working there are some common issues we can troubleshoot:
- Missing a bracket or a semicolon
- Arduino board connected to the wrong port
- Accidental interruption of cable connection
Conclusion
In this tutorial we learned what the APDS9960 sensor is, how to use the one embedded in the Arduino Nano 33 BLE Sense board and the APDS9960 library. In addition, we demonstrated how to create your own proximity detection monitor which can operate the RGB LED in various color and time patterns.
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.