diff --git a/7_distance_and_light_sensor.py b/7_distance_and_light_sensor.py
new file mode 100644
index 0000000..867e39b
--- /dev/null
+++ b/7_distance_and_light_sensor.py
@@ -0,0 +1,26 @@
+#
+# Copyright (C) Orange
+#
+# This software is distributed under the terms and conditions of the 'MIT'
+# license which can be found in the file 'LICENSE.md' in this package distribution
+import sys
+import time
+import LiveObjects
+
+# Create LiveObjects
+lo = LiveObjects.Connection()
+sensor = LiveObjects.SensorVL6180X()
+
+MESSAGE_RATE = 5
+
+# Main program
+lo.connect() # Connect to LiveObjects
+last = uptime = time.time()
+
+while True:
+ if (time.time()) >= last + MESSAGE_RATE:
+ lo.add_to_payload("distance", sensor.range)
+ lo.add_to_payload("ambient_light", sensor.amb_light())
+ lo.send_data() # Sending data to cloud
+ last = time.time()
+ lo.loop() # Check for incoming messages and if connection is still active
diff --git a/LiveObjects/Connection.py b/LiveObjects/Connection.py
index 0efa679..8501c71 100644
--- a/LiveObjects/Connection.py
+++ b/LiveObjects/Connection.py
@@ -212,6 +212,7 @@ def get_parameter(self, name):
return 0
def add_to_payload(self, name, val):
+ self.add_model("Orange")
self.__payload[self.__value][name] = val
def set_object_as_payload(self, val):
diff --git a/LiveObjects/hal.py b/LiveObjects/hal.py
index c59e7d6..7277dd5 100644
--- a/LiveObjects/hal.py
+++ b/LiveObjects/hal.py
@@ -210,10 +210,70 @@ def get_client_id(self):
return self.get_lang_str() + ':' + get_mac()
-class BoardsFactory:
+class RaspberryPi(Linux):
+ pass
+
+
+def is_raspberrypi():
+ try:
+ with open('/proc/device-tree/model') as f:
+ return f.read().startswith('Raspberry')
+ except FileNotFoundError:
+ return False
+
+class BoardsFactory:
def __new__(cls, net_type):
s = sys.platform
sn = s[0].upper() + s[1:] # capitalize first letter
+ if sn == 'Linux':
+ sn = 'RaspberryPi' if is_raspberrypi() else 'Linux'
board = eval(sn)(net_type) # instance of board w/ net type: WiFi, LTE, etc.
return board
+
+
+MAX_DEV_NB = 20
+
+
+def get_i2c():
+ import machine
+ typical_gpio = ([22, 23], [5, 4], [22, 21], [23, 18])
+ for gpio in typical_gpio:
+ scl, sda = gpio
+ i2c = None
+ try: # MicroPython 1.19.1 20220618-v1.19.1
+ i2c = machine.SoftI2C(scl=machine.Pin(scl), sda=machine.Pin(sda), freq=100000)
+ if i2c.scan() and len(i2c.scan()) < MAX_DEV_NB:
+ return i2c
+ except ValueError: # next sda, scl
+ pass
+ except AttributeError: # Pycom MicroPython 1.20.2.r6 [v1.11-c5a0a97] on 2021-10-28
+ i2c = machine.I2C(0)
+ return i2c
+ del i2c
+ raise RuntimeError("No I2C devices found. Check SDA and SCL lines and add respective GPIO to 'typical_gpio'.")
+
+
+class SensorVL6180X:
+ def __new__(cls):
+ try: # Python@RPi
+ import busio
+ import adafruit_vl6180x
+ import board
+
+ class VL6180X(adafruit_vl6180x.VL6180X):
+ def amb_light(self):
+ """Implementing default gain"""
+ return self.read_lux(gain=0x06) # ALS_GAIN_1
+
+ i2c = busio.I2C(board.SCL, board.SDA)
+ return VL6180X(i2c)
+
+ except ImportError: # microPython
+ import vl6180x_micro
+ i2c = get_i2c()
+ return vl6180x_micro.Sensor(i2c)
+
+ except NotImplementedError: # if no I2C device
+ print("No GPIO present.")
+ sys.exit()
diff --git a/README.md b/README.md
index a5d9785..ea06cf0 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Prototype with Orange using Live Objects
-### Discover Orange [**Live Objects**](https://liveobjects.orange-business.com) using dedicated SDK for **Python and uPython compatible** boards and systems.
+### Discover Orange [**Live Objects**](https://liveobjects.orange-business.com) using dedicated SDK for **Python 3 and uPython compatible** boards and systems.
This code wraps all the functions necessary to make your object work with Live Objects.
@@ -23,7 +23,7 @@ Code uses MQTT connection to exchange data with Live objects under the hood to k
This code needs a few libraries to run:
- Python needs [paho-mqtt](https://pypi.org/project/paho-mqtt/)
- Python for Windows needs [python-certifi-win32](https://pypi.org/project/python-certifi-win32/)
-- uPython needs [umqttsimple, umqttrobust and ssl](https://github.com/micropython/micropython-lib)
+- uPython needs [umqttsimple](https://github.com/micropython/micropython-lib/blob/master/micropython/umqtt.simple/umqtt/simple.py) and [umqttrobust](https://github.com/micropython/micropython-lib/blob/master/micropython/umqtt.robust/umqtt/robust.py)
## How to use ##
@@ -236,12 +236,55 @@ You need to override specific methods - e.g. `connect` which is depended on type
All specific functions are placed in `services.py`.
If your board needs function supporting its equipment you need to put it in this file.
+## VL6180X Sensor use-case ##
+
+We can connect sensor using I2C to board supporting Python like **Raspberry Pi**.
+
+The [VL6180X](https://www.st.com/en/imaging-and-photonics-solutions/vl6180x.html) is the latest product based on ST’s patented FlightSense™technology.
+This is a ground-breaking technology allowing absolute distance to be measured independent of target reflectance.
+Instead of estimating the distance by measuring the amount of light reflected back from the object (which is significantly influenced by color and surface),
+the VL6180X precisely measures the time the light takes to travel to the nearest object and reflect back to the sensor (Time-of-Flight).
+Description from st.com.
+
+### Prerequisites ###
+
+#### Enabling I2C ####
+Enable (if needed) **I2C** interface on your Raspberry Pi using terminal and command:
+```bash
+sudo raspi-config
+```
+and selecting: **3 Interface Options** -> **P5 I2C** -> **\**
+
+![I2C_Enabling](image/enable_I2C.png)
+
+#### Wiring ####
+![Wiring](https://www.raspberrypi-spy.co.uk/wp-content/uploads/2012/06/Raspberry-Pi-GPIO-Header-with-Photo-768x512.png "Mapping")
+
+
+
+Example of development module using VL6180X you can find [here](https://kamami.pl/en/kamod-kamami-peripheral-modules/559362-kamodvl6180x-a-module-with-distance-gesture-and-als-sensor.html). Below diagram shows how to connect it to Raspberry Pi.
+
+![Schematics](image/RPi_VL6180X.png "Schematics")
+
+#### Adding VL6180X Python module ####
+Necessary module by [Adafruit](https://learn.adafruit.com/adafruit-vl6180x-time-of-flight-micro-lidar-distance-sensor-breakout/python-circuitpython) can be installed using `pip`
+```bash
+pip3 install adafruit-circuitpython-vl6180x
+```
+
+#### How to use ####
+To run you need to use below command:
+```bash
+python3 7_distance_and_light_sensor.py
+```
+
+---
# Installation guide for uPython #
## Example for ESP32 / ESP8266 ##
### Requirements ###
1. [ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy)
-2. [umqttsimple, umqttrobust and ssl](https://github.com/micropython/micropython-lib)
+2. [umqttsimple, umqttrobust and ssl](https://github.com/micropython/micropython-lib) (for your convenience they are included in `micropython` folder)
3. [PuTTY](https://www.putty.org/) (for Windows)
### Installation steps ###
@@ -264,6 +307,7 @@ You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py`
> ampy -pCOMXX put main.py
```
+
4. Connect to device and check if it's working using PuTTY
Ctrl + D soft resets device
@@ -274,25 +318,75 @@ You can use one of example ones (`1_send_data.py`, ...) renaming it to `main.py`
After all steps content of the device should look like below:
```commandline
-> ampy -pCOMXX ls
+> ampy --port COMx ls
/LiveObjects
/boot.py
/main.py
/umqttrobust.py
/simple.py
-> ampy -pCOMXX ls LiveObjects
+> ampy --port COMx ls LiveObjects
/LiveObjects/Connection.py
/LiveObjects/__init__.py
/LiveObjects/hal.py
/LiveObjects/credentials.py
/LiveObjects/services.py
```
+where COMx means port on your computer (e.g. COM8) with connected microPython board.
## Example for LoPy / GPy ##
You can do the steps as above but better is to use [Pymakr plug-in](https://pycom.io/products/supported-networks/pymakr/) for **Visual Studio Code** or **Atom** delivered by [Pycom](https://pycom.io/).
Plug-in supports code development, its upload to the board and communication with board.
+## VL6180X Sensor use-case ##
+
+Sensor described in this [section](#vl6180x-sensor-use-case) can be used on boards supporting microPython.
+
+### Prerequisites ###
+
+#### Wiring ####
+You need to connect I2C interface (SCL & SDA) and power lines on the board with corresponding pins on the sensor.
+You need to be aware that **boards can use different GPIOs for I2C** purposes. Set of typical pairs is placed
+in function `get_i2c()` in file `hal.py`. If your board uses other GPIO pins, you need to add them to the tuple `typical_gpio`.
+```Python
+def get_i2c():
+ import machine
+ typical_gpio = ([22, 23], [5, 4], [22, 21])
+...
+```
+![ESP32_sch](image/ESP32_VL6180X_sch.png)
+
+Example of wiring ESP32 board with GPIO22 and GPIO21 (_source: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/_)
+
+![ESP32](image/ESP32_VL6180X.jpg)
+
+#### How to use ####
+1. You need to upload additional library for VL6180X support (it is placed in `micropython` folder):
+```commandline
+> ampy -pCOMXX put vl6180x_micro.py
+```
+2. Copy `7_distance_and_light_sensor.py` as `main.py` and upload it into board.
+
+After above operations you can see:
+```commandline
+> ampy --port COMx ls
+/LiveObjects
+/boot.py
+/main.py
+/umqttrobust.py
+/simple.py
+/vl6180x_micro.py
+
+> ampy --port COMx ls LiveObjects
+/LiveObjects/Connection.py
+/LiveObjects/__init__.py
+/LiveObjects/hal.py
+/LiveObjects/credentials.py
+/LiveObjects/services.py
+```
+3. Connect to device and check if it's working using PuTTY.
+
+
## Troubleshooting ##
If you are getting 'MQTT exception: 5' check your api key
\ No newline at end of file
diff --git a/image/ESP32_VL6180X.jpg b/image/ESP32_VL6180X.jpg
new file mode 100644
index 0000000..56d0507
Binary files /dev/null and b/image/ESP32_VL6180X.jpg differ
diff --git a/image/ESP32_VL6180X_sch.png b/image/ESP32_VL6180X_sch.png
new file mode 100644
index 0000000..f0a4f31
Binary files /dev/null and b/image/ESP32_VL6180X_sch.png differ
diff --git a/image/RPi_VL6180X.png b/image/RPi_VL6180X.png
new file mode 100644
index 0000000..aa3025c
Binary files /dev/null and b/image/RPi_VL6180X.png differ
diff --git a/image/enable_I2C.png b/image/enable_I2C.png
new file mode 100644
index 0000000..11c6bf3
Binary files /dev/null and b/image/enable_I2C.png differ
diff --git a/micropython/simple.py b/micropython/simple.py
new file mode 100644
index 0000000..8216fa5
--- /dev/null
+++ b/micropython/simple.py
@@ -0,0 +1,204 @@
+import usocket as socket
+import ustruct as struct
+from ubinascii import hexlify
+
+class MQTTException(Exception):
+ pass
+
+class MQTTClient:
+
+ def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,
+ ssl=False, ssl_params={}):
+ if port == 0:
+ port = 8883 if ssl else 1883
+ self.client_id = client_id
+ self.sock = None
+ self.server = server
+ self.port = port
+ self.ssl = ssl
+ self.ssl_params = ssl_params
+ self.pid = 0
+ self.cb = None
+ self.user = user
+ self.pswd = password
+ self.keepalive = keepalive
+ self.lw_topic = None
+ self.lw_msg = None
+ self.lw_qos = 0
+ self.lw_retain = False
+
+ def _send_str(self, s):
+ self.sock.write(struct.pack("!H", len(s)))
+ self.sock.write(s)
+
+ def _recv_len(self):
+ n = 0
+ sh = 0
+ while 1:
+ b = self.sock.read(1)[0]
+ n |= (b & 0x7f) << sh
+ if not b & 0x80:
+ return n
+ sh += 7
+
+ def set_callback(self, f):
+ self.cb = f
+
+ def set_last_will(self, topic, msg, retain=False, qos=0):
+ assert 0 <= qos <= 2
+ assert topic
+ self.lw_topic = topic
+ self.lw_msg = msg
+ self.lw_qos = qos
+ self.lw_retain = retain
+
+ def connect(self, clean_session=True):
+ self.sock = socket.socket()
+ addr = socket.getaddrinfo(self.server, self.port)[0][-1]
+ self.sock.connect(addr)
+ if self.ssl:
+ import ussl
+ self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
+ premsg = bytearray(b"\x10\0\0\0\0\0")
+ msg = bytearray(b"\x04MQTT\x04\x02\0\0")
+
+ sz = 10 + 2 + len(self.client_id)
+ msg[6] = clean_session << 1
+ if self.user is not None:
+ sz += 2 + len(self.user) + 2 + len(self.pswd)
+ msg[6] |= 0xC0
+ if self.keepalive:
+ assert self.keepalive < 65536
+ msg[7] |= self.keepalive >> 8
+ msg[8] |= self.keepalive & 0x00FF
+ if self.lw_topic:
+ sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
+ msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
+ msg[6] |= self.lw_retain << 5
+
+ i = 1
+ while sz > 0x7f:
+ premsg[i] = (sz & 0x7f) | 0x80
+ sz >>= 7
+ i += 1
+ premsg[i] = sz
+
+ self.sock.write(premsg, i + 2)
+ self.sock.write(msg)
+ #print(hex(len(msg)), hexlify(msg, ":"))
+ self._send_str(self.client_id)
+ if self.lw_topic:
+ self._send_str(self.lw_topic)
+ self._send_str(self.lw_msg)
+ if self.user is not None:
+ self._send_str(self.user)
+ self._send_str(self.pswd)
+ resp = self.sock.read(4)
+ assert resp[0] == 0x20 and resp[1] == 0x02
+ if resp[3] != 0:
+ raise MQTTException(resp[3])
+ return resp[2] & 1
+
+ def disconnect(self):
+ self.sock.write(b"\xe0\0")
+ self.sock.close()
+
+ def ping(self):
+ self.sock.write(b"\xc0\0")
+
+ def publish(self, topic, msg, retain=False, qos=0):
+ pkt = bytearray(b"\x30\0\0\0")
+ pkt[0] |= qos << 1 | retain
+ sz = 2 + len(topic) + len(msg)
+ if qos > 0:
+ sz += 2
+ assert sz < 2097152
+ i = 1
+ while sz > 0x7f:
+ pkt[i] = (sz & 0x7f) | 0x80
+ sz >>= 7
+ i += 1
+ pkt[i] = sz
+ #print(hex(len(pkt)), hexlify(pkt, ":"))
+ self.sock.write(pkt, i + 1)
+ self._send_str(topic)
+ if qos > 0:
+ self.pid += 1
+ pid = self.pid
+ struct.pack_into("!H", pkt, 0, pid)
+ self.sock.write(pkt, 2)
+ self.sock.write(msg)
+ if qos == 1:
+ while 1:
+ op = self.wait_msg()
+ if op == 0x40:
+ sz = self.sock.read(1)
+ assert sz == b"\x02"
+ rcv_pid = self.sock.read(2)
+ rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
+ if pid == rcv_pid:
+ return
+ elif qos == 2:
+ assert 0
+
+ def subscribe(self, topic, qos=0):
+ assert self.cb is not None, "Subscribe callback is not set"
+ pkt = bytearray(b"\x82\0\0\0")
+ self.pid += 1
+ struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
+ #print(hex(len(pkt)), hexlify(pkt, ":"))
+ self.sock.write(pkt)
+ self._send_str(topic)
+ self.sock.write(qos.to_bytes(1, "little"))
+ while 1:
+ op = self.wait_msg()
+ if op == 0x90:
+ resp = self.sock.read(4)
+ #print(resp)
+ assert resp[1] == pkt[2] and resp[2] == pkt[3]
+ if resp[3] == 0x80:
+ raise MQTTException(resp[3])
+ return
+
+ # Wait for a single incoming MQTT message and process it.
+ # Subscribed messages are delivered to a callback previously
+ # set by .set_callback() method. Other (internal) MQTT
+ # messages processed internally.
+ def wait_msg(self):
+ res = self.sock.read(1)
+ self.sock.setblocking(True)
+ if res is None:
+ return None
+ if res == b"":
+ raise OSError(-1)
+ if res == b"\xd0": # PINGRESP
+ sz = self.sock.read(1)[0]
+ assert sz == 0
+ return None
+ op = res[0]
+ if op & 0xf0 != 0x30:
+ return op
+ sz = self._recv_len()
+ topic_len = self.sock.read(2)
+ topic_len = (topic_len[0] << 8) | topic_len[1]
+ topic = self.sock.read(topic_len)
+ sz -= topic_len + 2
+ if op & 6:
+ pid = self.sock.read(2)
+ pid = pid[0] << 8 | pid[1]
+ sz -= 2
+ msg = self.sock.read(sz)
+ self.cb(topic, msg)
+ if op & 6 == 2:
+ pkt = bytearray(b"\x40\x02\0\0")
+ struct.pack_into("!H", pkt, 2, pid)
+ self.sock.write(pkt)
+ elif op & 6 == 4:
+ assert 0
+
+ # Checks whether a pending message from server is available.
+ # If not, returns immediately with None. Otherwise, does
+ # the same processing as wait_msg.
+ def check_msg(self):
+ self.sock.setblocking(False)
+ return self.wait_msg()
diff --git a/micropython/umqttrobust.py b/micropython/umqttrobust.py
new file mode 100755
index 0000000..a1e91fe
--- /dev/null
+++ b/micropython/umqttrobust.py
@@ -0,0 +1,43 @@
+import utime
+import simple
+
+class MQTTClient(simple.MQTTClient):
+
+ DELAY = 2
+ DEBUG = False
+
+ def delay(self, i):
+ utime.sleep(self.DELAY)
+
+ def log(self, in_reconnect, e):
+ if self.DEBUG:
+ if in_reconnect:
+ print("mqtt reconnect: %r" % e)
+ else:
+ print("mqtt: %r" % e)
+
+ def reconnect(self):
+ i = 0
+ while 1:
+ try:
+ return super().connect(False)
+ except OSError as e:
+ self.log(True, e)
+ i += 1
+ self.delay(i)
+
+ def publish(self, topic, msg, retain=False, qos=0):
+ while 1:
+ try:
+ return super().publish(topic, msg, retain, qos)
+ except OSError as e:
+ self.log(False, e)
+ self.reconnect()
+
+ def wait_msg(self):
+ while 1:
+ try:
+ return super().wait_msg()
+ except OSError as e:
+ self.log(False, e)
+ self.reconnect()
diff --git a/micropython/vl6180x_micro.py b/micropython/vl6180x_micro.py
new file mode 100644
index 0000000..1b5e33e
--- /dev/null
+++ b/micropython/vl6180x_micro.py
@@ -0,0 +1,174 @@
+#
+# Copyright (C) Orange
+#
+# This software is distributed under the terms and conditions of the 'MIT'
+# license which can be found in the file 'LICENSE.md' in this package distribution
+#
+# This file incorporates work covered by the following copyright and
+# permission notice:
+#
+# Copyright (c) 2018, Ledbelly2142
+# https://github.com/Ledbelly2142/VL6180X/blob/master/LICENSE
+#
+# Copyright (c) 2022, Adafruit
+# https://github.com/adafruit/Adafruit_CircuitPython_VL6180X/blob/main/LICENSE
+
+import ustruct
+import struct
+import time
+from machine import I2C
+
+
+class Sensor:
+ """
+ Micropython library for VL6180X sensor measuring distance and ambient light
+ """
+ def __init__(self, i2c, address=0x29):
+ self.i2c = i2c
+ self._address = address
+ self.default_settings()
+ self.init()
+
+ def _i2c_write(self, register, regValue):
+ return self.i2c.writeto_mem(self._address, register, bytearray([regValue]), addrsize=16), 'big'
+
+ def _i2c_read(self, register, nb_bytes=1):
+ value = int.from_bytes(
+ self.i2c.readfrom_mem(self._address, register, nb_bytes, addrsize=16),
+ 'big'
+ )
+ return value & 0xFFFF
+
+ def init(self):
+ if self._i2c_read(0x0016) != 1:
+ raise RuntimeError("Failure reset")
+
+ # Recommended setup from the datasheet
+ self._i2c_write(0x0207, 0x01)
+ self._i2c_write(0x0208, 0x01)
+ self._i2c_write(0x0096, 0x00)
+ self._i2c_write(0x0097, 0xfd)
+ self._i2c_write(0x00e3, 0x00)
+ self._i2c_write(0x00e4, 0x04)
+ self._i2c_write(0x00e5, 0x02)
+ self._i2c_write(0x00e6, 0x01)
+ self._i2c_write(0x00e7, 0x03)
+ self._i2c_write(0x00f5, 0x02)
+ self._i2c_write(0x00d9, 0x05)
+ self._i2c_write(0x00db, 0xce)
+ self._i2c_write(0x00dc, 0x03)
+ self._i2c_write(0x00dd, 0xf8)
+ self._i2c_write(0x009f, 0x00)
+ self._i2c_write(0x00a3, 0x3c)
+ self._i2c_write(0x00b7, 0x00)
+ self._i2c_write(0x00bb, 0x3c)
+ self._i2c_write(0x00b2, 0x09)
+ self._i2c_write(0x00ca, 0x09)
+ self._i2c_write(0x0198, 0x01)
+ self._i2c_write(0x01b0, 0x17)
+ self._i2c_write(0x01ad, 0x00)
+ self._i2c_write(0x00ff, 0x05)
+ self._i2c_write(0x0100, 0x05)
+ self._i2c_write(0x0199, 0x05)
+ self._i2c_write(0x01a6, 0x1b)
+ self._i2c_write(0x01ac, 0x3e)
+ self._i2c_write(0x01a7, 0x1f)
+ self._i2c_write(0x0030, 0x00)
+
+ def default_settings(self):
+ # Enables polling for ‘New Sample ready’ when measurement completes
+ self._i2c_write(0x0011, 0x10)
+ self._i2c_write(0x010A, 0x30) # Set Avg sample period
+ self._i2c_write(0x003f, 0x46) # Set the ALS gain
+ self._i2c_write(0x0031, 0xFF) # Set auto calibration period
+ # (Max = 255)/(OFF = 0)
+ self._i2c_write(0x0040, 0x63) # Set ALS integration time to 100ms
+ # perform a single temperature calibration
+ self._i2c_write(0x002E, 0x01)
+
+ # Optional settings from datasheet
+ self._i2c_write(0x001B, 0x09) # Set default ranging inter-measurement
+ # period to 100ms
+ self._i2c_write(0x003E, 0x0A) # Set default ALS inter-measurement
+ # period to 100ms
+ self._i2c_write(0x0014, 0x24) # Configures interrupt on ‘New Sample
+ # Ready threshold event’
+
+ # Additional settings defaults from community
+ self._i2c_write(0x001C, 0x32) # Max convergence time
+ self._i2c_write(0x002D, 0x10 | 0x01) # Range check enables
+ self._i2c_write(0x0022, 0x7B) # Early convergence estimate
+ self._i2c_write(0x0120, 0x01) # Firmware result scaler
+
+ def _read_range_single(self):
+ """Measure the distance in millimeters. Takes 0.01s."""
+ self._i2c_write(0x0018, 0x01) # Sysrange start
+ time.sleep(0.01)
+ return self._i2c_read(0x0062) # Result range value import ustruct
+
+ @property
+ def range(self):
+ return self._read_range_single()
+
+ def amb_light(self, gain=0x06):
+ """Read the lux (light value) from the sensor and return it. Must
+ specify the gain value to use for the lux reading:
+
+ ================= =====
+ Setting Value
+ ================= =====
+ ``ALS_GAIN_1`` 1x
+ ``ALS_GAIN_1_25`` 1.25x
+ ``ALS_GAIN_1_67`` 1.67x
+ ``ALS_GAIN_2_5`` 2.5x
+ ``ALS_GAIN_5`` 5x
+ ``ALS_GAIN_10`` 10x
+ ``ALS_GAIN_20`` 20x
+ ``ALS_GAIN_40`` 40x
+ ================= =====
+
+ :param int gain: The gain value to use
+ """
+
+ reg = self._i2c_read(0x0014)
+ reg &= ~0x38
+ reg |= 0x4 << 3 # IRQ on ALS ready
+ self._i2c_write(0x0014, reg)
+ # 100 ms integration period
+ self._i2c_write(0x0040, 0)
+ self._i2c_write(0x0041, 100)
+ # analog gain
+ gain = min(gain, 0x07)
+ self._i2c_write(0x003F, 0x40 | gain)
+ # start ALS
+ self._i2c_write(0x0038, 1)
+ # Poll until "New Sample Ready threshold event" is set
+ while (
+ (self._i2c_read(0x004F) >> 3) & 0x7
+ ) != 4:
+ pass
+ # read lux!
+ lux = self._i2c_read(0x0050, 2)
+ # clear interrupt
+ self._i2c_write(0x0015, 0x07)
+ lux *= 0.32 # calibrated count/lux
+
+ if gain == 0x06: # ALS_GAIN_1:
+ pass
+ elif gain == 0x05: # ALS_GAIN_1_25:
+ lux /= 1.25
+ elif gain == 0x04: # ALS_GAIN_1_67:
+ lux /= 1.67
+ elif gain == 0x03: # ALS_GAIN_2_5:
+ lux /= 2.5
+ elif gain == 0x02: # ALS_GAIN_5:
+ lux /= 5
+ elif gain == 0x01: # ALS_GAIN_10:
+ lux /= 10
+ elif gain == 0x00: # ALS_GAIN_20:
+ lux /= 20
+ elif gain == 0x07: # ALS_GAIN_40:
+ lux /= 40
+ lux *= 100
+ lux /= 100 # integration time in ms
+ return lux
diff --git a/setup.py b/setup.py
index c0e343a..d26e74a 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@
include_package_data=True,
install_requires=['paho-mqtt'],
- version='2.0.2',
+ version='2.1.0',
license='MIT',