Integrate calibration loading and add comprehensive mode support

- Automatically load calibration constants in begin() method
- Remove separate getCalibrations() call from example sketch
- Add selectable measurement modes in example with commented options
- Implement proper SOC (Start of Conversion) triggering for step modes
- Support all measurement modes: Continuous, Step, and Sleeping Step
- Optimize loop for efficient new data flag handling
- Add automatic single measurement triggering for step-based modes
- Tested and verified both continuous and step mode operation
- Apply clang-format code formatting to all C++ files

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ladyada 2025-08-02 16:29:51 -04:00
parent 195681dc69
commit c93ea16dd6
3 changed files with 442 additions and 341 deletions

View file

@ -21,8 +21,8 @@
* @brief Instantiates a new MLX90632 class * @brief Instantiates a new MLX90632 class
*/ */
Adafruit_MLX90632::Adafruit_MLX90632() { Adafruit_MLX90632::Adafruit_MLX90632() {
TO0 = 25.0; // Initialize previous object temperature TO0 = 25.0; // Initialize previous object temperature
TA0 = 25.0; // Initialize previous ambient temperature TA0 = 25.0; // Initialize previous ambient temperature
} }
/*! /*!
@ -42,7 +42,7 @@ Adafruit_MLX90632::~Adafruit_MLX90632() {
* The Wire object to be used for I2C connections. * The Wire object to be used for I2C connections.
* @return True if initialization was successful, otherwise false. * @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) { if (i2c_dev) {
delete i2c_dev; delete i2c_dev;
} }
@ -52,14 +52,19 @@ bool Adafruit_MLX90632::begin(uint8_t i2c_address, TwoWire *wire) {
return false; return false;
} }
Adafruit_BusIO_Register product_code_reg = Adafruit_BusIO_Register product_code_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2);
uint16_t product_code = product_code_reg.read(); uint16_t product_code = product_code_reg.read();
if (product_code == 0xFFFF || product_code == 0x0000) { if (product_code == 0xFFFF || product_code == 0x0000) {
return false; return false;
} }
// Load calibration constants automatically
if (!getCalibrations()) {
return false;
}
return true; return true;
} }
@ -68,12 +73,12 @@ bool Adafruit_MLX90632::begin(uint8_t i2c_address, TwoWire *wire) {
* @return Product ID (48-bit value in uint64_t) * @return Product ID (48-bit value in uint64_t)
*/ */
uint64_t Adafruit_MLX90632::getProductID() { uint64_t Adafruit_MLX90632::getProductID() {
Adafruit_BusIO_Register id0_reg = Adafruit_BusIO_Register id0_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_ID0), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_ID0), 2, MSBFIRST, 2);
Adafruit_BusIO_Register id1_reg = Adafruit_BusIO_Register id1_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_ID1), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_ID1), 2, MSBFIRST, 2);
Adafruit_BusIO_Register id2_reg = Adafruit_BusIO_Register id2_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_ID2), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_ID2), 2, MSBFIRST, 2);
uint16_t id0 = id0_reg.read(); uint16_t id0 = id0_reg.read();
uint16_t id1 = id1_reg.read(); uint16_t id1 = id1_reg.read();
@ -87,8 +92,8 @@ uint64_t Adafruit_MLX90632::getProductID() {
* @return Product code (16-bit value) * @return Product code (16-bit value)
*/ */
uint16_t Adafruit_MLX90632::getProductCode() { uint16_t Adafruit_MLX90632::getProductCode() {
Adafruit_BusIO_Register product_code_reg = Adafruit_BusIO_Register product_code_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_PRODUCT_CODE), 2, MSBFIRST, 2);
return product_code_reg.read(); return product_code_reg.read();
} }
@ -97,8 +102,8 @@ uint16_t Adafruit_MLX90632::getProductCode() {
* @return EEPROM version (16-bit value) * @return EEPROM version (16-bit value)
*/ */
uint16_t Adafruit_MLX90632::getEEPROMVersion() { uint16_t Adafruit_MLX90632::getEEPROMVersion() {
Adafruit_BusIO_Register version_reg = Adafruit_BusIO_Register version_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_VERSION), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_VERSION), 2, MSBFIRST, 2);
return version_reg.read(); return version_reg.read();
} }
@ -107,8 +112,8 @@ uint16_t Adafruit_MLX90632::getEEPROMVersion() {
* @return True if write succeeded, false otherwise * @return True if write succeeded, false otherwise
*/ */
bool Adafruit_MLX90632::startSingleMeasurement() { bool Adafruit_MLX90632::startSingleMeasurement() {
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits soc_bit = Adafruit_BusIO_RegisterBits soc_bit =
Adafruit_BusIO_RegisterBits(&control_reg, 1, 3); Adafruit_BusIO_RegisterBits(&control_reg, 1, 3);
@ -120,8 +125,8 @@ bool Adafruit_MLX90632::startSingleMeasurement() {
* @return True if write succeeded, false otherwise * @return True if write succeeded, false otherwise
*/ */
bool Adafruit_MLX90632::startFullMeasurement() { bool Adafruit_MLX90632::startFullMeasurement() {
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits sob_bit = Adafruit_BusIO_RegisterBits sob_bit =
Adafruit_BusIO_RegisterBits(&control_reg, 1, 11); Adafruit_BusIO_RegisterBits(&control_reg, 1, 11);
@ -134,8 +139,8 @@ bool Adafruit_MLX90632::startFullMeasurement() {
* @return True if write succeeded, false otherwise * @return True if write succeeded, false otherwise
*/ */
bool Adafruit_MLX90632::setMode(mlx90632_mode_t mode) { bool Adafruit_MLX90632::setMode(mlx90632_mode_t mode) {
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits mode_bits = Adafruit_BusIO_RegisterBits mode_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 2, 1); Adafruit_BusIO_RegisterBits(&control_reg, 2, 1);
@ -147,8 +152,8 @@ bool Adafruit_MLX90632::setMode(mlx90632_mode_t mode) {
* @return The current measurement mode * @return The current measurement mode
*/ */
mlx90632_mode_t Adafruit_MLX90632::getMode() { mlx90632_mode_t Adafruit_MLX90632::getMode() {
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits mode_bits = Adafruit_BusIO_RegisterBits mode_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 2, 1); Adafruit_BusIO_RegisterBits(&control_reg, 2, 1);
@ -160,9 +165,10 @@ mlx90632_mode_t Adafruit_MLX90632::getMode() {
* @param meas_select The measurement select type to set * @param meas_select The measurement select type to set
* @return True if write succeeded, false otherwise * @return True if write succeeded, false otherwise
*/ */
bool Adafruit_MLX90632::setMeasurementSelect(mlx90632_meas_select_t meas_select) { bool Adafruit_MLX90632::setMeasurementSelect(
Adafruit_BusIO_Register control_reg = mlx90632_meas_select_t meas_select) {
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 meas_select_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 5, 4); Adafruit_BusIO_RegisterBits(&control_reg, 5, 4);
@ -174,8 +180,8 @@ bool Adafruit_MLX90632::setMeasurementSelect(mlx90632_meas_select_t meas_select)
* @return The current measurement select type * @return The current measurement select type
*/ */
mlx90632_meas_select_t Adafruit_MLX90632::getMeasurementSelect() { mlx90632_meas_select_t Adafruit_MLX90632::getMeasurementSelect() {
Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register control_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_CONTROL), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits meas_select_bits = Adafruit_BusIO_RegisterBits meas_select_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 5, 4); Adafruit_BusIO_RegisterBits(&control_reg, 5, 4);
@ -187,8 +193,8 @@ mlx90632_meas_select_t Adafruit_MLX90632::getMeasurementSelect() {
* @return True if device is busy, false otherwise * @return True if device is busy, false otherwise
*/ */
bool Adafruit_MLX90632::isBusy() { bool Adafruit_MLX90632::isBusy() {
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits device_busy_bit = Adafruit_BusIO_RegisterBits device_busy_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 10); Adafruit_BusIO_RegisterBits(&status_reg, 1, 10);
@ -200,8 +206,8 @@ bool Adafruit_MLX90632::isBusy() {
* @return True if EEPROM is busy, false otherwise * @return True if EEPROM is busy, false otherwise
*/ */
bool Adafruit_MLX90632::isEEPROMBusy() { bool Adafruit_MLX90632::isEEPROMBusy() {
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits eeprom_busy_bit = Adafruit_BusIO_RegisterBits eeprom_busy_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 9); Adafruit_BusIO_RegisterBits(&status_reg, 1, 9);
@ -230,8 +236,8 @@ bool Adafruit_MLX90632::reset() {
* @return Current cycle position (0-31) * @return Current cycle position (0-31)
*/ */
uint8_t Adafruit_MLX90632::readCyclePosition() { uint8_t Adafruit_MLX90632::readCyclePosition() {
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits cycle_position_bits = Adafruit_BusIO_RegisterBits cycle_position_bits =
Adafruit_BusIO_RegisterBits(&status_reg, 5, 2); Adafruit_BusIO_RegisterBits(&status_reg, 5, 2);
@ -243,8 +249,8 @@ uint8_t Adafruit_MLX90632::readCyclePosition() {
* @return True if write succeeded, false otherwise * @return True if write succeeded, false otherwise
*/ */
bool Adafruit_MLX90632::resetNewData() { bool Adafruit_MLX90632::resetNewData() {
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits new_data_bit = Adafruit_BusIO_RegisterBits new_data_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 0); Adafruit_BusIO_RegisterBits(&status_reg, 1, 0);
@ -256,8 +262,8 @@ bool Adafruit_MLX90632::resetNewData() {
* @return True if new data is available, false otherwise * @return True if new data is available, false otherwise
*/ */
bool Adafruit_MLX90632::isNewData() { bool Adafruit_MLX90632::isNewData() {
Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register status_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_STATUS), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits new_data_bit = Adafruit_BusIO_RegisterBits new_data_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 0); Adafruit_BusIO_RegisterBits(&status_reg, 1, 0);
@ -271,8 +277,8 @@ bool Adafruit_MLX90632::isNewData() {
*/ */
bool Adafruit_MLX90632::setRefreshRate(mlx90632_refresh_rate_t refresh_rate) { bool Adafruit_MLX90632::setRefreshRate(mlx90632_refresh_rate_t refresh_rate) {
// Set refresh rate in EE_MEAS_1 register (bits 10:8) // Set refresh rate in EE_MEAS_1 register (bits 10:8)
Adafruit_BusIO_Register meas1_reg = Adafruit_BusIO_Register meas1_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_1), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_1), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits meas1_refresh_bits = Adafruit_BusIO_RegisterBits meas1_refresh_bits =
Adafruit_BusIO_RegisterBits(&meas1_reg, 3, 8); Adafruit_BusIO_RegisterBits(&meas1_reg, 3, 8);
@ -281,8 +287,8 @@ bool Adafruit_MLX90632::setRefreshRate(mlx90632_refresh_rate_t refresh_rate) {
} }
// Set refresh rate in EE_MEAS_2 register (bits 10:8) // Set refresh rate in EE_MEAS_2 register (bits 10:8)
Adafruit_BusIO_Register meas2_reg = Adafruit_BusIO_Register meas2_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_2), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_2), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits meas2_refresh_bits = Adafruit_BusIO_RegisterBits meas2_refresh_bits =
Adafruit_BusIO_RegisterBits(&meas2_reg, 3, 8); Adafruit_BusIO_RegisterBits(&meas2_reg, 3, 8);
@ -294,8 +300,8 @@ bool Adafruit_MLX90632::setRefreshRate(mlx90632_refresh_rate_t refresh_rate) {
* @return The current refresh rate * @return The current refresh rate
*/ */
mlx90632_refresh_rate_t Adafruit_MLX90632::getRefreshRate() { mlx90632_refresh_rate_t Adafruit_MLX90632::getRefreshRate() {
Adafruit_BusIO_Register meas1_reg = Adafruit_BusIO_Register meas1_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_1), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_MEAS_1), 2, MSBFIRST, 2);
Adafruit_BusIO_RegisterBits meas1_refresh_bits = Adafruit_BusIO_RegisterBits meas1_refresh_bits =
Adafruit_BusIO_RegisterBits(&meas1_reg, 3, 8); Adafruit_BusIO_RegisterBits(&meas1_reg, 3, 8);
@ -344,68 +350,90 @@ bool Adafruit_MLX90632::getCalibrations() {
uint32_t ee_ga = read32BitRegister(MLX90632_REG_EE_GA_LSW); uint32_t ee_ga = read32BitRegister(MLX90632_REG_EE_GA_LSW);
// Read 16-bit calibration constants // Read 16-bit calibration constants
Adafruit_BusIO_Register gb_reg = Adafruit_BusIO_Register gb_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_GB), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_GB), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ka_reg = Adafruit_BusIO_Register ka_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_KA), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_KA), 2, MSBFIRST, 2);
Adafruit_BusIO_Register kb_reg = Adafruit_BusIO_Register kb_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_KB), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_KB), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ha_reg = Adafruit_BusIO_Register ha_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_HA), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_HA), 2, MSBFIRST, 2);
Adafruit_BusIO_Register hb_reg = Adafruit_BusIO_Register hb_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_EE_HB), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_EE_HB), 2, MSBFIRST, 2);
// Convert to proper double values with scaling factors from datasheet // 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_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_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_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 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 Aa = (double)(int32_t)ee_aa * (double)pow(2, -16); // 2^-16
Ab = (double)(int32_t)ee_ab * (double)pow(2, -8); // 2^-8 Ab = (double)(int32_t)ee_ab * (double)pow(2, -8); // 2^-8
Ba = (double)(int32_t)ee_ba * (double)pow(2, -16); // 2^-16 Ba = (double)(int32_t)ee_ba * (double)pow(2, -16); // 2^-16
Bb = (double)(int32_t)ee_bb * (double)pow(2, -8); // 2^-8 Bb = (double)(int32_t)ee_bb * (double)pow(2, -8); // 2^-8
Ca = (double)(int32_t)ee_ca * (double)pow(2, -16); // 2^-16 Ca = (double)(int32_t)ee_ca * (double)pow(2, -16); // 2^-16
Cb = (double)(int32_t)ee_cb * (double)pow(2, -8); // 2^-8 Cb = (double)(int32_t)ee_cb * (double)pow(2, -8); // 2^-8
Da = (double)(int32_t)ee_da * (double)pow(2, -16); // 2^-16 Da = (double)(int32_t)ee_da * (double)pow(2, -16); // 2^-16
Db = (double)(int32_t)ee_db * (double)pow(2, -8); // 2^-8 Db = (double)(int32_t)ee_db * (double)pow(2, -8); // 2^-8
Ea = (double)(int32_t)ee_ea * (double)pow(2, -16); // 2^-16 Ea = (double)(int32_t)ee_ea * (double)pow(2, -16); // 2^-16
Eb = (double)(int32_t)ee_eb * (double)pow(2, -8); // 2^-8 Eb = (double)(int32_t)ee_eb * (double)pow(2, -8); // 2^-8
Fa = (double)(int32_t)ee_fa * (double)pow(2, -46); // 2^-46 Fa = (double)(int32_t)ee_fa * (double)pow(2, -46); // 2^-46
Fb = (double)(int32_t)ee_fb * (double)pow(2, -36); // 2^-36 Fb = (double)(int32_t)ee_fb * (double)pow(2, -36); // 2^-36
Ga = (double)(int32_t)ee_ga * (double)pow(2, -36); // 2^-36 Ga = (double)(int32_t)ee_ga * (double)pow(2, -36); // 2^-36
// 16-bit signed values with scaling // 16-bit signed values with scaling
Gb = (double)(int16_t)gb_reg.read() * (double)pow(2, -10); // 2^-10 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 Ka = (double)(int16_t)ka_reg.read() * (double)pow(2, -10); // 2^-10
Kb = (int16_t)kb_reg.read(); // No scaling Kb = (int16_t)kb_reg.read(); // No scaling
Ha = (double)(int16_t)ha_reg.read() * (double)pow(2, -14); // 2^-14 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 Hb = (double)(int16_t)hb_reg.read() * (double)pow(2, -10); // 2^-10
#ifdef MLX90632_DEBUG #ifdef MLX90632_DEBUG
// Debug: Print calibration constants // Debug: Print calibration constants
Serial.println(F("Calibration constants:")); Serial.println(F("Calibration constants:"));
Serial.print(F(" P_R = ")); Serial.println(P_R, 8); Serial.print(F(" P_R = "));
Serial.print(F(" P_G = ")); Serial.println(P_G, 8); Serial.println(P_R, 8);
Serial.print(F(" P_T = ")); Serial.println(P_T, 12); Serial.print(F(" P_G = "));
Serial.print(F(" P_O = ")); Serial.println(P_O, 8); Serial.println(P_G, 8);
Serial.print(F(" Aa = ")); Serial.println(Aa, 8); Serial.print(F(" P_T = "));
Serial.print(F(" Ab = ")); Serial.println(Ab, 8); Serial.println(P_T, 12);
Serial.print(F(" Ba = ")); Serial.println(Ba, 8); Serial.print(F(" P_O = "));
Serial.print(F(" Bb = ")); Serial.println(Bb, 8); Serial.println(P_O, 8);
Serial.print(F(" Ca = ")); Serial.println(Ca, 8); Serial.print(F(" Aa = "));
Serial.print(F(" Cb = ")); Serial.println(Cb, 8); Serial.println(Aa, 8);
Serial.print(F(" Da = ")); Serial.println(Da, 8); Serial.print(F(" Ab = "));
Serial.print(F(" Db = ")); Serial.println(Db, 8); Serial.println(Ab, 8);
Serial.print(F(" Ea = ")); Serial.println(Ea, 8); Serial.print(F(" Ba = "));
Serial.print(F(" Eb = ")); Serial.println(Eb, 8); Serial.println(Ba, 8);
Serial.print(F(" Fa = ")); Serial.println(Fa, 12); Serial.print(F(" Bb = "));
Serial.print(F(" Fb = ")); Serial.println(Fb, 10); Serial.println(Bb, 8);
Serial.print(F(" Ga = ")); Serial.println(Ga, 10); Serial.print(F(" Ca = "));
Serial.print(F(" Gb = ")); Serial.println(Gb, 8); Serial.println(Ca, 8);
Serial.print(F(" Ka = ")); Serial.println(Ka, 8); Serial.print(F(" Cb = "));
Serial.print(F(" Kb = ")); Serial.println(Kb); Serial.println(Cb, 8);
Serial.print(F(" Ha = ")); Serial.println(Ha, 8); Serial.print(F(" Da = "));
Serial.print(F(" Hb = ")); Serial.println(Hb, 8); 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 #endif
return true; return true;
@ -423,19 +451,19 @@ double Adafruit_MLX90632::getAmbientTemperature() {
if (meas_mode == MLX90632_MEAS_EXTENDED_RANGE) { if (meas_mode == MLX90632_MEAS_EXTENDED_RANGE) {
// Extended range mode: use RAM_54 and RAM_57 // Extended range mode: use RAM_54 and RAM_57
Adafruit_BusIO_Register ram54_reg = Adafruit_BusIO_Register ram54_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_54), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_54), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram57_reg = Adafruit_BusIO_Register ram57_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_57), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_57), 2, MSBFIRST, 2);
ram_ambient = (int16_t)ram54_reg.read(); ram_ambient = (int16_t)ram54_reg.read();
ram_ref = (int16_t)ram57_reg.read(); ram_ref = (int16_t)ram57_reg.read();
} else { } else {
// Medical mode: use RAM_6 and RAM_9 (default) // Medical mode: use RAM_6 and RAM_9 (default)
Adafruit_BusIO_Register ram6_reg = Adafruit_BusIO_Register ram6_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_6), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_6), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram9_reg = Adafruit_BusIO_Register ram9_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_9), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_9), 2, MSBFIRST, 2);
ram_ambient = (int16_t)ram6_reg.read(); ram_ambient = (int16_t)ram6_reg.read();
ram_ref = (int16_t)ram9_reg.read(); ram_ref = (int16_t)ram9_reg.read();
@ -452,14 +480,23 @@ double Adafruit_MLX90632::getAmbientTemperature() {
#ifdef MLX90632_DEBUG #ifdef MLX90632_DEBUG
// Debug output // Debug output
Serial.print(F(" Mode = ")); Serial.println(meas_mode == MLX90632_MEAS_EXTENDED_RANGE ? F("Extended") : F("Medical")); Serial.print(F(" Mode = "));
Serial.print(F(" RAM_ambient = ")); Serial.println(ram_ambient); Serial.println(meas_mode == MLX90632_MEAS_EXTENDED_RANGE ? F("Extended")
Serial.print(F(" RAM_ref = ")); Serial.println(ram_ref); : F("Medical"));
Serial.print(F(" Gb = ")); Serial.println(Gb, 8); Serial.print(F(" RAM_ambient = "));
Serial.print(F(" VRTA = ")); Serial.println(VRTA, 8); Serial.println(ram_ambient);
Serial.print(F(" AMB = ")); Serial.println(AMB, 8); Serial.print(F(" RAM_ref = "));
Serial.print(F(" AMB - P_R = ")); Serial.println(amb_diff, 8); Serial.println(ram_ref);
Serial.print(F(" Ambient Temp = ")); Serial.println(ambient_temp, 8); 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 #endif
return ambient_temp; return ambient_temp;
@ -467,7 +504,8 @@ double Adafruit_MLX90632::getAmbientTemperature() {
/*! /*!
* @brief Calculate object temperature * @brief Calculate object temperature
* @return Object temperature in degrees Celsius or NaN if invalid cycle position * @return Object temperature in degrees Celsius or NaN if invalid cycle
* position
*/ */
double Adafruit_MLX90632::getObjectTemperature() { double Adafruit_MLX90632::getObjectTemperature() {
// Check measurement mode to determine which calculation to use // Check measurement mode to determine which calculation to use
@ -478,22 +516,22 @@ double Adafruit_MLX90632::getObjectTemperature() {
if (meas_mode == MLX90632_MEAS_EXTENDED_RANGE) { if (meas_mode == MLX90632_MEAS_EXTENDED_RANGE) {
// Extended range mode: use RAM_52-59 // Extended range mode: use RAM_52-59
Adafruit_BusIO_Register ram52_reg = Adafruit_BusIO_Register ram52_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_52), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_52), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram53_reg = Adafruit_BusIO_Register ram53_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_53), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_53), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram54_reg = Adafruit_BusIO_Register ram54_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_54), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_54), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram55_reg = Adafruit_BusIO_Register ram55_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_55), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_55), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram56_reg = Adafruit_BusIO_Register ram56_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_56), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_56), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram57_reg = Adafruit_BusIO_Register ram57_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_57), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_57), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram58_reg = Adafruit_BusIO_Register ram58_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_58), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_58), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram59_reg = Adafruit_BusIO_Register ram59_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_59), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_59), 2, MSBFIRST, 2);
int16_t ram52 = (int16_t)ram52_reg.read(); int16_t ram52 = (int16_t)ram52_reg.read();
int16_t ram53 = (int16_t)ram53_reg.read(); int16_t ram53 = (int16_t)ram53_reg.read();
@ -505,7 +543,8 @@ double Adafruit_MLX90632::getObjectTemperature() {
int16_t ram59 = (int16_t)ram59_reg.read(); int16_t ram59 = (int16_t)ram59_reg.read();
// Extended range S calculation // Extended range S calculation
S = ((double)ram52 - (double)ram53 - (double)ram55 + (double)ram56) / 2.0 + (double)ram58 + (double)ram59; S = ((double)ram52 - (double)ram53 - (double)ram55 + (double)ram56) / 2.0 +
(double)ram58 + (double)ram59;
ram_ambient = ram54; ram_ambient = ram54;
ram_ref = ram57; ram_ref = ram57;
@ -513,18 +552,18 @@ double Adafruit_MLX90632::getObjectTemperature() {
// Medical mode: use cycle position and RAM_4-9 // Medical mode: use cycle position and RAM_4-9
uint8_t cycle_pos = readCyclePosition(); uint8_t cycle_pos = readCyclePosition();
Adafruit_BusIO_Register ram4_reg = Adafruit_BusIO_Register ram4_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_4), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_4), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram5_reg = Adafruit_BusIO_Register ram5_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_5), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_5), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram6_reg = Adafruit_BusIO_Register ram6_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_6), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_6), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram7_reg = Adafruit_BusIO_Register ram7_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_7), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_7), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram8_reg = Adafruit_BusIO_Register ram8_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_8), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_8), 2, MSBFIRST, 2);
Adafruit_BusIO_Register ram9_reg = Adafruit_BusIO_Register ram9_reg = Adafruit_BusIO_Register(
Adafruit_BusIO_Register(i2c_dev, swapBytes(MLX90632_REG_RAM_9), 2, MSBFIRST, 2); i2c_dev, swapBytes(MLX90632_REG_RAM_9), 2, MSBFIRST, 2);
int16_t ram4 = (int16_t)ram4_reg.read(); int16_t ram4 = (int16_t)ram4_reg.read();
int16_t ram5 = (int16_t)ram5_reg.read(); int16_t ram5 = (int16_t)ram5_reg.read();
@ -568,29 +607,45 @@ double Adafruit_MLX90632::getObjectTemperature() {
double TODUT = TADUT; double TODUT = TADUT;
// Calculate final object temperature: // Calculate final object temperature:
// TO = pow( STO / (emiss * Fa * Ha * (1 + Ga * (TODUT - TO0) + Fb * (TADUT - TA0))) + TAK^4, 0.25) - 273.15 - Hb // TO = pow( STO / (emiss * Fa * Ha * (1 + Ga * (TODUT - TO0) + Fb * (TADUT -
double denominator = emissivity * Fa * Ha * (1.0 + Ga * (TODUT - TO0) + Fb * (TADUT - TA0)); // 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 TAK4 = pow(TAK, 4);
double TO_K4 = (STO / denominator) + TAK4; double TO_K4 = (STO / denominator) + TAK4;
double TO = pow(TO_K4, 0.25) - 273.15 - Hb; double TO = pow(TO_K4, 0.25) - 273.15 - Hb;
#ifdef MLX90632_DEBUG #ifdef MLX90632_DEBUG
// Debug output // Debug output
Serial.print(F(" Mode = ")); Serial.println(meas_mode == MLX90632_MEAS_EXTENDED_RANGE ? F("Extended") : F("Medical")); Serial.print(F(" Mode = "));
Serial.println(meas_mode == MLX90632_MEAS_EXTENDED_RANGE ? F("Extended")
: F("Medical"));
if (meas_mode == MLX90632_MEAS_MEDICAL) { if (meas_mode == MLX90632_MEAS_MEDICAL) {
Serial.print(F(" Cycle Position = ")); Serial.println(readCyclePosition()); Serial.print(F(" Cycle Position = "));
Serial.println(readCyclePosition());
} }
Serial.print(F(" RAM_ambient = ")); Serial.println(ram_ambient); Serial.print(F(" RAM_ambient = "));
Serial.print(F(" RAM_ref = ")); Serial.println(ram_ref); Serial.println(ram_ambient);
Serial.print(F(" S = ")); Serial.println(S, 8); Serial.print(F(" RAM_ref = "));
Serial.print(F(" Ka = ")); Serial.println(Ka, 8); Serial.println(ram_ref);
Serial.print(F(" VRTO = ")); Serial.println(VRTO, 8); Serial.print(F(" S = "));
Serial.print(F(" STO = ")); Serial.println(STO, 8); Serial.println(S, 8);
Serial.print(F(" VRTA = ")); Serial.println(VRTA, 8); Serial.print(F(" Ka = "));
Serial.print(F(" AMB = ")); Serial.println(AMB, 8); Serial.println(Ka, 8);
Serial.print(F(" TADUT = ")); Serial.println(TADUT, 8); Serial.print(F(" VRTO = "));
Serial.print(F(" TODUT = ")); Serial.println(TODUT, 8); Serial.println(VRTO, 8);
Serial.print(F(" TAK = ")); Serial.println(TAK, 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 = ")); Serial.print(F(" TAK^4 = "));
if (TAK4 >= 1e9) { if (TAK4 >= 1e9) {
Serial.print(TAK4 / 1e9, 2); Serial.print(TAK4 / 1e9, 2);
@ -601,10 +656,14 @@ double Adafruit_MLX90632::getObjectTemperature() {
} else { } else {
Serial.println(TAK4, 2); Serial.println(TAK4, 2);
} }
Serial.print(F(" TO0 = ")); Serial.println(TO0, 8); Serial.print(F(" TO0 = "));
Serial.print(F(" TA0 = ")); Serial.println(TA0, 8); Serial.println(TO0, 8);
Serial.print(F(" Emissivity = ")); Serial.println(emissivity, 8); Serial.print(F(" TA0 = "));
Serial.print(F(" Denominator = ")); Serial.println(denominator, 8); 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 = ")); Serial.print(F(" TO_K^4 = "));
if (TO_K4 >= 1e9) { if (TO_K4 >= 1e9) {
Serial.print(TO_K4 / 1e9, 2); Serial.print(TO_K4 / 1e9, 2);
@ -615,12 +674,13 @@ double Adafruit_MLX90632::getObjectTemperature() {
} else { } else {
Serial.println(TO_K4, 2); Serial.println(TO_K4, 2);
} }
Serial.print(F(" TO = ")); Serial.println(TO, 8); Serial.print(F(" TO = "));
Serial.println(TO, 8);
#endif #endif
// Update TO0 and TA0 with current measurements for next calculation // Update TO0 and TA0 with current measurements for next calculation
TO0 = TO; // Use calculated object temperature TO0 = TO; // Use calculated object temperature
TA0 = TADUT; // Update with current ambient temperature calculation TA0 = TADUT; // Update with current ambient temperature calculation
return TO; return TO;
} }

View file

@ -16,11 +16,12 @@
#ifndef _ADAFRUIT_MLX90632_H #ifndef _ADAFRUIT_MLX90632_H
#define _ADAFRUIT_MLX90632_H #define _ADAFRUIT_MLX90632_H
#include "Arduino.h"
#include <Adafruit_BusIO_Register.h> #include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h> #include <Adafruit_I2CDevice.h>
#include <Wire.h> #include <Wire.h>
#include "Arduino.h"
/*========================================================================= /*=========================================================================
I2C ADDRESS/BITS I2C ADDRESS/BITS
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
@ -31,85 +32,120 @@
REGISTERS REGISTERS
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
// EEPROM addresses // EEPROM addresses
#define MLX90632_REG_MELEXIS_RESERVED0 0x2400 ///< Melexis reserved #define MLX90632_REG_MELEXIS_RESERVED0 0x2400 ///< Melexis reserved
#define MLX90632_REG_MELEXIS_RESERVED1 0x2401 ///< Melexis reserved #define MLX90632_REG_MELEXIS_RESERVED1 0x2401 ///< Melexis reserved
#define MLX90632_REG_MELEXIS_RESERVED2 0x2402 ///< Melexis reserved #define MLX90632_REG_MELEXIS_RESERVED2 0x2402 ///< Melexis reserved
#define MLX90632_REG_MELEXIS_RESERVED3 0x2403 ///< Melexis reserved #define MLX90632_REG_MELEXIS_RESERVED3 0x2403 ///< Melexis reserved
#define MLX90632_REG_MELEXIS_RESERVED4 0x2404 ///< Melexis reserved #define MLX90632_REG_MELEXIS_RESERVED4 0x2404 ///< Melexis reserved
#define MLX90632_REG_ID0 0x2405 ///< Chip ID #define MLX90632_REG_ID0 0x2405 ///< Chip ID
#define MLX90632_REG_ID1 0x2406 ///< Chip ID #define MLX90632_REG_ID1 0x2406 ///< Chip ID
#define MLX90632_REG_ID2 0x2407 ///< Chip ID #define MLX90632_REG_ID2 0x2407 ///< Chip ID
#define MLX90632_REG_ID_CRC16 0x2408 ///< CRC #define MLX90632_REG_ID_CRC16 0x2408 ///< CRC
#define MLX90632_REG_EE_PRODUCT_CODE 0x2409 ///< Sensor information #define MLX90632_REG_EE_PRODUCT_CODE 0x2409 ///< Sensor information
#define MLX90632_REG_MELEXIS_RESERVED10 0x240A ///< Melexis reserved #define MLX90632_REG_MELEXIS_RESERVED10 0x240A ///< Melexis reserved
#define MLX90632_REG_EE_VERSION 0x240B ///< EEPROM version #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_LSW \
#define MLX90632_REG_EE_P_R_MSW 0x240D ///< P_R calibration constant (16-bit, Most Significant Word) 0x240C ///< P_R calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_P_G_LSW 0x240E ///< P_G calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_P_R_MSW \
#define MLX90632_REG_EE_P_G_MSW 0x240F ///< P_G calibration constant (16-bit, Most Significant Word) 0x240D ///< P_R 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_G_LSW \
#define MLX90632_REG_EE_P_T_MSW 0x2411 ///< P_T calibration constant (16-bit, Most Significant Word) 0x240E ///< P_G calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_P_O_LSW 0x2412 ///< P_O calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_P_G_MSW \
#define MLX90632_REG_EE_P_O_MSW 0x2413 ///< P_O calibration constant (16-bit, Most Significant Word) 0x240F ///< P_G 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_P_T_LSW \
#define MLX90632_REG_EE_AA_MSW 0x2415 ///< Aa calibration constant (16-bit, Most Significant Word) 0x2410 ///< P_T calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_AB_LSW 0x2416 ///< Ab calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_P_T_MSW \
#define MLX90632_REG_EE_AB_MSW 0x2417 ///< Ab calibration constant (16-bit, Most Significant Word) 0x2411 ///< P_T 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_P_O_LSW \
#define MLX90632_REG_EE_BA_MSW 0x2419 ///< Ba calibration constant (16-bit, Most Significant Word) 0x2412 ///< P_O calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_BB_LSW 0x241A ///< Bb calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_P_O_MSW \
#define MLX90632_REG_EE_BB_MSW 0x241B ///< Bb calibration constant (16-bit, Most Significant Word) 0x2413 ///< P_O 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_AA_LSW \
#define MLX90632_REG_EE_CA_MSW 0x241D ///< Ca calibration constant (16-bit, Most Significant Word) 0x2414 ///< Aa calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_CB_LSW 0x241E ///< Cb calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_AA_MSW \
#define MLX90632_REG_EE_CB_MSW 0x241F ///< Cb calibration constant (16-bit, Most Significant Word) 0x2415 ///< Aa 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_AB_LSW \
#define MLX90632_REG_EE_DA_MSW 0x2421 ///< Da calibration constant (16-bit, Most Significant Word) 0x2416 ///< Ab calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_DB_LSW 0x2422 ///< Db calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_AB_MSW \
#define MLX90632_REG_EE_DB_MSW 0x2423 ///< Db calibration constant (16-bit, Most Significant Word) 0x2417 ///< Ab 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_BA_LSW \
#define MLX90632_REG_EE_EA_MSW 0x2425 ///< Ea calibration constant (16-bit, Most Significant Word) 0x2418 ///< Ba calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_EB_LSW 0x2426 ///< Eb calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_BA_MSW \
#define MLX90632_REG_EE_EB_MSW 0x2427 ///< Eb calibration constant (16-bit, Most Significant Word) 0x2419 ///< Ba 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_BB_LSW \
#define MLX90632_REG_EE_FA_MSW 0x2429 ///< Fa calibration constant (16-bit, Most Significant Word) 0x241A ///< Bb calibration constant (16-bit, Least Significant Word)
#define MLX90632_REG_EE_FB_LSW 0x242A ///< Fb calibration constant (16-bit, Least Significant Word) #define MLX90632_REG_EE_BB_MSW \
#define MLX90632_REG_EE_FB_MSW 0x242B ///< Fb calibration constant (16-bit, Most Significant Word) 0x241B ///< Bb 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_CA_LSW \
#define MLX90632_REG_EE_GA_MSW 0x242D ///< Ga calibration constant (16-bit, Most Significant Word) 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_GB 0x242E ///< Gb calibration constant (16-bit)
#define MLX90632_REG_EE_KA 0x242F ///< Ka 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_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_RESERVED127 0x247F ///< Melexis reserved
#define MLX90632_REG_MELEXIS_RESERVED128 0x2480 ///< 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_HA 0x2481 ///< Ha Customer calibration constant (16 bit)
#define MLX90632_REG_EE_HB 0x2482 ///< Hb 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_MELEXIS_RESERVED131 0x2483 ///< Melexis reserved
#define MLX90632_REG_CUSTOMER_DATA_START 0x24C0 ///< Customer data start #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_MELEXIS_RESERVED208 0x24D0 ///< Melexis reserved
#define MLX90632_REG_EE_CONTROL 0x24D4 ///< EEPROM Control register, measurement control #define MLX90632_REG_EE_CONTROL \
#define MLX90632_REG_EE_I2C_ADDRESS 0x24D5 ///< I2C slave address >> 1 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_MELEXIS_RESERVED214 0x24D6 ///< Melexis reserved
#define MLX90632_REG_EE_MEAS_1 0x24E1 ///< Measurement settings 1 #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_2 0x24E2 ///< Measurement settings 2
// Control and Status registers // Control and Status registers
#define MLX90632_REG_I2C_ADDRESS 0x3000 ///< I2C slave address >> 1 #define MLX90632_REG_I2C_ADDRESS 0x3000 ///< I2C slave address >> 1
#define MLX90632_REG_CONTROL 0x3001 ///< Control register, measurement mode #define MLX90632_REG_CONTROL 0x3001 ///< Control register, measurement mode
#define MLX90632_REG_STATUS 0x3FFF ///< Status register: data available #define MLX90632_REG_STATUS 0x3FFF ///< Status register: data available
// RAM addresses // RAM addresses
#define MLX90632_REG_RAM_1 0x4000 ///< Raw data 1 #define MLX90632_REG_RAM_1 0x4000 ///< Raw data 1
#define MLX90632_REG_RAM_2 0x4001 ///< Raw data 2 #define MLX90632_REG_RAM_2 0x4001 ///< Raw data 2
#define MLX90632_REG_RAM_3 0x4002 ///< Raw data 3 #define MLX90632_REG_RAM_3 0x4002 ///< Raw data 3
#define MLX90632_REG_RAM_4 0x4003 ///< Raw data 4 #define MLX90632_REG_RAM_4 0x4003 ///< Raw data 4
#define MLX90632_REG_RAM_5 0x4004 ///< Raw data 5 #define MLX90632_REG_RAM_5 0x4004 ///< Raw data 5
#define MLX90632_REG_RAM_6 0x4005 ///< Raw data 6 #define MLX90632_REG_RAM_6 0x4005 ///< Raw data 6
#define MLX90632_REG_RAM_7 0x4006 ///< Raw data 7 #define MLX90632_REG_RAM_7 0x4006 ///< Raw data 7
#define MLX90632_REG_RAM_8 0x4007 ///< Raw data 8 #define MLX90632_REG_RAM_8 0x4007 ///< Raw data 8
#define MLX90632_REG_RAM_9 0x4008 ///< Raw data 9 #define MLX90632_REG_RAM_9 0x4008 ///< Raw data 9
#define MLX90632_REG_RAM_52 0x4033 ///< Raw data 52 #define MLX90632_REG_RAM_52 0x4033 ///< Raw data 52
#define MLX90632_REG_RAM_53 0x4034 ///< Raw data 53 #define MLX90632_REG_RAM_53 0x4034 ///< Raw data 53
#define MLX90632_REG_RAM_54 0x4035 ///< Raw data 54 #define MLX90632_REG_RAM_54 0x4035 ///< Raw data 54
@ -128,32 +164,32 @@
* @brief MLX90632 measurement modes * @brief MLX90632 measurement modes
*/ */
typedef enum { typedef enum {
MLX90632_MODE_HALT = 0x00, ///< Halt mode for EEPROM operations MLX90632_MODE_HALT = 0x00, ///< Halt mode for EEPROM operations
MLX90632_MODE_SLEEPING_STEP = 0x01, ///< Sleeping step mode MLX90632_MODE_SLEEPING_STEP = 0x01, ///< Sleeping step mode
MLX90632_MODE_STEP = 0x02, ///< Step mode MLX90632_MODE_STEP = 0x02, ///< Step mode
MLX90632_MODE_CONTINUOUS = 0x03 ///< Continuous mode MLX90632_MODE_CONTINUOUS = 0x03 ///< Continuous mode
} mlx90632_mode_t; } mlx90632_mode_t;
/*! /*!
* @brief MLX90632 measurement types * @brief MLX90632 measurement types
*/ */
typedef enum { typedef enum {
MLX90632_MEAS_MEDICAL = 0x00, ///< Medical measurement MLX90632_MEAS_MEDICAL = 0x00, ///< Medical measurement
MLX90632_MEAS_EXTENDED_RANGE = 0x11 ///< Extended range measurement MLX90632_MEAS_EXTENDED_RANGE = 0x11 ///< Extended range measurement
} mlx90632_meas_select_t; } mlx90632_meas_select_t;
/*! /*!
* @brief MLX90632 refresh rates * @brief MLX90632 refresh rates
*/ */
typedef enum { typedef enum {
MLX90632_REFRESH_0_5HZ = 0, ///< 0.5 Hz (2000ms) MLX90632_REFRESH_0_5HZ = 0, ///< 0.5 Hz (2000ms)
MLX90632_REFRESH_1HZ = 1, ///< 1 Hz (1000ms) MLX90632_REFRESH_1HZ = 1, ///< 1 Hz (1000ms)
MLX90632_REFRESH_2HZ = 2, ///< 2 Hz (500ms) MLX90632_REFRESH_2HZ = 2, ///< 2 Hz (500ms)
MLX90632_REFRESH_4HZ = 3, ///< 4 Hz (250ms) MLX90632_REFRESH_4HZ = 3, ///< 4 Hz (250ms)
MLX90632_REFRESH_8HZ = 4, ///< 8 Hz (125ms) MLX90632_REFRESH_8HZ = 4, ///< 8 Hz (125ms)
MLX90632_REFRESH_16HZ = 5, ///< 16 Hz (62.5ms) MLX90632_REFRESH_16HZ = 5, ///< 16 Hz (62.5ms)
MLX90632_REFRESH_32HZ = 6, ///< 32 Hz (31.25ms) MLX90632_REFRESH_32HZ = 6, ///< 32 Hz (31.25ms)
MLX90632_REFRESH_64HZ = 7 ///< 64 Hz (15.625ms) MLX90632_REFRESH_64HZ = 7 ///< 64 Hz (15.625ms)
} mlx90632_refresh_rate_t; } mlx90632_refresh_rate_t;
/*=========================================================================*/ /*=========================================================================*/
@ -162,10 +198,10 @@ typedef enum {
* MLX90632 Far Infrared Temperature Sensor * MLX90632 Far Infrared Temperature Sensor
*/ */
class Adafruit_MLX90632 { class Adafruit_MLX90632 {
public: public:
Adafruit_MLX90632(); Adafruit_MLX90632();
~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(); uint64_t getProductID();
uint16_t getProductCode(); uint16_t getProductCode();
uint16_t getEEPROMVersion(); uint16_t getEEPROMVersion();
@ -187,38 +223,40 @@ public:
double getAmbientTemperature(); double getAmbientTemperature();
double getObjectTemperature(); double getObjectTemperature();
private: private:
Adafruit_I2CDevice *i2c_dev; ///< Pointer to I2C bus interface Adafruit_I2CDevice* i2c_dev; ///< Pointer to I2C bus interface
uint16_t swapBytes(uint16_t value); ///< Byte swap helper for register addresses uint16_t swapBytes(
uint32_t read32BitRegister(uint16_t lsw_addr); ///< Helper to read 32-bit values uint16_t value); ///< Byte swap helper for register addresses
uint32_t read32BitRegister(
uint16_t lsw_addr); ///< Helper to read 32-bit values
// Calibration constants // Calibration constants
double P_R; ///< P_R calibration constant double P_R; ///< P_R calibration constant
double P_G; ///< P_G calibration constant double P_G; ///< P_G calibration constant
double P_T; ///< P_T calibration constant double P_T; ///< P_T calibration constant
double P_O; ///< P_O calibration constant double P_O; ///< P_O calibration constant
double Aa; ///< Aa calibration constant double Aa; ///< Aa calibration constant
double Ab; ///< Ab calibration constant double Ab; ///< Ab calibration constant
double Ba; ///< Ba calibration constant double Ba; ///< Ba calibration constant
double Bb; ///< Bb calibration constant double Bb; ///< Bb calibration constant
double Ca; ///< Ca calibration constant double Ca; ///< Ca calibration constant
double Cb; ///< Cb calibration constant double Cb; ///< Cb calibration constant
double Da; ///< Da calibration constant double Da; ///< Da calibration constant
double Db; ///< Db calibration constant double Db; ///< Db calibration constant
double Ea; ///< Ea calibration constant double Ea; ///< Ea calibration constant
double Eb; ///< Eb calibration constant double Eb; ///< Eb calibration constant
double Fa; ///< Fa calibration constant double Fa; ///< Fa calibration constant
double Fb; ///< Fb calibration constant double Fb; ///< Fb calibration constant
double Ga; ///< Ga calibration constant double Ga; ///< Ga calibration constant
double Gb; ///< Gb calibration constant double Gb; ///< Gb calibration constant
double Ka; ///< Ka calibration constant double Ka; ///< Ka calibration constant
int16_t Kb; ///< Kb calibration constant (16-bit signed) int16_t Kb; ///< Kb calibration constant (16-bit signed)
double Ha; ///< Ha calibration constant double Ha; ///< Ha calibration constant
double Hb; ///< Hb calibration constant double Hb; ///< Hb calibration constant
// Temperature calculation variables // Temperature calculation variables
double TO0; ///< Previous object temperature (starts at 25.0) double TO0; ///< Previous object temperature (starts at 25.0)
double TA0; ///< Previous ambient temperature (starts at 25.0) double TA0; ///< Previous ambient temperature (starts at 25.0)
}; };
#endif #endif

View file

@ -56,10 +56,12 @@ void setup() {
Serial.println(F("Unknown")); Serial.println(F("Unknown"));
} }
// Set and get mode (continuous) // Set and get mode - choose one:
Serial.println(F("\n--- Mode Settings ---")); Serial.println(F("\n--- Mode Settings ---"));
if (!mlx.setMode(MLX90632_MODE_CONTINUOUS)) { if (!mlx.setMode(MLX90632_MODE_CONTINUOUS)) {
Serial.println(F("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); } while (1) { delay(10); }
} }
@ -140,14 +142,6 @@ void setup() {
Serial.println(F("Unknown")); Serial.println(F("Unknown"));
} }
// Load calibration constants
Serial.println(F("\n--- Calibration Constants ---"));
if (!mlx.getCalibrations()) {
Serial.println(F("Failed to load calibration constants"));
while (1) { delay(10); }
}
Serial.println(F("Calibration constants loaded successfully"));
// Clear new data flag before starting continuous measurements // Clear new data flag before starting continuous measurements
Serial.println(F("\\n--- Starting Continuous Measurements ---")); Serial.println(F("\\n--- Starting Continuous Measurements ---"));
if (!mlx.resetNewData()) { if (!mlx.resetNewData()) {
@ -187,6 +181,15 @@ void loop() {
Serial.println(); // Add blank line between readings Serial.println(); // Add blank line between readings
} }
// 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 // Small delay to prevent overwhelming the I2C bus
delay(10); delay(10);
} }