diff --git a/bh1750/bh1750.go b/bh1750/bh1750.go new file mode 100644 index 0000000..6d9c5b1 --- /dev/null +++ b/bh1750/bh1750.go @@ -0,0 +1,70 @@ +// Package bh1750 provides a driver for the BH1750 digital Ambient Light +// +// Datasheet: +// https://www.mouser.com/ds/2/348/bh1750fvi-e-186247.pdf +// +package bh1750 + +import ( + "time" + + "machine" +) + +// SamplingMode is the sampling's resolution of the measurement +type SamplingMode byte + +// Device wraps an I2C connection to a bh1750 device. +type Device struct { + bus machine.I2C + mode SamplingMode +} + +// New creates a new bh1750 connection. The I2C bus must already be +// configured. +// +// This function only creates the Device object, it does not touch the device. +func New(bus machine.I2C) Device { + return Device{ + bus: bus, + mode: CONTINUOUS_HIGH_RES_MODE, + } +} + +// Configure sets up the device for communication +func (d *Device) Configure() { + d.bus.Tx(Address, []byte{POWER_ON}, nil) + d.SetMode(d.mode) +} + +// RawSensorData returns the raw value from the bh1750 +func (d *Device) RawSensorData() uint16 { + + buf := []byte{1, 0} + d.bus.Tx(Address, nil, buf) + return (uint16(buf[0]) << 8) | uint16(buf[1]) +} + +// Illuminance returns the adjusted value in mlx (milliLux) +func (d *Device) Illuminance() int32 { + + lux := uint32(d.RawSensorData()) + var coef uint32 + if d.mode == CONTINUOUS_HIGH_RES_MODE || d.mode == ONE_TIME_HIGH_RES_MODE { + coef = HIGH_RES + } else if d.mode == CONTINUOUS_HIGH_RES_MODE_2 || d.mode == ONE_TIME_HIGH_RES_MODE_2 { + coef = HIGH_RES2 + } else { + coef = LOW_RES + } + // 100 * coef * lux * (5/6) + // 5/6 = measurement accuracy as per the datasheet + return int32(250 * coef * lux / 3) +} + +// SetMode changes the reading mode for the sensor +func (d *Device) SetMode(mode SamplingMode) { + d.mode = mode + d.bus.Tx(Address, []byte{byte(d.mode)}, nil) + time.Sleep(10 * time.Millisecond) +} diff --git a/bh1750/registers.go b/bh1750/registers.go new file mode 100644 index 0000000..719b5ee --- /dev/null +++ b/bh1750/registers.go @@ -0,0 +1,24 @@ +package bh1750 + +// Constants/addresses used for I2C. + +// The I2C address which this device listens to. +const Address = 0x23 + +// Registers. Names, addresses and comments copied from the datasheet. +const ( + POWER_DOWN = 0x00 + POWER_ON = 0x01 + RESET = 0x07 + CONTINUOUS_HIGH_RES_MODE SamplingMode = 0x10 + CONTINUOUS_HIGH_RES_MODE_2 SamplingMode = 0x11 + CONTINUOUS_LOW_RES_MODE SamplingMode = 0x13 + ONE_TIME_HIGH_RES_MODE SamplingMode = 0x20 + ONE_TIME_HIGH_RES_MODE_2 SamplingMode = 0x21 + ONE_TIME_LOW_RES_MODE SamplingMode = 0x23 + + // resolution in 10*lx + HIGH_RES = 10 + HIGH_RES2 = 5 + LOW_RES = 40 +) diff --git a/examples/bh1750/main.go b/examples/bh1750/main.go new file mode 100644 index 0000000..6a30d04 --- /dev/null +++ b/examples/bh1750/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "time" + + "machine" + + "github.com/tinygo-org/drivers/bh1750" +) + +func main() { + machine.I2C0.Configure(machine.I2CConfig{}) + sensor := bh1750.New(machine.I2C0) + sensor.Configure() + + for { + lux := sensor.Illuminance() + println("Illuminance:", lux, "lx") + + time.Sleep(500 * time.Millisecond) + } +}