mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-21 15:09:00 +00:00
AMG88xx thermal camera module
This commit is contained in:
committed by
Ron Evans
parent
08cc84ce48
commit
ebceed6014
@@ -0,0 +1,158 @@
|
||||
// Package amg88xx provides a driver for the AMG88XX Thermal Camera
|
||||
//
|
||||
// Datasheet:
|
||||
// https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf
|
||||
package amg88xx // import "tinygo.org/x/drivers/amg88xx"
|
||||
|
||||
import (
|
||||
"machine"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Device wraps an I2C connection to a AMG88xx device.
|
||||
type Device struct {
|
||||
bus machine.I2C
|
||||
Address uint16
|
||||
data []uint8
|
||||
interruptMode InterruptMode
|
||||
interruptEnable uint8
|
||||
}
|
||||
|
||||
type InterruptMode uint8
|
||||
|
||||
type Config struct {
|
||||
}
|
||||
|
||||
// New creates a new AMG88xx connection. The I2C bus must already be
|
||||
// configured.
|
||||
//
|
||||
// This function only creates the Device object, it does not touch the device.
|
||||
func New(bus machine.I2C) Device {
|
||||
return Device{
|
||||
bus: bus,
|
||||
Address: AddressHigh,
|
||||
}
|
||||
}
|
||||
|
||||
// Configure sets up the device for communication
|
||||
func (d *Device) Configure(cfg Config) {
|
||||
d.data = make([]uint8, 128)
|
||||
|
||||
d.SetPCTL(NORMAL_MODE)
|
||||
d.SetReset(INITIAL_RESET)
|
||||
d.SetFrameRate(FPS_10)
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
// ReadPixels returns the 64 values (8x8 grid) of the sensor converted to millicelsius
|
||||
func (d *Device) ReadPixels(buffer *[64]int16) {
|
||||
d.bus.ReadRegister(uint8(d.Address), PIXEL_OFFSET, d.data)
|
||||
for i := 0; i < 64; i++ {
|
||||
buffer[i] = int16((uint16(d.data[2*i+1]) << 8) | uint16(d.data[2*i]))
|
||||
if (buffer[i] & (1 << 11)) > 0 { // temperature negative
|
||||
buffer[i] &= ^(1 << 11)
|
||||
buffer[i] = -buffer[i]
|
||||
}
|
||||
buffer[i] *= PIXEL_TEMP_CONVERSION
|
||||
}
|
||||
}
|
||||
|
||||
// SetPCTL sets the PCTL
|
||||
func (d *Device) SetPCTL(pctl uint8) {
|
||||
d.bus.WriteRegister(uint8(d.Address), PCTL, []byte{pctl})
|
||||
}
|
||||
|
||||
// SetReset sets the reset value
|
||||
func (d *Device) SetReset(rst uint8) {
|
||||
d.bus.WriteRegister(uint8(d.Address), RST, []byte{rst})
|
||||
}
|
||||
|
||||
// SetFrameRate configures the frame rate
|
||||
func (d *Device) SetFrameRate(framerate uint8) {
|
||||
d.bus.WriteRegister(uint8(d.Address), FPSC, []byte{framerate & 0x01})
|
||||
}
|
||||
|
||||
// SetMovingAverageMode sets the moving average mode
|
||||
func (d *Device) SetMovingAverageMode(mode bool) {
|
||||
var value uint8
|
||||
if mode {
|
||||
value = 1
|
||||
}
|
||||
d.bus.WriteRegister(uint8(d.Address), AVE, []byte{value << 5})
|
||||
}
|
||||
|
||||
// SetInterruptLevels sets the interrupt levels
|
||||
func (d *Device) SetInterruptLevels(high int16, low int16) {
|
||||
d.SetInterruptLevelsHysteresis(high, low, (high*95)/100)
|
||||
}
|
||||
|
||||
// SetInterruptLevelsHysteresis sets the interrupt levels with hysteresis
|
||||
func (d *Device) SetInterruptLevelsHysteresis(high int16, low int16, hysteresis int16) {
|
||||
high = high / PIXEL_TEMP_CONVERSION
|
||||
if high < -4095 {
|
||||
high = -4095
|
||||
}
|
||||
if high > 4095 {
|
||||
high = 4095
|
||||
}
|
||||
d.bus.WriteRegister(uint8(d.Address), INTHL, []byte{uint8(high & 0xFF)})
|
||||
d.bus.WriteRegister(uint8(d.Address), INTHL, []byte{uint8((high & 0xFF) >> 4)})
|
||||
|
||||
low = low / PIXEL_TEMP_CONVERSION
|
||||
if low < -4095 {
|
||||
low = -4095
|
||||
}
|
||||
if low > 4095 {
|
||||
low = 4095
|
||||
}
|
||||
d.bus.WriteRegister(uint8(d.Address), INTHL, []byte{uint8(low & 0xFF)})
|
||||
d.bus.WriteRegister(uint8(d.Address), INTHL, []byte{uint8((low & 0xFF) >> 4)})
|
||||
|
||||
hysteresis = hysteresis / PIXEL_TEMP_CONVERSION
|
||||
if hysteresis < -4095 {
|
||||
hysteresis = -4095
|
||||
}
|
||||
if hysteresis > 4095 {
|
||||
hysteresis = 4095
|
||||
}
|
||||
d.bus.WriteRegister(uint8(d.Address), INTHL, []byte{uint8(hysteresis & 0xFF)})
|
||||
d.bus.WriteRegister(uint8(d.Address), INTHL, []byte{uint8((hysteresis & 0xFF) >> 4)})
|
||||
}
|
||||
|
||||
// EnableInterrupt enables the interrupt pin on the device
|
||||
func (d *Device) EnableInterrupt() {
|
||||
d.interruptEnable = 1
|
||||
d.bus.WriteRegister(uint8(d.Address), INTC, []byte{((uint8(d.interruptMode) << 1) | d.interruptEnable) & 0x03})
|
||||
}
|
||||
|
||||
// DisableInterrupt disables the interrupt pin on the device
|
||||
func (d *Device) DisableInterrupt() {
|
||||
d.interruptEnable = 0
|
||||
d.bus.WriteRegister(uint8(d.Address), INTC, []byte{((uint8(d.interruptMode) << 1) | d.interruptEnable) & 0x03})
|
||||
}
|
||||
|
||||
// SetInterruptMode sets the interrupt mode
|
||||
func (d *Device) SetInterruptMode(mode InterruptMode) {
|
||||
d.interruptMode = mode
|
||||
d.bus.WriteRegister(uint8(d.Address), INTC, []byte{((uint8(d.interruptMode) << 1) | d.interruptEnable) & 0x03})
|
||||
}
|
||||
|
||||
// GetInterrupt reads the state of the triggered interrupts
|
||||
func (d *Device) GetInterrupt() []uint8 {
|
||||
data := make([]uint8, 8)
|
||||
d.bus.ReadRegister(uint8(d.Address), INT_OFFSET, data)
|
||||
return data
|
||||
}
|
||||
|
||||
// ClearInterrupt clears any triggered interrupts
|
||||
func (d *Device) ClearInterrupt() {
|
||||
d.SetReset(FLAG_RESET)
|
||||
}
|
||||
|
||||
// ReadThermistor reads the onboard thermistor
|
||||
func (d *Device) ReadThermistor() int16 {
|
||||
data := make([]uint8, 2)
|
||||
d.bus.ReadRegister(uint8(d.Address), TTHL, data)
|
||||
return (int16((uint16(data[1])<<8)|uint16(data[0])) * THERMISTOR_CONVERSION) / 10
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package amg88xx
|
||||
|
||||
// The I2C address which this device listens to.
|
||||
const AddressHigh = 0x69
|
||||
const AddressLow = 0x68
|
||||
|
||||
const (
|
||||
PCTL = 0x00
|
||||
RST = 0x01
|
||||
FPSC = 0x02
|
||||
INTC = 0x03
|
||||
STAT = 0x04
|
||||
SCLR = 0x05
|
||||
AVE = 0x07
|
||||
INTHL = 0x08
|
||||
INTHH = 0x09
|
||||
INTLL = 0x0A
|
||||
INTLH = 0x0B
|
||||
IHYSL = 0x0C
|
||||
IHYSH = 0x0D
|
||||
TTHL = 0x0E
|
||||
TTHH = 0x0F
|
||||
INT_OFFSET = 0x010
|
||||
PIXEL_OFFSET = 0x80
|
||||
|
||||
// power modes
|
||||
NORMAL_MODE = 0x00
|
||||
SLEEP_MODE = 0x01
|
||||
STAND_BY_60 = 0x20
|
||||
STAND_BY_10 = 0x21
|
||||
|
||||
// resets
|
||||
FLAG_RESET = 0x30
|
||||
INITIAL_RESET = 0x3F
|
||||
|
||||
// frame rates
|
||||
FPS_10 = 0x00
|
||||
FPS_1 = 0x01
|
||||
|
||||
// interrupt modes
|
||||
DIFFERENCE InterruptMode = 0x00
|
||||
ABSOLUTE_VALUE InterruptMode = 0x01
|
||||
|
||||
PIXEL_TEMP_CONVERSION = 250
|
||||
THERMISTOR_CONVERSION = 625
|
||||
)
|
||||
Reference in New Issue
Block a user