自制红外热像仪(二) MLX90640移植 RP2040 STM32 ESP32

针对移植,我们首先需要找到相关原厂驱动地址,如下所示:(包含API手册以及驱动程序)

其中的相关内容如下图所示:说明相关驱动层以及应用层的代码

针对于MLX90640_I2C_Driver.h的移植,由于本身不用到MLX90640_I2CGeneralReset这个函数,这个函数的用意是,实现 I2C 总线的标准复位操作,根据 I2C 协议规范,用于重置总线上支持该复位条件的所有设备。

其次就是平台兼容的问题了,为不同硬件平台设置合适的 I2C 缓冲区大小,使得代码可以通用。

避免因为平台硬件特性(如内存大小或 I2C 硬件实现差异)导致的问题。

接着就是MLX90640_I2C_Driver.cpp了硬件IIC,如下所示:(这边仅仅展示读跟写)

cpp 复制代码
//Read a number of words from startAddress. Store into Data array.
//Returns 0 if successful, -1 if error
int MLX90640_I2CRead(uint8_t _deviceAddress, unsigned int startAddress, unsigned int nWordsRead, uint16_t *data)
{

  //Caller passes number of 'unsigned ints to read', increase this to 'bytes to read'
  uint16_t bytesRemaining = nWordsRead * 2;

  //It doesn't look like sequential read works. Do we need to re-issue the address command each time?

  uint16_t dataSpot = 0; //Start at beginning of array

  //Setup a series of chunked I2C_BUFFER_LENGTH byte reads
  while (bytesRemaining > 0)
  {
    Wire.beginTransmission(_deviceAddress);
    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((uint8_t)_deviceAddress, (uint8_t)numberOfBytesToRead);
    if (Wire.available())
    {
      for (uint16_t x = 0 ; x < numberOfBytesToRead / 2; x++)
      {
        //Store data into array
        data[dataSpot] = Wire.read() << 8; //MSB
        data[dataSpot] |= Wire.read(); //LSB

        dataSpot++;
      }
    }

    bytesRemaining -= numberOfBytesToRead;

    startAddress += numberOfBytesToRead / 2;
    
  }

  return (0); //Success
}
  • _deviceAddress: I2C 从设备地址。
  • startAddress: 起始地址,指示从哪里开始读取数据。
  • nWordsRead: 要读取的 16 位数据(uint16_t)数量。
  • data: 存储读取数据的指针(调用者提供的数组)。
  • Wire.beginTransmission(_deviceAddress) 开始与从设备通信。
  • Wire.write(startAddress >> 8)Wire.write(startAddress & 0xFF) 将 16 位起始地址分为高字节和低字节,依次发送。
  • Wire.endTransmission(false) 将命令传输给设备,但不释放总线(false 参数)。
  • 功能: 每次读取的字节数不能超过 I2C 缓冲区的大小(I2C_BUFFER_LENGTH)。
  • 如果剩余的字节数超出缓冲区大小,就读取 I2C_BUFFER_LENGTH,否则读取剩余字节。
  • 使用 Wire.requestFrom 请求指定数量的字节数据。
  • 确保缓冲区中有可用数据(Wire.available())。
  • 将读取的高字节(MSB)和低字节(LSB)组合成一个 16 位数据,存入 data 数组。
cpp 复制代码
//Write two bytes to a two byte address
int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data)
{
  Wire.beginTransmission((uint8_t)_deviceAddress);
  Wire.write(writeAddress >> 8); //MSB
  Wire.write(writeAddress & 0xFF); //LSB
  Wire.write(data >> 8); //MSB
  Wire.write(data & 0xFF); //LSB
  if (Wire.endTransmission() != 0)
  {
    //Sensor did not ACK
    Serial.println("Error: Sensor did not ack");
    return (-1);
  }

  uint16_t dataCheck;
  MLX90640_I2CRead(_deviceAddress, writeAddress, 1, &dataCheck);
  if (dataCheck != data)
  {
    //Serial.println("The write request didn't stick");
    return -2;
  }

追根溯源,其实就是平台API的替换嘛,哪里报错改哪里。

最后就是MLX90640_API.h与MLX90640_API.cpp了,如下所示原厂驱动:

如下是我移植后的,如下所示:

cpp 复制代码
/**
 * @copyright (C) 2017 Melexis N.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#ifndef _MLX640_API_H_
#define _MLX640_API_H_
    
  typedef struct
    {
        int16_t kVdd;
        int16_t vdd25;
        float KvPTAT;
        float KtPTAT;
        uint16_t vPTAT25;
        float alphaPTAT;
        int16_t gainEE;
        float tgc;
        float cpKv;
        float cpKta;
        uint8_t resolutionEE;
        uint8_t calibrationModeEE;
        float KsTa;
        float ksTo[4];
        int16_t ct[4];
        float alpha[768];    
        int16_t offset[768];    
        float kta[768];    
        float kv[768];
        float cpAlpha[2];
        int16_t cpOffset[2];
        float ilChessC[3]; 
        uint16_t brokenPixels[5];
        uint16_t outlierPixels[5];  
    } paramsMLX90640;
    
    int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData);
    int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData);
    int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
    float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params);
    float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params);
    void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result);
    void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result);
    int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution);
    int MLX90640_GetCurResolution(uint8_t slaveAddr);
    int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate);   
    int MLX90640_GetRefreshRate(uint8_t slaveAddr);  
    int MLX90640_GetSubPageNumber(uint16_t *frameData);
    int MLX90640_GetCurMode(uint8_t slaveAddr); 
    int MLX90640_SetInterleavedMode(uint8_t slaveAddr);
    int MLX90640_SetChessMode(uint8_t slaveAddr);
    
#endif

相关宏去除,直接写在了cpp里面。

因此我们如何进行app层调用,如下所示:

接下来就是STM32以及ESP32的相关代码了,如下所示:

如下是esp32你需要注意的:

因为跟RP2040同一个平台其实本质就是兼容arduino的API仅此而已。

相关推荐
豆芽8191 小时前
图解YOLO(You Only Look Once)目标检测(v1-v5)
人工智能·深度学习·学习·yolo·目标检测·计算机视觉
狄加山6751 小时前
STM32 I2C总线通信协议
stm32·单片机·嵌入式硬件
北上ing1 小时前
从FP32到BF16,再到混合精度的全景解析
人工智能·pytorch·深度学习·计算机视觉·stable diffusion
Eric.Lee20212 小时前
数据集-目标检测系列- F35 战斗机 检测数据集 F35 plane >> DataBall
人工智能·算法·yolo·目标检测·计算机视觉
白熊1882 小时前
【计算机视觉】CV实践- 基于PaddleSeg的遥感建筑变化检测全解析:从U-Net 3+原理到工程实践
人工智能·计算机视觉
码小文4 小时前
Cadence学习笔记之---原理图设计基本操作
笔记·单片机·学习·硬件工程·pcb工艺
FCC9985 小时前
STM32嵌入式
stm32·单片机·嵌入式硬件
小禾苗_6 小时前
32单片机——GPIO配置步骤
单片机
ryh20048127 小时前
STM32移植最新版FATFS
stm32·fatfs
起个破名想半天了11 小时前
计算机视觉cv入门之答题卡自动批阅
人工智能·opencv·计算机视觉