mirror of
https://github.com/kidoman/embd
synced 2024-12-22 12:50:19 +01:00
- add support for tmp006
- refactor the i2c interface
This commit is contained in:
parent
1a6f97f102
commit
0563d2be5c
146
i2c/i2c.go
146
i2c/i2c.go
@ -22,22 +22,26 @@ const (
|
|||||||
|
|
||||||
// A Bus implements access to the I2C two wire bus.
|
// A Bus implements access to the I2C two wire bus.
|
||||||
type Bus interface {
|
type Bus interface {
|
||||||
// Read a byte from the given address.
|
// ReadByte reads a byte from the given address.
|
||||||
ReadByte(addr byte) (value byte, err error)
|
ReadByte(addr byte) (value byte, err error)
|
||||||
// Write a byte to the given address.
|
// WriteByte writes a byte to the given address.
|
||||||
WriteByte(addr, value byte) error
|
WriteByte(addr, value byte) error
|
||||||
// Write a bunch of bytes ot the given address.
|
// WriteBytes writes a slice bytes to the given address.
|
||||||
WriteBytes(addr byte, value []byte) error
|
WriteBytes(addr byte, value []byte) error
|
||||||
|
|
||||||
// Read a bunch of bytes (len(value)) from the given address and register.
|
// ReadFromReg reads n (len(value)) bytes from the given address and register.
|
||||||
ReadFromReg(addr, reg byte, value []byte) (err error)
|
ReadFromReg(addr, reg byte, value []byte) error
|
||||||
// Read a byte from the given address and register.
|
// ReadByteFromReg reads a byte from the given address and register.
|
||||||
ReadByteFromReg(addr, reg byte) (value byte, err error)
|
ReadByteFromReg(addr, reg byte) (value byte, err error)
|
||||||
// Read a int from the given address and register.
|
// ReadU16FromReg reads a unsigned 16 bit integer from the given address and register.
|
||||||
ReadInt(addr, reg byte) (value int, err error)
|
ReadWordFromReg(addr, reg byte) (value uint16, err error)
|
||||||
|
|
||||||
// Write a byte to the given address and register.
|
// WriteToReg writes len(value) bytes to the given address and register.
|
||||||
WriteToReg(addr, reg, value byte) error
|
WriteToReg(addr, reg byte, value []byte) error
|
||||||
|
// WriteByteToReg writes a byte to the given address and register.
|
||||||
|
WriteByteToReg(addr, reg, value byte) error
|
||||||
|
// WriteU16ToReg
|
||||||
|
WriteWordToReg(addr, reg byte, value uint16) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type i2c_msg struct {
|
type i2c_msg struct {
|
||||||
@ -108,7 +112,6 @@ func (b *bus) setAddress(addr byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a byte from the given address.
|
|
||||||
func (b *bus) ReadByte(addr byte) (value byte, err error) {
|
func (b *bus) ReadByte(addr byte) (value byte, err error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
@ -129,7 +132,6 @@ func (b *bus) ReadByte(addr byte) (value byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a byte to the given address.
|
|
||||||
func (b *bus) WriteByte(addr, value byte) (err error) {
|
func (b *bus) WriteByte(addr, value byte) (err error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
@ -147,7 +149,6 @@ func (b *bus) WriteByte(addr, value byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a bunch of bytes ot the given address.
|
|
||||||
func (b *bus) WriteBytes(addr byte, value []byte) error {
|
func (b *bus) WriteBytes(addr byte, value []byte) error {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
@ -172,7 +173,6 @@ func (b *bus) WriteBytes(addr byte, value []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a bunch of bytes (len(value)) from the given address and register.
|
|
||||||
func (b *bus) ReadFromReg(addr, reg byte, value []byte) (err error) {
|
func (b *bus) ReadFromReg(addr, reg byte, value []byte) (err error) {
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
@ -206,7 +206,6 @@ func (b *bus) ReadFromReg(addr, reg byte, value []byte) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a byte from the given address and register.
|
|
||||||
func (b *bus) ReadByteFromReg(addr, reg byte) (value byte, err error) {
|
func (b *bus) ReadByteFromReg(addr, reg byte) (value byte, err error) {
|
||||||
buf := make([]byte, 1)
|
buf := make([]byte, 1)
|
||||||
if err = b.ReadFromReg(addr, reg, buf); err != nil {
|
if err = b.ReadFromReg(addr, reg, buf); err != nil {
|
||||||
@ -216,18 +215,16 @@ func (b *bus) ReadByteFromReg(addr, reg byte) (value byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a int from the given address and register.
|
func (b *bus) ReadWordFromReg(addr, reg byte) (value uint16, err error) {
|
||||||
func (b *bus) ReadInt(addr, reg byte) (value int, err error) {
|
buf := make([]byte, 2)
|
||||||
var buf = make([]byte, 2)
|
|
||||||
if err = b.ReadFromReg(addr, reg, buf); err != nil {
|
if err = b.ReadFromReg(addr, reg, buf); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = int((int(buf[0]) << 8) | int(buf[1]))
|
value = uint16((uint16(buf[0]) << 8) | uint16(buf[1]))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a byte to the given address and register.
|
func (b *bus) WriteToReg(addr, reg byte, value []byte) (err error) {
|
||||||
func (b *bus) WriteToReg(addr, reg, value byte) (err error) {
|
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
@ -235,16 +232,81 @@ func (b *bus) WriteToReg(addr, reg, value byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var outbuf [2]byte
|
outbuf := append([]byte{reg}, value...)
|
||||||
|
|
||||||
|
hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&outbuf))
|
||||||
|
|
||||||
|
var message i2c_msg
|
||||||
|
message.addr = uint16(addr)
|
||||||
|
message.flags = 0
|
||||||
|
message.len = uint16(len(outbuf))
|
||||||
|
message.buf = uintptr(unsafe.Pointer(&hdrp.Data))
|
||||||
|
|
||||||
|
var packets i2c_rdwr_ioctl_data
|
||||||
|
|
||||||
|
packets.msgs = uintptr(unsafe.Pointer(&message))
|
||||||
|
packets.nmsg = 1
|
||||||
|
|
||||||
|
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, b.file.Fd(), rdrwCmd, uintptr(unsafe.Pointer(&packets))); errno != 0 {
|
||||||
|
err = syscall.Errno(errno)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bus) WriteByteToReg(addr, reg, value byte) (err error) {
|
||||||
|
b.mu.Lock()
|
||||||
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
|
if err = b.setAddress(addr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outbuf := [...]byte{
|
||||||
|
reg,
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
|
||||||
|
var message i2c_msg
|
||||||
|
message.addr = uint16(addr)
|
||||||
|
message.flags = 0
|
||||||
|
message.len = uint16(len(outbuf))
|
||||||
|
message.buf = uintptr(unsafe.Pointer(&outbuf))
|
||||||
|
|
||||||
|
var packets i2c_rdwr_ioctl_data
|
||||||
|
|
||||||
|
packets.msgs = uintptr(unsafe.Pointer(&message))
|
||||||
|
packets.nmsg = 1
|
||||||
|
|
||||||
|
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, b.file.Fd(), rdrwCmd, uintptr(unsafe.Pointer(&packets))); errno != 0 {
|
||||||
|
err = syscall.Errno(errno)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *bus) WriteWordToReg(addr, reg byte, value uint16) (err error) {
|
||||||
|
b.mu.Lock()
|
||||||
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
|
if err = b.setAddress(addr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outbuf := [...]byte{
|
||||||
|
reg,
|
||||||
|
byte(value >> 8),
|
||||||
|
byte(value),
|
||||||
|
}
|
||||||
|
|
||||||
var messages i2c_msg
|
var messages i2c_msg
|
||||||
messages.addr = uint16(addr)
|
messages.addr = uint16(addr)
|
||||||
messages.flags = 0
|
messages.flags = 0
|
||||||
messages.len = uint16(len(outbuf))
|
messages.len = uint16(len(outbuf))
|
||||||
messages.buf = uintptr(unsafe.Pointer(&outbuf))
|
messages.buf = uintptr(unsafe.Pointer(&outbuf))
|
||||||
|
|
||||||
outbuf[0] = reg
|
|
||||||
outbuf[1] = value
|
|
||||||
|
|
||||||
var packets i2c_rdwr_ioctl_data
|
var packets i2c_rdwr_ioctl_data
|
||||||
|
|
||||||
packets.msgs = uintptr(unsafe.Pointer(&messages))
|
packets.msgs = uintptr(unsafe.Pointer(&messages))
|
||||||
@ -258,37 +320,47 @@ func (b *bus) WriteToReg(addr, reg, value byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a byte from the given address.
|
// ReadByte reads a byte from the given address.
|
||||||
func ReadByte(addr byte) (value byte, err error) {
|
func ReadByte(addr byte) (value byte, err error) {
|
||||||
return Default.ReadByte(addr)
|
return Default.ReadByte(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a byte to the given address.
|
// WriteByte writes a byte to the given address.
|
||||||
func WriteByte(addr, value byte) (err error) {
|
func WriteByte(addr, value byte) error {
|
||||||
return Default.WriteByte(addr, value)
|
return Default.WriteByte(addr, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a bunch of bytes ot the given address.
|
// WriteBytes writes a slice bytes to the given address.
|
||||||
func WriteBytes(addr byte, value []byte) error {
|
func WriteBytes(addr byte, value []byte) error {
|
||||||
return Default.WriteBytes(addr, value)
|
return Default.WriteBytes(addr, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a bunch of bytes (len(value)) from the given address and register.
|
// ReadFromReg reads n (len(value)) bytes from the given address and register.
|
||||||
func ReadFromReg(addr, reg byte, value []byte) (err error) {
|
func ReadFromReg(addr, reg byte, value []byte) error {
|
||||||
return Default.ReadFromReg(addr, reg, value)
|
return Default.ReadFromReg(addr, reg, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a byte from the given address and register.
|
// ReadByteFromReg reads a byte from the given address and register.
|
||||||
func ReadByteFromReg(addr, reg byte) (value byte, err error) {
|
func ReadByteFromReg(addr, reg byte) (value byte, err error) {
|
||||||
return Default.ReadByteFromReg(addr, reg)
|
return Default.ReadByteFromReg(addr, reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a int from the given address and register.
|
// ReadU16FromReg reads a unsigned 16 bit integer from the given address and register.
|
||||||
func ReadInt(addr, reg byte) (value int, err error) {
|
func ReadWordFromReg(addr, reg byte) (value uint16, err error) {
|
||||||
return Default.ReadInt(addr, reg)
|
return Default.ReadWordFromReg(addr, reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a byte to the given address and register.
|
// WriteToReg writes len(value) bytes to the given address and register.
|
||||||
func WriteToReg(addr, reg, value byte) (err error) {
|
func WriteToReg(addr, reg byte, value []byte) error {
|
||||||
return Default.WriteToReg(addr, reg, value)
|
return Default.WriteToReg(addr, reg, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteByteToReg writes a byte to the given address and register.
|
||||||
|
func WriteByteToReg(addr, reg, value byte) error {
|
||||||
|
return Default.WriteByteToReg(addr, reg, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteU16ToReg
|
||||||
|
func WriteWordToReg(addr, reg byte, value uint16) error {
|
||||||
|
return Default.WriteWordToReg(addr, reg, value)
|
||||||
|
}
|
||||||
|
@ -14,11 +14,11 @@ func main() {
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lightingSensor := bh1750fvi.New(bh1750fvi.High, bus)
|
sensor := bh1750fvi.New(bh1750fvi.High, bus)
|
||||||
defer lightingSensor.Close()
|
defer sensor.Close()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
lighting, err := lightingSensor.Lighting()
|
lighting, err := sensor.Lighting()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
41
samples/tmp006.go
Normal file
41
samples/tmp006.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
|
||||||
|
"github.com/kid0m4n/go-rpi/i2c"
|
||||||
|
"github.com/kid0m4n/go-rpi/sensor/tmp006"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
bus, err := i2c.NewBus(1)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor := tmp006.New(bus, 0x40)
|
||||||
|
if status, err := sensor.Present(); err != nil || !status {
|
||||||
|
log.Print("tmp006: not found")
|
||||||
|
log.Print(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer sensor.Close()
|
||||||
|
|
||||||
|
sensor.Start()
|
||||||
|
|
||||||
|
stop := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(stop, os.Interrupt, os.Kill)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case temp := <-sensor.ObjTemps():
|
||||||
|
log.Printf("tmp006: got obj temp %.2f", temp)
|
||||||
|
case temp := <-sensor.RawDieTemps():
|
||||||
|
log.Printf("tmp006: got die temp %.2f", temp)
|
||||||
|
case <-stop:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -90,12 +90,12 @@ func (d *bh1750fvi) measureLighting() (lighting float64, err error) {
|
|||||||
}
|
}
|
||||||
time.Sleep(180 * time.Millisecond)
|
time.Sleep(180 * time.Millisecond)
|
||||||
|
|
||||||
var sensorReading int
|
var reading uint16
|
||||||
if sensorReading, err = d.bus.ReadInt(d.i2cAddr, defReadReg); err != nil {
|
if reading, err = d.bus.ReadWordFromReg(d.i2cAddr, defReadReg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
lighting = float64(sensorReading) / measurementAcuuracy
|
lighting = float64(int16(reading)) / measurementAcuuracy
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ func (d *bmp085) calibrate() (err error) {
|
|||||||
defer d.cmu.Unlock()
|
defer d.cmu.Unlock()
|
||||||
|
|
||||||
readInt16 := func(reg byte) (value int16, err error) {
|
readInt16 := func(reg byte) (value int16, err error) {
|
||||||
var v int
|
var v uint16
|
||||||
if v, err = d.bus.ReadInt(address, reg); err != nil {
|
if v, err = d.bus.ReadWordFromReg(address, reg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = int16(v)
|
value = int16(v)
|
||||||
@ -111,8 +111,8 @@ func (d *bmp085) calibrate() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readUInt16 := func(reg byte) (value uint16, err error) {
|
readUInt16 := func(reg byte) (value uint16, err error) {
|
||||||
var v int
|
var v uint16
|
||||||
if v, err = d.bus.ReadInt(address, reg); err != nil {
|
if v, err = d.bus.ReadWordFromReg(address, reg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = uint16(v)
|
value = uint16(v)
|
||||||
@ -185,16 +185,13 @@ func (d *bmp085) calibrate() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *bmp085) readUncompensatedTemp() (temp uint16, err error) {
|
func (d *bmp085) readUncompensatedTemp() (temp uint16, err error) {
|
||||||
if err = d.bus.WriteToReg(address, control, readTempCmd); err != nil {
|
if err = d.bus.WriteByteToReg(address, control, readTempCmd); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(tempReadDelay)
|
time.Sleep(tempReadDelay)
|
||||||
var t int
|
if temp, err = d.bus.ReadWordFromReg(address, tempData); err != nil {
|
||||||
t, err = d.bus.ReadInt(address, tempData)
|
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
temp = uint16(t)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +247,7 @@ func (d *bmp085) Temperature() (temp float64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *bmp085) readUncompensatedPressure() (pressure uint32, err error) {
|
func (d *bmp085) readUncompensatedPressure() (pressure uint32, err error) {
|
||||||
if err = d.bus.WriteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil {
|
if err = d.bus.WriteByteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(2+(3<<d.oss)) * time.Millisecond)
|
time.Sleep(time.Duration(2+(3<<d.oss)) * time.Millisecond)
|
||||||
|
@ -102,8 +102,8 @@ func (d *bmp180) calibrate() (err error) {
|
|||||||
defer d.cmu.Unlock()
|
defer d.cmu.Unlock()
|
||||||
|
|
||||||
readInt16 := func(reg byte) (value int16, err error) {
|
readInt16 := func(reg byte) (value int16, err error) {
|
||||||
var v int
|
var v uint16
|
||||||
if v, err = d.bus.ReadInt(address, reg); err != nil {
|
if v, err = d.bus.ReadWordFromReg(address, reg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = int16(v)
|
value = int16(v)
|
||||||
@ -111,8 +111,8 @@ func (d *bmp180) calibrate() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readUInt16 := func(reg byte) (value uint16, err error) {
|
readUInt16 := func(reg byte) (value uint16, err error) {
|
||||||
var v int
|
var v uint16
|
||||||
if v, err = d.bus.ReadInt(address, reg); err != nil {
|
if v, err = d.bus.ReadWordFromReg(address, reg); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value = uint16(v)
|
value = uint16(v)
|
||||||
@ -185,16 +185,13 @@ func (d *bmp180) calibrate() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *bmp180) readUncompensatedTemp() (temp uint16, err error) {
|
func (d *bmp180) readUncompensatedTemp() (temp uint16, err error) {
|
||||||
if err = d.bus.WriteToReg(address, control, readTempCmd); err != nil {
|
if err = d.bus.WriteByteToReg(address, control, readTempCmd); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(tempReadDelay)
|
time.Sleep(tempReadDelay)
|
||||||
var t int
|
if temp, err = d.bus.ReadWordFromReg(address, tempData); err != nil {
|
||||||
t, err = d.bus.ReadInt(address, tempData)
|
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
temp = uint16(t)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +247,7 @@ func (d *bmp180) Temperature() (temp float64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *bmp180) readUncompensatedPressure() (pressure uint32, err error) {
|
func (d *bmp180) readUncompensatedPressure() (pressure uint32, err error) {
|
||||||
if err = d.bus.WriteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil {
|
if err = d.bus.WriteByteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(time.Duration(2+(3<<d.oss)) * time.Millisecond)
|
time.Sleep(time.Duration(2+(3<<d.oss)) * time.Millisecond)
|
||||||
|
@ -213,10 +213,10 @@ func (d *l3gd20) setup() (err error) {
|
|||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
if err = d.bus.WriteToReg(address, ctrlReg1, ctrlReg1Default); err != nil {
|
if err = d.bus.WriteByteToReg(address, ctrlReg1, ctrlReg1Default); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = d.bus.WriteToReg(address, ctrlReg4, d.rng.value); err != nil {
|
if err = d.bus.WriteByteToReg(address, ctrlReg4, d.rng.value); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,5 +370,5 @@ func (d *l3gd20) Close() (err error) {
|
|||||||
if d.quit != nil {
|
if d.quit != nil {
|
||||||
d.quit <- struct{}{}
|
d.quit <- struct{}{}
|
||||||
}
|
}
|
||||||
return d.bus.WriteToReg(address, ctrlReg1, ctrlReg1Finished)
|
return d.bus.WriteByteToReg(address, ctrlReg1, ctrlReg1Finished)
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ type LSM303 interface {
|
|||||||
|
|
||||||
// Run starts the sensor data acquisition loop.
|
// Run starts the sensor data acquisition loop.
|
||||||
Run() error
|
Run() error
|
||||||
// Close closes the sensor data acquisition loop and put the LSM303 into sleep mode.
|
// Close closes the sensor data acquisition loop and puts the LSM303 into sleep mode.
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,10 +91,10 @@ func (d *lsm303) setup() (err error) {
|
|||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
if err = d.bus.WriteToReg(magAddress, magConfigRegA, MagCRADefault); err != nil {
|
if err = d.bus.WriteByteToReg(magAddress, magConfigRegA, MagCRADefault); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = d.bus.WriteToReg(magAddress, magModeReg, MagMRDefault); err != nil {
|
if err = d.bus.WriteByteToReg(magAddress, magModeReg, MagMRDefault); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ func (d *lsm303) Close() (err error) {
|
|||||||
if d.quit != nil {
|
if d.quit != nil {
|
||||||
d.quit <- struct{}{}
|
d.quit <- struct{}{}
|
||||||
}
|
}
|
||||||
err = d.bus.WriteToReg(magAddress, magModeReg, MagSleep)
|
err = d.bus.WriteByteToReg(magAddress, magModeReg, MagSleep)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
336
sensor/tmp006/tmp006.go
Normal file
336
sensor/tmp006/tmp006.go
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
package tmp006
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kid0m4n/go-rpi/i2c"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
b0 = -0.0000294
|
||||||
|
b1 = -0.00000057
|
||||||
|
b2 = 0.00000000463
|
||||||
|
c2 = 13.4
|
||||||
|
tref = 298.15
|
||||||
|
a2 = -0.00001678
|
||||||
|
a1 = 0.00175
|
||||||
|
s0 = 6.4
|
||||||
|
|
||||||
|
vObjReg = 0x00
|
||||||
|
tempAmbReg = 0x01
|
||||||
|
configReg = 0x02
|
||||||
|
manIdReg = 0xFE
|
||||||
|
manId = 0x5449
|
||||||
|
devIdReg = 0xFF
|
||||||
|
devId = 0x0067
|
||||||
|
|
||||||
|
reset = 0x8000
|
||||||
|
modeOn = 0x7000
|
||||||
|
drdyEn = 0x0100
|
||||||
|
|
||||||
|
configRegDefault = modeOn | drdyEn
|
||||||
|
)
|
||||||
|
|
||||||
|
type SampleRate struct {
|
||||||
|
enabler uint16
|
||||||
|
samples int
|
||||||
|
timeRequired float64
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
SR1 = &SampleRate{0x0000, 1, 0.25} // 1 sample, 0.25 second between measurements.
|
||||||
|
SR2 = &SampleRate{0x0200, 2, 0.5} // 2 samples, 0.5 second between measurements.
|
||||||
|
SR4 = &SampleRate{0x0400, 4, 1} // 4 samples, 1 second between measurements.
|
||||||
|
SR8 = &SampleRate{0x0600, 8, 2} // 8 samples, 2 seconds between measurements.
|
||||||
|
SR16 = &SampleRate{0x0800, 16, 4} // 16 samples, 4 seconds between measurements.
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device represents a TMP006 thermopile sensor.
|
||||||
|
type Device struct {
|
||||||
|
// Bus to communicate over.
|
||||||
|
Bus i2c.Bus
|
||||||
|
// Addr of the sensor.
|
||||||
|
Addr byte
|
||||||
|
// Debug turns on additional debug output.
|
||||||
|
Debug bool
|
||||||
|
// SampleRate specifies the sampling rate for the sensor.
|
||||||
|
SampleRate *SampleRate
|
||||||
|
|
||||||
|
initialized bool
|
||||||
|
mu sync.RWMutex
|
||||||
|
|
||||||
|
rawDieTemps chan float64
|
||||||
|
objTemps chan float64
|
||||||
|
closing chan chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new TMP006 sensor.
|
||||||
|
func New(bus i2c.Bus, addr byte) *Device {
|
||||||
|
return &Device{
|
||||||
|
Bus: bus,
|
||||||
|
Addr: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) validate() error {
|
||||||
|
if d.Bus == nil {
|
||||||
|
return errors.New("tmp006: bus is nil")
|
||||||
|
}
|
||||||
|
if d.Addr == 0x00 {
|
||||||
|
return fmt.Errorf("tmp006: %#x is not a valid address", d.Addr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close puts the device into low power mode.
|
||||||
|
func (d *Device) Close() (err error) {
|
||||||
|
if err = d.setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.closing != nil {
|
||||||
|
waitc := make(chan struct{})
|
||||||
|
d.closing <- waitc
|
||||||
|
<-waitc
|
||||||
|
}
|
||||||
|
if d.Debug {
|
||||||
|
log.Print("tmp006: resetting")
|
||||||
|
}
|
||||||
|
if err = d.Bus.WriteWordToReg(d.Addr, configReg, reset); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Present checks if the device is present at the given address.
|
||||||
|
func (d *Device) Present() (status bool, err error) {
|
||||||
|
if err = d.validate(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var mid, did uint16
|
||||||
|
if mid, err = d.Bus.ReadWordFromReg(d.Addr, manIdReg); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: got manufacturer id %#04x", mid)
|
||||||
|
}
|
||||||
|
if mid != manId {
|
||||||
|
err = fmt.Errorf("tmp006: not found at %#02x, manufacturer id mismatch", d.Addr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if did, err = d.Bus.ReadWordFromReg(d.Addr, devIdReg); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: got device id %#04x", did)
|
||||||
|
}
|
||||||
|
if did != devId {
|
||||||
|
err = fmt.Errorf("tmp006: not found at %#02x, device id mismatch", d.Addr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
status = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) setup() (err error) {
|
||||||
|
d.mu.RLock()
|
||||||
|
if d.initialized {
|
||||||
|
d.mu.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.mu.RUnlock()
|
||||||
|
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
if err = d.validate(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.SampleRate == nil {
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: sample rate = nil, using SR16")
|
||||||
|
}
|
||||||
|
d.SampleRate = SR16
|
||||||
|
}
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: configuring with %#04x", configRegDefault|d.SampleRate.enabler)
|
||||||
|
}
|
||||||
|
if err = d.Bus.WriteWordToReg(d.Addr, configReg, configRegDefault|d.SampleRate.enabler); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.initialized = true
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) measureRawDieTemp() (temp float64, err error) {
|
||||||
|
if err = d.setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var raw uint16
|
||||||
|
if raw, err = d.Bus.ReadWordFromReg(d.Addr, tempAmbReg); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
raw >>= 2
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: raw die temp %#04x", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = float64(int16(raw)) * 0.03125
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) measureRawVoltage() (volt int16, err error) {
|
||||||
|
if err = d.setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var vlt uint16
|
||||||
|
if vlt, err = d.Bus.ReadWordFromReg(d.Addr, vObjReg); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
volt = int16(vlt)
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: raw voltage %#04x", volt)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) measureObjTemp() (temp float64, err error) {
|
||||||
|
if err = d.setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tDie, err := d.measureRawDieTemp()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: tdie = %.2f C", tDie)
|
||||||
|
}
|
||||||
|
tDie += 273.15 // Convert to K
|
||||||
|
vo, err := d.measureRawVoltage()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vObj := float64(vo)
|
||||||
|
vObj *= 156.25 // 156.25 nV per LSB
|
||||||
|
vObj /= 1000 // nV -> uV
|
||||||
|
if d.Debug {
|
||||||
|
log.Printf("tmp006: vObj = %.5f uV", vObj)
|
||||||
|
}
|
||||||
|
vObj /= 1000 // uV -> mV
|
||||||
|
vObj /= 1000 // mV -> V
|
||||||
|
|
||||||
|
tdie_tref := tDie - tref
|
||||||
|
s := 1 + a1*tdie_tref + a2*tdie_tref*tdie_tref
|
||||||
|
s *= s0
|
||||||
|
s /= 10000000
|
||||||
|
s /= 10000000
|
||||||
|
|
||||||
|
Vos := b0 + b1*tdie_tref + b2*tdie_tref*tdie_tref
|
||||||
|
fVobj := (vObj - Vos) + c2*(vObj-Vos)*(vObj-Vos)
|
||||||
|
|
||||||
|
temp = math.Sqrt(math.Sqrt(tDie*tDie*tDie*tDie + fVobj/s))
|
||||||
|
temp -= 273.15
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawDieTemp returns the current raw die temp reading.
|
||||||
|
func (d *Device) RawDieTemp() (temp float64, err error) {
|
||||||
|
select {
|
||||||
|
case temp = <-d.rawDieTemps:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
return d.measureRawDieTemp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawDieTemps returns a channel to get future raw die temps from.
|
||||||
|
func (d *Device) RawDieTemps() <-chan float64 {
|
||||||
|
return d.rawDieTemps
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjTemp returns the current obj temp reading.
|
||||||
|
func (d *Device) ObjTemp() (temp float64, err error) {
|
||||||
|
select {
|
||||||
|
case temp = <-d.objTemps:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
return d.measureObjTemp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjTemps returns a channel to fetch obj temps from.
|
||||||
|
func (d *Device) ObjTemps() <-chan float64 {
|
||||||
|
return d.objTemps
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start starts the data acquisition loop.
|
||||||
|
func (d *Device) Start() (err error) {
|
||||||
|
if err = d.setup(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.rawDieTemps = make(chan float64)
|
||||||
|
d.objTemps = make(chan float64)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
var rawDieTemp, objTemp float64
|
||||||
|
var rdtAvlb, otAvlb bool
|
||||||
|
var err error
|
||||||
|
var timer <-chan time.Time
|
||||||
|
resetTimer := func() {
|
||||||
|
timer = time.After(time.Duration(d.SampleRate.timeRequired*1000) * time.Millisecond)
|
||||||
|
}
|
||||||
|
resetTimer()
|
||||||
|
|
||||||
|
for {
|
||||||
|
var rawDieTemps, objTemps chan float64
|
||||||
|
|
||||||
|
if rdtAvlb {
|
||||||
|
rawDieTemps = d.rawDieTemps
|
||||||
|
}
|
||||||
|
if otAvlb {
|
||||||
|
objTemps = d.objTemps
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timer:
|
||||||
|
var rdt float64
|
||||||
|
if rdt, err = d.measureRawDieTemp(); err != nil {
|
||||||
|
log.Printf("tmp006: %v", err)
|
||||||
|
} else {
|
||||||
|
rawDieTemp = rdt
|
||||||
|
rdtAvlb = true
|
||||||
|
}
|
||||||
|
var ot float64
|
||||||
|
if ot, err = d.measureObjTemp(); err != nil {
|
||||||
|
log.Printf("tmp006: %v", err)
|
||||||
|
} else {
|
||||||
|
objTemp = ot
|
||||||
|
otAvlb = true
|
||||||
|
}
|
||||||
|
resetTimer()
|
||||||
|
case rawDieTemps <- rawDieTemp:
|
||||||
|
rdtAvlb = false
|
||||||
|
case objTemps <- objTemp:
|
||||||
|
otAvlb = false
|
||||||
|
case waitc := <-d.closing:
|
||||||
|
waitc <- struct{}{}
|
||||||
|
close(d.rawDieTemps)
|
||||||
|
close(d.objTemps)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user