本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

自制便携式热成像仪

发布时间:2021-06-20
分享到:

自制便携式热成像仪

发布时间:2021-06-20
分享到:

该项目将展示如何使用 Mini Zed 来制造低成本的便携式热成像仪,即将具有 SPI 接口的 1.3 英寸彩色 TFT LCD 和 MLX90640 红外热像仪(可提供 32 *24 行热图像)连接到 MiniZed。

红外热像仪使用 I2C 接口,而 LCD 使用 SPI 接口,这两者都可以通过 MiniZed PS 轻松实现。然而,连接设备需要考虑一下,因为两者都不能直接插入电路板。

由于 I2C 摄像头和 LCD 的引脚,没有任何接地和电源引脚与 MiniZed 上的电源和接地引脚直接对齐,两个外设都将从3v3开始工作。

我想将热像仪连接到 Pmod 接口和屏蔽连接器上的 LCD 屏幕。这允许接地和信号引脚与 MiniZed 上可用的引脚对齐。

对于电源接口,将通过跳线将它们连接到 Pmod 和屏蔽连接器上的适当电源连接。

也就是说需要在不同方向的连接器上焊接,接地和信号连接从板的底部向下,而电源引脚从板的顶部向上。

Vivado 设计:

  • 创建一个针对 MiniZed 的新项目

  • 选择 RTL 作为项目类型

  • 选择 MiniZed

  • 选择完成

  • 创建新的块设计,并将 Zynq 处理系统添加到其中

  • 运行块自动化以配置项目

  • 重新配置 Zynq PS ,将 I2c 和 SPI 作为扩展 MIO,这使信号可用于可编程逻辑,以便我们可以将它们路由到 Pmod 和 Shield 接口。

  • EMIO 在框图中可用,我们需要将 SPI 和 IIC 信号设为外部

  • 与 SPI 一起,LCD 还使用两个附加信号 BL,它是 LCD 的背光,以及指示 SPI 是否包含命令信息或数据信息的 DC。为了确保信号路由到所需的接口,需要定义一个约束文件。

软件开发:

此应用程序的软件开发可能非常深入,因为 LCD 和温度传感器都需要相当多的软件框架。但是可以分叉和修改两个软件存储库,和 Zynq 一起使用。主要修改的是使其映射到所提供技术堆栈底部的正确 I2C 或 SPI 驱动程序中。

第一个库是由热像仪制造商提供的 Melexis mlx90640 库。这旨在与 Arm Mbed 类型的设备配合使用。

该软件的结构使得低级 I2C 命令包含在 I2C 驱动程序或 SWI2C 驱动程序两个文件之一中。SWI2C 驱动程序通过位组合端口实现 I2C 驱动程序,此应用程序不需要。I2C 驱动程序包括用于 Mbed 类型设备的 I2C 驱动程序。需要更新这些驱动程序才能使用 Zynq I2C 驱动程序。实际上,我们正在用 Zynq I2C 驱动程序调用替换 mbed I2C 驱动程序调用。

这允许 API 文件能够在只替换驱动程序的情况下不变地使用。关于读取 MLX90640 的注意事项需要 I2C 驱动程序执行重复启动,并且它也必须是 I2C 总线上的唯一设备。

MBed I2C 接口:

int MLX90640_I2CRead(uint8_t slaveAddr, uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data)
{
    uint8_t sa;                           
    int ack = 0;                               
    int cnt = 0;
    int i = 0;
    char cmd[2] = {0,0};
    char i2cData[1664] = {0};
    uint16_t *p;
    
    p = data;
    sa = (slaveAddr << 1);
    cmd[0] = startAddress >> 8;
    cmd[1] = startAddress & 0x00FF;
    
    i2c.stop();
    wait_us(5);    
    ack = i2c.write(sa, cmd, 2, 1);
    
    if (ack != 0x00)
    {
        return -1;
    }
             
    sa = sa | 0x01;
    ack = i2c.read(sa, i2cData, 2*nMemAddressRead, 0);
    
    if (ack != 0x00)
    {
        return -1; 
    }          
    i2c.stop();   
    
    for(cnt=0; cnt < nMemAddressRead; cnt++)
    {
        i = cnt << 1;
        *p++ = (uint16_t)i2cData[i]*256 + (uint16_t)i2cData[i+1];
    }
    
    return 0;   
}

使用 Zynq I2C 接口替换原来的 I2C 接口,更新I2C 读取功能:

int MLX90640_I2CRead(uint8_t slaveAddr,uint16_t startAddress, uint16_t nMemAddressRead, uint16_t *data)
{

    int cnt = 0;
    int i = 0;
    u8 cmd[2] = {0,0};
    u8 i2cData[1664] = {0};
    uint16_t *p;

    p = data;
    cmd[0] = startAddress >> 8;
    cmd[1] = startAddress & 0x00FF;
    XIicPs_SetOptions(&Iic,XIICPS_REP_START_OPTION);
    XIicPs_MasterSendPolled(&Iic, cmd,2, IIC_SLAVE_ADDR);
    //while (XIicPs_BusIsBusy(&Iic)) {
        /* NOP */
    //}

    XIicPs_MasterRecvPolled(&Iic, i2cData,2*nMemAddressRead, IIC_SLAVE_ADDR);
    while (XIicPs_BusIsBusy(&Iic)) {
        /* NOP */
    }
    XIicPs_ClearOptions(&Iic,XIICPS_REP_START_OPTION);

    for(cnt=0; cnt < nMemAddressRead; cnt++)
    {
        i = cnt << 1;
        *p++ = (uint16_t)i2cData[i]*256 + (uint16_t)i2cData[i+1];
    }

    return 0;
}

我们可对 API 进行函数调用,该 API 将配置和读取来自 MLX90640 传感器的数据。

为了能够与显示器一起工作,还可以为 1.3" LCD 使用的 ST7789V 驱动程序采用基于 STM32 的驱动程序

需要再次将较低级别的 SPI 驱动程序从 STM32 使用的 HAL 层转换为 Zynq SPI。

原始STM32 HAL层

static void ST7789_WriteCommand(uint8_t cmd)
{
ST7789_Select();
ST7789_DC_Clr();
HAL_SPI_Transmit(&ST7789_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY);
ST7789_UnSelect();
}

更新的 Zynq 命令

static void ST7789_WriteCommand(uint8_t cmd)
{

    XGpioPs_WritePin(&Gpio, DC, 0);
    XSpiPs_SetSlaveSelect(&SpiInstance_EMIO, 0x00);
    XSpiPs_PolledTransfer(&SpiInstance_EMIO, &cmd, NULL, sizeof(cmd));

}

更新 SPI 和 I2C 驱动程序后,必须测试驱动程序以确保 LCD 和 MLX90640 可以按预期工作。

将示波器连接到 Pmod 接口,确定 I2C 和 SPI 线路的范围

主软件应用程序执行以下步骤来配置系统:

  • 配置 Zynq 外设
  • 初始化显示 - 将背景颜色设置为全黑
  • 从 MLX90640 获取 EEPROM 参数
  • 从 EEPROM 转储中提取参数

在主循环内执行以下功能:

  • 从 MLX90640 获取一帧数据
  • 获取阵列的温度
  • 计算数组中每个元素的温度
  • 通过 RS232 输出每个数组元素进行分析和双重检查
  • 将阵列温度转换为 RGB 颜色
  • 液晶显示器上的显示

由于显示器的分辨率仅为 32 * 24,使用简单的缩放算法将显示器放大到 1.3" LCD:

MLX90640_DumpEE (0x33, eeMLX90640);
    MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
    while(1){


        MLX90640_GetFrameData(0x33,mlx90640Frame);
        Ta = MLX90640_GetTa (mlx90640Frame, &mlx90640) - TA_SHIFT;
        MLX90640_CalculateTo(mlx90640Frame, &mlx90640, emissivity, Ta, mlx90640To);
        for(int i =0; i <24 ;i++){
            for (int y= 0; y < 32; y++){
                printf(" %.2f ", mlx90640To[y+(i*32)]);
            }
            printf("\n\r");
        }
        ST7789_Fill_Display(&mlx90640To);
    }

显示中每个元素的场景温度:

可以将温度转换成一个颜色进行显示,以此来显示图像中的热量。

创建一个包含255种不同颜色的颜色地图,然后调整图像中的温度以适应255种颜色中的一种,并将其显示在屏幕上。

运行算法和成像热点元素显示如下图:

当成像仪查看环境温度时

 

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论