Home Code A Si1145 sensor Micropython example on an ESP32

A Si1145 sensor Micropython example on an ESP32

by shedboy71

In this example we connect a Si1145 sensor to an ESP32 running Micropython

The Si1145/46/47 is a low-power, reflectance-based, infrared proximity, ultraviolet (UV) index, and ambient light sensor with I2C digital interface and programmableevent interrupt output. This touchless sensor IC includes an analog-to-digital converter, integrated high-sensitivity visible and infrared photodiodes, digital signal processor, and one, two, or three integrated infrared LED drivers with fifteen selectable drive levels.

The Si1145/46/47 offers excellent performance under a wide dynamic range and a variety of light sources including direct sunlight. The Si1145/46/47 can also work under dark glass covers.

The photodiode response and associated digital conversion circuitry provide excellent immunity to artificial light flicker noise and natural light flutter noise. With two or more LEDs, the Si1146/47 is capable of supporting multiple-axis proximity motion detection


Parts List


Name Link
ESP32 WEMOS WiFi & Bluetooth Battery ESP32 development tool ESP32 battery esp8266 ESP WROOM 32 ESP32
Si1145 SI1145 UV IR Visible Sensor I2C GY1145 Light Breakout Board Module
Connecting cables Free shipping Dupont line 120pcs 20cm male to male + male to female and female to female jumper wire



An easy module to connect to an ESP32, SCL is 22 and SDA is 21 on the Wemos board I used, you can see this is the schematic below



You can use any method to upload files to the ESP32, I used uPyCraft

The following is based on a github library – https://github.com/neliogodoi/MicroPython-SI1145. The first part of this is the library which I upload to my ESP32

I used the si1145_lowmem.py library

[codesyntax lang=”python”]

MicroPython driver for SI1145 light I2C sensor, low memory version :
Version: 0.3.0 @ 2018/04/02

import time
from ustruct import unpack

class SI1145(object):

    def __init__(self, i2c=None, addr=0x60):
        if i2c is None:
            raise ValueError('An I2C object is required.')
        self._i2c = i2c
        self._addr = addr

    def _read8(self, register):
        result = unpack(
                self._addr, register, 1)
        )[0] & 0xFF
        return result

    def _read16(self, register, little_endian=True):
        result = unpack('BB', self._i2c.readfrom_mem(self._addr, register, 2))
        result = ((result[1] << 8) | (result[0] & 0xFF))
        if not little_endian:
            result = ((result << 8) & 0xFF00) + (result >> 8)
        return result

    def _write8(self, register, value):
        value = value & 0xFF
        self._i2c.writeto_mem(self._addr, register, bytes([value]))

    def _reset(self):
        self._write8(0x08, 0x00)
        self._write8(0x09, 0x00)
        self._write8(0x04, 0x00)
        self._write8(0x05, 0x00)
        self._write8(0x06, 0x00)
        self._write8(0x03, 0x00)
        self._write8(0x21, 0xFF)
        self._write8(0x18, 0x01)
        self._write8(0x07, 0x17)

    def _write_param(self, parameter, value):
        self._write8(0x17, value)
        self._write8(0x18, parameter | 0xA0)
        return self._read8(0x2E)

    def _load_calibration(self):
        self._write8(0x13, 0x7B)
        self._write8(0x14, 0x6B)
        self._write8(0x15, 0x01)
        self._write8(0x16, 0x00)
        self._write_param( 0x01, 0x80 | 0x40 | 0x20 | 0x10 | 0x01)
        self._write8(0x03, 0x01)
        self._write8(0x04, 0x01)
        self._i2c.writeto_mem(0x60, 0x0F, b'0x03')
        self._write_param(0x07, 0x03)
        self._write_param(0x02, 0x01)
        self._write_param(0x0B, 0)
        self._write_param(0x0A, 0x70)
        self._write_param(0x0C, 0x20 | 0x04)
        self._write_param(0x0E, 0x00)
        self._write_param(0x1E, 0)
        self._write_param(0x1D, 0x70)
        self._write_param(0x1F, 0x20)
        self._write_param(0x11, 0)
        self._write_param(0x10, 0x70)
        self._write_param(0x12, 0x20)
        self._write8(0x08, 0xFF)
        self._write8(0x18, 0x0F)

    def read_uv(self):
        return self._read16(0x2C, little_endian=True) / 100

    def read_visible(self):
        return self._read16(0x22, little_endian=True)

    def read_ir(self):
        return self._read16(0x24, little_endian=True)

    def read_prox(self):
        return self._read16(0x26, little_endian=True)


I then create a file called main.py and uploaded them to my ESP32

[codesyntax lang=”python”]

import machine
import si1145
import time

i2c = machine.I2C(sda=machine.Pin(21),scl=machine.Pin(22))
sensor = si1145.SI1145(i2c=i2c)

for i in range(10):
    uv = sensor.read_uv
    ir = sensor.read_ir
    view = sensor.read_visible
    print(" UV: %f\n IR: %f\n Visible: %f" % (uv, ir, view))



Open up the REPL window. Here is what I saw in uPyCraft

Ready to download this file,please wait!

download ok
UV: 0.000000
IR: 407.999992
Visible: 265.999984
UV: 0.040000
IR: 407.999992
Visible: 265.999984
UV: 0.040000
IR: 417.999982
Visible: 265.999984
UV: 0.040000
IR: 411.999988
Visible: 266.999983
UV: 0.040000
IR: 409.999990
Visible: 266.999983



You may also like

Leave a Comment