Library for Adafruit AMG8833. Forked from arduino version
Revision 0:9aaf1afdeac0, committed 2019-06-14
- Comitter:
- hisyamfs
- Date:
- Fri Jun 14 12:49:30 2019 +0000
- Commit message:
- okey;
Changed in this revision
AMG8833.cpp | Show annotated file Show diff for this revision Revisions of this file |
AMG8833.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 9aaf1afdeac0 AMG8833.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AMG8833.cpp Fri Jun 14 12:49:30 2019 +0000 @@ -0,0 +1,351 @@ +#include "AMG8833.h" + +//#define I2C_DEBUG + +/**************************************************************************/ +/*! + @brief Setups the I2C interface and hardware + @param addr Optional I2C address the sensor can be found on. Default is 0x69 + @returns True if device is set up, false on any failure +*/ +/**************************************************************************/ +Adafruit_AMG88xx::Adafruit_AMG88xx(PinName mysda, PinName myscl) : _i2c(mysda, myscl) +{ + +} + +int Adafruit_AMG88xx::begin(char addr) +{ + _i2caddr = addr; + + //enter normal mode + _pctl.PCTL = AMG88xx_NORMAL_MODE; + write8(AMG88xx_PCTL, _pctl.get()); + + //software reset + _rst.RST = AMG88xx_INITIAL_RESET; + write8(AMG88xx_RST, _rst.get()); + + //disable interrupts by default + disableInterrupt(); + + //set to 10 FPS + _fpsc.FPS = AMG88xx_FPS_10; + write8(AMG88xx_FPSC, _fpsc.get()); + + wait_ms(100); + + return 1; +} + +/**************************************************************************/ +/*! + @brief Set the moving average mode. + @param mode if True is passed, output will be twice the moving average +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::setMovingAverageMode(int mode) +{ + _ave.MAMOD = mode; + write8(AMG88xx_AVE, _ave.get()); +} + +/**************************************************************************/ +/*! + @brief Set the interrupt levels. The hysteresis value defaults to .95 * high + @param high the value above which an interrupt will be triggered + @param low the value below which an interrupt will be triggered +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::setInterruptLevels(float high, float low) +{ + setInterruptLevels(high, low, high * .95); +} + +/**************************************************************************/ +/*! + @brief Set the interrupt levels + @param high the value above which an interrupt will be triggered + @param low the value below which an interrupt will be triggered + @param hysteresis the hysteresis value for interrupt detection +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::setInterruptLevels(float high, float low, float hysteresis) +{ + int highConv = high / AMG88xx_PIXEL_TEMP_CONVERSION; + highConv = constrain(highConv, -4095, 4095); + _inthl.INT_LVL_H = highConv & 0xFF; + _inthh.INT_LVL_H = (highConv & 0xF) >> 4; + this->write8(AMG88xx_INTHL, _inthl.get()); + this->write8(AMG88xx_INTHH, _inthh.get()); + + int lowConv = low / AMG88xx_PIXEL_TEMP_CONVERSION; + lowConv = constrain(lowConv, -4095, 4095); + _intll.INT_LVL_L = lowConv & 0xFF; + _intlh.INT_LVL_L = (lowConv & 0xF) >> 4; + this->write8(AMG88xx_INTLL, _intll.get()); + this->write8(AMG88xx_INTLH, _intlh.get()); + + int hysConv = hysteresis / AMG88xx_PIXEL_TEMP_CONVERSION; + hysConv = constrain(hysConv, -4095, 4095); + _ihysl.INT_HYS = hysConv & 0xFF; + _ihysh.INT_HYS = (hysConv & 0xF) >> 4; + this->write8(AMG88xx_IHYSL, _ihysl.get()); + this->write8(AMG88xx_IHYSH, _ihysh.get()); +} + +/**************************************************************************/ +/*! + @brief enable the interrupt pin on the device. +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::enableInterrupt() +{ + _intc.INTEN = 1; + this->write8(AMG88xx_INTC, _intc.get()); +} + +/**************************************************************************/ +/*! + @brief disable the interrupt pin on the device +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::disableInterrupt() +{ + _intc.INTEN = 0; + this->write8(AMG88xx_INTC, _intc.get()); +} + +/**************************************************************************/ +/*! + @brief Set the interrupt to either absolute value or difference mode + @param mode passing AMG88xx_DIFFERENCE sets the device to difference mode, AMG88xx_ABSOLUTE_VALUE sets to absolute value mode. +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::setInterruptMode(uint8_t mode) +{ + _intc.INTMOD = mode; + this->write8(AMG88xx_INTC, _intc.get()); +} + +/**************************************************************************/ +/*! + @brief Read the state of the triggered interrupts on the device. The full interrupt register is 8 chars in length. + @param buf the pointer to where the returned data will be stored + @param size Optional number of chars to read. Default is 8 chars. + @returns up to 8 chars of data in buf +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::getInterrupt(uint8_t *buf, uint8_t size) +{ + uint8_t charsToRead = min(size, (uint8_t)8); + + this->read(AMG88xx_INT_OFFSET, buf, charsToRead); +} + +/**************************************************************************/ +/*! + @brief Clear any triggered interrupts +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::clearInterrupt() +{ + _rst.RST = AMG88xx_FLAG_RESET; + write8(AMG88xx_RST, _rst.get()); +} + +/**************************************************************************/ +/*! + @brief read the onboard thermistor + @returns a the floating point temperature in degrees Celsius +*/ +/**************************************************************************/ +float Adafruit_AMG88xx::readThermistor() +{ + uint8_t raw[2]; + this->read(AMG88xx_TTHL, raw, 2); + uint16_t recast = ((uint16_t) raw[1] << 8) | ((uint16_t) raw[0]); + + return signedMag12ToFloat(recast) * AMG88xx_THERMISTOR_CONVERSION; +} + +/**************************************************************************/ +/*! + @brief Read Infrared sensor values + @param buf the array to place the pixels in + @param size Optionsl number of chars to read (up to 64). Default is 64 chars. + @return up to 64 chars of pixel data in buf +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::readPixels(float *buf, uint8_t size) +{ + uint16_t recast; + float converted; + uint8_t charsToRead = min((uint8_t)(size << 1), (uint8_t)(AMG88xx_PIXEL_ARRAY_SIZE << 1)); + uint8_t rawArray[charsToRead]; + this->read(AMG88xx_PIXEL_OFFSET, rawArray, charsToRead); + + for(int i=0; i<size; i++){ + uint8_t pos = i << 1; + recast = ((uint16_t)rawArray[pos + 1] << 8) | ((uint16_t)rawArray[pos]); + + converted = int12ToFloat(recast) * AMG88xx_PIXEL_TEMP_CONVERSION; + buf[i] = converted; + } +} + +/**************************************************************************/ +/*! + @brief write one char of data to the specified register + @param reg the register to write to + @param value the value to write +*/ +/**************************************************************************/ +void Adafruit_AMG88xx::write8(uint8_t reg, uint8_t value) +{ + this->write(reg, &value, 1); +} + +/**************************************************************************/ +/*! + @brief read one char of data from the specified register + @param reg the register to read + @returns one char of register data +*/ +/**************************************************************************/ +uint8_t Adafruit_AMG88xx::read8(uint8_t reg) +{ + uint8_t ret; + this->read(reg, &ret, 1); + return ret; +} + +int Adafruit_AMG88xx::read(uint8_t reg, uint8_t *buf, uint8_t num) +{ +// char value; +// char pos = 0; + +// //on arduino we need to read in AMG_I2C_CHUNKSIZE char chunks +// while(pos < num){ +// char read_now = min((char)AMG_I2C_CHUNKSIZE, (char)(num - pos)); +// Wire.beginTransmission((char)_i2caddr); +// Wire.write((char)reg + pos); +// Wire.endTransmission(); +// Wire.requestFrom((char)_i2caddr, read_now); + +// #ifdef I2C_DEBUG +// Serial.print("[$"); Serial.print(reg + pos, HEX); Serial.print("] -> "); +// #endif +// for(int i=0; i<read_now; i++){ +// buf[pos] = Wire.read(); +// #ifdef I2C_DEBUG +// Serial.print("0x"); Serial.print(buf[pos], HEX); Serial.print(", "); +// #endif +// pos++; +// } +// #ifdef I2C_DEBUG +// Serial.println(); +// #endif +// } + char reg_dest = reg; + char rx_buf[num]; + int nack = _i2c.write(_i2caddr, ®_dest, 1, 1); // no stop + nack = _i2c.read(_i2caddr, rx_buf, num); + for (int i = 0; i < num; i++) { + buf[i] = (uint8_t) rx_buf[i]; + } + return nack; +} + +int Adafruit_AMG88xx::write(uint8_t reg, uint8_t *buf, uint8_t num) +{ +// #ifdef I2C_DEBUG + // Serial.print("[$"); Serial.print(reg, HEX); Serial.print("] <- "); +// #endif + // Wire.beginTransmission((char)_i2caddr); + // Wire.write((char)reg); + // for (int i=0; i<num; i++) { + // Wire.write(buf[i]); +// #ifdef I2C_DEBUG + // Serial.print("0x"); Serial.print(buf[i], HEX); Serial.print(", "); +// #endif + // } + // Wire.endTransmission(); +// #ifdef I2C_DEBUG + // Serial.println(); +// #endif + char reg_dest = reg; + char tx_buf[num]; + for (int i = 0; i < num; i++) { + tx_buf[i] = (char) buf[i]; + } + int nack = _i2c.write(_i2caddr, ®_dest, 1, 1); // no stop + nack = _i2c.write(_i2caddr, tx_buf, num); + return nack; +} + +/**************************************************************************/ +/*! + @brief convert a 12-bit signed magnitude value to a floating point number + @param val the 12-bit signed magnitude value to be converted + @returns the converted floating point value +*/ +/**************************************************************************/ +float Adafruit_AMG88xx::signedMag12ToFloat(uint16_t val) +{ + //take first 11 bits as absolute val + uint16_t absVal = (val & 0x7FF); + + return (val & 0x800) ? 0 - (float)absVal : (float)absVal ; +} + +/**************************************************************************/ +/*! + @brief convert a 12-bit integer two's complement value to a floating point number + @param val the 12-bit integer two's complement value to be converted + @returns the converted floating point value +*/ +/**************************************************************************/ +float Adafruit_AMG88xx::int12ToFloat(uint16_t val) +{ + uint16_t sVal = (val << 4); //shift to left so that sign bit of 12 bit integer number is placed on sign bit of 16 bit signed integer number + return sVal >> 4; //shift back the signed number, return converts to float +} + +/** + * @brief helper function, constraints the value + * @param value variable to be constrained + * @param min minimum value of the variable + */ +int Adafruit_AMG88xx::constrain(int value, int min, int max) +{ + if (value > max) { + return max; + } + else if (value < min) { + return min; + } + else { + return value; + } +} + +int Adafruit_AMG88xx::min(int val1, int val2) { + if (val1 < val2) return val1; + else return val2; +} + +int Adafruit_AMG88xx::max(int val1, int val2) { + if (val1 > val2) return val1; + else return val2; +} + +uint8_t Adafruit_AMG88xx::min(uint8_t val1, uint8_t val2) { + if (val1 < val2) return val1; + else return val2; +} + +uint8_t Adafruit_AMG88xx::max(uint8_t val1, uint8_t val2) { + if (val1 > val2) return val1; + else return val2; +} \ No newline at end of file
diff -r 000000000000 -r 9aaf1afdeac0 AMG8833.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AMG8833.h Fri Jun 14 12:49:30 2019 +0000 @@ -0,0 +1,340 @@ +#ifndef LIB_ADAFRUIT_AMG88XX_H +#define LIB_ADAFRUIT_AMG88XX_H + +#include "mbed.h" + +/*========================================================================= + I2C ADDRESS/BITS + -----------------------------------------------------------------------*/ + #define AMG88xx_ADDRESS (0x69 << 1) +/*=========================================================================*/ + +/*========================================================================= + REGISTERS + -----------------------------------------------------------------------*/ + enum + { + AMG88xx_PCTL = 0x00, + AMG88xx_RST = 0x01, + AMG88xx_FPSC = 0x02, + AMG88xx_INTC = 0x03, + AMG88xx_STAT = 0x04, + AMG88xx_SCLR = 0x05, + //0x06 reserved + AMG88xx_AVE = 0x07, + AMG88xx_INTHL = 0x08, + AMG88xx_INTHH = 0x09, + AMG88xx_INTLL = 0x0A, + AMG88xx_INTLH = 0x0B, + AMG88xx_IHYSL = 0x0C, + AMG88xx_IHYSH = 0x0D, + AMG88xx_TTHL = 0x0E, + AMG88xx_TTHH = 0x0F, + AMG88xx_INT_OFFSET = 0x010, + AMG88xx_PIXEL_OFFSET = 0x80 + }; + + enum power_modes{ + AMG88xx_NORMAL_MODE = 0x00, + AMG88xx_SLEEP_MODE = 0x01, + AMG88xx_STAND_BY_60 = 0x20, + AMG88xx_STAND_BY_10 = 0x21 + }; + + enum sw_resets { + AMG88xx_FLAG_RESET = 0x30, + AMG88xx_INITIAL_RESET = 0x3F + }; + + enum frame_rates { + AMG88xx_FPS_10 = 0x00, + AMG88xx_FPS_1 = 0x01 + }; + + enum int_enables{ + AMG88xx_INT_DISABLED = 0x00, + AMG88xx_INT_ENABLED = 0x01 + }; + + enum int_modes { + AMG88xx_DIFFERENCE = 0x00, + AMG88xx_ABSOLUTE_VALUE = 0x01 + }; + +/*=========================================================================*/ + +#define AMG88xx_PIXEL_ARRAY_SIZE 64 +#define AMG88xx_PIXEL_TEMP_CONVERSION .25 +#define AMG88xx_THERMISTOR_CONVERSION .0625 + +/**************************************************************************/ +/*! + @brief Class that stores state and functions for interacting with AMG88xx IR sensor chips +*/ +/**************************************************************************/ +class Adafruit_AMG88xx { + public: + //constructors + Adafruit_AMG88xx(PinName sda, PinName scl); + + int begin(char addr = AMG88xx_ADDRESS); + + void readPixels(float *buf, uint8_t size = AMG88xx_PIXEL_ARRAY_SIZE); + float readThermistor(); + + void setMovingAverageMode(int mode); + + void enableInterrupt(); + void disableInterrupt(); + void setInterruptMode(uint8_t mode); + void getInterrupt(uint8_t *buf, uint8_t size = 8); + void clearInterrupt(); + + //this will automatically set hysteresis to 95% of the high value + void setInterruptLevels(float high, float low); + + //this will manually set hysteresis + void setInterruptLevels(float high, float low, float hysteresis); + + private: + char _i2caddr; + + I2C _i2c; + + void write8(uint8_t reg, uint8_t value); + void write16(uint8_t reg, uint16_t value); + uint8_t read8(uint8_t reg); + + int read(uint8_t reg, uint8_t *buf, uint8_t num); + int write(uint8_t reg, uint8_t *buf, uint8_t num); + void _i2c_init(); + + float signedMag12ToFloat(uint16_t val); + float int12ToFloat(uint16_t val); + + int constrain(int value, int min, int max); + int min(int val1, int val2); + int max(int val1, int val2); + + uint8_t min(uint8_t val1, uint8_t val2); + uint8_t max(uint8_t val1, uint8_t val2); + + // The power control register + struct pctl { + // 0x00 = Normal Mode + // 0x01 = Sleep Mode + // 0x20 = Stand-by mode (60 sec intermittence) + // 0x21 = Stand-by mode (10 sec intermittence) + + uint8_t PCTL : 8; + + uint8_t get() { + return PCTL; + } + }; + pctl _pctl; + + //reset register + struct rst { + //0x30 = flag reset (all clear status reg 0x04, interrupt flag and interrupt table) + //0x3F = initial reset (brings flag reset and returns to initial setting) + + uint8_t RST : 8; + + uint8_t get() { + return RST; + } + }; + rst _rst; + + //frame rate register + struct fpsc { + + //0 = 10FPS + //1 = 1FPS + uint8_t FPS : 1; + + uint8_t get() { + return FPS & 0x01; + } + }; + fpsc _fpsc; + + //interrupt control register + struct intc { + + // 0 = INT output reactive (Hi-Z) + // 1 = INT output active + uint8_t INTEN : 1; + + // 0 = Difference interrupt mode + // 1 = absolute value interrupt mode + uint8_t INTMOD : 1; + + uint8_t get(){ + return (INTMOD << 1 | INTEN) & 0x03; + } + }; + intc _intc; + + //status register + struct stat { + uint8_t unused : 1; + //interrupt outbreak (val of interrupt table reg) + uint8_t INTF : 1; + + //temperature output overflow (val of temperature reg) + uint8_t OVF_IRS : 1; + + //thermistor temperature output overflow (value of thermistor) + uint8_t OVF_THS : 1; + + uint8_t get(){ + return ( (OVF_THS << 3) | (OVF_IRS << 2) | (INTF << 1) ) & 0x0E; + } + }; + stat _stat; + + //status clear register + //write to clear overflow flag and interrupt flag + //after writing automatically turns to 0x00 + struct sclr { + uint8_t unused : 1; + //interrupt flag clear + uint8_t INTCLR : 1; + //temp output overflow flag clear + uint8_t OVS_CLR : 1; + //thermistor temp output overflow flag clear + uint8_t OVT_CLR : 1; + + uint8_t get(){ + return ((OVT_CLR << 3) | (OVS_CLR << 2) | (INTCLR << 1)) & 0x0E; + } + }; + sclr _sclr; + + //average register + //for setting moving average output mode + struct ave { + uint8_t unused : 5; + //1 = twice moving average mode + uint8_t MAMOD : 1; + + uint8_t get(){ + return (MAMOD << 5); + } + }; + struct ave _ave; + + //interrupt level registers + //for setting upper / lower limit hysteresis on interrupt level + + //interrupt level upper limit setting. Interrupt output + // and interrupt pixel table are set when value exceeds set value + struct inthl { + uint8_t INT_LVL_H : 8; + + uint8_t get(){ + return INT_LVL_H; + } + }; + struct inthl _inthl; + + struct inthh { + uint8_t INT_LVL_H : 4; + + uint8_t get(){ + return INT_LVL_H; + } + }; + struct inthh _inthh; + + //interrupt level lower limit. Interrupt output + //and interrupt pixel table are set when value is lower than set value + struct intll { + uint8_t INT_LVL_L : 8; + + uint8_t get(){ + return INT_LVL_L; + } + }; + struct intll _intll; + + struct intlh { + uint8_t INT_LVL_L : 4; + + uint8_t get(){ + return (INT_LVL_L & 0xF); + } + }; + struct intlh _intlh; + + //setting of interrupt hysteresis level when interrupt is generated. + //should not be higher than interrupt level + struct ihysl { + uint8_t INT_HYS : 8; + + uint8_t get(){ + return INT_HYS; + } + }; + struct ihysl _ihysl; + + struct ihysh { + uint8_t INT_HYS : 4; + + uint8_t get(){ + return (INT_HYS & 0xF); + } + }; + struct ihysh _ihysh; + + //thermistor register + //SIGNED MAGNITUDE FORMAT + struct tthl { + uint8_t TEMP : 8; + + uint8_t get(){ + return TEMP; + } + }; + struct tthl _tthl; + + struct tthh { + uint8_t TEMP : 3; + uint8_t SIGN : 1; + + uint8_t get(){ + return ( (SIGN << 3) | TEMP) & 0xF; + } + }; + struct tthh _tthh; + + //temperature registers 0x80 - 0xFF + /* + //read to indicate temperature data per 1 pixel + //SIGNED MAGNITUDE FORMAT + struct t01l { + char TEMP : 8; + + char get(){ + return TEMP; + } + }; + struct t01l _t01l; + + struct t01h { + char TEMP : 3; + char SIGN : 1; + + char get(){ + return ( (SIGN << 3) | TEMP) & 0xF; + } + }; + struct t01h _t01h; + */ + + +}; + +#endif \ No newline at end of file