From 65fd7aa1a130d0bb02397fb6eb474fb7e298ba5c Mon Sep 17 00:00:00 2001 From: Alan Wang <44191076+alankrantas@users.noreply.github.com> Date: Sat, 6 Nov 2021 18:22:39 +0800 Subject: [PATCH] Add support for APDS-9960, Digital Proximity, Ambient Light, RGB and Gesture Sensor (#308) apds9960: add support for apds9960 --- Makefile | 4 +- apds9960/apds9960.go | 461 ++++++++++++++++++++++++++++ apds9960/apds9960_generic.go | 14 + apds9960/apds9960_nano_33_ble.go | 29 ++ apds9960/registers.go | 78 +++++ examples/apds9960/color/main.go | 38 +++ examples/apds9960/gesture/main.go | 51 +++ examples/apds9960/proximity/main.go | 38 +++ 8 files changed, 712 insertions(+), 1 deletion(-) create mode 100644 apds9960/apds9960.go create mode 100644 apds9960/apds9960_generic.go create mode 100644 apds9960/apds9960_nano_33_ble.go create mode 100644 apds9960/registers.go create mode 100644 examples/apds9960/color/main.go create mode 100644 examples/apds9960/gesture/main.go create mode 100644 examples/apds9960/proximity/main.go diff --git a/Makefile b/Makefile index 9fc05da..f9099ee 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,8 @@ smoke-test: @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/main.go @md5sum ./build/test.hex + tinygo build -size short -o ./build/test.hex -target=nano-33-ble ./examples/apds9960/proximity/main.go + @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=itsybitsy-m0 ./examples/apa102/itsybitsy-m0/main.go @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=microbit ./examples/at24cx/main.go @@ -216,7 +218,7 @@ DRIVERS = $(wildcard */) NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \ hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \ hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \ - pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb + pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS)) unit-test: diff --git a/apds9960/apds9960.go b/apds9960/apds9960.go new file mode 100644 index 0000000..84bc34d --- /dev/null +++ b/apds9960/apds9960.go @@ -0,0 +1,461 @@ +// Package apds9960 implements a driver for APDS-9960, +// a digital proximity, ambient light, RGB and gesture sensor. +// +// Datasheet: https://cdn.sparkfun.com/assets/learn_tutorials/3/2/1/Avago-APDS-9960-datasheet.pdf +// +package apds9960 + +import ( + "time" + + "tinygo.org/x/drivers" +) + +// Device wraps an I2C connection to a APDS-9960 device. +type Device struct { + bus drivers.I2C + Address uint8 + mode uint8 + gesture gestureData +} + +// Configuration for APDS-9960 device. +type Configuration struct { + ProximityPulseLength uint8 + ProximityPulseCount uint8 + GesturePulseLength uint8 + GesturePulseCount uint8 + ProximityGain uint8 + GestureGain uint8 + ColorGain uint8 + ADCIntegrationCycles uint16 + LEDBoost uint16 + threshold uint8 + sensitivity uint8 +} + +// for gesture-related data +type gestureData struct { + detected uint8 + threshold uint8 + sensitivity uint8 + gXDelta int16 + gYDelta int16 + gXPrevDelta int16 + gYPrevDelta int16 + received bool +} + +// for enabling various device function +type enableConfig struct { + GEN bool + PIEN bool + AIEN bool + WEN bool + PEN bool + AEN bool + PON bool +} + +// Connected returns whether APDS-9960 has been found. +// It does a "who am I" request and checks the response. +func (d *Device) Connected() bool { + data := []byte{0} + d.bus.ReadRegister(d.Address, APDS9960_ID_REG, data) + return data[0] == 0xAB +} + +// Configure sets up the APDS-9960 device. +func (d *Device) Configure(cfg Configuration) { + d.DisableAll() // turn off everything + + // "default" settings + if cfg.ProximityPulseLength == 0 { + cfg.ProximityPulseLength = 16 + } + if cfg.ProximityPulseCount == 0 { + cfg.ProximityPulseCount = 64 + } + if cfg.GesturePulseLength == 0 { + cfg.GesturePulseLength = 16 + } + if cfg.GesturePulseCount == 0 { + cfg.GesturePulseCount = 64 + } + if cfg.ProximityGain == 0 { + cfg.ProximityGain = 1 + } + if cfg.GestureGain == 0 { + cfg.GestureGain = 1 + } + if cfg.ColorGain == 0 { + cfg.ColorGain = 4 + } + if cfg.ADCIntegrationCycles == 0 { + cfg.ADCIntegrationCycles = 4 + } + if cfg.threshold == 0 { + d.gesture.threshold = 30 + } + if cfg.sensitivity == 0 { + d.gesture.sensitivity = 20 + } + + d.SetProximityPulse(cfg.ProximityPulseLength, cfg.ProximityPulseCount) + d.SetGesturePulse(cfg.GesturePulseLength, cfg.GesturePulseCount) + d.SetGains(cfg.ProximityGain, cfg.GestureGain, cfg.ColorGain) + d.SetADCIntegrationCycles(cfg.ADCIntegrationCycles) + + if cfg.LEDBoost > 0 { + d.LEDBoost(cfg.LEDBoost) + } +} + +// GetMode returns current engine mode +func (d *Device) GetMode() uint8 { + return d.mode +} + +// DisableAll turns off the device and all functions +func (d *Device) DisableAll() { + d.enable(enableConfig{}) + d.bus.WriteRegister(d.Address, APDS9960_GCONF4_REG, []byte{0x00}) + d.mode = MODE_NONE + d.gesture.detected = GESTURE_NONE +} + +// SetProximityPulse sets proximity pulse length (4, 8, 16, 32) and count (1~64) +// default: 16, 64 +func (d *Device) SetProximityPulse(length, count uint8) { + d.bus.WriteRegister(d.Address, APDS9960_PPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)}) +} + +// SetGesturePulse sets gesture pulse length (4, 8, 16, 32) and count (1~64) +// default: 16, 64 +func (d *Device) SetGesturePulse(length, count uint8) { + d.bus.WriteRegister(d.Address, APDS9960_GPULSE_REG, []byte{getPulseLength(length)<<6 | getPulseCount(count)}) +} + +// SetADCIntegrationCycles sets ALS/color ADC internal integration cycles (1~256, 1 cycle = 2.78 ms) +// default: 4 (~10 ms) +func (d *Device) SetADCIntegrationCycles(cycles uint16) { + if cycles > 256 { + cycles = 256 + } + d.bus.WriteRegister(d.Address, APDS9960_ATIME_REG, []byte{uint8(256 - cycles)}) +} + +// SetGains sets proximity/gesture gain (1, 2, 4, 8x) and ALS/color gain (1, 4, 16, 64x) +// default: 1, 1, 4 +func (d *Device) SetGains(proximityGain, gestureGain, colorGain uint8) { + d.bus.WriteRegister(d.Address, APDS9960_CONTROL_REG, []byte{getProximityGain(proximityGain)<<2 | getALSGain(colorGain)}) + d.bus.WriteRegister(d.Address, APDS9960_GCONF2_REG, []byte{getProximityGain(gestureGain) << 5}) +} + +// LEDBoost sets proximity and gesture LED current level (100, 150, 200, 300 (%)) +// default: 100 +func (d *Device) LEDBoost(percent uint16) { + var v uint8 + switch percent { + case 100: + v = 0 + case 150: + v = 1 + case 200: + v = 2 + case 300: + v = 3 + } + d.bus.WriteRegister(d.Address, APDS9960_CONFIG2_REG, []byte{0x01 | v<<4}) +} + +// Setthreshold sets threshold (0~255) for detecting gestures +// default: 30 +func (d *Device) Setthreshold(t uint8) { + d.gesture.threshold = t +} + +// Setsensitivity sets sensivity (0~100) for detecting gestures +// default: 20 +func (d *Device) Setsensitivity(s uint8) { + if s > 100 { + s = 100 + } + d.gesture.sensitivity = 100 - s +} + +// EnableProximity starts the proximity engine +func (d *Device) EnableProximity() { + if d.mode != MODE_NONE { + d.DisableAll() + } + d.enable(enableConfig{PON: true, PEN: true, WEN: true}) + d.mode = MODE_PROXIMITY +} + +// ProximityAvailable reports if proximity data is available +func (d *Device) ProximityAvailable() bool { + if d.mode == MODE_PROXIMITY && d.readStatus("PVALID") { + return true + } + return false +} + +// ReadProximity reads proximity data (0~255) +func (d *Device) ReadProximity() (proximity int32) { + if d.mode != MODE_PROXIMITY { + return 0 + } + data := []byte{0} + d.bus.ReadRegister(d.Address, APDS9960_PDATA_REG, data) + return 255 - int32(data[0]) +} + +// EnableColor starts the color engine +func (d *Device) EnableColor() { + if d.mode != MODE_NONE { + d.DisableAll() + } + d.enable(enableConfig{PON: true, AEN: true, WEN: true}) + d.mode = MODE_COLOR +} + +// ColorAvailable reports if color data is available +func (d *Device) ColorAvailable() bool { + if d.mode == MODE_COLOR && d.readStatus("AVALID") { + return true + } + return false +} + +// ReadColor reads color data (red, green, blue, clear color/brightness) +func (d *Device) ReadColor() (r int32, g int32, b int32, clear int32) { + if d.mode != MODE_COLOR { + return + } + data := []byte{0, 0, 0, 0, 0, 0, 0, 0} + d.bus.ReadRegister(d.Address, APDS9960_CDATAL_REG, data[:1]) + d.bus.ReadRegister(d.Address, APDS9960_CDATAH_REG, data[1:2]) + d.bus.ReadRegister(d.Address, APDS9960_RDATAL_REG, data[2:3]) + d.bus.ReadRegister(d.Address, APDS9960_RDATAH_REG, data[3:4]) + d.bus.ReadRegister(d.Address, APDS9960_GDATAL_REG, data[4:5]) + d.bus.ReadRegister(d.Address, APDS9960_GDATAH_REG, data[5:6]) + d.bus.ReadRegister(d.Address, APDS9960_BDATAL_REG, data[6:7]) + d.bus.ReadRegister(d.Address, APDS9960_BDATAH_REG, data[7:]) + clear = int32(uint16(data[1])<<8 | uint16(data[0])) + r = int32(uint16(data[3])<<8 | uint16(data[2])) + g = int32(uint16(data[5])<<8 | uint16(data[4])) + b = int32(uint16(data[7])<<8 | uint16(data[6])) + return +} + +// EnableGesture starts the gesture engine +func (d *Device) EnableGesture() { + if d.mode != MODE_NONE { + d.DisableAll() + } + d.enable(enableConfig{PON: true, PEN: true, GEN: true, WEN: true}) + d.mode = MODE_GESTURE + d.gesture.detected = GESTURE_NONE + d.gesture.gXDelta = 0 + d.gesture.gYDelta = 0 + d.gesture.gXPrevDelta = 0 + d.gesture.gYPrevDelta = 0 + d.gesture.received = false +} + +// GestureAvailable reports if gesture data is available +func (d *Device) GestureAvailable() bool { + if d.mode != MODE_GESTURE { + return false + } + + data := []byte{0, 0, 0, 0} + + // check GVALID + d.bus.ReadRegister(d.Address, APDS9960_GSTATUS_REG, data[:1]) + if data[0]&0x01 == 0 { + return false + } + + // get number of data sets available in FIFO + d.bus.ReadRegister(d.Address, APDS9960_GFLVL_REG, data[:1]) + availableDataSets := data[0] + if availableDataSets == 0 { + return false + } + + // read up, down, left and right proximity data from FIFO + var dataSets [32][4]uint8 + for i := uint8(0); i < availableDataSets; i++ { + d.bus.ReadRegister(d.Address, APDS9960_GFIFO_U_REG, data[:1]) + d.bus.ReadRegister(d.Address, APDS9960_GFIFO_D_REG, data[1:2]) + d.bus.ReadRegister(d.Address, APDS9960_GFIFO_L_REG, data[2:3]) + d.bus.ReadRegister(d.Address, APDS9960_GFIFO_R_REG, data[3:4]) + for j := uint8(0); j < 4; j++ { + dataSets[i][j] = data[j] + } + } + + // gesture detection process + d.gesture.detected = GESTURE_NONE + for i := uint8(0); i < availableDataSets; i++ { + U := dataSets[i][0] + D := dataSets[i][1] + L := dataSets[i][2] + R := dataSets[i][3] + + // if all readings fall below threshold, it's possible that + // a movement's just been made + if U < d.gesture.threshold && D < d.gesture.threshold && L < d.gesture.threshold && R < d.gesture.threshold { + d.gesture.received = true + // if there were movement in the previous step (including the last data sets) + if d.gesture.gXPrevDelta != 0 && d.gesture.gYPrevDelta != 0 { + totalX := d.gesture.gXPrevDelta - d.gesture.gXDelta + totalY := d.gesture.gYPrevDelta - d.gesture.gYDelta + // if previous and current movement are in opposite directions (pass through one led then next) + // and the difference is big enough, the gesture is recorded + switch { + case totalX < -int16(d.gesture.sensitivity): + d.gesture.detected = GESTURE_LEFT + case totalX > int16(d.gesture.sensitivity): + d.gesture.detected = GESTURE_RIGHT + case totalY > int16(d.gesture.sensitivity): + d.gesture.detected = GESTURE_DOWN + case totalY < -int16(d.gesture.sensitivity): + d.gesture.detected = GESTURE_UP + } + d.gesture.gXDelta = 0 + d.gesture.gYDelta = 0 + d.gesture.gXPrevDelta = 0 + d.gesture.gYPrevDelta = 0 + } + continue + } + + // recording current movement + d.gesture.gXDelta = int16(R) - int16(L) + d.gesture.gYDelta = int16(D) - int16(U) + if d.gesture.received { + d.gesture.received = false + d.gesture.gXPrevDelta = d.gesture.gXDelta + d.gesture.gYPrevDelta = d.gesture.gYDelta + } + } + + return d.gesture.detected != GESTURE_NONE +} + +// ReadGesture reads last gesture data +func (d *Device) ReadGesture() (gesture int32) { + return int32(d.gesture.detected) +} + +// private functions + +func (d *Device) enable(cfg enableConfig) { + var gen, pien, aien, wen, pen, aen, pon uint8 + + if cfg.GEN { + gen = 1 + } + if cfg.PIEN { + pien = 1 + } + if cfg.AIEN { + aien = 1 + } + if cfg.WEN { + wen = 1 + } + if cfg.PEN { + pen = 1 + } + if cfg.AEN { + aen = 1 + } + if cfg.PON { + pon = 1 + } + + data := []byte{gen<<6 | pien<<5 | aien<<4 | wen<<3 | pen<<2 | aen<<1 | pon} + d.bus.WriteRegister(d.Address, APDS9960_ENABLE_REG, data) + + if cfg.PON { + time.Sleep(time.Millisecond * 10) + } +} + +func (d *Device) readStatus(param string) bool { + data := []byte{0} + d.bus.ReadRegister(d.Address, APDS9960_STATUS_REG, data) + + switch param { + case "CPSAT": + return data[0]>>7&0x01 == 1 + case "PGSAT": + return data[0]>>6&0x01 == 1 + case "PINT": + return data[0]>>5&0x01 == 1 + case "AINT": + return data[0]>>4&0x01 == 1 + case "PVALID": + return data[0]>>1&0x01 == 1 + case "AVALID": + return data[0]&0x01 == 1 + default: + return false + } +} + +func getPulseLength(l uint8) uint8 { + switch l { + case 4: + return 0 + case 8: + return 1 + case 16: + return 2 + case 32: + return 3 + default: + return 0 + } +} + +func getPulseCount(c uint8) uint8 { + if c < 1 && c > 64 { + return 0 + } + return c - 1 +} + +func getProximityGain(g uint8) uint8 { + switch g { + case 1: + return 0 + case 2: + return 1 + case 4: + return 2 + case 8: + return 3 + default: + return 0 + } +} + +func getALSGain(g uint8) uint8 { + switch g { + case 1: + return 0 + case 4: + return 1 + case 16: + return 2 + case 64: + return 3 + default: + return 0 + } +} diff --git a/apds9960/apds9960_generic.go b/apds9960/apds9960_generic.go new file mode 100644 index 0000000..29265ab --- /dev/null +++ b/apds9960/apds9960_generic.go @@ -0,0 +1,14 @@ +//go:build !nano_33_ble +// +build !nano_33_ble + +package apds9960 + +import "tinygo.org/x/drivers" + +// New creates a new APDS-9960 connection. The I2C bus must already be +// configured. +// +// This function only creates the Device object, it does not touch the device. +func New(bus drivers.I2C) Device { + return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE} +} diff --git a/apds9960/apds9960_nano_33_ble.go b/apds9960/apds9960_nano_33_ble.go new file mode 100644 index 0000000..a17ca68 --- /dev/null +++ b/apds9960/apds9960_nano_33_ble.go @@ -0,0 +1,29 @@ +//go:build nano_33_ble +// +build nano_33_ble + +package apds9960 + +import ( + "machine" + "time" + + "tinygo.org/x/drivers" +) + +// New creates a new APDS-9960 connection. The I2C bus must already be +// configured. +// +// This function only creates the Device object, it does not touch the device. +func New(bus drivers.I2C) Device { + // turn on internal power pin (machine.P0_22) and I2C1 pullups power pin (machine.P1_00) + // and wait a moment. + ENV := machine.P0_22 + ENV.Configure(machine.PinConfig{Mode: machine.PinOutput}) + ENV.High() + R := machine.P1_00 + R.Configure(machine.PinConfig{Mode: machine.PinOutput}) + R.High() + time.Sleep(time.Millisecond * 10) + + return Device{bus: bus, Address: ADPS9960_ADDRESS, mode: MODE_NONE} +} diff --git a/apds9960/registers.go b/apds9960/registers.go new file mode 100644 index 0000000..b6d610b --- /dev/null +++ b/apds9960/registers.go @@ -0,0 +1,78 @@ +package apds9960 + +const ( + + // I2C address + ADPS9960_ADDRESS = 0x39 + + // control/status registers + APDS9960_RAM_REG = 0x00 + APDS9960_ENABLE_REG = 0x80 + APDS9960_ATIME_REG = 0x81 + APDS9960_WTIME_REG = 0x83 + APDS9960_AILTIL_REG = 0x84 + APDS9960_AILTH_REG = 0x85 + APDS9960_AIHTL_REG = 0x86 + APDS9960_AIHTH_REG = 0x87 + APDS9960_PILT_REG = 0x89 + APDS9960_PIHT_REG = 0x8B + APDS9960_PERS_REG = 0x8C + APDS9960_CONFIG1_REG = 0x8D + APDS9960_PPULSE_REG = 0x8E + APDS9960_CONTROL_REG = 0x8F + APDS9960_CONFIG2_REG = 0x90 + APDS9960_ID_REG = 0x92 + APDS9960_STATUS_REG = 0x93 + APDS9960_CDATAL_REG = 0x94 + APDS9960_CDATAH_REG = 0x95 + APDS9960_RDATAL_REG = 0x96 + APDS9960_RDATAH_REG = 0x97 + APDS9960_GDATAL_REG = 0x98 + APDS9960_GDATAH_REG = 0x99 + APDS9960_BDATAL_REG = 0x9A + APDS9960_BDATAH_REG = 0x9B + APDS9960_PDATA_REG = 0x9C + APDS9960_POFFSET_UR_REG = 0x9D + APDS9960_POFFSET_DL_REG = 0x9E + APDS9960_CONFIG3_REG = 0x9F + APDS9960_GPENTH_REG = 0xA0 + APDS9960_GEXTH_REG = 0xA1 + APDS9960_GCONF1_REG = 0xA2 + APDS9960_GCONF2_REG = 0xA3 + APDS9960_GOFFSET_U_REG = 0xA4 + APDS9960_GOFFSET_D_REG = 0xA5 + APDS9960_GOFFSET_L_REG = 0xA7 + APDS9960_GOFFSET_R_REG = 0xA9 + APDS9960_GPULSE_REG = 0xA6 + APDS9960_GCONF3_REG = 0xAA + APDS9960_GCONF4_REG = 0xAB + APDS9960_GFLVL_REG = 0xAE + APDS9960_GSTATUS_REG = 0xAF + APDS9960_IFORCE_REG = 0xE4 + APDS9960_PICLEAR_REG = 0xE5 + APDS9960_CICLEAR_REG = 0xE6 + APDS9960_AICLEAR_REG = 0xE7 + APDS9960_GFIFO_U_REG = 0xFC + APDS9960_GFIFO_D_REG = 0xFD + APDS9960_GFIFO_L_REG = 0xFE + APDS9960_GFIFO_R_REG = 0xFF +) + +const ( + + // sensor modes + MODE_NONE = iota + MODE_PROXIMITY + MODE_COLOR + MODE_GESTURE +) + +const ( + + // detected gestures + GESTURE_NONE = iota + GESTURE_UP + GESTURE_DOWN + GESTURE_LEFT + GESTURE_RIGHT +) diff --git a/examples/apds9960/color/main.go b/examples/apds9960/color/main.go new file mode 100644 index 0000000..27a1bdd --- /dev/null +++ b/examples/apds9960/color/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/apds9960" +) + +func main() { + + machine.I2C1.Configure(machine.I2CConfig{ + SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense + SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense + Frequency: machine.TWI_FREQ_400KHZ, + }) + + sensor := apds9960.New(machine.I2C1) + + if !sensor.Connected() { + println("APDS-9960 not connected!") + return + } + + sensor.Configure(apds9960.Configuration{}) // use default settings + + sensor.EnableColor() // enable color engine + + for { + + if sensor.ColorAvailable() { + r, g, b, c := sensor.ReadColor() + println("Red =", r, "\tGreen =", g, "\tBlue =", b, "\tClear =", c) + } + time.Sleep(time.Millisecond * 100) + } + +} diff --git a/examples/apds9960/gesture/main.go b/examples/apds9960/gesture/main.go new file mode 100644 index 0000000..1e04b78 --- /dev/null +++ b/examples/apds9960/gesture/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/apds9960" +) + +func main() { + + machine.I2C1.Configure(machine.I2CConfig{ + SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense + SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense + Frequency: machine.TWI_FREQ_400KHZ, + }) + + sensor := apds9960.New(machine.I2C1) + + if !sensor.Connected() { + println("APDS-9960 not connected!") + return + } + + sensor.Configure(apds9960.Configuration{}) // use default settings + + sensor.EnableGesture() // enable gesture engine + + for { + + // wave your hand (not too slow) about 10 cm above the sensor + if sensor.GestureAvailable() { + + gesture := sensor.ReadGesture() + print("Detected gesture: ") + switch gesture { + case apds9960.GESTURE_UP: + println("Up") + case apds9960.GESTURE_DOWN: + println("Down") + case apds9960.GESTURE_LEFT: + println("Left") + case apds9960.GESTURE_RIGHT: + println("Right") + } + } + // note: the delay shouldn't be too long, otherwise new gesture data might be lost + time.Sleep(time.Millisecond * 250) + } + +} diff --git a/examples/apds9960/proximity/main.go b/examples/apds9960/proximity/main.go new file mode 100644 index 0000000..c591414 --- /dev/null +++ b/examples/apds9960/proximity/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/apds9960" +) + +func main() { + + machine.I2C1.Configure(machine.I2CConfig{ + SCL: machine.P0_15, // SCL1 on Nano 33 BLE Sense + SDA: machine.P0_14, // SDA1 on Nano 33 BLE Sense + Frequency: machine.TWI_FREQ_400KHZ, + }) + + sensor := apds9960.New(machine.I2C1) + + if !sensor.Connected() { + println("APDS-9960 not connected!") + return + } + + sensor.Configure(apds9960.Configuration{}) // use default settings + + sensor.EnableProximity() // enable proximity engine + + for { + + if sensor.ProximityAvailable() { + p := sensor.ReadProximity() + println("Proximity:", p) + } + time.Sleep(time.Millisecond * 100) + } + +}