当前位置: 首页 > article >正文

嵌入式产品级-超小尺寸热成像相机(从0到1 硬件-软件-外壳)

Thermal_Imaging_Camera 
This is a small thermal imaging camera that includes everything from hardware and software.

小尺寸热成像相机-Pico-LVGL-RTOS

基于RP2040 Pico主控与RTOS,榨干双核性能实现LVGL和成图任务并行。ST7789驱动240×280屏,CST816T触摸IC,MLX90640传感器实现热成像功能。充电采用SGM4056,DC-DC使用SGM6031等等。

产品描述:树莓派RP204 Pico, 双核 LVGL RTOS,合理分配热成像呈现内容,UI画面的更新反馈。

探头既可支持长焦的BAB款,支持广角的BAA款,MCU + ST7789屏幕(240 * 280)+ CST816T 触摸IC + MLX90640热成像传感器 + 充电采用SGM4056,DC-DC使用SGM6031等等。

ui类似Apple Watch,按键1开启ui,支持卡尔曼滤波、插值切换、7种显示色彩和温度,折线图,电池电量。按键2拍照,触摸屏显示任意位置温度不限个数,支持调光。

传统热成像设备的痛点

  • 价格昂贵:大多数热成像设备由于采用高端传感器和复杂的硬件设计,导致成本高昂。
  • 体积较大:便携性较差,限制了其在移动应用或小型设备中的应用。
  • 开发门槛高:传统设备通常依赖复杂的嵌入式系统,难以快速定制化开发。

用户需求

  • 对于消费者和开发者而言,市场需要一种低成本、小尺寸、易用的热成像解决方案,同时具备良好的图像质量和功能拓展性。

产品优势

  • 低成本实现

    • 通过使用 RP2040 Pico 和 MLX90640 这类性价比高的硬件组合,实现了功能的最大化。
    • 使用开源的 LVGL 图形库,避免高额商业软件授权费用。
  • 小尺寸设计

    • 紧凑的硬件结构使设备便于携带和嵌入其他系统,例如无人机、手持设备等场景。
  • 高性能多任务

    • 基于 RTOS 实现多任务调度,充分利用 RP2040 的双核性能,在图像处理和触摸交互中保持流畅性能。
  • 高扩展性

    • 支持通过触摸屏实现用户交互(例如温度调节、热图切换)。
    • 支持电池供电,搭配 SGM4056 和 SGM6031 提供高效的电源管理。

项目包含下述内容

  • 硬件部分、PCB制板、BOM表文件等等 (Hardware)
  • 软件程序、用于RP2040软件程序以及LVGL UI等等(Software)
  • 上位机(UpperComputerQT上位机 待更新!
  • 二次开发方案
  • 技术支持、全项目内容答疑
  • 项目持续更新中(任何问题和想法 功能都可以跟我提,我会慢慢跟进解决

功能图例

下图为用户配置设置界面,你可以设置配置你想要的参数,例如是否插值,是否启用卡尔曼滤波,色彩选择等。

下图是温度折线图界面,左滑即可。

下图为电源状态管理界面,右滑即可。

下图为相机状态,也就是捕捉热源成像。

下述就是不同色彩呈现的图示了。

更多内容附在资料包中~

代码部分如下所示:展示部分。

void my_disp_flush( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p )
{
    uint32_t w = ( area->x2 - area->x1 + 1 );
    uint32_t h = ( area->y2 - area->y1 + 1 );

    tft.startWrite();
    #if (ROTATE == 0 || ROTATE == 2)
    tft.setAddrWindow( area->x1, area->y1, w, h );
    #endif
    #if (ROTATE == 1 || ROTATE == 3)
    tft.setAddrWindow( area->x1, area->y1, w, h );
    #endif
    tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
    tft.endWrite();

    lv_disp_flush_ready( disp_drv );
}

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{

    touch.update();
    // Serial.print( "touch called " );
    // Serial.println( touch.tp.touching );
    bool touched = touch.tp.touching;
    if( !touched )
    // if( 0!=touch.data.points )
    {
        data->state = LV_INDEV_STATE_REL;
    }
    else
    {
        data->state = LV_INDEV_STATE_PR;
        #if (ROTATE == 0)
        /*Change to your screen resolution*/
        data->point.x = touch.tp.x;
        data->point.y = touch.tp.y;
        #endif
        #if (ROTATE == 1)
        /*Change to your screen resolution*/
        data->point.x = touch.tp.y;
        data->point.y = 240-touch.tp.x;
        #endif
        #if (ROTATE == 2)
        /*Change to your screen resolution*/
        data->point.x = 240-touch.tp.x;
        data->point.y = 280-touch.tp.y;
        #endif

        #if (ROTATE == 3)
        data->point.x = 280-touch.tp.y;
        data->point.y = touch.tp.x;
        #endif
        // data->point.x = touch.tp.x;
        // data->point.y = touch.tp.y;
        // Serial.print( "Data x " );
        // Serial.println( touch.tp.x );

        // Serial.print( "Data y " );
        // Serial.println( touch.tp.y );  
    }
}

// 按键输入设备读取回调函数
void my_keypad_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
    int button_state = digitalRead(24);  // 读取按键的状态,假设按键接地为 LOW
    if (button_state == LOW) {
        // 如果按键按下,记录开始按下的时间
        if (btn2_pushed_start_time == 0) {
            btn2_pushed_start_time = millis();
        }
        // 检测是否为长按
        if (millis() - btn2_pushed_start_time >= BTN_LONG_PUSH_T) {
            if (!btn2_long_pushed) {
                btn2_long_pushed = true;  // 标记为长按
                // 长按的处理,例如切换到不同屏幕
                
            }
        }
        data->state = LV_INDEV_STATE_PRESSED;  // 按键按下
    } else {
        // 按键松开,判断是否为短按
        if (btn2_pushed_start_time != 0) {
            if (!btn2_long_pushed) {
                btn2_pushed = true;  // 短按标记
                // 短按的处理,例如切换到不同屏幕
                if (!btn2_long_pushed){freeze = !freeze; } //切换 freeze 状态
            }
            btn2_pushed_start_time = 0;  // 重置按下时间
        }
        // 清除长按标记
        btn2_long_pushed = false;
        data->state = LV_INDEV_STATE_RELEASED;  // 按键松开
    }
}

void my_keypad_bootsel_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
    if (BOOTSEL) {
        // 如果按键按下,记录开始按下的时间
        if (btn1_pushed_start_time == 0) {
            btn1_pushed_start_time = millis();
        }
        // 检测是否为长按
        if (millis() - btn1_pushed_start_time >= BTN_LONG_PUSH_T) {
            if (!btn1_long_pushed) {
                btn1_long_pushed = true;  // 标记为长按
                // 长按的处理,例如切换到不同屏幕
                _ui_screen_change(&ui_Screen3, LV_SCR_LOAD_ANIM_FADE_ON, 500, 0, &ui_Screen3_screen_init);
            }
        }
        data->state = LV_INDEV_STATE_PRESSED;  // 按键按下
    } else {
        // 按键松开,判断是否为短按
        if (btn1_pushed_start_time != 0) {
            if (!btn1_long_pushed) {
                btn1_pushed = true;  // 短按标记
                // 短按的处理,例如切换到不同屏幕
                user_ui_flag = !user_ui_flag;
                if(user_ui_flag){
                  test_points[0][0] = 0; // 重置测试点数据
                  test_points[0][1] = 0;
                  _ui_screen_change(&ui_Screen2, LV_SCR_LOAD_ANIM_FADE_ON, 500, 0, &ui_Screen2_screen_init);
                } else {
                  _ui_screen_change(&ui_Screen1, LV_SCR_LOAD_ANIM_FADE_ON, 0, 0, &ui_Screen1_screen_init);
                }
            }
            btn1_pushed_start_time = 0;  // 重置按下时间
        }
        // 清除长按标记
        btn1_long_pushed = false;
        data->state = LV_INDEV_STATE_RELEASED;  // 按键松开
    }
}

http://www.kler.cn/a/513547.html

相关文章:

  • 2024年美赛C题评委文章及O奖论文解读 | AI工具如何影响数学建模?从评委和O奖论文出发-O奖论文做对了什么?
  • systemverilog中的force,release和assign
  • 解决npm install安装出现packages are looking for funding run `npm fund` for details问题
  • 第14篇:从入门到精通:掌握python上下文管理器
  • Fabric区块链网络搭建:保姆级图文详解
  • 直驱式风电储能制氢仿真模型matlab/simulink
  • 【C++】开源:libpcap网络数据捕获库安装与应用
  • 【python】实现图像中的阴影去除 | 方案和代码
  • Nginx HTTP 服务器基础配置
  • 2090. 半径为 k 的子数组平均值
  • 【深度学习基础】多层感知机 | 多层感知机概述
  • Android开发,待办事项提醒App的设计与实现(个人中心页)
  • httpx上传文件/IO流缓慢的问题分析及解决
  • SQL-leetcode—1141. 查询近30天活跃用户数
  • 在亚马逊云科技上用AI提示词优化功能写出漂亮提示词(下)
  • css动画水球图
  • 【数学建模美赛速成系列】O奖论文绘图复现代码
  • VM模块开发 C++ 工程配置
  • “大模型横扫千军”背后的大数据挖掘--浅谈MapReduce
  • Spring Boot + Netty + WebSocket 实现消息推送
  • 深挖——final
  • 分布式搜索引擎02
  • Emacs折腾日记(十一)——求值规则
  • EXCEL的一些用法记录
  • 每日一刷——1.20——准备蓝桥杯
  • 【全栈】SprintBoot+vue3迷你商城(5)