Compare commits
10 commits
dfa2379739
...
1d237a6695
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d237a6695 | ||
|
|
1846a7318a | ||
|
|
dd363596d7 | ||
|
|
25ae7b4997 | ||
|
|
39dd3c54fe | ||
|
|
1da8a7438c | ||
|
|
c93ea16dd6 | ||
|
|
195681dc69 | ||
|
|
4552553eb3 | ||
|
|
374dbc0494 |
6 changed files with 825 additions and 170 deletions
|
|
@ -10,15 +10,23 @@
|
|||
* please support Adafruit and open-source hardware by purchasing products from
|
||||
* Adafruit!
|
||||
*
|
||||
* BSD license (see license.txt)
|
||||
* Written by Limor "Ladyada" Fried with assistance from Claude Code.
|
||||
*
|
||||
* MIT license, see LICENSE for more information
|
||||
*/
|
||||
|
||||
#include "Adafruit_MLX90632.h"
|
||||
|
||||
#define MLX90632_DEBUG
|
||||
|
||||
/*!
|
||||
* @brief Instantiates a new MLX90632 class
|
||||
*/
|
||||
Adafruit_MLX90632::Adafruit_MLX90632() {}
|
||||
Adafruit_MLX90632::Adafruit_MLX90632() {
|
||||
TO0 = 25.0; // Initialize previous object temperature
|
||||
TA0 = 25.0; // Initialize previous ambient temperature
|
||||
i2c_dev = nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Cleans up the MLX90632
|
||||
|
|
@ -37,7 +45,7 @@ Adafruit_MLX90632::~Adafruit_MLX90632() {
|
|||
* The Wire object to be used for I2C connections.
|
||||
* @return True if initialization was successful, otherwise false.
|
||||
*/
|
||||
bool Adafruit_MLX90632::begin(uint8_t i2c_address, TwoWire *wire) {
|
||||
bool Adafruit_MLX90632::begin(uint8_t i2c_address, TwoWire* wire) {
|
||||
if (i2c_dev) {
|
||||
delete i2c_dev;
|
||||
}
|
||||
|
|
@ -47,14 +55,19 @@ bool Adafruit_MLX90632::begin(uint8_t i2c_address, TwoWire *wire) {
|
|||
return false;
|
||||
}
|
||||
|
||||
Adafruit_BusIO_Register product_code_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register product_code_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2);
|
||||
uint16_t product_code = product_code_reg.read();
|
||||
|
||||
|
||||
if (product_code == 0xFFFF || product_code == 0x0000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load calibration constants automatically
|
||||
if (!getCalibrations()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -63,17 +76,17 @@ bool Adafruit_MLX90632::begin(uint8_t i2c_address, TwoWire *wire) {
|
|||
* @return Product ID (48-bit value in uint64_t)
|
||||
*/
|
||||
uint64_t Adafruit_MLX90632::getProductID() {
|
||||
Adafruit_BusIO_Register id0_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_ID0), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register id1_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_ID1), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register id2_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_ID2), 2, MSBFIRST, 2);
|
||||
|
||||
Adafruit_BusIO_Register id0_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_ID0), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register id1_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_ID1), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register id2_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_ID2), 2, MSBFIRST, 2);
|
||||
|
||||
uint16_t id0 = id0_reg.read();
|
||||
uint16_t id1 = id1_reg.read();
|
||||
uint16_t id2 = id2_reg.read();
|
||||
|
||||
|
||||
return ((uint64_t)id2 << 32) | ((uint64_t)id1 << 16) | id0;
|
||||
}
|
||||
|
||||
|
|
@ -82,34 +95,44 @@ uint64_t Adafruit_MLX90632::getProductID() {
|
|||
* @return Product code (16-bit value)
|
||||
*/
|
||||
uint16_t Adafruit_MLX90632::getProductCode() {
|
||||
Adafruit_BusIO_Register product_code_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register product_code_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2);
|
||||
return product_code_reg.read();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read the EEPROM version
|
||||
* @return EEPROM version (16-bit value)
|
||||
*/
|
||||
uint16_t Adafruit_MLX90632::getEEPROMVersion() {
|
||||
Adafruit_BusIO_Register version_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_VERSION), 2, MSBFIRST, 2);
|
||||
return version_reg.read();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Start a single measurement (SOC)
|
||||
* @return True if write succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::startSingleMeasurement() {
|
||||
Adafruit_BusIO_Register control_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits soc_bit =
|
||||
Adafruit_BusIO_RegisterBits(&control_reg, 1, 3);
|
||||
|
||||
|
||||
return soc_bit.write(1);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Start a full measurement table (SOB)
|
||||
* @brief Start a full measurement table (SOB)
|
||||
* @return True if write succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::startFullMeasurement() {
|
||||
Adafruit_BusIO_Register control_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits sob_bit =
|
||||
Adafruit_BusIO_RegisterBits(&control_reg, 1, 11);
|
||||
|
||||
|
||||
return sob_bit.write(1);
|
||||
}
|
||||
|
||||
|
|
@ -119,11 +142,11 @@ bool Adafruit_MLX90632::startFullMeasurement() {
|
|||
* @return True if write succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::setMode(mlx90632_mode_t mode) {
|
||||
Adafruit_BusIO_Register control_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits mode_bits =
|
||||
Adafruit_BusIO_RegisterBits(&control_reg, 2, 1);
|
||||
|
||||
|
||||
return mode_bits.write(mode);
|
||||
}
|
||||
|
||||
|
|
@ -132,11 +155,11 @@ bool Adafruit_MLX90632::setMode(mlx90632_mode_t mode) {
|
|||
* @return The current measurement mode
|
||||
*/
|
||||
mlx90632_mode_t Adafruit_MLX90632::getMode() {
|
||||
Adafruit_BusIO_Register control_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits mode_bits =
|
||||
Adafruit_BusIO_RegisterBits(&control_reg, 2, 1);
|
||||
|
||||
|
||||
return (mlx90632_mode_t)mode_bits.read();
|
||||
}
|
||||
|
||||
|
|
@ -145,12 +168,13 @@ mlx90632_mode_t Adafruit_MLX90632::getMode() {
|
|||
* @param meas_select The measurement select type to set
|
||||
* @return True if write succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::setMeasurementSelect(mlx90632_meas_select_t meas_select) {
|
||||
Adafruit_BusIO_Register control_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
bool Adafruit_MLX90632::setMeasurementSelect(
|
||||
mlx90632_meas_select_t meas_select) {
|
||||
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits meas_select_bits =
|
||||
Adafruit_BusIO_RegisterBits(&control_reg, 5, 4);
|
||||
|
||||
|
||||
return meas_select_bits.write(meas_select);
|
||||
}
|
||||
|
||||
|
|
@ -159,11 +183,11 @@ bool Adafruit_MLX90632::setMeasurementSelect(mlx90632_meas_select_t meas_select)
|
|||
* @return The current measurement select type
|
||||
*/
|
||||
mlx90632_meas_select_t Adafruit_MLX90632::getMeasurementSelect() {
|
||||
Adafruit_BusIO_Register control_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits meas_select_bits =
|
||||
Adafruit_BusIO_RegisterBits(&control_reg, 5, 4);
|
||||
|
||||
|
||||
return (mlx90632_meas_select_t)meas_select_bits.read();
|
||||
}
|
||||
|
||||
|
|
@ -172,11 +196,11 @@ mlx90632_meas_select_t Adafruit_MLX90632::getMeasurementSelect() {
|
|||
* @return True if device is busy, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::isBusy() {
|
||||
Adafruit_BusIO_Register status_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits device_busy_bit =
|
||||
Adafruit_BusIO_RegisterBits(&status_reg, 1, 10);
|
||||
|
||||
|
||||
return device_busy_bit.read();
|
||||
}
|
||||
|
||||
|
|
@ -185,11 +209,11 @@ bool Adafruit_MLX90632::isBusy() {
|
|||
* @return True if EEPROM is busy, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::isEEPROMBusy() {
|
||||
Adafruit_BusIO_Register status_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits eeprom_busy_bit =
|
||||
Adafruit_BusIO_RegisterBits(&status_reg, 1, 9);
|
||||
|
||||
|
||||
return eeprom_busy_bit.read();
|
||||
}
|
||||
|
||||
|
|
@ -203,10 +227,10 @@ bool Adafruit_MLX90632::reset() {
|
|||
if (!i2c_dev->write(reset_cmd, 4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Wait for reset to complete (at least 150us as per datasheet)
|
||||
delay(1);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -215,11 +239,11 @@ bool Adafruit_MLX90632::reset() {
|
|||
* @return Current cycle position (0-31)
|
||||
*/
|
||||
uint8_t Adafruit_MLX90632::readCyclePosition() {
|
||||
Adafruit_BusIO_Register status_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits cycle_position_bits =
|
||||
Adafruit_BusIO_RegisterBits(&status_reg, 5, 2);
|
||||
|
||||
|
||||
return cycle_position_bits.read();
|
||||
}
|
||||
|
||||
|
|
@ -228,11 +252,11 @@ uint8_t Adafruit_MLX90632::readCyclePosition() {
|
|||
* @return True if write succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::resetNewData() {
|
||||
Adafruit_BusIO_Register status_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits new_data_bit =
|
||||
Adafruit_BusIO_RegisterBits(&status_reg, 1, 0);
|
||||
|
||||
|
||||
return new_data_bit.write(0);
|
||||
}
|
||||
|
||||
|
|
@ -241,14 +265,429 @@ bool Adafruit_MLX90632::resetNewData() {
|
|||
* @return True if new data is available, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::isNewData() {
|
||||
Adafruit_BusIO_Register status_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits new_data_bit =
|
||||
Adafruit_BusIO_RegisterBits(&status_reg, 1, 0);
|
||||
|
||||
|
||||
return new_data_bit.read();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Set the refresh rate for both measurement registers
|
||||
* @param refresh_rate The refresh rate to set
|
||||
* @return True if both writes succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::setRefreshRate(mlx90632_refresh_rate_t refresh_rate) {
|
||||
// Set refresh rate in EE_MEAS_1 register (bits 10:8)
|
||||
Adafruit_BusIO_Register meas1_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_1), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits meas1_refresh_bits =
|
||||
Adafruit_BusIO_RegisterBits(&meas1_reg, 3, 8);
|
||||
|
||||
if (!meas1_refresh_bits.write(refresh_rate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set refresh rate in EE_MEAS_2 register (bits 10:8)
|
||||
Adafruit_BusIO_Register meas2_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_2), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits meas2_refresh_bits =
|
||||
Adafruit_BusIO_RegisterBits(&meas2_reg, 3, 8);
|
||||
|
||||
return meas2_refresh_bits.write(refresh_rate);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the refresh rate from EE_MEAS_1 register
|
||||
* @return The current refresh rate
|
||||
*/
|
||||
mlx90632_refresh_rate_t Adafruit_MLX90632::getRefreshRate() {
|
||||
Adafruit_BusIO_Register meas1_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_1), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_RegisterBits meas1_refresh_bits =
|
||||
Adafruit_BusIO_RegisterBits(&meas1_reg, 3, 8);
|
||||
|
||||
return (mlx90632_refresh_rate_t)meas1_refresh_bits.read();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Helper function to read 32-bit values from consecutive registers
|
||||
* @param lsw_addr Address of the least significant word register
|
||||
* @return 32-bit value (LSW + MSW)
|
||||
*/
|
||||
uint32_t Adafruit_MLX90632::read32BitRegister(uint16_t lsw_addr) {
|
||||
Adafruit_BusIO_Register lsw_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(lsw_addr), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register msw_reg =
|
||||
Adafruit_BusIO_Register(i2c_dev, swapBytes(lsw_addr + 1), 2, MSBFIRST, 2);
|
||||
|
||||
uint16_t lsw = lsw_reg.read();
|
||||
uint16_t msw = msw_reg.read();
|
||||
|
||||
return ((uint32_t)msw << 16) | lsw;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Read all calibration constants from EEPROM
|
||||
* @return True if all reads succeeded, false otherwise
|
||||
*/
|
||||
bool Adafruit_MLX90632::getCalibrations() {
|
||||
// Read 32-bit calibration constants
|
||||
uint32_t ee_p_r = read32BitRegister(MLX90632_REG_EE_P_R_LSW);
|
||||
uint32_t ee_p_g = read32BitRegister(MLX90632_REG_EE_P_G_LSW);
|
||||
uint32_t ee_p_t = read32BitRegister(MLX90632_REG_EE_P_T_LSW);
|
||||
uint32_t ee_p_o = read32BitRegister(MLX90632_REG_EE_P_O_LSW);
|
||||
uint32_t ee_aa = read32BitRegister(MLX90632_REG_EE_AA_LSW);
|
||||
uint32_t ee_ab = read32BitRegister(MLX90632_REG_EE_AB_LSW);
|
||||
uint32_t ee_ba = read32BitRegister(MLX90632_REG_EE_BA_LSW);
|
||||
uint32_t ee_bb = read32BitRegister(MLX90632_REG_EE_BB_LSW);
|
||||
uint32_t ee_ca = read32BitRegister(MLX90632_REG_EE_CA_LSW);
|
||||
uint32_t ee_cb = read32BitRegister(MLX90632_REG_EE_CB_LSW);
|
||||
uint32_t ee_da = read32BitRegister(MLX90632_REG_EE_DA_LSW);
|
||||
uint32_t ee_db = read32BitRegister(MLX90632_REG_EE_DB_LSW);
|
||||
uint32_t ee_ea = read32BitRegister(MLX90632_REG_EE_EA_LSW);
|
||||
uint32_t ee_eb = read32BitRegister(MLX90632_REG_EE_EB_LSW);
|
||||
uint32_t ee_fa = read32BitRegister(MLX90632_REG_EE_FA_LSW);
|
||||
uint32_t ee_fb = read32BitRegister(MLX90632_REG_EE_FB_LSW);
|
||||
uint32_t ee_ga = read32BitRegister(MLX90632_REG_EE_GA_LSW);
|
||||
|
||||
// Read 16-bit calibration constants
|
||||
Adafruit_BusIO_Register gb_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_GB), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ka_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_KA), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register kb_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_KB), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ha_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_HA), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register hb_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_EE_HB), 2, MSBFIRST, 2);
|
||||
|
||||
// Convert to proper double values with scaling factors from datasheet
|
||||
P_R = (double)(int32_t)ee_p_r * (double)pow(2, -8); // 2^-8
|
||||
P_G = (double)(int32_t)ee_p_g * (double)pow(2, -20); // 2^-20
|
||||
P_T = (double)(int32_t)ee_p_t * (double)pow(2, -44); // 2^-44
|
||||
P_O = (double)(int32_t)ee_p_o * (double)pow(2, -8); // 2^-8
|
||||
Aa = (double)(int32_t)ee_aa * (double)pow(2, -16); // 2^-16
|
||||
Ab = (double)(int32_t)ee_ab * (double)pow(2, -8); // 2^-8
|
||||
Ba = (double)(int32_t)ee_ba * (double)pow(2, -16); // 2^-16
|
||||
Bb = (double)(int32_t)ee_bb * (double)pow(2, -8); // 2^-8
|
||||
Ca = (double)(int32_t)ee_ca * (double)pow(2, -16); // 2^-16
|
||||
Cb = (double)(int32_t)ee_cb * (double)pow(2, -8); // 2^-8
|
||||
Da = (double)(int32_t)ee_da * (double)pow(2, -16); // 2^-16
|
||||
Db = (double)(int32_t)ee_db * (double)pow(2, -8); // 2^-8
|
||||
Ea = (double)(int32_t)ee_ea * (double)pow(2, -16); // 2^-16
|
||||
Eb = (double)(int32_t)ee_eb * (double)pow(2, -8); // 2^-8
|
||||
Fa = (double)(int32_t)ee_fa * (double)pow(2, -46); // 2^-46
|
||||
Fb = (double)(int32_t)ee_fb * (double)pow(2, -36); // 2^-36
|
||||
Ga = (double)(int32_t)ee_ga * (double)pow(2, -36); // 2^-36
|
||||
|
||||
// 16-bit signed values with scaling
|
||||
Gb = (double)(int16_t)gb_reg.read() * (double)pow(2, -10); // 2^-10
|
||||
Ka = (double)(int16_t)ka_reg.read() * (double)pow(2, -10); // 2^-10
|
||||
Kb = (int16_t)kb_reg.read(); // No scaling
|
||||
Ha = (double)(int16_t)ha_reg.read() * (double)pow(2, -14); // 2^-14
|
||||
Hb = (double)(int16_t)hb_reg.read() * (double)pow(2, -10); // 2^-10
|
||||
|
||||
#ifdef MLX90632_DEBUG
|
||||
// Debug: Print calibration constants
|
||||
Serial.println(F("Calibration constants:"));
|
||||
Serial.print(F(" P_R = "));
|
||||
Serial.println(P_R, 8);
|
||||
Serial.print(F(" P_G = "));
|
||||
Serial.println(P_G, 8);
|
||||
Serial.print(F(" P_T = "));
|
||||
Serial.println(P_T, 12);
|
||||
Serial.print(F(" P_O = "));
|
||||
Serial.println(P_O, 8);
|
||||
Serial.print(F(" Aa = "));
|
||||
Serial.println(Aa, 8);
|
||||
Serial.print(F(" Ab = "));
|
||||
Serial.println(Ab, 8);
|
||||
Serial.print(F(" Ba = "));
|
||||
Serial.println(Ba, 8);
|
||||
Serial.print(F(" Bb = "));
|
||||
Serial.println(Bb, 8);
|
||||
Serial.print(F(" Ca = "));
|
||||
Serial.println(Ca, 8);
|
||||
Serial.print(F(" Cb = "));
|
||||
Serial.println(Cb, 8);
|
||||
Serial.print(F(" Da = "));
|
||||
Serial.println(Da, 8);
|
||||
Serial.print(F(" Db = "));
|
||||
Serial.println(Db, 8);
|
||||
Serial.print(F(" Ea = "));
|
||||
Serial.println(Ea, 8);
|
||||
Serial.print(F(" Eb = "));
|
||||
Serial.println(Eb, 8);
|
||||
Serial.print(F(" Fa = "));
|
||||
Serial.println(Fa, 12);
|
||||
Serial.print(F(" Fb = "));
|
||||
Serial.println(Fb, 10);
|
||||
Serial.print(F(" Ga = "));
|
||||
Serial.println(Ga, 10);
|
||||
Serial.print(F(" Gb = "));
|
||||
Serial.println(Gb, 8);
|
||||
Serial.print(F(" Ka = "));
|
||||
Serial.println(Ka, 8);
|
||||
Serial.print(F(" Kb = "));
|
||||
Serial.println(Kb);
|
||||
Serial.print(F(" Ha = "));
|
||||
Serial.println(Ha, 8);
|
||||
Serial.print(F(" Hb = "));
|
||||
Serial.println(Hb, 8);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Calculate ambient temperature
|
||||
* @return Ambient temperature in degrees Celsius
|
||||
*/
|
||||
double Adafruit_MLX90632::getAmbientTemperature() {
|
||||
// Check measurement mode to determine which RAM registers to use
|
||||
mlx90632_meas_select_t meas_mode = getMeasurementSelect();
|
||||
|
||||
int16_t ram_ambient, ram_ref;
|
||||
|
||||
if (meas_mode == MLX90632_MEAS_EXTENDED_RANGE) {
|
||||
// Extended range mode: use RAM_54 and RAM_57
|
||||
Adafruit_BusIO_Register ram54_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_54), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram57_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_57), 2, MSBFIRST, 2);
|
||||
|
||||
ram_ambient = (int16_t)ram54_reg.read();
|
||||
ram_ref = (int16_t)ram57_reg.read();
|
||||
} else {
|
||||
// Medical mode: use RAM_6 and RAM_9 (default)
|
||||
Adafruit_BusIO_Register ram6_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_6), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram9_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_9), 2, MSBFIRST, 2);
|
||||
|
||||
ram_ambient = (int16_t)ram6_reg.read();
|
||||
ram_ref = (int16_t)ram9_reg.read();
|
||||
}
|
||||
|
||||
// Pre-calculations for ambient temperature (same for both modes)
|
||||
// Gb = EE_Gb * 2^-10 (already calculated in getCalibrations())
|
||||
double VRTA = (double)ram_ref + Gb * ((double)ram_ambient / 12.0);
|
||||
double AMB = ((double)ram_ambient / 12.0) / VRTA * (double)pow(2, 19);
|
||||
|
||||
// Calculate ambient temperature: P_O + (AMB - P_R)/P_G + P_T * (AMB - P_R)^2
|
||||
double amb_diff = AMB - P_R;
|
||||
double ambient_temp = P_O + (amb_diff / P_G) + P_T * (amb_diff * amb_diff);
|
||||
|
||||
#ifdef MLX90632_DEBUG
|
||||
// Debug output
|
||||
Serial.print(F(" Mode = "));
|
||||
Serial.println(meas_mode == MLX90632_MEAS_EXTENDED_RANGE ? F("Extended")
|
||||
: F("Medical"));
|
||||
Serial.print(F(" RAM_ambient = "));
|
||||
Serial.println(ram_ambient);
|
||||
Serial.print(F(" RAM_ref = "));
|
||||
Serial.println(ram_ref);
|
||||
Serial.print(F(" Gb = "));
|
||||
Serial.println(Gb, 8);
|
||||
Serial.print(F(" VRTA = "));
|
||||
Serial.println(VRTA, 8);
|
||||
Serial.print(F(" AMB = "));
|
||||
Serial.println(AMB, 8);
|
||||
Serial.print(F(" AMB - P_R = "));
|
||||
Serial.println(amb_diff, 8);
|
||||
Serial.print(F(" Ambient Temp = "));
|
||||
Serial.println(ambient_temp, 8);
|
||||
#endif
|
||||
|
||||
return ambient_temp;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Calculate object temperature
|
||||
* @return Object temperature in degrees Celsius or NaN if invalid cycle
|
||||
* position
|
||||
*/
|
||||
double Adafruit_MLX90632::getObjectTemperature() {
|
||||
// Check measurement mode to determine which calculation to use
|
||||
mlx90632_meas_select_t meas_mode = getMeasurementSelect();
|
||||
|
||||
double S;
|
||||
int16_t ram_ambient, ram_ref;
|
||||
|
||||
if (meas_mode == MLX90632_MEAS_EXTENDED_RANGE) {
|
||||
// Extended range mode: use RAM_52-59
|
||||
Adafruit_BusIO_Register ram52_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_52), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram53_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_53), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram54_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_54), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram55_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_55), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram56_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_56), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram57_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_57), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram58_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_58), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram59_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_59), 2, MSBFIRST, 2);
|
||||
|
||||
int16_t ram52 = (int16_t)ram52_reg.read();
|
||||
int16_t ram53 = (int16_t)ram53_reg.read();
|
||||
int16_t ram54 = (int16_t)ram54_reg.read();
|
||||
int16_t ram55 = (int16_t)ram55_reg.read();
|
||||
int16_t ram56 = (int16_t)ram56_reg.read();
|
||||
int16_t ram57 = (int16_t)ram57_reg.read();
|
||||
int16_t ram58 = (int16_t)ram58_reg.read();
|
||||
int16_t ram59 = (int16_t)ram59_reg.read();
|
||||
|
||||
// Extended range S calculation
|
||||
S = ((double)ram52 - (double)ram53 - (double)ram55 + (double)ram56) / 2.0 +
|
||||
(double)ram58 + (double)ram59;
|
||||
ram_ambient = ram54;
|
||||
ram_ref = ram57;
|
||||
|
||||
} else {
|
||||
// Medical mode: use cycle position and RAM_4-9
|
||||
uint8_t cycle_pos = readCyclePosition();
|
||||
|
||||
Adafruit_BusIO_Register ram4_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_4), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram5_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_5), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram6_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_6), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram7_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_7), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram8_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_8), 2, MSBFIRST, 2);
|
||||
Adafruit_BusIO_Register ram9_reg = Adafruit_BusIO_Register(
|
||||
i2c_dev, swapBytes(MLX90632_REG_RAM_9), 2, MSBFIRST, 2);
|
||||
|
||||
int16_t ram4 = (int16_t)ram4_reg.read();
|
||||
int16_t ram5 = (int16_t)ram5_reg.read();
|
||||
int16_t ram6 = (int16_t)ram6_reg.read();
|
||||
int16_t ram7 = (int16_t)ram7_reg.read();
|
||||
int16_t ram8 = (int16_t)ram8_reg.read();
|
||||
int16_t ram9 = (int16_t)ram9_reg.read();
|
||||
|
||||
// Medical mode S calculation based on cycle position
|
||||
if (cycle_pos == 2) {
|
||||
S = ((double)ram4 + (double)ram5) / 2.0;
|
||||
} else if (cycle_pos == 1) {
|
||||
S = ((double)ram7 + (double)ram8) / 2.0;
|
||||
} else {
|
||||
// Invalid cycle position - return NaN
|
||||
return NAN;
|
||||
}
|
||||
|
||||
ram_ambient = ram6;
|
||||
ram_ref = ram9;
|
||||
}
|
||||
|
||||
// Pre-calculations for object temperature (same for both modes)
|
||||
// VRTO = ram_ref + Ka * (ram_ambient / 12)
|
||||
// Ka = EE_Ka * 2^-10 (already calculated in getCalibrations())
|
||||
double VRTO = (double)ram_ref + Ka * ((double)ram_ambient / 12.0);
|
||||
|
||||
// STO = [S/12]/VRTO * 2^19
|
||||
double STO = ((S / 12.0) / VRTO) * (double)pow(2, 19);
|
||||
|
||||
// Calculate AMB for ambient temperature (needed for TADUT)
|
||||
double VRTA = (double)ram_ref + Gb * ((double)ram_ambient / 12.0);
|
||||
double AMB = ((double)ram_ambient / 12.0) / VRTA * (double)pow(2, 19);
|
||||
|
||||
// Additional temperature calculations
|
||||
double TADUT = (AMB - Eb) / Ea + 25.0;
|
||||
double TAK = TADUT + 273.15;
|
||||
double emissivity = 1.0;
|
||||
|
||||
// For the first iteration, use current TADUT as TODUT approximation
|
||||
double TODUT = TADUT;
|
||||
|
||||
// Calculate final object temperature:
|
||||
// TO = pow( STO / (emiss * Fa * Ha * (1 + Ga * (TODUT - TO0) + Fb * (TADUT -
|
||||
// TA0))) + TAK^4, 0.25) - 273.15 - Hb
|
||||
double denominator =
|
||||
emissivity * Fa * Ha * (1.0 + Ga * (TODUT - TO0) + Fb * (TADUT - TA0));
|
||||
double TAK4 = pow(TAK, 4);
|
||||
double TO_K4 = (STO / denominator) + TAK4;
|
||||
double TO = pow(TO_K4, 0.25) - 273.15 - Hb;
|
||||
|
||||
#ifdef MLX90632_DEBUG
|
||||
// Debug output
|
||||
Serial.print(F(" Mode = "));
|
||||
Serial.println(meas_mode == MLX90632_MEAS_EXTENDED_RANGE ? F("Extended")
|
||||
: F("Medical"));
|
||||
if (meas_mode == MLX90632_MEAS_MEDICAL) {
|
||||
Serial.print(F(" Cycle Position = "));
|
||||
Serial.println(readCyclePosition());
|
||||
}
|
||||
Serial.print(F(" RAM_ambient = "));
|
||||
Serial.println(ram_ambient);
|
||||
Serial.print(F(" RAM_ref = "));
|
||||
Serial.println(ram_ref);
|
||||
Serial.print(F(" S = "));
|
||||
Serial.println(S, 8);
|
||||
Serial.print(F(" Ka = "));
|
||||
Serial.println(Ka, 8);
|
||||
Serial.print(F(" VRTO = "));
|
||||
Serial.println(VRTO, 8);
|
||||
Serial.print(F(" STO = "));
|
||||
Serial.println(STO, 8);
|
||||
Serial.print(F(" VRTA = "));
|
||||
Serial.println(VRTA, 8);
|
||||
Serial.print(F(" AMB = "));
|
||||
Serial.println(AMB, 8);
|
||||
Serial.print(F(" TADUT = "));
|
||||
Serial.println(TADUT, 8);
|
||||
Serial.print(F(" TODUT = "));
|
||||
Serial.println(TODUT, 8);
|
||||
Serial.print(F(" TAK = "));
|
||||
Serial.println(TAK, 8);
|
||||
Serial.print(F(" TAK^4 = "));
|
||||
if (TAK4 >= 1e9) {
|
||||
Serial.print(TAK4 / 1e9, 2);
|
||||
Serial.println(F("e+09"));
|
||||
} else if (TAK4 >= 1e6) {
|
||||
Serial.print(TAK4 / 1e6, 2);
|
||||
Serial.println(F("e+06"));
|
||||
} else {
|
||||
Serial.println(TAK4, 2);
|
||||
}
|
||||
Serial.print(F(" TO0 = "));
|
||||
Serial.println(TO0, 8);
|
||||
Serial.print(F(" TA0 = "));
|
||||
Serial.println(TA0, 8);
|
||||
Serial.print(F(" Emissivity = "));
|
||||
Serial.println(emissivity, 8);
|
||||
Serial.print(F(" Denominator = "));
|
||||
Serial.println(denominator, 8);
|
||||
Serial.print(F(" TO_K^4 = "));
|
||||
if (TO_K4 >= 1e9) {
|
||||
Serial.print(TO_K4 / 1e9, 2);
|
||||
Serial.println(F("e+09"));
|
||||
} else if (TO_K4 >= 1e6) {
|
||||
Serial.print(TO_K4 / 1e6, 2);
|
||||
Serial.println(F("e+06"));
|
||||
} else {
|
||||
Serial.println(TO_K4, 2);
|
||||
}
|
||||
Serial.print(F(" TO = "));
|
||||
Serial.println(TO, 8);
|
||||
#endif
|
||||
|
||||
// Update TO0 and TA0 with current measurements for next calculation
|
||||
TO0 = TO; // Use calculated object temperature
|
||||
TA0 = TADUT; // Update with current ambient temperature calculation
|
||||
|
||||
return TO;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Byte swap helper for register addresses
|
||||
* @param value 16-bit value to swap
|
||||
|
|
@ -256,4 +695,4 @@ bool Adafruit_MLX90632::isNewData() {
|
|||
*/
|
||||
uint16_t Adafruit_MLX90632::swapBytes(uint16_t value) {
|
||||
return (value << 8) | (value >> 8);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,20 @@
|
|||
* please support Adafruit and open-source hardware by purchasing products from
|
||||
* Adafruit!
|
||||
*
|
||||
* BSD license (see license.txt)
|
||||
* Written by Limor "Ladyada" Fried with assistance from Claude Code.
|
||||
*
|
||||
* MIT license, see LICENSE for more information
|
||||
*/
|
||||
|
||||
#ifndef _ADAFRUIT_MLX90632_H
|
||||
#define _ADAFRUIT_MLX90632_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <Adafruit_BusIO_Register.h>
|
||||
#include <Adafruit_I2CDevice.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
/*=========================================================================
|
||||
I2C ADDRESS/BITS
|
||||
-----------------------------------------------------------------------*/
|
||||
|
|
@ -31,85 +34,120 @@
|
|||
REGISTERS
|
||||
-----------------------------------------------------------------------*/
|
||||
// EEPROM addresses
|
||||
#define MLX90632_REG_MELEXIS_RESERVED0 0x2400 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED1 0x2401 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED2 0x2402 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED3 0x2403 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED4 0x2404 ///< Melexis reserved
|
||||
#define MLX90632_REG_ID0 0x2405 ///< Chip ID
|
||||
#define MLX90632_REG_ID1 0x2406 ///< Chip ID
|
||||
#define MLX90632_REG_ID2 0x2407 ///< Chip ID
|
||||
#define MLX90632_REG_ID_CRC16 0x2408 ///< CRC
|
||||
#define MLX90632_REG_EE_PRODUCT_CODE 0x2409 ///< Sensor information
|
||||
#define MLX90632_REG_MELEXIS_RESERVED0 0x2400 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED1 0x2401 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED2 0x2402 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED3 0x2403 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED4 0x2404 ///< Melexis reserved
|
||||
#define MLX90632_REG_ID0 0x2405 ///< Chip ID
|
||||
#define MLX90632_REG_ID1 0x2406 ///< Chip ID
|
||||
#define MLX90632_REG_ID2 0x2407 ///< Chip ID
|
||||
#define MLX90632_REG_ID_CRC16 0x2408 ///< CRC
|
||||
#define MLX90632_REG_EE_PRODUCT_CODE 0x2409 ///< Sensor information
|
||||
#define MLX90632_REG_MELEXIS_RESERVED10 0x240A ///< Melexis reserved
|
||||
#define MLX90632_REG_EE_VERSION 0x240B ///< EEPROM version
|
||||
#define MLX90632_REG_EE_P_R_LSW 0x240C ///< P_R calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_R_MSW 0x240D ///< P_R calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_P_G_LSW 0x240E ///< P_G calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_G_MSW 0x240F ///< P_G calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_P_T_LSW 0x2410 ///< P_T calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_T_MSW 0x2411 ///< P_T calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_P_O_LSW 0x2412 ///< P_O calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_O_MSW 0x2413 ///< P_O calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_AA_LSW 0x2414 ///< Aa calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_AA_MSW 0x2415 ///< Aa calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_AB_LSW 0x2416 ///< Ab calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_AB_MSW 0x2417 ///< Ab calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_BA_LSW 0x2418 ///< Ba calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_BA_MSW 0x2419 ///< Ba calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_BB_LSW 0x241A ///< Bb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_BB_MSW 0x241B ///< Bb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_CA_LSW 0x241C ///< Ca calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_CA_MSW 0x241D ///< Ca calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_CB_LSW 0x241E ///< Cb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_CB_MSW 0x241F ///< Cb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_DA_LSW 0x2420 ///< Da calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_DA_MSW 0x2421 ///< Da calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_DB_LSW 0x2422 ///< Db calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_DB_MSW 0x2423 ///< Db calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_EA_LSW 0x2424 ///< Ea calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_EA_MSW 0x2425 ///< Ea calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_EB_LSW 0x2426 ///< Eb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_EB_MSW 0x2427 ///< Eb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_FA_LSW 0x2428 ///< Fa calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_FA_MSW 0x2429 ///< Fa calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_FB_LSW 0x242A ///< Fb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_FB_MSW 0x242B ///< Fb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_GA_LSW 0x242C ///< Ga calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_GA_MSW 0x242D ///< Ga calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_VERSION 0x240B ///< EEPROM version
|
||||
#define MLX90632_REG_EE_P_R_LSW \
|
||||
0x240C ///< P_R calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_R_MSW \
|
||||
0x240D ///< P_R calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_P_G_LSW \
|
||||
0x240E ///< P_G calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_G_MSW \
|
||||
0x240F ///< P_G calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_P_T_LSW \
|
||||
0x2410 ///< P_T calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_T_MSW \
|
||||
0x2411 ///< P_T calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_P_O_LSW \
|
||||
0x2412 ///< P_O calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_P_O_MSW \
|
||||
0x2413 ///< P_O calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_AA_LSW \
|
||||
0x2414 ///< Aa calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_AA_MSW \
|
||||
0x2415 ///< Aa calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_AB_LSW \
|
||||
0x2416 ///< Ab calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_AB_MSW \
|
||||
0x2417 ///< Ab calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_BA_LSW \
|
||||
0x2418 ///< Ba calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_BA_MSW \
|
||||
0x2419 ///< Ba calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_BB_LSW \
|
||||
0x241A ///< Bb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_BB_MSW \
|
||||
0x241B ///< Bb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_CA_LSW \
|
||||
0x241C ///< Ca calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_CA_MSW \
|
||||
0x241D ///< Ca calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_CB_LSW \
|
||||
0x241E ///< Cb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_CB_MSW \
|
||||
0x241F ///< Cb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_DA_LSW \
|
||||
0x2420 ///< Da calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_DA_MSW \
|
||||
0x2421 ///< Da calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_DB_LSW \
|
||||
0x2422 ///< Db calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_DB_MSW \
|
||||
0x2423 ///< Db calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_EA_LSW \
|
||||
0x2424 ///< Ea calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_EA_MSW \
|
||||
0x2425 ///< Ea calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_EB_LSW \
|
||||
0x2426 ///< Eb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_EB_MSW \
|
||||
0x2427 ///< Eb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_FA_LSW \
|
||||
0x2428 ///< Fa calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_FA_MSW \
|
||||
0x2429 ///< Fa calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_FB_LSW \
|
||||
0x242A ///< Fb calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_FB_MSW \
|
||||
0x242B ///< Fb calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_GA_LSW \
|
||||
0x242C ///< Ga calibration constant (16-bit, Least Significant Word)
|
||||
#define MLX90632_REG_EE_GA_MSW \
|
||||
0x242D ///< Ga calibration constant (16-bit, Most Significant Word)
|
||||
#define MLX90632_REG_EE_GB 0x242E ///< Gb calibration constant (16-bit)
|
||||
#define MLX90632_REG_EE_KA 0x242F ///< Ka calibration constant (16-bit)
|
||||
#define MLX90632_REG_EE_KB 0x2430 ///< Kb calibration constant (16-bit)
|
||||
#define MLX90632_REG_MELEXIS_RESERVED49 0x2431 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED49 0x2431 ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED127 0x247F ///< Melexis reserved
|
||||
#define MLX90632_REG_MELEXIS_RESERVED128 0x2480 ///< Melexis reserved
|
||||
#define MLX90632_REG_EE_HA 0x2481 ///< Ha Customer calibration constant (16 bit)
|
||||
#define MLX90632_REG_EE_HB 0x2482 ///< Hb Customer calibration constant (16 bit)
|
||||
#define MLX90632_REG_MELEXIS_RESERVED131 0x2483 ///< Melexis reserved
|
||||
#define MLX90632_REG_CUSTOMER_DATA_START 0x24C0 ///< Customer data start
|
||||
#define MLX90632_REG_CUSTOMER_DATA_END 0x24CF ///< Customer data end
|
||||
#define MLX90632_REG_CUSTOMER_DATA_END 0x24CF ///< Customer data end
|
||||
#define MLX90632_REG_MELEXIS_RESERVED208 0x24D0 ///< Melexis reserved
|
||||
#define MLX90632_REG_EE_CONTROL 0x24D4 ///< EEPROM Control register, measurement control
|
||||
#define MLX90632_REG_EE_I2C_ADDRESS 0x24D5 ///< I2C slave address >> 1
|
||||
#define MLX90632_REG_EE_CONTROL \
|
||||
0x24D4 ///< EEPROM Control register, measurement control
|
||||
#define MLX90632_REG_EE_I2C_ADDRESS 0x24D5 ///< I2C slave address >> 1
|
||||
#define MLX90632_REG_MELEXIS_RESERVED214 0x24D6 ///< Melexis reserved
|
||||
#define MLX90632_REG_EE_MEAS_1 0x24E1 ///< Measurement settings 1
|
||||
#define MLX90632_REG_EE_MEAS_2 0x24E2 ///< Measurement settings 2
|
||||
#define MLX90632_REG_EE_MEAS_1 0x24E1 ///< Measurement settings 1
|
||||
#define MLX90632_REG_EE_MEAS_2 0x24E2 ///< Measurement settings 2
|
||||
|
||||
// Control and Status registers
|
||||
#define MLX90632_REG_I2C_ADDRESS 0x3000 ///< I2C slave address >> 1
|
||||
#define MLX90632_REG_CONTROL 0x3001 ///< Control register, measurement mode
|
||||
#define MLX90632_REG_STATUS 0x3FFF ///< Status register: data available
|
||||
#define MLX90632_REG_CONTROL 0x3001 ///< Control register, measurement mode
|
||||
#define MLX90632_REG_STATUS 0x3FFF ///< Status register: data available
|
||||
|
||||
// RAM addresses
|
||||
#define MLX90632_REG_RAM_1 0x4000 ///< Raw data 1
|
||||
#define MLX90632_REG_RAM_2 0x4001 ///< Raw data 2
|
||||
#define MLX90632_REG_RAM_3 0x4002 ///< Raw data 3
|
||||
#define MLX90632_REG_RAM_4 0x4003 ///< Raw data 4
|
||||
#define MLX90632_REG_RAM_5 0x4004 ///< Raw data 5
|
||||
#define MLX90632_REG_RAM_6 0x4005 ///< Raw data 6
|
||||
#define MLX90632_REG_RAM_7 0x4006 ///< Raw data 7
|
||||
#define MLX90632_REG_RAM_8 0x4007 ///< Raw data 8
|
||||
#define MLX90632_REG_RAM_9 0x4008 ///< Raw data 9
|
||||
#define MLX90632_REG_RAM_1 0x4000 ///< Raw data 1
|
||||
#define MLX90632_REG_RAM_2 0x4001 ///< Raw data 2
|
||||
#define MLX90632_REG_RAM_3 0x4002 ///< Raw data 3
|
||||
#define MLX90632_REG_RAM_4 0x4003 ///< Raw data 4
|
||||
#define MLX90632_REG_RAM_5 0x4004 ///< Raw data 5
|
||||
#define MLX90632_REG_RAM_6 0x4005 ///< Raw data 6
|
||||
#define MLX90632_REG_RAM_7 0x4006 ///< Raw data 7
|
||||
#define MLX90632_REG_RAM_8 0x4007 ///< Raw data 8
|
||||
#define MLX90632_REG_RAM_9 0x4008 ///< Raw data 9
|
||||
#define MLX90632_REG_RAM_52 0x4033 ///< Raw data 52
|
||||
#define MLX90632_REG_RAM_53 0x4034 ///< Raw data 53
|
||||
#define MLX90632_REG_RAM_54 0x4035 ///< Raw data 54
|
||||
|
|
@ -128,19 +166,33 @@
|
|||
* @brief MLX90632 measurement modes
|
||||
*/
|
||||
typedef enum {
|
||||
MLX90632_MODE_HALT = 0x00, ///< Halt mode for EEPROM operations
|
||||
MLX90632_MODE_SLEEPING_STEP = 0x01, ///< Sleeping step mode
|
||||
MLX90632_MODE_STEP = 0x02, ///< Step mode
|
||||
MLX90632_MODE_CONTINUOUS = 0x03 ///< Continuous mode
|
||||
MLX90632_MODE_HALT = 0x00, ///< Halt mode for EEPROM operations
|
||||
MLX90632_MODE_SLEEPING_STEP = 0x01, ///< Sleeping step mode
|
||||
MLX90632_MODE_STEP = 0x02, ///< Step mode
|
||||
MLX90632_MODE_CONTINUOUS = 0x03 ///< Continuous mode
|
||||
} mlx90632_mode_t;
|
||||
|
||||
/*!
|
||||
* @brief MLX90632 measurement types
|
||||
*/
|
||||
typedef enum {
|
||||
MLX90632_MEAS_MEDICAL = 0x00, ///< Medical measurement
|
||||
MLX90632_MEAS_EXTENDED_RANGE = 0x11 ///< Extended range measurement
|
||||
MLX90632_MEAS_MEDICAL = 0x00, ///< Medical measurement
|
||||
MLX90632_MEAS_EXTENDED_RANGE = 0x11 ///< Extended range measurement
|
||||
} mlx90632_meas_select_t;
|
||||
|
||||
/*!
|
||||
* @brief MLX90632 refresh rates
|
||||
*/
|
||||
typedef enum {
|
||||
MLX90632_REFRESH_0_5HZ = 0, ///< 0.5 Hz (2000ms)
|
||||
MLX90632_REFRESH_1HZ = 1, ///< 1 Hz (1000ms)
|
||||
MLX90632_REFRESH_2HZ = 2, ///< 2 Hz (500ms)
|
||||
MLX90632_REFRESH_4HZ = 3, ///< 4 Hz (250ms)
|
||||
MLX90632_REFRESH_8HZ = 4, ///< 8 Hz (125ms)
|
||||
MLX90632_REFRESH_16HZ = 5, ///< 16 Hz (62.5ms)
|
||||
MLX90632_REFRESH_32HZ = 6, ///< 32 Hz (31.25ms)
|
||||
MLX90632_REFRESH_64HZ = 7 ///< 64 Hz (15.625ms)
|
||||
} mlx90632_refresh_rate_t;
|
||||
/*=========================================================================*/
|
||||
|
||||
/*!
|
||||
|
|
@ -148,12 +200,13 @@ typedef enum {
|
|||
* MLX90632 Far Infrared Temperature Sensor
|
||||
*/
|
||||
class Adafruit_MLX90632 {
|
||||
public:
|
||||
public:
|
||||
Adafruit_MLX90632();
|
||||
~Adafruit_MLX90632();
|
||||
bool begin(uint8_t i2c_addr = MLX90632_DEFAULT_ADDR, TwoWire *wire = &Wire);
|
||||
bool begin(uint8_t i2c_addr = MLX90632_DEFAULT_ADDR, TwoWire* wire = &Wire);
|
||||
uint64_t getProductID();
|
||||
uint16_t getProductCode();
|
||||
uint16_t getEEPROMVersion();
|
||||
bool startSingleMeasurement();
|
||||
bool startFullMeasurement();
|
||||
bool setMode(mlx90632_mode_t mode);
|
||||
|
|
@ -166,10 +219,46 @@ public:
|
|||
uint8_t readCyclePosition();
|
||||
bool resetNewData();
|
||||
bool isNewData();
|
||||
bool setRefreshRate(mlx90632_refresh_rate_t refresh_rate);
|
||||
mlx90632_refresh_rate_t getRefreshRate();
|
||||
bool getCalibrations();
|
||||
double getAmbientTemperature();
|
||||
double getObjectTemperature();
|
||||
|
||||
private:
|
||||
Adafruit_I2CDevice *i2c_dev; ///< Pointer to I2C bus interface
|
||||
uint16_t swapBytes(uint16_t value); ///< Byte swap helper for register addresses
|
||||
private:
|
||||
Adafruit_I2CDevice* i2c_dev; ///< Pointer to I2C bus interface
|
||||
uint16_t swapBytes(
|
||||
uint16_t value); ///< Byte swap helper for register addresses
|
||||
uint32_t read32BitRegister(
|
||||
uint16_t lsw_addr); ///< Helper to read 32-bit values
|
||||
|
||||
// Calibration constants
|
||||
double P_R; ///< P_R calibration constant
|
||||
double P_G; ///< P_G calibration constant
|
||||
double P_T; ///< P_T calibration constant
|
||||
double P_O; ///< P_O calibration constant
|
||||
double Aa; ///< Aa calibration constant
|
||||
double Ab; ///< Ab calibration constant
|
||||
double Ba; ///< Ba calibration constant
|
||||
double Bb; ///< Bb calibration constant
|
||||
double Ca; ///< Ca calibration constant
|
||||
double Cb; ///< Cb calibration constant
|
||||
double Da; ///< Da calibration constant
|
||||
double Db; ///< Db calibration constant
|
||||
double Ea; ///< Ea calibration constant
|
||||
double Eb; ///< Eb calibration constant
|
||||
double Fa; ///< Fa calibration constant
|
||||
double Fb; ///< Fb calibration constant
|
||||
double Ga; ///< Ga calibration constant
|
||||
double Gb; ///< Gb calibration constant
|
||||
double Ka; ///< Ka calibration constant
|
||||
int16_t Kb; ///< Kb calibration constant (16-bit signed)
|
||||
double Ha; ///< Ha calibration constant
|
||||
double Hb; ///< Hb calibration constant
|
||||
|
||||
// Temperature calculation variables
|
||||
double TO0; ///< Previous object temperature (starts at 25.0)
|
||||
double TA0; ///< Previous ambient temperature (starts at 25.0)
|
||||
};
|
||||
|
||||
#endif
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Adafruit Industries
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
18
README.md
18
README.md
|
|
@ -2,6 +2,20 @@
|
|||
|
||||
Arduino library for the MLX90632 Far Infrared Temperature Sensor
|
||||
|
||||
This library provides a complete interface for the MLX90632 Far Infrared Temperature Sensor, supporting both medical and extended range measurement modes with automatic calibration loading and comprehensive temperature calculations using the Stefan-Boltzmann law.
|
||||
|
||||
## Features
|
||||
|
||||
- Complete MLX90632 register control and status monitoring
|
||||
- Support for all measurement modes: Continuous, Step, and Sleeping Step
|
||||
- Automatic calibration constant loading from EEPROM
|
||||
- Both medical and extended range measurement support
|
||||
- Stefan-Boltzmann law temperature calculations for accurate object temperature
|
||||
- Double precision calibration with proper scaling factors
|
||||
- Efficient new data flag handling for optimal performance
|
||||
- Debug output control with preprocessor directives
|
||||
- Hardware tested and verified functionality
|
||||
|
||||
## Dependencies
|
||||
* [Adafruit BusIO](https://github.com/adafruit/Adafruit_BusIO)
|
||||
|
||||
|
|
@ -27,7 +41,7 @@ Note that the formatting output by `clang-format` is what the automated formatti
|
|||
|
||||
## About this Driver
|
||||
|
||||
Written by Adafruit Industries.
|
||||
Written by Limor "Ladyada" Fried for Adafruit Industries with assistance from Claude Code.
|
||||
|
||||
MIT license, check license.txt for more information.
|
||||
MIT license, check LICENSE for more information.
|
||||
All text above must be included in any redistribution.
|
||||
|
|
@ -8,106 +8,188 @@ void setup() {
|
|||
Serial.begin(115200);
|
||||
while (!Serial) delay(10);
|
||||
|
||||
Serial.println("Adafruit MLX90632 test");
|
||||
Serial.println(F("Adafruit MLX90632 test"));
|
||||
|
||||
if (!mlx.begin()) {
|
||||
Serial.println("Failed to find MLX90632 chip");
|
||||
Serial.println(F("Failed to find MLX90632 chip"));
|
||||
while (1) { delay(10); }
|
||||
}
|
||||
Serial.println("MLX90632 Found!");
|
||||
Serial.println(F("MLX90632 Found!"));
|
||||
|
||||
// Reset the device
|
||||
if (!mlx.reset()) {
|
||||
Serial.println("Device reset failed");
|
||||
Serial.println(F("Device reset failed"));
|
||||
while (1) { delay(10); }
|
||||
}
|
||||
Serial.println("Device reset: SUCCESS");
|
||||
Serial.println(F("Device reset: SUCCESS"));
|
||||
|
||||
uint64_t productID = mlx.getProductID();
|
||||
Serial.print("Product ID: 0x");
|
||||
Serial.print(F("Product ID: 0x"));
|
||||
Serial.print((uint32_t)(productID >> 32), HEX);
|
||||
Serial.println((uint32_t)(productID & 0xFFFFFFFF), HEX);
|
||||
|
||||
uint16_t productCode = mlx.getProductCode();
|
||||
Serial.print("Product Code: 0x");
|
||||
Serial.print(F("Product Code: 0x"));
|
||||
Serial.println(productCode, HEX);
|
||||
|
||||
uint16_t eepromVersion = mlx.getEEPROMVersion();
|
||||
Serial.print(F("EEPROM Version: 0x"));
|
||||
Serial.println(eepromVersion, HEX);
|
||||
|
||||
// Decode product code bits
|
||||
uint8_t fov = (productCode >> 8) & 0x3;
|
||||
uint8_t package = (productCode >> 5) & 0x7;
|
||||
uint8_t accuracy = productCode & 0x1F;
|
||||
|
||||
Serial.print("FOV: ");
|
||||
Serial.println(fov == 0 ? "50°" : "Unknown");
|
||||
Serial.print(F("FOV: "));
|
||||
Serial.println(fov == 0 ? F("50°") : F("Unknown"));
|
||||
|
||||
Serial.print("Package: ");
|
||||
Serial.println(package == 1 ? "SFN 3x3" : "Unknown");
|
||||
Serial.print(F("Package: "));
|
||||
Serial.println(package == 1 ? F("SFN 3x3") : F("Unknown"));
|
||||
|
||||
Serial.print("Accuracy: ");
|
||||
Serial.print(F("Accuracy: "));
|
||||
if (accuracy == 1) {
|
||||
Serial.println("Medical");
|
||||
Serial.println(F("Medical"));
|
||||
} else if (accuracy == 2) {
|
||||
Serial.println("Standard");
|
||||
Serial.println(F("Standard"));
|
||||
} else {
|
||||
Serial.println("Unknown");
|
||||
Serial.println(F("Unknown"));
|
||||
}
|
||||
|
||||
// Set and get mode (continuous)
|
||||
Serial.println("\n--- Mode Settings ---");
|
||||
// Set and get mode - choose one:
|
||||
Serial.println(F("\n--- Mode Settings ---"));
|
||||
if (!mlx.setMode(MLX90632_MODE_CONTINUOUS)) {
|
||||
Serial.println("Failed to set mode to Continuous");
|
||||
// if (!mlx.setMode(MLX90632_MODE_STEP)) { // Uncomment for step mode testing
|
||||
// if (!mlx.setMode(MLX90632_MODE_SLEEPING_STEP)) { // Uncomment for sleeping step mode testing
|
||||
Serial.println(F("Failed to set mode"));
|
||||
while (1) { delay(10); }
|
||||
}
|
||||
|
||||
mlx90632_mode_t currentMode = mlx.getMode();
|
||||
Serial.print("Current mode: ");
|
||||
Serial.print(F("Current mode: "));
|
||||
switch (currentMode) {
|
||||
case MLX90632_MODE_HALT:
|
||||
Serial.println("Halt");
|
||||
Serial.println(F("Halt"));
|
||||
break;
|
||||
case MLX90632_MODE_SLEEPING_STEP:
|
||||
Serial.println("Sleeping Step");
|
||||
Serial.println(F("Sleeping Step"));
|
||||
break;
|
||||
case MLX90632_MODE_STEP:
|
||||
Serial.println("Step");
|
||||
Serial.println(F("Step"));
|
||||
break;
|
||||
case MLX90632_MODE_CONTINUOUS:
|
||||
Serial.println("Continuous");
|
||||
Serial.println(F("Continuous"));
|
||||
break;
|
||||
default:
|
||||
Serial.println("Unknown");
|
||||
Serial.println(F("Unknown"));
|
||||
}
|
||||
|
||||
// Set and get measurement select (medical)
|
||||
Serial.println("\n--- Measurement Select Settings ---");
|
||||
Serial.println(F("\n--- Measurement Select Settings ---"));
|
||||
if (!mlx.setMeasurementSelect(MLX90632_MEAS_MEDICAL)) {
|
||||
Serial.println("Failed to set measurement select to Medical");
|
||||
Serial.println(F("Failed to set measurement select to Medical"));
|
||||
while (1) { delay(10); }
|
||||
}
|
||||
|
||||
mlx90632_meas_select_t currentMeasSelect = mlx.getMeasurementSelect();
|
||||
Serial.print("Current measurement select: ");
|
||||
Serial.print(F("Current measurement select: "));
|
||||
switch (currentMeasSelect) {
|
||||
case MLX90632_MEAS_MEDICAL:
|
||||
Serial.println("Medical");
|
||||
Serial.println(F("Medical"));
|
||||
break;
|
||||
case MLX90632_MEAS_EXTENDED_RANGE:
|
||||
Serial.println("Extended Range");
|
||||
Serial.println(F("Extended Range"));
|
||||
break;
|
||||
default:
|
||||
Serial.println("Unknown");
|
||||
Serial.println(F("Unknown"));
|
||||
}
|
||||
|
||||
// Set and get refresh rate (default to 2Hz)
|
||||
Serial.println(F("\n--- Refresh Rate Settings ---"));
|
||||
if (!mlx.setRefreshRate(MLX90632_REFRESH_2HZ)) {
|
||||
Serial.println(F("Failed to set refresh rate to 2Hz"));
|
||||
while (1) { delay(10); }
|
||||
}
|
||||
|
||||
mlx90632_refresh_rate_t currentRefreshRate = mlx.getRefreshRate();
|
||||
Serial.print(F("Current refresh rate: "));
|
||||
switch (currentRefreshRate) {
|
||||
case MLX90632_REFRESH_0_5HZ:
|
||||
Serial.println(F("0.5 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_1HZ:
|
||||
Serial.println(F("1 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_2HZ:
|
||||
Serial.println(F("2 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_4HZ:
|
||||
Serial.println(F("4 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_8HZ:
|
||||
Serial.println(F("8 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_16HZ:
|
||||
Serial.println(F("16 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_32HZ:
|
||||
Serial.println(F("32 Hz"));
|
||||
break;
|
||||
case MLX90632_REFRESH_64HZ:
|
||||
Serial.println(F("64 Hz"));
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("Unknown"));
|
||||
}
|
||||
|
||||
// Clear new data flag before starting continuous measurements
|
||||
Serial.println(F("\\n--- Starting Continuous Measurements ---"));
|
||||
if (!mlx.resetNewData()) {
|
||||
Serial.println(F("Failed to reset new data flag"));
|
||||
while (1) { delay(10); }
|
||||
}
|
||||
Serial.println(F("New data flag reset - starting measurements"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print("Device Busy: ");
|
||||
Serial.print(mlx.isBusy() ? "YES" : "NO");
|
||||
Serial.print(" EEPROM Busy: ");
|
||||
Serial.print(mlx.isEEPROMBusy() ? "YES" : "NO");
|
||||
Serial.print(" New Data: ");
|
||||
Serial.print(mlx.isNewData() ? "YES" : "NO");
|
||||
Serial.print(" Cycle Position: ");
|
||||
Serial.println(mlx.readCyclePosition());
|
||||
// Only check new data flag - much more efficient for continuous mode
|
||||
if (mlx.isNewData()) {
|
||||
Serial.print(F("New Data Available - Cycle Position: "));
|
||||
Serial.println(mlx.readCyclePosition());
|
||||
|
||||
// Read ambient temperature
|
||||
double ambientTemp = mlx.getAmbientTemperature();
|
||||
Serial.print(F("Ambient Temperature: "));
|
||||
Serial.print(ambientTemp, 4);
|
||||
Serial.println(F(" °C"));
|
||||
|
||||
// Read object temperature
|
||||
double objectTemp = mlx.getObjectTemperature();
|
||||
Serial.print(F("Object Temperature: "));
|
||||
if (isnan(objectTemp)) {
|
||||
Serial.println(F("NaN (invalid cycle position)"));
|
||||
} else {
|
||||
Serial.print(objectTemp, 4);
|
||||
Serial.println(F(" °C"));
|
||||
}
|
||||
|
||||
// Reset new data flag after reading
|
||||
if (!mlx.resetNewData()) {
|
||||
Serial.println(F("Failed to reset new data flag"));
|
||||
}
|
||||
|
||||
Serial.println(); // Add blank line between readings
|
||||
}
|
||||
|
||||
delay(500);
|
||||
// Check if we need to trigger a new measurement for step modes
|
||||
mlx90632_mode_t currentMode = mlx.getMode();
|
||||
if (currentMode == MLX90632_MODE_STEP || currentMode == MLX90632_MODE_SLEEPING_STEP) {
|
||||
// Trigger single measurement (SOC bit) for step modes
|
||||
if (!mlx.startSingleMeasurement()) {
|
||||
Serial.println(F("Failed to start single measurement"));
|
||||
}
|
||||
}
|
||||
|
||||
// Small delay to prevent overwhelming the I2C bus
|
||||
delay(10);
|
||||
}
|
||||
10
library.properties
Normal file
10
library.properties
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
name=Adafruit MLX90632 Library
|
||||
version=1.0.2
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Arduino library for MLX90632 Far Infrared Temperature Sensor
|
||||
paragraph=This library provides a complete interface for the MLX90632 Far Infrared Temperature Sensor. Supports both medical and extended range measurement modes, automatic calibration loading, and comprehensive temperature calculations using the Stefan-Boltzmann law.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_MLX90632
|
||||
architectures=*
|
||||
depends=Adafruit BusIO
|
||||
Loading…
Reference in a new issue