1
0
mirror of https://github.com/kidoman/embd synced 2024-11-01 15:58:42 +01:00
embd/sensor/bh1750fvi/bh1750fvi.go

123 lines
2.6 KiB
Go
Raw Normal View History

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