MicroPython APDS-9960 & APDS-9900 RAM optimized Library

Documentation Status

Another APDS9960 / GY-9960LLC / APDS9900 micro python library optimized for ESP8266 / ESP12-E for:
  • Light Sensing (Ambient Light and RGB Color Sensing)
  • Proximity Sensing

Documentation

Complete documentation is hosted on the “Read the Docs” page upy-apds9960.readthedocs.io

Dependencies

This driver depends on:

Tested on:
Sensor: GY-9960LLC
Sensor: APDS-9900
Devboard: Node MCU v1.0 & Raspberry PI Pico

Installation

  • Flash the device with MicroPython
  • Copy the folder uPy_APDS9960 and content (apds9960LITE.py) to the root folder for APDS9960 circuits
  • Copy the folder uPy_APDS9900 and content (apds9900LITE.py) to the root folder for APDS9900 circuits

The steps above is descsribed in the Thonny IDE tutorial.

Examples

The examples in theis respository uses the NodeMCU devboard the devboard to use rpi pico please change the I2C inferface as show in the code below

#Change I2C interface from:
#  i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))
#to:
i2c =  machine.I2C(0,scl=machine.Pin(17), sda=machine.Pin(16))

Here is the NodeMCU Hookup.

APDS9960 Example

import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

#Init I2C Buss on RP2040
i2c =  machine.I2C(0,scl=machine.Pin(17), sda=machine.Pin(16))

apds9960=APDS9960LITE(i2c)      # Enable sensor
apds9960.prox.enableSensor()    # Enable Proximit sensing

while True:
        sleep_ms(25) # wait for readout to be ready
        print(apds9960.prox.proximityLevel)   #Print the proximity value

APDS9900 Example

import machine
from time import sleep_ms
from uPy_APDS9900.apds9900LITE import APDS9900LITE

#Init I2C Buss on RP2040
i2c =  machine.I2C(0,scl=machine.Pin(17), sda=machine.Pin(16))

apds9900=APDS9900LITE(i2c)      # Enable sensor
apds9900.prox.enableSensor()    # Enable Proximit sensing

while True:
        sleep_ms(25) # wait for readout to be ready
        print(apds9900.prox.proximityLevel)   #Print the proximity value

Hardware Set-up

Connect Vin to 3.3 V or 5 V power source, GND to ground, SCL and SDA to the appropriate pins to the Raspberry PI Pico

APDS9960 Name Remarks RPI PICO Function
1 VIN +3.3V Power 36 3V3
2 GND Ground GND GND
3 SCL I2C clock 22 GP17 (SCL)
4 SDA I2C Data 21 GP16 (SDA)
5 INT Interrupt 26 GP20

Basics

Of course, you must import the device and library :)

import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

To set-up the device to gather data, initialize the I2C-device using SCL and SDA pins. Then initialize the library.

i2c =  machine.I2C(0,scl=machine.Pin(17), sda=machine.Pin(16))
apds9960=APDS9960LITE(i2c)         # Poweron APDS9960

Proximity

Proximity funxtionalites is accessed torough the apds9960.prox member PROX

apds9960.prox.enableSensor()         # Enable Proximity sensing
sleep_ms(25)                         # wait for readout to be ready
print(apds9960.prox.proximityLevel)  # Print the proximity value

Light Sensing

Proximity funxtionalites is accessed torough the apds9960.als member ALS

apds9960.als.enableSensor()           # Enable Light sensor
sleep_ms(25)                          # Wait for readout to be ready
print(apds9960.als.ambientLightLevel) # Print the ambient light value

Debug

If things does not work try to run the script below to verify that it i2c communication with the apds9960 is working as expected

import machine
i2c =  machine.I2C(0,scl=machine.Pin(17), sda=machine.Pin(16))

print('Scan i2c bus...')
devices = i2c.scan()

if len(devices) == 0:
  print("No i2c device !")
else:
  print('i2c devices found:',len(devices))

  for device in devices:
    print("Decimal address: ",device," | Hexa address: ",hex(device))

    if(device==0x39): # APDS9960 Address = 0x39
        deviceID=i2c.readfrom_mem(devices[0],0x92, 1) #Get deviceID
        deviceID=int.from_bytes(deviceID,'big')       #Conv byte to int
        if(deviceID==0x29):
           deviceID=9900
        elif(deviceID==0x20):
            deviceID=9901
        else:
            deviceID=9960

        print("Found ADPS-",deviceID)

If successful the output should be:

Scan i2c bus...
i2c devices found: 1
Decimal address:  57  | Hexa address:  0x39
Found ADPS- 9960

Note

Be aware if the output shows:

"many i2c devices was listed"  check if the i2c pins are allocated correctly
"No i2c device"                check if the power is correctly connected

The Device id can be 0xa8, 0xab 0x9c or 0x55.)

Sphinx documentation

Sphinx the Python Documentation Generator is used for this documentation, if you like to build a local copy of the documentation install Sphinx :

python -m pip install sphinx

Ceate html doc by

cd docs
make html

The html pages would be located at : docs/_build/html

Contributing

Contributions are welcome! Please read our Code of Conduct before contributing to help this project stay welcoming.

Table of Contents

Proximity & Light Sensing

Proximity Examples

Examples that demostrates the use of apds9960 as a proximity sensor

Simple Example

Basic proximity test program.

examples/prox/simple_proximity_apds9960.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

#Init I2C Buss
i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))

apds9960=APDS9960LITE(i2c)      # Enable sensor
apds9960.prox.enableSensor()    # Enable Proximit sensing

while True:
        sleep_ms(25) # wait for readout to be ready
        print(apds9960.prox.proximityLevel)   #Print the proximity value

Regular Example

Example exposing more functions

examples/prox/proximity_apds9960.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

# Proximity Gain (PGAIN) values
APDS9960_PGAIN_1X = const(0)
APDS9960_PGAIN_2X = const(1)
APDS9960_PGAIN_4X = const(2)
APDS9960_PGAIN_8X = const(3)

# LED Drive values
APDS9960_LED_DRIVE_100MA  = const(0)
APDS9960_LED_DRIVE_50MA   = const(1)
APDS9960_LED_DRIVE_25MA   = const(2)
APDS9960_LED_DRIVE_12_5MA = const(3)

i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))

apds9960=APDS9960LITE(i2c)
apds9960.prox.eLEDCurrent   =APDS9960_LED_DRIVE_100MA    
apds9960.prox.eProximityGain=APDS9960_PGAIN_8X   
apds9960.prox.enableSensor()

sleep_ms(50)

while True:
    sleep_ms(50)
    print("proximity:", apds9960.prox.proximityLevel )

Simple IRQ

Example showing use of a hardware IRQ raised at a given proximity value

examples/prox/simple_irq_proximity_apds9960.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))

apds9960=APDS9960LITE(i2c)
apds9960.prox.eLEDCurrent    =0 # LED_DRIVE_100MA    
apds9960.prox.eProximityGain =3 # PGAIN_8X   
apds9960.prox.enableSensor()

#IRQ Functionalities
apds9960.prox.setInterruptThreshold(high=10,low=0,persistance=7)
apds9960.prox.enableInterrupt()

ProxThPin=machine.Pin(0, machine.Pin.IN ,machine.Pin.PULL_UP)

sleep_ms(50)

while True:
    sleep_ms(50)

    if(ProxThPin.value()==0):
        print("proximity:", apds9960.prox.proximityLevel )
        apds9960.prox.clearInterrupt()  

IRQ Example

Example showing use of interrupts exposing more functionalities

examples/prox/irq_proximity_apds9960.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

# Proximity Gain (PGAIN) values
APDS9960_PGAIN_1X = const(0)
APDS9960_PGAIN_2X = const(1)
APDS9960_PGAIN_4X = const(2)
APDS9960_PGAIN_8X = const(3)

# LED Drive values
APDS9960_LED_DRIVE_100MA  = const(0)
APDS9960_LED_DRIVE_50MA   = const(1)
APDS9960_LED_DRIVE_25MA   = const(2)
APDS9960_LED_DRIVE_12_5MA = const(3)

i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))
print("Lite APDS-9960 Proximity test ")

apds9960=APDS9960LITE(i2c)
apds9960.prox.eLEDCurrent   =APDS9960_LED_DRIVE_100MA    
apds9960.prox.eProximityGain=APDS9960_PGAIN_8X   

apds9960.prox.enableSensor()
apds9960.prox.setInterruptThreshold(high=10,low=0,persistance=7)
apds9960.prox.enableInterrupt()

ProxThPin=machine.Pin(0, machine.Pin.IN ,machine.Pin.PULL_UP)

sleep_ms(50)

while True:
    sleep_ms(50)

    if(ProxThPin.value()==0):
        print("proximity:", apds9960.prox.proximityLevel )
        apds9960.prox.clearInterrupt()  

Light Sensor Examples

Light sensing example

Ambient Light and RGB Color Sensing test program.

examples/als/simple_light_apds9960.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import machine
from time import sleep_ms
from uPy_APDS9960.apdsS9960LITE import APDS9960LITE

#Init I2C Buss
i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))

apds9960=APDS9960LITE(i2c)         # Enable sensor
print("Enable light Sensor")

apds9960.als.enableSensor()   # Enable Light sensor
apds9960.als.eLightGain=3          # x64 gain
#apds9960.prox.enableProximity()
sleep_ms(50)
print("Clear Light level: ", apds9960.als.ambientLightLevel)
print("Red   Light level: "  , apds9960.als.redLightLevel)
print("Green Light level: ", apds9960.als.greenLightLevel)
print("Blue  Light level: " , apds9960.als.blueLightLevel)

Ambient light IRQ

Ambient Light IRQ test program.

examples/als/simple_light_irq_apds9960.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import machine
from time import sleep_ms
from uPy_APDS9960.apds9960LITE import APDS9960LITE

#Init I2C Buss
i2c =  machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))

apds9960=APDS9960LITE(i2c)         # Enable sensor
apds9960.als.enableSensor()   # Enable Light sensor
apds9960.als.eLightGain=3          # x64 gain
apds9960.als.setInterruptThreshold(high=100,low=0,persistance=7)
apds9960.als.enableInterrupt(True)     # Enable interrupt
apds9960.als.clearInterrupt()          # Clear interrupt
sleep_ms(50)

IrqThPin=machine.Pin(0, machine.Pin.IN ,machine.Pin.PULL_UP)
sleep_ms(50)

while True:
    sleep_ms(50)

    if(IrqThPin.value()==0):
        print("Ambient light level:", apds9960.als.ambientLightLevel )
        apds9960.als.clearInterrupt()

Debug

I2C Debug Example

Test program for testing the I2C connection the the aps9960

examples/debug/i2c_test.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import machine
i2c = machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4))

print('Scan i2c bus...')
devices = i2c.scan()

if len(devices) == 0:
  print("No i2c device !")
else:
  print('i2c devices found:',len(devices))

  for device in devices:
    print("Decimal address: ",device," | Hexa address: ",hex(device))

    if(device==0x39): # APDS9960 Address = 0x39
        deviceID=i2c.readfrom_mem(devices[0],0x92, 1) #G et deviceID
        print("Found ADPS9960: Device ID: ",deviceID)

Thonny IDE Turorial

This is a short visual tutorial on how to use the Thonny IDE to flash the ESP8266 chip and upload and test the uPy_APDS9960 library

Download and install

The latest version of tonny can be found at thonny.org

In this tutorial we uses the windows version and install Thonny on your computer

Download up Micropython (ESP8266) dev enviroment

Download latest MicroPython firmware for ESP8266

Start Thonny

Windows comand prompt showing Thonny

Flash new firmware

Installing esptool.py

From the menu “Tools” select “Manage Plut-ins…”

Manage Plut-ins...

In the text field enter “esptool” and click the button “Find packages from PyPI”

Install esptool from PyPI...

Click the “Install” button to finish the esptool installation

Seting up Micropython (ESP8266) dev enviroment

From the menu “Run” select “Select intepreter…”

Select python intepreter to ESP8266

The ESP8266 firmware install/upgrade dialog is shown

Shows ESP8266 firmware options dialog

Make sure thet the ESP8266 development kit is connected. Select the “port dropdown” arrow to select the serial port for flashing the ESP8266.

Shows ESP8266 firmware options dialog

In the “Firmware” text field select the .bin file that was downloaded and click the install button

Shows ESP8266 firmware options dialog

Click the stop icon to reset and connect to the ESP8266 board

Shows ESP8266 software reset

Now you should be up and running as shown in the thonny shell windows

ESP8266 terminal window

Running the examples

Start by uploadting the uPy_APDS9960 library.

Uploading uPy_APDS9960

From the files windows under “This computer” right click on the folder “uPy_APDS9960” and from the dropdown menu select “Upload to /”

_images/UploadModule.PNG _images/UploadTo.PNG

Running a example program

From the files windows under “This computer” click on the ‘+’ sign infront of the folder “examples” to expand it.

_images/ExampleFolder.PNG

Double clikc on the file simple_proximity_apds9960.py and it wil be open the the editor

_images/Editor.PNG

You are now ready to run the program entring F5 or selecting the menu “Run” and “Run current script”

_images/RunCurrentScript.PNG

Click the stop icon to stop the program and return the command prompt

Shows ESP8266 software reset

Have fun :)

uPy_APDS9960 Module

_images/classdiagrams.png

Indices and tables