Add comprehensive MLX90632 control and status register functionality

- Add getProductCode() function with product code decoding
- Add control register functions: startSingleMeasurement(), startFullMeasurement()
- Add mode control: setMode(), getMode() with enum support
- Add measurement select: setMeasurementSelect(), getMeasurementSelect()
- Add status register functions: isBusy(), isEEPROMBusy(), reset()
- Add data monitoring: readCyclePosition(), resetNewData(), isNewData()
- Add measurement mode and type enums (HALT, STEP, CONTINUOUS, MEDICAL, EXTENDED_RANGE)
- Update test sketch with full register testing and status monitoring
- All functions use proper RegisterBits for clean bit manipulation
- All setter functions return bool for I2C write verification

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
ladyada 2025-08-01 14:55:31 -04:00
parent d38f88cb80
commit dfa2379739
3 changed files with 293 additions and 0 deletions

View file

@ -77,6 +77,178 @@ uint64_t Adafruit_MLX90632::getProductID() {
return ((uint64_t)id2 << 32) | ((uint64_t)id1 << 16) | id0;
}
/*!
* @brief Read the product code
* @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);
return product_code_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_RegisterBits soc_bit =
Adafruit_BusIO_RegisterBits(&control_reg, 1, 3);
return soc_bit.write(1);
}
/*!
* @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_RegisterBits sob_bit =
Adafruit_BusIO_RegisterBits(&control_reg, 1, 11);
return sob_bit.write(1);
}
/*!
* @brief Set the measurement mode
* @param mode The measurement mode to set
* @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_RegisterBits mode_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 2, 1);
return mode_bits.write(mode);
}
/*!
* @brief Get the measurement 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_RegisterBits mode_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 2, 1);
return (mlx90632_mode_t)mode_bits.read();
}
/*!
* @brief Set the measurement select type
* @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);
Adafruit_BusIO_RegisterBits meas_select_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 5, 4);
return meas_select_bits.write(meas_select);
}
/*!
* @brief Get the measurement select type
* @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_RegisterBits meas_select_bits =
Adafruit_BusIO_RegisterBits(&control_reg, 5, 4);
return (mlx90632_meas_select_t)meas_select_bits.read();
}
/*!
* @brief Check if device is busy with measurement
* @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_RegisterBits device_busy_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 10);
return device_busy_bit.read();
}
/*!
* @brief Check if EEPROM is busy
* @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_RegisterBits eeprom_busy_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 9);
return eeprom_busy_bit.read();
}
/*!
* @brief Reset device using addressed reset command
* @return True if reset succeeded, false otherwise
*/
bool Adafruit_MLX90632::reset() {
// Send addressed reset command: 0x3005, 0x0006
uint8_t reset_cmd[] = {0x30, 0x05, 0x00, 0x06};
if (!i2c_dev->write(reset_cmd, 4)) {
return false;
}
// Wait for reset to complete (at least 150us as per datasheet)
delay(1);
return true;
}
/*!
* @brief Read the cycle position
* @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_RegisterBits cycle_position_bits =
Adafruit_BusIO_RegisterBits(&status_reg, 5, 2);
return cycle_position_bits.read();
}
/*!
* @brief Reset the new data flag to 0
* @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_RegisterBits new_data_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 0);
return new_data_bit.write(0);
}
/*!
* @brief Check if new data is available
* @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_RegisterBits new_data_bit =
Adafruit_BusIO_RegisterBits(&status_reg, 1, 0);
return new_data_bit.read();
}
/*!
* @brief Byte swap helper for register addresses
* @param value 16-bit value to swap

View file

@ -121,6 +121,28 @@
#define MLX90632_REG_RAM_60 0x403B ///< Raw data 60
/*=========================================================================*/
/*=========================================================================
CONTROL REGISTER ENUMS
-----------------------------------------------------------------------*/
/*!
* @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_t;
/*!
* @brief MLX90632 measurement types
*/
typedef enum {
MLX90632_MEAS_MEDICAL = 0x00, ///< Medical measurement
MLX90632_MEAS_EXTENDED_RANGE = 0x11 ///< Extended range measurement
} mlx90632_meas_select_t;
/*=========================================================================*/
/*!
* @brief Class that stores state and functions for interacting with
* MLX90632 Far Infrared Temperature Sensor
@ -131,6 +153,19 @@ public:
~Adafruit_MLX90632();
bool begin(uint8_t i2c_addr = MLX90632_DEFAULT_ADDR, TwoWire *wire = &Wire);
uint64_t getProductID();
uint16_t getProductCode();
bool startSingleMeasurement();
bool startFullMeasurement();
bool setMode(mlx90632_mode_t mode);
mlx90632_mode_t getMode();
bool setMeasurementSelect(mlx90632_meas_select_t meas_select);
mlx90632_meas_select_t getMeasurementSelect();
bool isBusy();
bool isEEPROMBusy();
bool reset();
uint8_t readCyclePosition();
bool resetNewData();
bool isNewData();
private:
Adafruit_I2CDevice *i2c_dev; ///< Pointer to I2C bus interface

View file

@ -16,12 +16,98 @@ void setup() {
}
Serial.println("MLX90632 Found!");
// Reset the device
if (!mlx.reset()) {
Serial.println("Device reset failed");
while (1) { delay(10); }
}
Serial.println("Device reset: SUCCESS");
uint64_t productID = mlx.getProductID();
Serial.print("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.println(productCode, 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("Package: ");
Serial.println(package == 1 ? "SFN 3x3" : "Unknown");
Serial.print("Accuracy: ");
if (accuracy == 1) {
Serial.println("Medical");
} else if (accuracy == 2) {
Serial.println("Standard");
} else {
Serial.println("Unknown");
}
// Set and get mode (continuous)
Serial.println("\n--- Mode Settings ---");
if (!mlx.setMode(MLX90632_MODE_CONTINUOUS)) {
Serial.println("Failed to set mode to Continuous");
while (1) { delay(10); }
}
mlx90632_mode_t currentMode = mlx.getMode();
Serial.print("Current mode: ");
switch (currentMode) {
case MLX90632_MODE_HALT:
Serial.println("Halt");
break;
case MLX90632_MODE_SLEEPING_STEP:
Serial.println("Sleeping Step");
break;
case MLX90632_MODE_STEP:
Serial.println("Step");
break;
case MLX90632_MODE_CONTINUOUS:
Serial.println("Continuous");
break;
default:
Serial.println("Unknown");
}
// Set and get measurement select (medical)
Serial.println("\n--- Measurement Select Settings ---");
if (!mlx.setMeasurementSelect(MLX90632_MEAS_MEDICAL)) {
Serial.println("Failed to set measurement select to Medical");
while (1) { delay(10); }
}
mlx90632_meas_select_t currentMeasSelect = mlx.getMeasurementSelect();
Serial.print("Current measurement select: ");
switch (currentMeasSelect) {
case MLX90632_MEAS_MEDICAL:
Serial.println("Medical");
break;
case MLX90632_MEAS_EXTENDED_RANGE:
Serial.println("Extended Range");
break;
default:
Serial.println("Unknown");
}
}
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());
delay(500);
}