tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/amg88xx/amg88xx.go (about) 1 // Package amg88xx provides a driver for the AMG88XX Thermal Camera 2 // 3 // Datasheet: 4 // https://cdn-learn.adafruit.com/assets/assets/000/043/261/original/Grid-EYE_SPECIFICATIONS%28Reference%29.pdf 5 package amg88xx // import "tinygo.org/x/drivers/amg88xx" 6 7 import ( 8 "time" 9 10 "tinygo.org/x/drivers" 11 "tinygo.org/x/drivers/internal/legacy" 12 ) 13 14 // Device wraps an I2C connection to a AMG88xx device. 15 type Device struct { 16 bus drivers.I2C 17 Address uint16 18 data []uint8 19 interruptMode InterruptMode 20 interruptEnable uint8 21 } 22 23 type InterruptMode uint8 24 25 type Config struct { 26 } 27 28 // New creates a new AMG88xx connection. The I2C bus must already be 29 // configured. 30 // 31 // This function only creates the Device object, it does not touch the device. 32 func New(bus drivers.I2C) Device { 33 return Device{ 34 bus: bus, 35 Address: AddressHigh, 36 } 37 } 38 39 // Configure sets up the device for communication 40 func (d *Device) Configure(cfg Config) { 41 d.data = make([]uint8, 128) 42 43 d.SetPCTL(NORMAL_MODE) 44 d.SetReset(INITIAL_RESET) 45 d.SetFrameRate(FPS_10) 46 47 time.Sleep(100 * time.Millisecond) 48 } 49 50 // ReadPixels returns the 64 values (8x8 grid) of the sensor converted to millicelsius 51 func (d *Device) ReadPixels(buffer *[64]int16) { 52 legacy.ReadRegister(d.bus, uint8(d.Address), PIXEL_OFFSET, d.data) 53 for i := 0; i < 64; i++ { 54 buffer[i] = int16((uint16(d.data[2*i+1]) << 8) | uint16(d.data[2*i])) 55 if (buffer[i] & (1 << 11)) > 0 { // temperature negative 56 buffer[i] &= ^(1 << 11) 57 buffer[i] = -buffer[i] 58 } 59 buffer[i] *= PIXEL_TEMP_CONVERSION 60 } 61 } 62 63 // SetPCTL sets the PCTL 64 func (d *Device) SetPCTL(pctl uint8) { 65 legacy.WriteRegister(d.bus, uint8(d.Address), PCTL, []byte{pctl}) 66 } 67 68 // SetReset sets the reset value 69 func (d *Device) SetReset(rst uint8) { 70 legacy.WriteRegister(d.bus, uint8(d.Address), RST, []byte{rst}) 71 } 72 73 // SetFrameRate configures the frame rate 74 func (d *Device) SetFrameRate(framerate uint8) { 75 legacy.WriteRegister(d.bus, uint8(d.Address), FPSC, []byte{framerate & 0x01}) 76 } 77 78 // SetMovingAverageMode sets the moving average mode 79 func (d *Device) SetMovingAverageMode(mode bool) { 80 var value uint8 81 if mode { 82 value = 1 83 } 84 legacy.WriteRegister(d.bus, uint8(d.Address), AVE, []byte{value << 5}) 85 } 86 87 // SetInterruptLevels sets the interrupt levels 88 func (d *Device) SetInterruptLevels(high int16, low int16) { 89 d.SetInterruptLevelsHysteresis(high, low, (high*95)/100) 90 } 91 92 // SetInterruptLevelsHysteresis sets the interrupt levels with hysteresis 93 func (d *Device) SetInterruptLevelsHysteresis(high int16, low int16, hysteresis int16) { 94 high = high / PIXEL_TEMP_CONVERSION 95 if high < -4095 { 96 high = -4095 97 } 98 if high > 4095 { 99 high = 4095 100 } 101 legacy.WriteRegister(d.bus, uint8(d.Address), INTHL, []byte{uint8(high & 0xFF)}) 102 legacy.WriteRegister(d.bus, uint8(d.Address), INTHL, []byte{uint8((high & 0xFF) >> 4)}) 103 104 low = low / PIXEL_TEMP_CONVERSION 105 if low < -4095 { 106 low = -4095 107 } 108 if low > 4095 { 109 low = 4095 110 } 111 legacy.WriteRegister(d.bus, uint8(d.Address), INTHL, []byte{uint8(low & 0xFF)}) 112 legacy.WriteRegister(d.bus, uint8(d.Address), INTHL, []byte{uint8((low & 0xFF) >> 4)}) 113 114 hysteresis = hysteresis / PIXEL_TEMP_CONVERSION 115 if hysteresis < -4095 { 116 hysteresis = -4095 117 } 118 if hysteresis > 4095 { 119 hysteresis = 4095 120 } 121 legacy.WriteRegister(d.bus, uint8(d.Address), INTHL, []byte{uint8(hysteresis & 0xFF)}) 122 legacy.WriteRegister(d.bus, uint8(d.Address), INTHL, []byte{uint8((hysteresis & 0xFF) >> 4)}) 123 } 124 125 // EnableInterrupt enables the interrupt pin on the device 126 func (d *Device) EnableInterrupt() { 127 d.interruptEnable = 1 128 legacy.WriteRegister(d.bus, uint8(d.Address), INTC, []byte{((uint8(d.interruptMode) << 1) | d.interruptEnable) & 0x03}) 129 } 130 131 // DisableInterrupt disables the interrupt pin on the device 132 func (d *Device) DisableInterrupt() { 133 d.interruptEnable = 0 134 legacy.WriteRegister(d.bus, uint8(d.Address), INTC, []byte{((uint8(d.interruptMode) << 1) | d.interruptEnable) & 0x03}) 135 } 136 137 // SetInterruptMode sets the interrupt mode 138 func (d *Device) SetInterruptMode(mode InterruptMode) { 139 d.interruptMode = mode 140 legacy.WriteRegister(d.bus, uint8(d.Address), INTC, []byte{((uint8(d.interruptMode) << 1) | d.interruptEnable) & 0x03}) 141 } 142 143 // GetInterrupt reads the state of the triggered interrupts 144 func (d *Device) GetInterrupt() []uint8 { 145 data := make([]uint8, 8) 146 legacy.ReadRegister(d.bus, uint8(d.Address), INT_OFFSET, data) 147 return data 148 } 149 150 // ClearInterrupt clears any triggered interrupts 151 func (d *Device) ClearInterrupt() { 152 d.SetReset(FLAG_RESET) 153 } 154 155 // ReadThermistor reads the onboard thermistor 156 func (d *Device) ReadThermistor() int16 { 157 data := make([]uint8, 2) 158 legacy.ReadRegister(d.bus, uint8(d.Address), TTHL, data) 159 return (int16((uint16(data[1])<<8)|uint16(data[0])) * THERMISTOR_CONVERSION) / 10 160 }