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 APDS9960 sensor.
The APDS9960 sensor.

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.

Finding the library in the Web Editor.
Finding the library in the Web Editor.

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.

Selecting the board.
Selecting the 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 outputs
2 pinMode(LEDR, OUTPUT);
3 pinMode(LEDG, OUTPUT);
4 pinMode(LEDB, OUTPUT);
5
6 // turn all the LEDs off
7 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 available
4 if (APDS.proximityAvailable()) {
5 // read the proximity
6 // - 0 => close
7 // - 255 => far
8 // - -1 => error
9 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 rest
13 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 rest
13 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 rest
13 digitalWrite(LEDR, ledState);
14 digitalWrite(LEDB, HIGH);
15 digitalWrite(LEDG, HIGH);
16 }
17 }
18
19 // print value to the Serial Monitor
20 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 outputs
20 pinMode(LEDR, OUTPUT);
21 pinMode(LEDG, OUTPUT);
22 pinMode(LEDB, OUTPUT);
23
24 // turn all the LEDs off
25 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 available
34 if (APDS.proximityAvailable()) {
35 // read the proximity
36 // - 0 => close
37 // - 255 => far
38 // - -1 => error
39 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 rest
53 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 rest
71 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 rest
89 digitalWrite(LEDR, ledState);
90 digitalWrite(LEDB, HIGH);
91 digitalWrite(LEDG, HIGH);
92 }
93 }
94
95 // print value to the Serial Monitor
96 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.

LED blinking according to object's distance.
LED blinking according to object's distance.

Here is a screenshot example of the sketch returning values through the Serial Monitor.

Sensor data printed in the Serial Monitor.
Sensor data printed in 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.