这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享开发笔记,赚取电动螺丝刀】迈来芯热成像传感器新品MLX90642到手把玩—

共2条 1/1 1 跳转至

【分享开发笔记,赚取电动螺丝刀】迈来芯热成像传感器新品MLX90642到手把玩——驱动

助工
2025-08-11 09:45:48     打赏

使用3D打印,制作了个外壳。把板子和芯片包裹起来。接口使用GROVE接口。

image.png

image.png

拿到芯片之前,想着这个MLX90642应该和他的前辈MLX90640可以使用同样的驱动代码来驱动,结果试了一下,根本行不通。只能重新写驱动。

第一步:先要确定能够识别到传感器。使用GROVE线,将传感器和单片机连接起来。我这里单片机选用的是M5StickC Plus主控采用ESP32-PICO-D4模组。开发我使用Vscode+platformio。先扫描I2C设备,寻找到传感器。可以看见,单片机成功识别到了传感器,I2C地址为0X66

image.png

image.png

第二步:从官网提供的https://github.com/melexis/mlx90642-library.git下载源码,但是下载的源码并不完整,MLX90642_depends.h文件中定义的方法都没有做实现。参考着readme文件,新建MLX90642_depends.cpp文件,实现了以下几个函数。

#include "MLX90642_depends.h"
#include "MLX90642.h"
#include <Arduino.h>
#include <Wire.h>
// 从I2C总线上读取数据
int MLX90642_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *rData)
{
  uint16_t bytesRemaining = nMemAddressRead * 2;
  uint16_t dataSpot = 0; // Start at beginning of array
  // Setup a series of chunked I2C_BUFFER_LENGTH byte reads
  while (bytesRemaining > 0)
  {
    Wire.beginTransmission(slaveAddr);
    Wire.write(startAddress >> 8);        // MSB
    Wire.write(startAddress & 0xFF);      // LSB
    if (Wire.endTransmission(false) != 0) // Do not release bus
    {
      Serial.println("No ack read");
      return (0); // Sensor did not ACK
    }
 
    uint16_t numberOfBytesToRead = bytesRemaining;
    if (numberOfBytesToRead > I2C_BUFFER_LENGTH)
      numberOfBytesToRead = I2C_BUFFER_LENGTH;
 
    Wire.requestFrom(slaveAddr, (uint8_t)numberOfBytesToRead);
    if (Wire.available())
    {
      for (uint16_t x = 0; x < numberOfBytesToRead / 2; x++)
      {
        // Store data into array
        rData[dataSpot] = Wire.read() << 8; // MSB
        rData[dataSpot] |= Wire.read();     // LSB
        dataSpot++;
      }
    }
    bytesRemaining -= numberOfBytesToRead;
    startAddress += numberOfBytesToRead / 2;
  }
 
  return (0); // Success
}
 
// 指定位置写一个word
int MLX90642_Config(uint8_t slaveAddr, uint16_t writeAddress, uint16_t wData)
{
  Wire.beginTransmission((uint8_t)slaveAddr);
  Wire.write(writeAddress >> 8);   // MSB
  Wire.write(writeAddress & 0xFF); // LSB
  Wire.write(wData >> 8);          // MSB
  Wire.write(wData & 0xFF);        // LSB
  if (Wire.endTransmission() != 0)
  {
    // Sensor did not ACK
    Serial.println("Error: Sensor did not ack");
    return (-1);
  }
 
  uint16_t dataCheck;
  MLX90642_I2CRead(slaveAddr, writeAddress, 2, &dataCheck);
  // Serial.printf("Write:%d  %d\n",dataCheck, wData);
  if (dataCheck != wData)
  {
    // Serial.println("The write request didn't stick");
    return -2;
  }
 
  return (0); // Success
}
int MLX90642_I2CCmd(uint8_t slaveAddr, uint16_t i2c_cmd)
{
  int res;
  switch (i2c_cmd)
  {
  case MLX90642_START_SYNC_MEAS_CMD:
    res = MLX90642_Config(slaveAddr, MLX90642_CMD_OPCODE, i2c_cmd);
    break;
  case MLX90642_SLEEP_CMD:
    Serial.println("come here too");
    res = MLX90642_Config(slaveAddr, MLX90642_CMD_OPCODE, i2c_cmd);
    break;
  default:
    res = -1;
    break;
  }
  Serial.printf("I2CCmd res = %d\n", res);
  return res;
 
}
void MLX90642_Wait_ms(uint16_t time_ms)
{
  delay(time_ms / 1000);
}

然后在setup方法中首先初始化mlx90642,但是这里初始化时,总是有个报错。查看代码应该是:

image.png

查看官方文档,应该是这个设置。

image.png

image.png

但是不明白这里向寄存器写入数据总是出错,卡了好久都没能解决。最后无奈,只能将这段代码的错误屏蔽掉,跳过了这个异步设置的错误,好在对后边读取温度信息没啥影响。

image.png

第三步:初始化完成后,就可以在loop循环中不停地读取传感器的数据矩阵了。mlx90642传感器获得到的温度信息,为一个32x24的数据矩阵。可以看见传感器获得的温度矩阵数据,每个数据都是个整形数据。最后还需要装换为常用的摄氏度。

image.png

第四步:转换数据。

image.png

参考官方文档,将整形转换为摄氏度,使用1位小数输出。

image.png

#include <Arduino.h>
#include <M5StickCPlus.h>
#include <Wire.h>
#include "MLX90642.h"
int status = 0;
static uint16_t s_temp[MLX90642_TOTAL_NUMBER_OF_PIXELS + 1];
void setup()
{
  M5.begin();            // Initialize M5StickC Plus.  初始化 M5StickC PLus
  M5.Lcd.setTextSize(3); // Set font size.  设置字体大小
  M5.Lcd.setRotation(3); // Rotate the screen. 将屏幕旋转
  M5.Lcd.print("Hello World");
  Wire.begin(32, 33); // sda= GPIO_21 /scl= GPIO_22       //外接I2C 和 内部I2C
  delay(8000);
  uint8_t version[3];
  status = MLX90642_GetFWver(SA_90642_DEFAULT, version);
  // 如果status < 0,则处理错误
  Serial.printf("FW version: %d.%d.%d    %d\r\n", version[0], version[1], version[2], status);
  status = MLX90642_SetMeasMode(SA_90642_DEFAULT, MLX90642_STEP_MEAS_MODE);
  Serial.println(status);
  status = MLX90642_Init(SA_90642_DEFAULT);
    // Serial.printf("MLX90642_Init:%d\r\n", status);
  // status = MLX90642_SetRefreshRate(SA_90642_DEFAULT, MLX90642_REF_RATE_2HZ);
  // Serial.printf("MLX90642_SetRefreshRate:%d\r\n", status);
  // status = MLX90642_SetOutputFormat(SA_90642_DEFAULT, MLX90642_TEMPERATURE_OUTPUT);
  // Serial.printf("MLX90642_SetOutputFormat:%d\r\n", status);
  // status = MLX90642_SetI2CLevel(SA_90642_DEFAULT, MLX90642_I2C_LEVEL_VDD);
  // Serial.printf("MLX90642_SetI2CLevel:%d\r\n", status);
  // status = MLX90642_SetSDALimitState(SA_90642_DEFAULT, MLX90642_I2C_SDA_CUR_LIMIT_OFF);
  // Serial.printf("MLX90642_SetSDALimitState:%d\r\n", status);
  // status = MLX90642_SetI2CMode(SA_90642_DEFAULT, MLX90642_I2C_MODE_FM_PLUS);
  // Serial.printf("MLX90642_SetI2CMode:%d\r\n", status);
  // MLX90642_Set_Delay(20ul);
}
 
void loop()
{
  delay(3000);
  status = MLX90642_IsReadWindowOpen(SA_90642_DEFAULT);
  Serial.printf("MLX90642_IsReadWindowOpen:%d\r\n", status);
  status = MLX90642_GetImage(SA_90642_DEFAULT, s_temp);
  Serial.printf("MLX90642_GetImage:%d\r\n", status);
 
  for (uint8_t i = 0; i < 32; i++)
  {
    for(uint8_t j = 0; j < 24; j++){
      Serial.printf("%.1f, ", float(s_temp[i*24+j])/50.00);
      // Serial.printf("%d, ", s_temp[i*24+j]);
    }
    Serial.println("");
  }    
  Serial.println();
}






院士
2025-08-11 15:36:03     打赏
2楼

这颗芯片的可玩度好高啊!



共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]