From 9a96639962b8d3158d6a23a32e43b947cb0b6e99 Mon Sep 17 00:00:00 2001 From: Ryan Cox Date: Thu, 25 Sep 2014 19:12:04 -0700 Subject: [PATCH 1/5] Add initial support for isl29125 rgb sensor --- samples/.gitignore | 1 + samples/isl29125.go | 36 ++++++++ sensor/isl29125/isl29125.go | 175 ++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 samples/isl29125.go create mode 100644 sensor/isl29125/isl29125.go diff --git a/samples/.gitignore b/samples/.gitignore index af9b180..5a92db3 100644 --- a/samples/.gitignore +++ b/samples/.gitignore @@ -8,6 +8,7 @@ gpio gpiodetect gpiodirect gpioshort +isl29125 l3gd20 led ledshort diff --git a/samples/isl29125.go b/samples/isl29125.go new file mode 100644 index 0000000..f1c54cd --- /dev/null +++ b/samples/isl29125.go @@ -0,0 +1,36 @@ +// +build ignore + +package main + +import ( + "fmt" + "time" + + "github.com/kidoman/embd" + "github.com/kidoman/embd/sensor/isl29125" + + _ "github.com/kidoman/embd/host/all" +) + +func main() { + + if err := embd.InitI2C(); err != nil { + panic(err) + } + defer embd.CloseI2C() + + bus := embd.NewI2CBus(1) + + isl := isl29125.New(isl29125.DefaultConfig, bus) + defer isl.Close() + + for { + r, err := isl.Reading() + if err != nil { + panic(err) + } + fmt.Printf("%v", r) + + time.Sleep(500 * time.Millisecond) + } +} diff --git a/sensor/isl29125/isl29125.go b/sensor/isl29125/isl29125.go new file mode 100644 index 0000000..b278d7e --- /dev/null +++ b/sensor/isl29125/isl29125.go @@ -0,0 +1,175 @@ +// Package isl29125 allows interfacing with the ISL29125 RGB light sensor +// Datasheet: http://www.intersil.com/content/dam/Intersil/documents/isl2/isl29125.pdf +package isl29125 + +/* + + TODO: + - improve constructor + - add support for config register 2 and 3 + - add support for lux calculation +*/ + +import ( + "time" + + "github.com/golang/glog" + "github.com/kidoman/embd" +) + +const ( + sensorI2cAddr = 0x44 + + pollDelay = 250 + + deviceRegisterAddr = 0x00 + conf1RegisterAddr = 0x01 + flagRegisterAdr = 0x08 +) + +const ( + ModePowerDown = 0x00 + ModeGreenOnly = 0x01 + ModeRedOnly = 0x02 + ModeBlueOnly = 0x03 + ModeStandBy = 0x04 + ModeRGB = 0x05 + ModeRG = 0x06 + ModeGB = 0x07 +) + +const ( + LuxRange375 = 0x00 + LuxRange10k = 0x08 +) + +const ( + Resolution16Bit = 0x00 + Resolution12Bit = 0x10 +) + +const ( + SyncStartOnWrite = 0x00 + SyncStartOnInt = 0x20 +) + +const ( + RegisterGreenLow = 0x09 + RegisterGreenHigh = 0x0a + RegisterRedLow = 0x0b + RegisterRedHigh = 0x0c + RegisterBlueLow = 0x0d + RegisterBlueHigh = 0x0e +) + +const ( + FlagInterrupt = 0x01 + FlagConversion = 0x02 + FlagPowerDownOrBrownOut = 0x04 + FlagGreenConverting = 0x10 + FlagRedConverting = 0x20 + FlagBlueConverting = 0x30 +) + +const ( + DefaultConfig = ModePowerDown | LuxRange375 | Resolution16Bit | SyncStartOnWrite +) + +const ( + DeviceID = 0x7d +) + +// Reading represents a single reading from an RGB light sensor +type Reading struct { + Red uint16 + Green uint16 + Blue uint16 + Lux uint16 + LuxRange int + Resolution int +} + +// ISL29125 represents an RGB light sensor +type ISL29125 struct { + Bus embd.I2CBus + Poll int + + readings chan *Reading + quit chan bool + + mode int + luxRange int + resolution int + syncStart int +} + +// New returns an ISL29125 for a given config +func New(config int, bus embd.I2CBus) *ISL29125 { + glog.Info("Creating new ISL29125") + return &ISL29125{Bus: bus, Poll: pollDelay} +} + +func (i *ISL29125) getReading() (*Reading, error) { + + glog.Info("Getting reading") + red, err := i.Bus.ReadWordFromReg(sensorI2cAddr, RegisterRedLow) + if err != nil { + return nil, err + } + green, err := i.Bus.ReadWordFromReg(sensorI2cAddr, RegisterGreenLow) + if err != nil { + return nil, err + } + blue, err := i.Bus.ReadWordFromReg(sensorI2cAddr, RegisterBlueLow) + if err != nil { + return nil, err + } + + return &Reading{Red: red, Green: green, Blue: blue}, nil +} + +// Reading returns a single sensor reading +func (i *ISL29125) Reading() (*Reading, error) { + select { + case r := <-i.readings: + return r, nil + default: + return i.getReading() + } +} + +// Run starts continuous sensor data acquisition loop. +func (i *ISL29125) Run() { + glog.Info("Running sensor") + go func() { + i.quit = make(chan bool) + i.readings = make(chan *Reading) + timer := time.Tick(time.Duration(i.Poll) * time.Millisecond) + + var reading *Reading + + for { + select { + case i.readings <- reading: + case <-timer: + r, err := i.getReading() + if err == nil { + reading = r + } + case <-i.quit: + i.readings = nil + return + } + } + }() + return +} + +// Close down sensor +func (i *ISL29125) Close() { + glog.Info("Closing sensor") + if i.quit != nil { + i.quit <- true + } + return +} From 3f7fe59036353141f33678e75c4c840b13cad16f Mon Sep 17 00:00:00 2001 From: Ryan Cox Date: Wed, 22 Oct 2014 09:07:12 -0700 Subject: [PATCH 2/5] Add support for isl29125 RGB light sensor --- samples/isl29125.go | 4 +- sensor/isl29125/isl29125.go | 107 +++++++++++++++++++++++++++++------- 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/samples/isl29125.go b/samples/isl29125.go index f1c54cd..799a8e2 100644 --- a/samples/isl29125.go +++ b/samples/isl29125.go @@ -7,9 +7,8 @@ import ( "time" "github.com/kidoman/embd" - "github.com/kidoman/embd/sensor/isl29125" - _ "github.com/kidoman/embd/host/all" + "github.com/kidoman/embd/sensor/isl29125" ) func main() { @@ -23,6 +22,7 @@ func main() { isl := isl29125.New(isl29125.DefaultConfig, bus) defer isl.Close() + isl.Init() for { r, err := isl.Reading() diff --git a/sensor/isl29125/isl29125.go b/sensor/isl29125/isl29125.go index b278d7e..6dd5f48 100644 --- a/sensor/isl29125/isl29125.go +++ b/sensor/isl29125/isl29125.go @@ -5,12 +5,15 @@ package isl29125 /* TODO: - - improve constructor - - add support for config register 2 and 3 - - add support for lux calculation + - add support for the following: + - config register 2 and 3 + - lux calculation + - powerdown / power up + - interupt config / monitor */ import ( + "fmt" "time" "github.com/golang/glog" @@ -18,13 +21,7 @@ import ( ) const ( - sensorI2cAddr = 0x44 - pollDelay = 250 - - deviceRegisterAddr = 0x00 - conf1RegisterAddr = 0x01 - flagRegisterAdr = 0x08 ) const ( @@ -43,6 +40,12 @@ const ( LuxRange10k = 0x08 ) +const ( + IRAdjustLow = 0x00 + IRAdjustMed = 0x20 + IRAdjustHigh = 0x3f +) + const ( Resolution16Bit = 0x00 Resolution12Bit = 0x10 @@ -54,6 +57,11 @@ const ( ) const ( + RegisterDeviceID = 0x00 + RegisterConfig1 = 0x01 + RegisterConfig2 = 0x02 + RegisterConfig3 = 0x03 + RegisterFlags = 0x08 RegisterGreenLow = 0x09 RegisterGreenHigh = 0x0a RegisterRedLow = 0x0b @@ -63,6 +71,7 @@ const ( ) const ( + FlagReady = 0x00 FlagInterrupt = 0x01 FlagConversion = 0x02 FlagPowerDownOrBrownOut = 0x04 @@ -72,11 +81,17 @@ const ( ) const ( - DefaultConfig = ModePowerDown | LuxRange375 | Resolution16Bit | SyncStartOnWrite + DefaultConfig = ModeRGB | LuxRange375 | Resolution16Bit | SyncStartOnWrite ) const ( - DeviceID = 0x7d + SensorAddr = 0x44 + DeviceID = 0x7d +) + +const ( + CmdGetStatus = 0x08 + CmdReset = 0x46 ) // Reading represents a single reading from an RGB light sensor @@ -97,30 +112,82 @@ type ISL29125 struct { readings chan *Reading quit chan bool - mode int - luxRange int - resolution int - syncStart int + mode uint8 } // New returns an ISL29125 for a given config -func New(config int, bus embd.I2CBus) *ISL29125 { +func New(config uint8, bus embd.I2CBus) *ISL29125 { glog.Info("Creating new ISL29125") - return &ISL29125{Bus: bus, Poll: pollDelay} + return &ISL29125{Bus: bus, Poll: pollDelay, mode: config} +} + +func (i *ISL29125) Init() error { + + // verify that i2c device is reachable on specified bus and that it reports back the correct ID + id, err := i.Bus.ReadByteFromReg(SensorAddr, RegisterDeviceID) + if err != nil { + return err + } + if DeviceID != id { + return fmt.Errorf("Invalid device id. Expected [%x] but device reports [%x]", DeviceID, id) + } + + // power down device ( don't know current state; assume it's running ) + err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig1, ModePowerDown) + if err != nil { + return err + } + time.Sleep(100 * time.Millisecond) + + // reset device + err = i.Bus.WriteByteToReg(SensorAddr, DeviceID, CmdReset) + if err != nil { + return err + } + time.Sleep(100 * time.Millisecond) + + // verify status after reset is ready + status, err := i.Bus.ReadByteFromReg(SensorAddr, CmdGetStatus) + if err != nil { + return err + } + if status != FlagReady { + return fmt.Errorf("Invalid device status. Expected [%x] but device reports [%x]", FlagReady, status) + } + + // set config 1 to user specified mode + err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig1, i.mode) + if err != nil { + return err + } + // set config 2 to fixed value + err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig2, IRAdjustHigh) + if err != nil { + return err + } + + // set config 3 to fixed value + err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig3, 0x0) + if err != nil { + return err + } + + return nil + } func (i *ISL29125) getReading() (*Reading, error) { glog.Info("Getting reading") - red, err := i.Bus.ReadWordFromReg(sensorI2cAddr, RegisterRedLow) + red, err := i.Bus.ReadWordFromReg(SensorAddr, RegisterRedLow) if err != nil { return nil, err } - green, err := i.Bus.ReadWordFromReg(sensorI2cAddr, RegisterGreenLow) + green, err := i.Bus.ReadWordFromReg(SensorAddr, RegisterGreenLow) if err != nil { return nil, err } - blue, err := i.Bus.ReadWordFromReg(sensorI2cAddr, RegisterBlueLow) + blue, err := i.Bus.ReadWordFromReg(SensorAddr, RegisterBlueLow) if err != nil { return nil, err } From b26f74efe8b3de8f89eb24eab9bedae9d1fe630c Mon Sep 17 00:00:00 2001 From: Ryan Cox Date: Tue, 25 Aug 2015 20:52:48 -0700 Subject: [PATCH 3/5] changes from PR comments --- sensor/isl29125/isl29125.go | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/sensor/isl29125/isl29125.go b/sensor/isl29125/isl29125.go index 6dd5f48..03b5293 100644 --- a/sensor/isl29125/isl29125.go +++ b/sensor/isl29125/isl29125.go @@ -94,7 +94,7 @@ const ( CmdReset = 0x46 ) -// Reading represents a single reading from an RGB light sensor +// Reading represents a single reading from an RGB light sensor. type Reading struct { Red uint16 Green uint16 @@ -104,7 +104,7 @@ type Reading struct { Resolution int } -// ISL29125 represents an RGB light sensor +// ISL29125 represents an RGB light sensor. type ISL29125 struct { Bus embd.I2CBus Poll int @@ -115,9 +115,9 @@ type ISL29125 struct { mode uint8 } -// New returns an ISL29125 for a given config +// New returns an ISL29125 for a given config. func New(config uint8, bus embd.I2CBus) *ISL29125 { - glog.Info("Creating new ISL29125") + glog.V(1).Info("Creating new ISL29125") return &ISL29125{Bus: bus, Poll: pollDelay, mode: config} } @@ -147,28 +147,25 @@ func (i *ISL29125) Init() error { time.Sleep(100 * time.Millisecond) // verify status after reset is ready - status, err := i.Bus.ReadByteFromReg(SensorAddr, CmdGetStatus) - if err != nil { + if status, err := i.Bus.ReadByteFromReg(SensorAddr, CmdGetStatus); err != nil { return err } + if status != FlagReady { return fmt.Errorf("Invalid device status. Expected [%x] but device reports [%x]", FlagReady, status) } // set config 1 to user specified mode - err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig1, i.mode) - if err != nil { + if err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig1, i.mode); err != nil { return err } // set config 2 to fixed value - err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig2, IRAdjustHigh) - if err != nil { + if err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig2, IRAdjustHigh); err != nil { return err } // set config 3 to fixed value - err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig3, 0x0) - if err != nil { + if err = i.Bus.WriteByteToReg(SensorAddr, RegisterConfig3, 0x0); err != nil { return err } @@ -178,7 +175,7 @@ func (i *ISL29125) Init() error { func (i *ISL29125) getReading() (*Reading, error) { - glog.Info("Getting reading") + glog.V(1).Info("Getting reading") red, err := i.Bus.ReadWordFromReg(SensorAddr, RegisterRedLow) if err != nil { return nil, err @@ -195,7 +192,7 @@ func (i *ISL29125) getReading() (*Reading, error) { return &Reading{Red: red, Green: green, Blue: blue}, nil } -// Reading returns a single sensor reading +// Reading returns a single sensor reading. func (i *ISL29125) Reading() (*Reading, error) { select { case r := <-i.readings: @@ -207,11 +204,12 @@ func (i *ISL29125) Reading() (*Reading, error) { // Run starts continuous sensor data acquisition loop. func (i *ISL29125) Run() { - glog.Info("Running sensor") + glog.V(1).Info("Running sensor") go func() { i.quit = make(chan bool) i.readings = make(chan *Reading) - timer := time.Tick(time.Duration(i.Poll) * time.Millisecond) + timer := time.NewTicker(time.Duration(i.Poll) * time.Millisecond) + defer timer.Stop() var reading *Reading @@ -232,9 +230,9 @@ func (i *ISL29125) Run() { return } -// Close down sensor +// Close down sensor. func (i *ISL29125) Close() { - glog.Info("Closing sensor") + glog.V(1).Info("Closing sensor") if i.quit != nil { i.quit <- true } From 578a00988096f90ad228384f6a784fbd5c624914 Mon Sep 17 00:00:00 2001 From: Ryan Cox Date: Tue, 25 Aug 2015 21:03:19 -0700 Subject: [PATCH 4/5] PR changes --- samples/isl29125.go | 1 - sensor/isl29125/isl29125.go | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/samples/isl29125.go b/samples/isl29125.go index 799a8e2..0603da1 100644 --- a/samples/isl29125.go +++ b/samples/isl29125.go @@ -22,7 +22,6 @@ func main() { isl := isl29125.New(isl29125.DefaultConfig, bus) defer isl.Close() - isl.Init() for { r, err := isl.Reading() diff --git a/sensor/isl29125/isl29125.go b/sensor/isl29125/isl29125.go index 03b5293..d682753 100644 --- a/sensor/isl29125/isl29125.go +++ b/sensor/isl29125/isl29125.go @@ -112,7 +112,8 @@ type ISL29125 struct { readings chan *Reading quit chan bool - mode uint8 + mode uint8 + initialized bool } // New returns an ISL29125 for a given config. @@ -121,7 +122,12 @@ func New(config uint8, bus embd.I2CBus) *ISL29125 { return &ISL29125{Bus: bus, Poll: pollDelay, mode: config} } -func (i *ISL29125) Init() error { +// Setup initializes the sensor. +func (i *ISL29125) setup() error { + + if i.initialized { + return nil + } // verify that i2c device is reachable on specified bus and that it reports back the correct ID id, err := i.Bus.ReadByteFromReg(SensorAddr, RegisterDeviceID) @@ -169,11 +175,15 @@ func (i *ISL29125) Init() error { return err } + i.initialized = true return nil } func (i *ISL29125) getReading() (*Reading, error) { + if err := i.setup(); err != nil { + return nil, err + } glog.V(1).Info("Getting reading") red, err := i.Bus.ReadWordFromReg(SensorAddr, RegisterRedLow) From 21a23f897ccda9db0097ab5b1d44fec5630550b4 Mon Sep 17 00:00:00 2001 From: Ryan Cox Date: Tue, 25 Aug 2015 21:29:22 -0700 Subject: [PATCH 5/5] ticker syntax fix --- sensor/isl29125/isl29125.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sensor/isl29125/isl29125.go b/sensor/isl29125/isl29125.go index d682753..da36d48 100644 --- a/sensor/isl29125/isl29125.go +++ b/sensor/isl29125/isl29125.go @@ -153,7 +153,9 @@ func (i *ISL29125) setup() error { time.Sleep(100 * time.Millisecond) // verify status after reset is ready - if status, err := i.Bus.ReadByteFromReg(SensorAddr, CmdGetStatus); err != nil { + status, err := i.Bus.ReadByteFromReg(SensorAddr, CmdGetStatus) + + if err != nil { return err } @@ -218,15 +220,15 @@ func (i *ISL29125) Run() { go func() { i.quit = make(chan bool) i.readings = make(chan *Reading) - timer := time.NewTicker(time.Duration(i.Poll) * time.Millisecond) - defer timer.Stop() + ticker := time.NewTicker(time.Duration(i.Poll) * time.Millisecond) + defer ticker.Stop() var reading *Reading for { select { case i.readings <- reading: - case <-timer: + case <-ticker.C: r, err := i.getReading() if err == nil { reading = r