2014-03-23 15:47:58 +05:30
|
|
|
// Package BH1750FVI allows interfacing with the BH1750FVI ambient light sensor through I2C.
|
2013-12-21 01:52:36 +05:30
|
|
|
package bh1750fvi
|
2013-12-17 20:37:58 +05:30
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2014-03-03 00:51:23 +05:30
|
|
|
"github.com/kidoman/embd"
|
2013-12-17 20:37:58 +05:30
|
|
|
)
|
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
//accuracy = sensorValue/actualValue] (min = 0.96, typ = 1.2, max = 1.44
|
2013-12-17 20:37:58 +05:30
|
|
|
const (
|
2013-12-20 00:43:40 +05:30
|
|
|
High = "H"
|
|
|
|
High2 = "H2"
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
measurementAcuuracy = 1.2
|
|
|
|
defReadReg = 0x00
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
sensorI2cAddr = 0x23
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
highResOpCode = 0x10
|
|
|
|
highResMode2OpCode = 0x11
|
2013-12-17 20:37:58 +05:30
|
|
|
|
|
|
|
pollDelay = 150
|
|
|
|
)
|
|
|
|
|
2014-03-23 15:47:58 +05:30
|
|
|
// BH1750FVI represents a BH1750FVI ambient light sensor.
|
2014-03-03 00:51:23 +05:30
|
|
|
type BH1750FVI struct {
|
|
|
|
Bus embd.I2CBus
|
|
|
|
Poll int
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2014-03-03 00:51:23 +05:30
|
|
|
mu sync.RWMutex
|
2013-12-17 20:37:58 +05:30
|
|
|
|
|
|
|
lightingReadings chan float64
|
|
|
|
quit chan bool
|
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
i2cAddr byte
|
|
|
|
operationCode byte
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
|
|
|
|
2014-03-23 15:47:58 +05:30
|
|
|
// New returns a BH1750FVI sensor at the specific resolution mode.
|
2014-03-03 00:51:23 +05:30
|
|
|
func New(mode string, bus embd.I2CBus) *BH1750FVI {
|
2013-12-17 20:37:58 +05:30
|
|
|
switch mode {
|
2013-12-20 00:43:40 +05:30
|
|
|
case High:
|
2014-03-03 00:51:23 +05:30
|
|
|
return &BH1750FVI{Bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResOpCode, Poll: pollDelay}
|
2013-12-20 00:43:40 +05:30
|
|
|
case High2:
|
2014-03-03 00:51:23 +05:30
|
|
|
return &BH1750FVI{Bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResMode2OpCode, Poll: pollDelay}
|
2013-12-17 20:37:58 +05:30
|
|
|
default:
|
2014-03-03 00:51:23 +05:30
|
|
|
return &BH1750FVI{Bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResOpCode, Poll: pollDelay}
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-23 15:47:58 +05:30
|
|
|
// NewHighMode returns a BH1750FVI sensor on high resolution mode (1lx resolution)
|
2014-03-03 00:51:23 +05:30
|
|
|
func NewHighMode(bus embd.I2CBus) *BH1750FVI {
|
2013-12-20 00:43:40 +05:30
|
|
|
return New(High, bus)
|
|
|
|
}
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2014-03-23 15:47:58 +05:30
|
|
|
// NewHighMode returns a BH1750FVI sensor on high resolution mode2 (0.5lx resolution)
|
2014-03-03 00:51:23 +05:30
|
|
|
func NewHigh2Mode(bus embd.I2CBus) *BH1750FVI {
|
2013-12-20 00:43:40 +05:30
|
|
|
return New(High2, bus)
|
|
|
|
}
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2014-03-31 18:46:04 +05:30
|
|
|
func (d *BH1750FVI) measureLighting() (float64, error) {
|
|
|
|
if err := d.Bus.WriteByte(d.i2cAddr, d.operationCode); err != nil {
|
|
|
|
return 0, err
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
2013-12-20 00:43:40 +05:30
|
|
|
time.Sleep(180 * time.Millisecond)
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2014-03-31 18:46:04 +05:30
|
|
|
reading, err := d.Bus.ReadWordFromReg(d.i2cAddr, defReadReg)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
|
|
|
|
2014-03-31 18:46:04 +05:30
|
|
|
return float64(int16(reading)) / measurementAcuuracy, nil
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
// Lighting returns the ambient lighting in lx.
|
2014-03-31 18:46:04 +05:30
|
|
|
func (d *BH1750FVI) Lighting() (float64, error) {
|
2013-12-17 20:37:58 +05:30
|
|
|
select {
|
2014-03-31 18:46:04 +05:30
|
|
|
case lighting := <-d.lightingReadings:
|
|
|
|
return lighting, nil
|
2013-12-17 20:37:58 +05:30
|
|
|
default:
|
2013-12-20 00:43:40 +05:30
|
|
|
return d.measureLighting()
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
// Run starts continuous sensor data acquisition loop.
|
2014-03-31 18:46:04 +05:30
|
|
|
func (d *BH1750FVI) Run() {
|
2013-12-17 20:37:58 +05:30
|
|
|
go func() {
|
2013-12-20 00:43:40 +05:30
|
|
|
d.quit = make(chan bool)
|
2013-12-17 20:37:58 +05:30
|
|
|
|
2014-03-03 00:51:23 +05:30
|
|
|
timer := time.Tick(time.Duration(d.Poll) * time.Millisecond)
|
2013-12-17 20:37:58 +05:30
|
|
|
|
|
|
|
var lighting float64
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
2013-12-20 00:43:40 +05:30
|
|
|
case d.lightingReadings <- lighting:
|
2013-12-17 20:37:58 +05:30
|
|
|
case <-timer:
|
2014-03-31 18:46:04 +05:30
|
|
|
l, err := d.measureLighting()
|
|
|
|
if err == nil {
|
2013-12-17 20:37:58 +05:30
|
|
|
lighting = l
|
|
|
|
}
|
2013-12-20 00:43:40 +05:30
|
|
|
if err == nil && d.lightingReadings == nil {
|
|
|
|
d.lightingReadings = make(chan float64)
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
2013-12-20 00:43:40 +05:30
|
|
|
case <-d.quit:
|
|
|
|
d.lightingReadings = nil
|
2013-12-17 20:37:58 +05:30
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-12-20 00:43:40 +05:30
|
|
|
// Close.
|
2014-03-03 00:51:23 +05:30
|
|
|
func (d *BH1750FVI) Close() {
|
2013-12-20 00:43:40 +05:30
|
|
|
if d.quit != nil {
|
|
|
|
d.quit <- true
|
2013-12-17 20:37:58 +05:30
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|