mirror of https://github.com/periph/devices
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.6 KiB
Go
141 lines
3.6 KiB
Go
// Copyright 2018 The Periph Authors. All rights reserved.
|
|
// Use of this source code is governed under the Apache License, Version 2.0
|
|
// that can be found in the LICENSE file.
|
|
|
|
package bh1750
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"time"
|
|
|
|
"periph.io/x/conn/i2c"
|
|
"periph.io/x/conn/physic"
|
|
)
|
|
|
|
// I2CAddr i2c default address.
|
|
const I2CAddr uint16 = 0x23
|
|
|
|
// AlternativeI2CAddr i2c alternative address.
|
|
const AlternativeI2CAddr uint16 = 0x5c
|
|
|
|
// Resolution represents the measurements modes.
|
|
type Resolution uint8
|
|
|
|
const (
|
|
// ContinuousHighResMode start measurement at 1lx resolution. Measurement time is approx 120ms.
|
|
ContinuousHighResMode Resolution = 0x10
|
|
|
|
// ContinuousHighResMode2 start measurement at 0.5lx resolution. Measurement time is approx 120ms.
|
|
ContinuousHighResMode2 Resolution = 0x11
|
|
|
|
// ContinuousLowResMode start measurement at 4lx resolution. Measurement time is approx 16ms.
|
|
ContinuousLowResMode Resolution = 0x13
|
|
|
|
// OneTimeHighResMode measurement at 1lx resolution and the device is automatically set to Power Down after measurement.
|
|
OneTimeHighResMode Resolution = 0x20
|
|
|
|
// OneTimeHighResMode2 measurement at 0.5lx resolution and the device is automatically set to Power Down after measurement.
|
|
OneTimeHighResMode2 Resolution = 0x21
|
|
|
|
// OneTimeLowResMode measurement at 4lx resolution and the device is automatically set to Power Down after measurement.
|
|
OneTimeLowResMode Resolution = 0x23
|
|
|
|
safetyTimeout = 20 * time.Millisecond
|
|
)
|
|
|
|
// Map of timeouts for measurement type.
|
|
var timeout = map[Resolution]time.Duration{
|
|
ContinuousHighResMode: 120*time.Millisecond + safetyTimeout,
|
|
ContinuousHighResMode2: 120*time.Millisecond + safetyTimeout,
|
|
ContinuousLowResMode: 16*time.Millisecond + safetyTimeout,
|
|
OneTimeHighResMode: 120*time.Millisecond + safetyTimeout,
|
|
OneTimeHighResMode2: 120*time.Millisecond + safetyTimeout,
|
|
OneTimeLowResMode: 16*time.Millisecond + safetyTimeout,
|
|
}
|
|
|
|
// Mode - device mode.
|
|
type Mode uint8
|
|
|
|
const (
|
|
// PowerDown - no active state.
|
|
PowerDown Mode = 0x00
|
|
|
|
// PowerOn - waiting for measurement command.
|
|
PowerOn Mode = 0x01
|
|
)
|
|
|
|
const (
|
|
dataRegister uint8 = 0x00
|
|
measurementTimeRegister uint8 = 0x45
|
|
reset uint8 = 0x07
|
|
)
|
|
|
|
// Dev is a handler to bh1750 controller
|
|
type Dev struct {
|
|
dev i2c.Dev
|
|
res Resolution
|
|
mode Mode
|
|
}
|
|
|
|
// NewI2C opens a handle to an bh1750 sensor.
|
|
//
|
|
// To use on the default address, bh1750.I2CAddr must be passed as argument.
|
|
func NewI2C(bus i2c.Bus, address uint16) (*Dev, error) {
|
|
dev := &Dev{dev: i2c.Dev{Bus: bus, Addr: address}}
|
|
|
|
if err := dev.init(); err != nil {
|
|
return nil, err
|
|
}
|
|
return dev, nil
|
|
}
|
|
|
|
func (d *Dev) init() error {
|
|
if err := d.SetMode(PowerOn); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := d.SetResolution(ContinuousHighResMode); err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err := d.dev.Write([]byte{reset})
|
|
return err
|
|
}
|
|
|
|
// SetMode set the sleep mode of the sensor.
|
|
func (d *Dev) SetMode(m Mode) error {
|
|
d.mode = m
|
|
_, err := d.dev.Write([]byte{reset})
|
|
return err
|
|
}
|
|
|
|
// SetResolution set the resolution mode of the sensor.
|
|
func (d *Dev) SetResolution(r Resolution) error {
|
|
d.res = r
|
|
_, err := d.dev.Write([]byte{byte(r)})
|
|
return err
|
|
}
|
|
|
|
// Sense reads the light value from the bh1750 sensor.
|
|
func (d *Dev) Sense() (physic.LuminousFlux, error) {
|
|
if err := d.SetResolution(d.res); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
time.Sleep(timeout[d.res])
|
|
|
|
buf := [2]byte{}
|
|
if err := d.dev.Tx([]byte{byte(d.res)}, buf[:]); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
rawValue := binary.BigEndian.Uint16(buf[:])
|
|
lux := physic.LuminousFlux(float64(rawValue) / 1.2)
|
|
return lux * physic.Lumen, nil
|
|
}
|
|
|
|
// Halt turn off device.
|
|
func (d *Dev) Halt() error {
|
|
return d.SetMode(PowerDown)
|
|
}
|