自制红外热像仪(二) 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仅此而已。

相关推荐
文军的烹饪实验室2 小时前
处理器架构、单片机、芯片、光刻机之间的关系
单片机·嵌入式硬件·架构
lihuayong2 小时前
计算机视觉:主流数据集整理
人工智能·计算机视觉·mnist数据集·coco数据集·图像数据集·cifar-10数据集·imagenet数据集
Leiditech__3 小时前
人工智能时代电子机器人静电问题及电路设计防范措施
人工智能·嵌入式硬件·机器人·硬件工程
DCcsdnDC3 小时前
Airsim仿真双目相机时间戳不同步的解决办法
计算机视觉
jmlinux3 小时前
STM32 HAL库USART串口DMA IDLE中断编程:避坑指南
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi5 小时前
基于单片机的智能电表设计(论文+源码)
单片机·嵌入式硬件·电能表·数字电能表
半导体老登5 小时前
新能源汽车核心元件揭秘:二极管、三极管结构与工作原理解析(2/2)
人工智能·单片机·嵌入式硬件·汽车
【云轩】6 小时前
基于STM32与BD623x的电机控制实战——从零搭建无人机/机器人驱动系统
stm32·机器人·无人机
猿~~~7 小时前
STM32的HAL库开发---多通道ADC采集(DMA读取)实验
stm32·单片机·嵌入式硬件
Freak嵌入式8 小时前
开源一款I2C电机驱动扩展板-FreakStudio多米诺系列
嵌入式硬件·嵌入式·智能硬件·开源硬件·micropython·电机驱动·电子模块