老杰瑞 发表于 2024-11-7 16:19

【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴

本帖最后由 老杰瑞 于 2024-11-11 10:31 编辑

<div>
<div>
<div>
<div>【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴</div>

<div>
<div>先来看看(半)成品效果:</div>

<div>22f8b169f7022e1886ae700967c139f9<br />
&nbsp;</div>

<div>Emmm,热成像模块给我玩坏了,下面是没玩坏之前的效果:</div>

<div>9060f93a8cc3f35bcf3d8bdf59751547<br />
ef301120630b267fd9541db17a3ed50e</div>

<div>&nbsp;</div>
</div>

<div>下面介绍一下项目想法:</div>

<div>我是一名自动化的电子开发者,在开发电路过程中老是需要焊接各种pcb元器件,有一天我在网上看到焊接烟雾会导致不孕不育,我害怕极了,我才20几.还没小孩呢!伤心~</div>

<div>我痛定思痛,决定开发一款桌面式焊接吸烟器.</div>

<div>在着手开发这款便携式红外智能吸烟器之前,我曾浏览淘宝,寻找市面上是否有类似产品。然而,我发现现有的吸烟器普遍存在体积庞大、必须连接电源且噪音大等问题,这与我心中理想的吸烟器相去甚远。因此,我决定自行设计一款既便携又智能的吸烟器。</div>

<div><strong>作品目的</strong>:我们在焊接过程中用的焊锡丝,由焊锡和铅组成,并含有少量助焊剂。焊接时会产生金属颗粒物、金属氧化物和有机挥发物。长期吸入这些有害气体和颗粒物可能会导致焊工出现咳嗽、气喘、胸闷、慢性支气管炎、角膜炎等一系列呼吸道系统疾病。此外,焊接地点经常光线昏暗,不利于焊工的操作和视觉健康,容易导致疲劳和操作失误。,以及焊接环境光线昏暗的问题,设计一款智能吸烟器,以保护焊接人员的健康并改善工作环境。</div>

<div></div>

<div><strong>采用方法</strong>:该智能吸烟器通过热电偶传感器检测烙铁是否开启,自动启动风扇和滤网系统,有效吸收和过滤焊接产生的有害气体和颗粒物。同时,内置可调光LED灯,提供充足照明,改善焊接环境。</div>

<div></div>

<div>项目启动与挑战</div>

<div>我在3D模型分享网站上找到了一款外壳模型,但它仅具备基本的开关功能,且必须连接电源。这激发了我对其进行改造的想法。<a href="https://www.thingiverse.com/thing:3474360">Minimalist 3D Printed Fume Extractor by rdmmkr - Thingiverse</a></div>

<div></div>

<div>在尝试为其安装电池后,我面临了一个新问题:设备频繁耗尽电量,而我也经常忘记关闭它。由于焊接和调试是一个反复开关烙铁的过程,我决定开发一款能够通过红外检测温度自动控制风扇启停的吸烟器。幸运的是,本次大赛提供的物料中包含了一款红外热成像模块,这为项目的诞生提供了关键技术支持。</div>

<div>软硬件架构图:</div>

<div></div>

<div>流程图:</div>

<div></div>

<div>功能示意图:</div>

<div></div>

<div>系统工作的照片:</div>

<div></div>

<div>技术难题与解决方案</div>

<div>尽管项目本身难度不大,但使用ESP32C6芯片后,情况变得复杂。首先,我习惯使用PlatformIO进行代码开发,但发现其官方版本并未适配ESP32C6的Arduino环境。经过一番努力,我终于成功配置了ESP32C6。其次,屏幕驱动也是一个挑战。我通常使用TFT_eSPI库开发屏幕,但在ESP32C6上也未适配。经过数日的努力,我成功将屏幕库移植至ESP32C6。</div>

<div>接下来,热成像数据的读取成为了难题。最初,我尝试采用插值算法,但经过五六天的调试仍未达到预期效果,最终决定采用32&times;16像素的色块输出方案。</div>

<div>编码器配置是另一个技术挑战。通常情况下,编码器库可以解决这一问题,但ESP32C6的适配问题让我花费了两三天时间。由于涉及到底层脉冲寄存器配置,我尝试从ESP32C3的适配中逆向工程,但发现ESP32C3和ESP32S3系列的核心配置函数与ESP32C6并不相似。经过几天的努力,我最终放弃了库适配,转而采用中断方式实现编码器检测。然而,这又导致了一个新的问题:编码器快速转动时系统会卡死并重启。在朋友的指点下,我意识到可能是热成像数据读取时的中断导致的数据读取错误。最终,我改为使用定时器检测编码器状态,成功解决了这一问题。</div>

<div>界面设计与展示</div>

<div>在开发过程中,我还尝试了LVGL库,以期实现更高级的界面效果。以下是我的效果展示:</div>

<div></div>

<div>然而,由于时间限制与能力不够,发现热成像传感器只能通过打点函数进行显示。然后我又是用的图形化界面编辑的lvgl,不太会写lvgl的代码,经过五六天的努力尝试仍未能解决,我决定回归到更传统的显示方案。</div>

<div>源码及说明:</div>

<div>编码器与按键读取代码</div>

<div>编码器用定时器,按键用中断:</div>

<div>
<pre>
<code>// 此函数将由定时器调用以检查编码器状态
void checkEncoder() {
    static unsigned long lastChangeTime = 0;  // 记录上次状态改变的时间
    unsigned long currentTime = millis();     // 获取当前时间
    int currentEncoderA = digitalRead(ENCODER_A);  // 读取编码器A的状态
    int currentEncoderB = digitalRead(ENCODER_B);  // 读取编码器B的状态
    static int lastEncoderB = LOW;  // 添加B信号的上一个状态
    // 检查编码器A状态是否发生变化,并加入时间间隔判断
    if (currentEncoderA != lastEncoderA &amp;&amp; (currentTime - lastChangeTime) &gt; 5) { // 5ms去抖
        if (currentEncoderA == HIGH) {
            // 通过比较A和B的变化序列来判断方向
            if (lastEncoderB != currentEncoderB) {
                encoderDirection = (currentEncoderB == HIGH) ? 1 : -1;
            }
            lastChangeTime = currentTime;  // 更新状态改变时间
        }
        lastEncoderA = currentEncoderA;  // 更新前一个状态
        lastEncoderB = currentEncoderB;  // 更新B的前一个状态
    }
}
// 风扇按钮中断服务例程
void IRAM_ATTR fanButtonISR() {
  unsigned long currentMillis = millis();  // 获取当前时间
  // 只有当当前时间与上次按下时间的间隔大于去抖动时间时,才认为是有效的按下
  if (currentMillis - lastFanButtonPress &gt; DEBOUNCE_TIME) {
    fanButtonPressed = true;  // 设置风扇按钮按下状态为真
    lastFanButtonPress = currentMillis;  // 更新上次按下时间
    Serial.print("fanButtonPressed");  // 串口打印
  }
}
// LED按钮中断服务例程
void IRAM_ATTR ledButtonISR() {
  unsigned long currentMillis = millis();  // 获取当前时间
  // 只有当当前时间与上次按下时间的间隔大于去抖动时间时,才认为是有效的按下
  if (currentMillis - lastLedButtonPress &gt; DEBOUNCE_TIME) {
    ledButtonPressed = true;  // 设置LED按钮按下状态为真
    lastLedButtonPress = currentMillis;  // 更新上次按下时间
    Serial.print("ledButtonPressed");  // 串口打印
  }
}</code></pre>

<p>&nbsp;</p>
</div>

<div>快速排列,得出温度最大值:</div>

<div>
<pre>
<code>    //快排-得到最大值
    qusort(frame, 0, 32 * 24 - 1);
    max_temp += frame;
//Quick sort
//通过递归分治的方式将一个大数组分为两个子数组,子数组的元素分别小于和大于基准值。
void qusort(float s[], int start, int end) //自定义函数 qusort()
{
    int i, j;        //定义变量为基本整型
    i = start;       //将每组首个元素赋给i
    j = end;         //将每组末尾元素赋给j
    s = s; //设置基准值
    while (i &lt; j)
    {
        while (i &lt; j &amp;&amp; s &lt; s)
            j--; //位置左移
        if (i &lt; j)
        {
            s = s; //将s放到s的位置上
            i++;         //位置右移
        }
        while (i &lt; j &amp;&amp; s &lt;= s)
            i++; //位置左移
        if (i &lt; j)
        {
            s = s; //将大于基准值的s放到s位置
            j--;         //位置左移
        }
    }
    s = s; //将基准值放入指定位置
    if (start &lt; i)
        qusort(s, start, j - 1); //对分割出的部分递归调用qusort()函数
    if (i &lt; end)
        qusort(s, j + 1, end);
}</code></pre>

<p>&nbsp;</p>
</div>

<div>关键的热成像数据显示代码:</div>

<div>
<pre>
<code>        //Display with 32*24 pixel-160*120  172-52-26
        for (uint8_t h = 0; h &lt; 24; h++)
        {
            for (uint8_t w = 0; w &lt; 32; w++)
            {
                //看看什么原理
                uint8_t colorIndex = map_f(temp_frame, MINTEMP, MAXTEMP);
                tft.fillRect(5 * w, 5 * h+26, 5, 5, camColors);
            }
        }</code></pre>

<p>&nbsp;</p>
</div>

<div>把温度值通过函数map_f转换为颜色值,通过tft色块代码显示</div>

<div>其余代码看下面这个链接,里面有完整的项目代码</div>

<div><a href="https://download.eeworld.com.cn/detail/%E8%80%81%E6%9D%B0%E7%91%9E/634908">download.eeworld.com.cn/detail/老杰瑞/634908</a></div>

<div>模型后续我会发在评论区,因为还不是最终版本,还在迭代中</div>

<div>项目展望</div>

<div>尽管面临重重挑战,我并未放弃。新的板子已经在来的路上,这次我将采用ESP32-WROOM-32芯片,并更换热成像模块为热电偶模块,类似于疫情期间用于检测人体温度的那种。这样的改动将使成本控制在50元以内,更适合大家复刻。敬请期待我的新作品!</div>
<!--importdoc-->

<p>下面是项目过程中的分享贴</p>

<p><a href="https://bbs.eeworld.com.cn/thread-1298345-1-1.html">【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6使用MLX90640显示图像测试 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)</a></p>

<p><a href="https://bbs.eeworld.com.cn/thread-1296311-1-1.html">【2024 DigiKey创意大赛】+便携式红外智能吸烟器+ESP32C6驱动1.54寸st7789屏幕 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)</a></p>

<p>&nbsp;</p>
</div>

<p><!--importdoc--></p>
</div>
<!--importdoc--></div>

<p><!--importdoc--></p>

老杰瑞 发表于 2024-11-10 21:34

本帖最后由 老杰瑞 于 2024-11-10 21:39 编辑

<div class="quote">
<blockquote><font size="2"><a href="forum.php?mod=redirect&amp;goto=findpost&amp;pid=3373276&amp;ptid=1298543" target="_blank"><font color="#999999">wangerxian 发表于 2024-11-7 17:48</font></a></font> 没坏之前的效果视频是不是没有传成功?</blockquote>
</div>

<p>好像是欸,我重新上传ada05516cd8330c0f90521b51ac6d466</p>

wangerxian 发表于 2024-11-7 17:48

<p>没坏之前的效果视频是不是没有传成功?</p>

hellokitty_bean 发表于 2024-11-8 17:36

<p>LVGL(light and versatile Graphics library)学习曲线这么陡峭吗?</p>

<p>还没尝试过。<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/smile.gif" width="48" /></p>

老杰瑞 发表于 2024-11-10 21:41

hellokitty_bean 发表于 2024-11-8 17:36
LVGL(light and versatile Graphics library)学习曲线这么陡峭吗?

还没尝试过。

<p>可以试试,用gui来配置挺快的</p>
页: [1]
查看完整版本: 【2024 DigiKey创意大赛】+便携式红外智能吸烟器+结项贴