, ,

APDS9900 cellphone presence sensor

Posted by

Let’s discuss the APDS9900 cellphone presence sensor, a sensor used in cellphones to control the screen ON/OFF. This little sensor manufactured by Broadcom was used in some cellphones to control its screen, both for brightness and body approximation.

APDS-9900 light and movement sensor
APDS-9900 light and movement sensor

I bought one from Aliexpress in the hopes of writing a full article for you, only to find out there is no working library for it. The thing is, I found this library that compiles and spits some values on the Arduino IDE serial monitor. It does light level, the sensor used for cellphone screen brightness, but it does not work for body presence/approximation.

Ambient light level is a value between 0 and 65535, and it stays around 26000 for a sunny spring afternoon when the sensor is indoors close to a window. This value falls to 3100 when I cover the sensor with my hand.

Presence/approximation in the other hand is also a value between 0 and 65535, but it keeps going up and down at different rates and moments. By approximating my hand of it (closer than 100mm) the value does jump, but never to a predictable spot. The library creators themselves state in the Github that this presence/approximation part is not fully working yet.

The circuit

Due to using i2c protocol communication, the connections between the sensor and the ESP32-C6 are simplified. All you need is SDA, SCL, 3V3 and GND. Connect the ESP32-C6 to the computer or laptop via a USB-C cable.

APDS-9900 and ESP32 circuit
APDS-9900 and ESP32 circuit
APDS9900 light and presence sensor
APDS-9900 on a breadboard

The code

This is my code so far, that lights a LED when a hand (or other object) is detected in front of the sensor. It is a workaround, since as stated the proximity part of this code does no work properly.

#include <Wire.h>
#include <APDS9900.h>

// Global Variables
APDS9900 apds = APDS9900();
uint16_t proximity_data = 0;

long proximity_before;

void setup() {

  Wire.begin(D4, D5); // A4, A5 is default for Arduino
  
  pinMode(D10, OUTPUT);
  
  // Initialize Serial port
  Serial.begin(115200); // 9600 baud is default for Arduino
  Serial.println();
  Serial.println(F("------------------------------------"));
  Serial.println(F("    APDS-9900 - Proximity Sensor    "));
  Serial.println(F("------------------------------------"));
  
  // Initialize APDS-9900 (configure I2C and initial values)
  if ( apds.init() ) {
    Serial.println(F("APDS-9900 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during APDS-9900 init!"));
  }
  
  // Adjust the Proximity sensor gain
  if ( !apds.setProximityGain(0) ) {
    Serial.println(F("Something went wrong trying to set PGAIN"));
  }

  // Start running the APDS-9900 light sensor (no interrupts)
  if ( apds.enableLightSensor(false) ) {
    Serial.println(F("Light sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during light sensor init!"));
  }

    // Start running the APDS-9900 proximity sensor (no interrupts)
  if ( apds.enableProximitySensor(false) ) {
    Serial.println(F("Proximity sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during proximity sensor init!"));
  }

  apds.setMode(ALL, true);
  //  apds.setAmbientIntLowThresh(300);
  //  apds.setAmbientIntHighThresh(500);

  Serial.print("proximity interrupt high thresh "); Serial.println(apds.getProxIntHighThresh());
  Serial.print("proximity interrupt low thresh "); Serial.println(apds.getProxIntLowThresh());
  Serial.print("getAmbientLightGain "); Serial.println(apds.getAmbientLightGain());
}

uint16_t ambient_light;

void loop() {  
  
  // Read the proximity value
  if ( !apds.readProximity(proximity_data) ) {
    Serial.println("Error reading proximity value");
  } else {
    Serial.print("Proximity: ");
    Serial.print(proximity_data);
    Serial.println("d");
   
  }

  if(proximity_data > (proximity_before + 5000) || proximity_data < (proximity_before - 5000)){
      digitalWrite(D10, HIGH);
      proximity_before= proximity_data;
    } else{
      digitalWrite(D10, LOW);
      //proximity_before= proximity_data;
    }

  // Read the proximity value
  if ( !apds.readAmbientLight(ambient_light) ) {
    Serial.println("Error reading ambient light value");
  } else {
    Serial.print("Ambience: ");
    Serial.println(ambient_light);
  }
  
  // Wait 250 ms before next reading
  delay(250);
}

The end result

What happens is that LED D10 lights more than once when presence is detected. This sensor could be used by some measurements, but would require a bit of software to do so. Watch the video and see for yourself.

Final words

Despite being used in real world cellphones, there is yet no Arduino code available for the APDS-9900. At least not a complete fully-functioning one. In the other hand, light level could be usable.

If you want to try the APDS-9900 yourself, please use my affiliate link here. Have fun!.

Leave a Reply

Your email address will not be published. Required fields are marked *