描述
<div>
<h3 style="line-height:1.8">* 1、项目功能介绍</h3>
<hr>
<p style="line-height:1.8"><span style="font-size:10pt"><span style="color:#95a5a6">想必耗材受潮导致的拉丝一定困扰着每一位3D打印爱好者,热床上的炒面和盘丝洞总能引发人们的沉思。</span></span></p>
<p style="line-height:1.8"><span style="font-size:10pt"><span style="color:#95a5a6">干燥箱和温湿度计已经成为每一位3D打印爱好者必备的道具。</span></span></p>
<p style="line-height:1.8;text-align:center"><img src="//image.lceda.cn/oshwhub/939f9fe60a384332bbc8e79f9828c78c.jpg" alt="" width="1200" height="901"></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图1 再也不会笑了.jpg(一堆温湿度计)</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">传统的干燥剂+密封箱组合的干燥箱只能维持耗材的受潮程度,并不能使耗材表现变好,随着时间的推移耗材依旧会出现质量变差的情况。</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">使用具有主动干燥(加热)功能的干燥箱能够降低耗材的受潮情况,在一定程度上能够改善打印拉丝、缺陷问题。</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">某宝上有许多具有主动功能的干燥箱,但每每看到图片下的价格,总会使我沉思,我在想,3D打印爱好者的钱是不是大风刮来的?</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">虽然与打印机和高质量耗材的价格相比,这样的定价并不算昂贵,但简单的加热元件、控制器及外壳能卖到如此高昂的价格实在让我难以接受。(觉得贵是我的问题,私密马赛)</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">一番思想斗争后还是认为不能给厂商捐款,决定自己动手。</span></p>
<p style="line-height:1.8"> </p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">也有部分DIY方案采用果蔬烘干器进行改造,但是220V的供电以及不能原生匹配耗材让我望而却步。</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">本干燥组件在常用的5L米桶干燥箱基础上进行附加,做小幅度改造以获得温湿度监测+主动干燥的功能。</span></p>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">以下是验证后实物展示:</span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/c3d6727d93d944fb8fb03b52c4a99e05.jpg" alt="" width="1200" height="900"></span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图2 实物展示图1</span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/faa7779395d0471b9a9700d34479e222.jpg" alt="" width="1200" height="900"></span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图3 实物展示图2</span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/833c8ef2f01a4cc39f7e2885dcae025f.jpg" alt="" width="1200" height="900"></span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图4 控制模块PCB展示</span></p>
<h3 style="line-height:1.8">*2、项目属性</h3>
<hr>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">项目首次公开;项目为原创;项目未曾在其他比赛中获奖;项目未在学校参加过答辩。</span></p>
<p style="line-height:1.8"> </p>
<h3 style="line-height:1.8">* 3、开源协议</h3>
<hr>
<p style="line-height:1.8"><span style="color:#95a5a6;font-size:10pt">CC BY-NC-SA 4.0</span></p>
<p style="line-height:1.8"> </p>
<h3 style="line-height:1.8">*4、硬件部分</h3>
<hr>
<ul>
<li style="line-height:1.8"><span style="color:#95a5a6;font-size:14pt">4.1 基本特性</span></li>
</ul>
<p style="line-height:1.8;text-align:left;padding-left:40px"><span style="color:#95a5a6;font-size:10pt">有效输入电压:10-20V(10V为软件设定欠压保护下限,可更改;20V为PTC元件电气性能限制)</span></p>
<p style="line-height:1.8;text-align:left;padding-left:40px"><span style="color:#95a5a6;font-size:10pt">干燥温度范围:0-255℃(由软件设置;回答我,你不会真的加热到255℃,对吧?)</span></p>
<p style="line-height:1.8;text-align:left;padding-left:40px"><span style="color:#95a5a6;font-size:10pt">设计最大功率:Type-C输入 - 60W;DC输入 - 80W(可以通过软件设置限制输出功率)</span></p>
<p style="line-height:1.8;text-align:left;padding-left:40px"><span style="color:#95a5a6;font-size:10pt">人机交互:0.96 OLED显示、EC11编码器交互</span></p>
<p style="line-height:1.8;text-align:left;padding-left:40px"> </p>
<ul>
<li style="line-height:1.8;text-align:left"><span style="color:#95a5a6;font-size:14pt">4.2 系统结构</span></li>
</ul>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">本组件主要由MCU、电源部分、主动干燥部分、温湿度监测以及人机交互部分构成。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">系统结构图如下所示:</span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:14pt"><img src="//image.lceda.cn/oshwhub/fa54b74e288e448d9fddc31536a92433.png" alt="" width="1200" height="560"></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图5 系统结构图</span></p>
<p> </p>
<ul>
<li style="text-align:left"><span style="color:#95a5a6;font-size:14pt">4.3 硬件设计</span></li>
</ul>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">· MCU采用ESP32-C3-MINI-1-N4模组,自带USB支持JTAG,用过都说好!不是第一次在项目中使用改模组,但每一次在项目中使用总能学习到新的内容。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6"><span style="font-size:13.3333px">片上有12位ADC,用于PT1000和输入电压的采样(飘也是真的飘,不校准完全不能用)。</span></span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">改模组具备WIFI功能,后续可以考虑接入物联网等。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">其余功能随后续内容描述。</span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/90281392bb6946cbb5ac6a20f7d2aa68.png" alt="" width="1200" height="589"></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图6 MCU部分原理图</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">· 电源部分,输入采用DC插口+Type-C的方案;主供电VBUS直接供给PTC加热器、风扇;主供电经过DC-DC降压获得3.3V电压用于ESP32-C3、OLED等的供电。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">DC插口与VBUS间接入肖特基二极管SS54,做防反接、防倒灌;接入TVS,防止输入电压大于20V损坏PTC。Type-C后接CH224K,用于PD诱骗,Rset设置为NC,诱骗20V电压。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">DC-DC采用Buck拓扑、使用MP2359芯片控制(<span style="text-decoration:line-through">杰盛微可白嫖</span>&Pin2Pin芯片很多)。其中,FB电压为0.8V,通过电阻分压得到。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">分压电阻使用Matlab编写遗传算法程序,带入电压条件迭代求得,理论误差为0V。</span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/cdd1917cf80649a3b4d0da95edbed8b1.png" alt="" width="1200" height="586"></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图7 FB电阻计算</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">但注意输出电压可能不完全等于3.3V,并且后续ADC校准需要视情况更改校准参数。(本项目测试中实际电压为3.345V,由LCSC530+万用表测量得到)</span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/dd7040e30f7e4860bc2759c901df6bae.png" alt="" width="1200" height="585"></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图8 电源部分原理图</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">· 主动干燥部分由PTC加热控制、风扇控制和PT1000测量组成。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">PTC加热控制、风扇控制采用NMOS开关电路实现。风扇电流较小,使用AO3400 NMOS;PTC所需电流较大,但也仅有数A,一般DFN-8(5x6)封装的NMOS都能满足条件。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">PT1000测量则是与1k电阻构成分压电路,测量PT1000与1k电阻中间点的电压。(懒了,不想加运放做量程变换,直接软件算吧)</span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/d142c443e7b04813996a8642969feba6.png" alt="" width="1200" height="585"></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图9 主动干燥部分原理图</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6"><span style="font-size:13.3333px">· 温湿度监测部分采用盛思锐SHT30温湿度传感器,以I2C总线进行数据交互。</span></span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">· 人机交互部分由0.96" OLED及其驱动电路、EC11编码器组成。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">本项目OLED选型为SH1106 128x64 0.96" 30Pin I2C协议OLED。一般30Pin 0.96" OLED均兼容;EC11编码器柄高随意。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">SHT30与OLED使用同一个硬件I2C。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">在之前的设计当中,分别使用了两对引脚,计划使用两组I2C总线。但在程序编写过程当中,调用库函数难以实现Wire1的使用(对不起,我的代码水平雀食不行),因此改为同一对引脚、同一个硬件I2C总线。</span></p>
<p style="padding-left:40px;text-align:left"><span style="color:#95a5a6;font-size:10pt">使用软件I2C进行屏幕的调用延迟较大,会在后续的软件部分说明。</span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:10pt"><img src="//image.lceda.cn/oshwhub/bee9232b85234f6984d38a38cd015e08.png" alt="" width="1200" height="533"></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图10 温湿度监测部分&人机交互部分原理图</span></p>
<p style="padding-left:40px;text-align:left"> </p>
<p style="padding-left:40px;text-align:left"> </p>
<h3 style="line-height:1.8">*5、软件部分</h3>
<hr>
<ul>
<li style="line-height:1.8"><span style="color:#95a5a6;font-size:12pt">5.1 软件设计思路</span></li>
</ul>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">本项目基于Arduino框架开发,开发环境为VSCode PlatformIO。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">项目中,将程序设计整体分为以下几个部分:显示(U8g2)、交互输入(Encoder、OneButton)、温湿度传感器(Adafruit_SHT31)、电压采样(analogRead)、风扇及PTC输出控制(analogWrite、PID)。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">交互输入通过在主循环中调用库函数实现;显示、数据采样、输出控制则是每隔一定间隔执行一次。</span></p>
<p style="padding-left:40px"> </p>
<ul>
<li><span style="color:#95a5a6;font-size:12pt">5.2 软件设计</span></li>
</ul>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">· 交互输入实现相对简单,分别通过调用Encoder.h、OneButton.h库函数实现。参照以上库提供的例程实现相应的按键和编码器功能。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">· 数据采样及输出控制中包含两个部分,分别为 需要严格保持时间间隔恒定执行 和 时间间隔要求宽松两种。</span></p>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">其中,PT1000的温度采样、PTC输出控制是需要严格保持时间间隔恒定执行的部分。这是因为该部分涉及PID控制,详细PID原理在此处不过多解释。</span><span style="color:#95a5a6">而其他的数据采样和风扇控制不需要严格进行控制。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">因此,将上述两种类型分别采用不同方法实现。设置一个定时器(项目中时间为200ms),需要严格时间控制的部分放置于定时器内;同时定义一个中断标志,当发生定时器中断时标志变为true,在主循环中由if判断标志并执行时间要求宽松的部分。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">· 显示也属于较为宽松的部分,并且其刷新需要占用较长时间,因此同上将其放置在if判断标志后执行。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">起初想将所有函数置于定时器中断服务函数中执行,但是这样导致了报错并循环重启(推测定时器再次发生中断时服务函数还未执行完,但在ESP32-S3的开发中没有遇到这样的情况)。因此,将函数分为时间严格、时间宽松两部分分别执行。</span></p>
<p style="padding-left:40px"> </p>
<ul>
<li><span style="color:#95a5a6;font-size:12pt">5.3 交互逻辑</span></li>
</ul>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">交互部分包含OLED的显示和EC11编码器的输入。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">· 菜单逻辑</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">本项目中菜单分为两级,第一级菜单用于显示当前系统的情况(温湿度、输入电压、系统状态);第二级菜单用于设置主动干燥时的参数(加热温度、加热时间、风扇及PTC的功率限制)。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">程序设计中,使用一个bool型变量判断菜单的层级;分别进入两级菜单,print对应的项目并请求对应的数值,使用String()转化为字符串后以“+”连接一次性进行绘制输出。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">二级菜单需要对具体的项目进行编辑,多了一个选中状态的选项,因此增加一个unsigned char型变量用于存储选中目标序号,范围为0-3。当目标序号=项目序号时,在该行末端输出一个“*”以作为选中标记。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">在二级菜单的程序编写中,使用了结构体,大大简化了编写程序的复杂程度(一级菜单部分凑合用,就懒得改了),在结构体中存储项目名称、单位、数值和调整刻度。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">使用for循环配合结构体print即可大大压缩显示使用的程序内容。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6;font-size:10pt">程序如下所示:</span></p>
<p style="padding-left:40px"><code>struct element{<br> char* name;<br> char* unit;<br> unsigned char value;<br> unsigned char scale;<br>};<br>element Setting_Element[] = {<br> {"加热温度: ","℃",60,1},<br> {"加热时间: ","min",0,1},<br> {"功率限制: ","",32,8},<br> {"风扇转速: ","",64,8},<br>};</code></p>
<div> </div>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">菜单显示逻辑如下所示:</span></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6"><span style="font-size:13.3333px"><img src="//image.lceda.cn/oshwhub/61c62bef8f114dc8afa916f14eae9e30.png" alt="" width="1200" height="608"></span></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图11 菜单显示逻辑</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">菜单显示效果如下所示:</span></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6"><span style="font-size:13.3333px"><img src="//image.lceda.cn/oshwhub/b5ccd1f16f724f6bb507fed4feb284cc.png" alt="" width="1200" height="356"></span></span></p>
<p style="padding-left:40px;text-align:center"><span style="font-size:8pt"><span style="color:#95a5a6">图12 菜单显示效果</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">· 输入逻辑</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">输入主要分为编码器输入和按键输入。编码器通过旋转可以增大或减小数值;按键则通过功能复用分别实现选中、切换效果。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">OneButton库提供了多种按键状态,本项目中仅使用按键单击和按键长按两种(由于主循环中显示占用时间较长,导致双击识别较不准确,故舍弃)。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">Encoder库可以记录当前编码器的位置,通过将当前位置与上一时刻位置进行比较可以判断数值增减(实际使用中还存在一定抖动)。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">输入交互逻辑如下图所示:</span></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6"><span style="font-size:13.3333px"><img src="//image.lceda.cn/oshwhub/97a3d63d22e04eaa9b65e3fbf55e4649.png" alt="" width="1200" height="593"></span></span></p>
<p style="padding-left:40px;text-align:center"><span style="font-size:8pt"><span style="color:#95a5a6">图13 输入交互逻辑</span></span></p>
<p style="padding-left:40px"> </p>
<ul>
<li><span style="font-size:12pt"><span style="color:#95a5a6">5.4 输出控制</span></span></li>
</ul>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">输出控制分为PTC输出和风扇输出两部分。其中,风扇输出简单调用analogWrite即可;PTC输出为了控制输出温度恒定需要采用PID控制。</span></span></p>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">PID控制采用增量式PID,即在前一时刻控制量基础上调整控制量数值,这样的控制方法代码量比较小(个人感觉)。</span></span></p>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">PID部分代码如下所示:</span></span></p>
<p style="padding-left:40px"><code>// PID</code><br><code>float Kp=0.1, Ti=125, Td=5;</code><br><code>uint16_t P_Term=0, I_Term=0, D_Term=0;</code></p>
<p style="padding-left:40px"><code>void PidCtrl(){</code><br><code> // PID项计算</code><br><code> P_Term = Error_Temperature[0] - Error_Temperature[1];</code><br><code> I_Term = Error_Temperature[0];</code><br><code> D_Term = Error_Temperature[0] - 2*Error_Temperature[1] + Error_Temperature[2];</code></p>
<p style="padding-left:40px"><code> OUT_Status = OUT_Status + Kp*( P_Term + Ts/Ti*I_Term + Td/Ts*D_Term );</code><br><code> // 功率限制</code><br><code> if(OUT_Status > Setting_Element[2].value){</code><br><code> OUT_Status = Setting_Element[2].value;</code><br><code> }</code><br><code> analogWrite(OUT,OUT_Status);</code><br><code> </code><br><code> // Serial.println(String(OUT_Status)+"*"+String(Error_Temperature[0]));</code></p>
<p style="padding-left:40px"><code> // 温度误差更新</code><br><code> Error_Temperature[2] = Error_Temperature[1];</code><br><code> Error_Temperature[1] = Error_Temperature[0];</code><br><code> Error_Temperature[0] = Setting_Element[0].value - temperature_PT1000;</code><br><code>}</code></p>
<ul>
<li><span style="font-size:12pt"><span style="color:#95a5a6">5.5 PT1000测量</span></span></li>
</ul>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">PT1000用于测量PTC加热器的温度。与SHT30测温不同,箱内温度在加热后需要一定时间才能上升,具有迟滞性且具有局部温度差异的情况。</span></span></p>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">若依靠SHT30测量值作为PID控制依据,很可能导致PTC过度加热,使得PTC出口附近温度过高、耗材融化。因此需要额外增加一个温度传感器用于测量PTC温度,使温度控制在合理范围。</span></span></p>
<p style="padding-left:40px"><span style="font-size:10pt"><span style="color:#95a5a6">PT1000在0℃时阻值为1kΩ,随温度上升增大阻值。但其关系并非线性,因此需要对其进行一定处理。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">考虑到加热温度多处于40~80℃,因此本项目抛弃40℃以下、80℃以上的测量准确性,采用局部拟合的方式得到温度与采样值之间的关系。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">根据PT1000温度计算公式,建立温度与电压的实际曲线,然后截取40-80℃部分使用Matlab cftool进行一阶线性拟合。拟合效果如下图所示:</span></span></p>
<p style="padding-left:40px;text-align:center"><span style="color:#95a5a6"><span style="font-size:13.3333px"><img src="//image.lceda.cn/oshwhub/f4928efb6a5a4d8394c4246199e527b9.png" alt="" width="1200" height="531"></span></span></p>
<p style="padding-left:40px;text-align:center"><span style="font-size:8pt"><span style="color:#95a5a6">图14 PT1000拟合效果</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">其中绿线(局部一阶拟合)是黑线(一阶拟合函数)的部分,在图中重合。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">但由于没有能够进行温度校<span style="color:#95a5a6">准的工具</span>,因此无法判断拟合的效果。并且由于ESP32-C3的ADC存在偏移,测量结果必然存在一定误差。</span></span></p>
<p style="padding-left:40px"> </p>
<h3 style="line-height:1.8">*6、BOM清单</h3>
<hr>
<ul>
<li style="line-height:1.8;text-align:left"><span style="color:#95a5a6"><span style="font-size:12pt">6.1 装配明细</span></span></li>
</ul>
<p style="text-align:center"><span style="color:#95a5a6;font-size:8pt">表1 装配明细</span></p>
<table style="border-collapse:collapse;width:80%;height:320px;margin-left:auto;margin-right:auto">
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">序号</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">项目</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">数量</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">备注</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">6CM风扇</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">厚度不限</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">2</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">6x3磁铁</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">8</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">安装时注意对吸</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">3</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M4x4x5.5土八螺母</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">4</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">4</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M4x14内六角螺栓</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">4</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">5</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M3x3x4.5土八螺母</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">4</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">6</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M3x12铜柱</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">7</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M3x8铜柱</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">8</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M3x4平头螺丝</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">2</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">9</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">PT1000</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">10</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">XH2.54-2P端子线</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">11</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">四氟管</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">一小段,外径4mm(玩3D打印的大家都有吧?)</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">12</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M3x10螺丝</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">2</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">圆头或平头</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">13</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">M3x8螺丝</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">4</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">沉头最佳</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">14</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">铜鼻子</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">2</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">孔内径>3mm</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">15</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">PTC加热器</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">12V 50W</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">16</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">控制器模块</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"> </td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">17</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">风嘴</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">打印件,见附件</span></td>
</tr>
<tr style="height:20.7656px">
<td style="width:11.8724%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">18</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">控制器座</span></td>
<td style="width:20.2929%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.7656px;line-height:1"><span style="font-size:10pt">打印件,见附件</span></td>
</tr>
<tr style="height:20.8281px">
<td style="width:11.8724%;text-align:center;height:20.8281px;line-height:1"><span style="font-size:10pt">19</span></td>
<td style="width:20.2929%;text-align:center;height:20.8281px;line-height:1"><span style="font-size:10pt">控制器盖</span></td>
<td style="width:20.2929%;text-align:center;height:20.8281px;line-height:1"><span style="font-size:10pt">1</span></td>
<td style="width:47.4895%;text-align:center;height:20.8281px;line-height:1"><span style="font-size:10pt">打印件,见附件</span></td>
</tr>
</table>
<p style="padding-left:40px"> </p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:14px"><img src="//image.lceda.cn/oshwhub/f5c87498b11c4c1b9ca21a7c0f67be3d.jpg" alt="" width="1200" height="900"></span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图15 模块组成展示</span></p>
<ul>
<li><span style="color:#95a5a6;font-size:12pt">6.2 模块装配</span></li>
</ul>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt"><img src="//image.lceda.cn/oshwhub/d0016c0a38bd48daba3352f4387647bd.png" alt="" width="1200" height="675"></span></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图16 装配爆炸图(部分)</span></p>
<p style="line-height:1.8;text-align:left;padding-left:40px"><span style="color:#95a5a6;font-size:10pt">安装时,5L米桶需要进行打孔处理,两个为PTC加热器接线柱、一个为四氟管伸出孔、方孔用于伸出XH座子和端子线。如下图所示:</span></p>
<p style="line-height:1.8;padding-left:40px;text-align:center"> <img src="//image.lceda.cn/oshwhub/46add3291d8a4f8f98a27bd7143b5754.jpg" alt="" width="1200" height="900"></p>
<p style="line-height:1.8;padding-left:40px;text-align:center"><span style="color:#95a5a6;font-size:8pt">图17 打孔标记</span></p>
<p style="line-height:1.8"> </p>
<h3 style="line-height:1.8">*7、大赛LOGO验证</h3>
<hr>
<p style="line-height:1.8;text-align:center"> </p>
<p style="line-height:1.8;text-align:center"><img src="//image.lceda.cn/oshwhub/0d6c6273f421438885cd73f4d827f8dd.jpg" alt="" width="1200" height="899"></p>
<p style="line-height:1.8;text-align:center"><span style="color:#95a5a6;font-size:8pt">图18 大赛Logo验证</span></p>
<p style="line-height:1.8"> </p>
<h3 style="line-height:1.8">* 8、演示您的项目并录制成视频上传</h3>
<hr>
<p style="line-height:1.8"><span style="font-size:10pt;color:#95a5a6">视频见附件。</span></p>
<p style="line-height:1.8"> </p>
<ul>
<li style="line-height:1.8"><span style="font-size:12pt;color:#95a5a6">8.1 项目附加说明</span></li>
</ul>
<p style="padding-left:40px"><span style="font-size:10pt;color:#95a5a6">在实物验证过程中,发现了部分不合理之处,不推荐直接对该项目进行复刻,建议做一定修改再行复刻。以下是待改进的点:</span></p>
<p style="padding-left:40px"><span style="font-size:10pt;color:#95a5a6">1.风扇噪声。风扇控制使用analoagWrite,PWM频率较低,在运行时存在较大的噪声,后续尝试改为ESP32的ledc控制。</span></p>
<p style="padding-left:40px"><span style="font-size:10pt;color:#95a5a6">2.风扇与PT1000连接。当前使用的XH插接位置较差,装配需要镊子辅助,应该将插座留在侧面方便连接;或者增加副板、更换PogoPin实现免插接并降低漏气可能。</span></p>
<p style="padding-left:40px"><span style="font-size:10pt;color:#95a5a6">3.屏幕刷新率较低。当前使用的是硬件I2C方案,虽然相较于原有的软件I2C有极大的改善,但是刷新时间仍较长,还有很大的改进空间。(在代码是也可以优化,个人软件水平一般,能力有限)</span></p>
<p style="padding-left:40px"><span style="font-size:10pt;color:#95a5a6">4.温湿度与主动干燥没有联动。当前还没有加入联动,例如设置湿度阈值进行主动干燥。</span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">5.干燥剂放置。原先计划将干燥剂以磁吸方式吸附在风扇另一侧,但实际安装中空间过小,无法放入。</span></span></p>
<p style="padding-left:40px"><span style="color:#95a5a6"><span style="font-size:13.3333px">本项目仅抛砖引玉,提供一些设计思路供各位大佬参考。</span></span></p>
<p style="line-height:1.8"> </p>
<h3 style="line-height:1.8">附录</h3>
<ul>
<li><span style="font-size:12pt">附录1 项目程序</span></li>
</ul>
<p style="padding-left:40px"><code>#include <Arduino.h></code><br><code>#include <Wire.h></code><br><code>#include <SPI.h></code><br><code>#include <U8g2lib.h></code><br><code>#include "Adafruit_SHT31.h"</code><br><code>#define ENCODER_OPTIMIZE_INTERRUPTS </code><br><code>#include <Encoder.h></code><br><code>#include "OneButton.h"</code></p>
<p style="padding-left:40px"><code>// IO Setting</code><br><code>#define OUT 4</code><br><code>#define FAN 5</code><br><code>#define UIN_IN 0</code><br><code>#define PT1000_IN 1</code></p>
<p style="padding-left:40px"><code>// Variable Definition</code><br><code>float temperature = 0; // 箱内温度</code><br><code>float humidity = 0; // 箱内湿度</code><br><code>uint16_t UIN = 0; // UIN读数</code><br><code>uint16_t PT1000 = 0; // PT1000读数</code><br><code>float voltage_UIN = 0; // UIN电压</code><br><code>float temperature_PT1000 = 0; // PT1000温度</code><br><code>unsigned char OUT_Status = 0; // PTC输出状态</code><br><code>float Error_Temperature[3] = {0}; // 温度误差队列</code><br><code>const uint16_t Ts = 200; // 采样、上传、控制周期设置</code><br><code>bool FLAG_timIT0 = 0; // timer0中断标志</code><br><code>bool System_Status = 0; // 系统状态 0 - 待机;1 - 加热</code><br><code>bool List_Level = 0; // 菜单层级 0 - 主页;1 - 设置</code><br><code>bool Choose_Status = 0; // 选中状态</code><br><code>bool UIN_Error = 0; // 输入电压过低标志</code><br><code>unsigned char UIN_threshold = 10; // 电压阈值</code><br><code>unsigned char Choose_Targrt = 0; // 选中目标</code><br><code>uint16_t heating_times = 0; // 加热时间计数器</code><br><code>uint16_t heating_sum_time = 0; // 加热计数器最大值</code></p>
<p style="padding-left:40px"><code>struct element{</code><br><code> char* name;</code><br><code> char* unit;</code><br><code> unsigned char value;</code><br><code> unsigned char scale;</code><br><code>};</code><br><code>element Setting_Element[] = {</code><br><code> {"加热温度: ","℃",60,1},</code><br><code> {"加热时间: ","min",0,1},</code><br><code> {"功率限制: ","",32,8},</code><br><code> {"风扇转速: ","",64,8},</code><br><code>};</code></p>
<p style="padding-left:40px"><code>// U8G2</code><br><code>#define SDA 7</code><br><code>#define SCL 6</code><br><code>// U8G2_SH1106_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);</code><br><code>U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);</code></p>
<p style="padding-left:40px"><code>// SHT30</code><br><code>Adafruit_SHT31 sht31 = Adafruit_SHT31();</code><br><code>#define SHT30_SDA 2</code><br><code>#define SHT30_SCL 3</code></p>
<p style="padding-left:40px"><code>// Encoder</code><br><code>#define KeyA 20</code><br><code>#define KeyB 21</code><br><code>Encoder Enc(KeyB, KeyA);</code><br><code>long oldPosition=-999;</code><br><code>long newPosition=0;</code></p>
<p style="padding-left:40px"><code>void EncoderRead(){</code><br><code> if(Enc.read() != oldPosition) {</code><br><code> newPosition = Enc.read();</code><br><code> Serial.println(newPosition);</code><br><code> if(List_Level){</code><br><code> if(Choose_Status){</code><br><code> if(newPosition>oldPosition){</code><br><code> Setting_Element[Choose_Targrt].value+=Setting_Element[Choose_Targrt].scale;</code><br><code> }</code><br><code> else{</code><br><code> Setting_Element[Choose_Targrt].value-=Setting_Element[Choose_Targrt].scale;</code><br><code> }</code><br><code> }</code><br><code> else{</code><br><code> if(newPosition>oldPosition){</code><br><code> Choose_Targrt+=1;</code><br><code> }</code><br><code> else{</code><br><code> Choose_Targrt-=1;</code><br><code> }</code><br><code> if(Choose_Targrt>3){</code><br><code> Choose_Targrt=0;</code><br><code> }</code><br><code> }</code><br><code> }</code><br><code> oldPosition=newPosition;</code><br><code> }</code><br><code>}</code></p>
<p style="padding-left:40px"><code>// OneButton</code><br><code>#define Key1 10</code><br><code>OneButton button(Key1, true);</code></p>
<p style="padding-left:40px"><code> // 按键单击</code><br><code>void Click1() {</code><br><code> Serial.println("click");</code><br><code> List_Level = !List_Level;</code><br><code> Choose_Status = 0;</code><br><code> Serial.println(List_Level);</code><br><code>}</code><br><code> // 按键长按</code><br><code>void longPressStart() {</code><br><code> Serial.println("longPressStart");</code><br><code> if(!List_Level){</code><br><code> if(1){//voltage_UIN > UIN_threshold){</code><br><code> System_Status = !System_Status;</code><br><code> heating_times = 0;</code><br><code> heating_sum_time = Setting_Element[1].value *300;</code><br><code> }</code><br><code> else{</code><br><code> UIN_Error = 1;</code><br><code> }</code><br><code> }</code><br><code> else{</code><br><code> Choose_Status = !Choose_Status;</code><br><code> }</code><br><code>}</code></p>
<p style="padding-left:40px"><code>// 数据读取</code><br><code>void dataRead() {</code><br><code> temperature = sht31.readTemperature();</code><br><code> humidity = sht31.readHumidity();</code><br><code> UIN = analogRead(UIN_IN);</code><br><code> voltage_UIN = UIN*0.006046; // 1/4096*3.3*8.5 取决于ESP32-C3系数需要自行校准</code><br><code> // PT1000 = analogRead(PT1000_IN);</code><br><code>}</code></p>
<p style="padding-left:40px"><code>// PID</code><br><code>float Kp=0.1, Ti=125, Td=5;</code><br><code>uint16_t P_Term=0, I_Term=0, D_Term=0;</code></p>
<p style="padding-left:40px"><code>void PidCtrl(){</code><br><code> // PID项计算</code><br><code> P_Term = Error_Temperature[0] - Error_Temperature[1];</code><br><code> I_Term = Error_Temperature[0];</code><br><code> D_Term = Error_Temperature[0] - 2*Error_Temperature[1] + Error_Temperature[2];</code></p>
<p style="padding-left:40px"><code> OUT_Status = OUT_Status + Kp*( P_Term + Ts/Ti*I_Term + Td/Ts*D_Term );</code><br><code> // 功率限制</code><br><code> if(OUT_Status > Setting_Element[2].value){</code><br><code> OUT_Status = Setting_Element[2].value;</code><br><code> }</code><br><code> analogWrite(OUT,OUT_Status);</code><br><code> </code><br><code> // Serial.println(String(OUT_Status)+"*"+String(Error_Temperature[0]));</code></p>
<p style="padding-left:40px"><code> // 温度误差更新</code><br><code> Error_Temperature[2] = Error_Temperature[1];</code><br><code> Error_Temperature[1] = Error_Temperature[0];</code><br><code> Error_Temperature[0] = Setting_Element[0].value - temperature_PT1000;</code><br><code>}</code></p>
<p style="padding-left:40px"><code>// 定时器设置</code><br><code>hw_timer_t *timer0 = NULL; // 定时器0 采样、上传、控制刷新</code><br><code> // 状态更新</code><br><code>void onTimer0() {</code><br><code> FLAG_timIT0 = 1;</code></p>
<p style="padding-left:40px"><code> PT1000 = analogRead(PT1000_IN) *0.85+52;</code><br><code> temperature_PT1000 = (PT1000-2070)/3.11;</code><br><code> // Serial.println(temperature_PT1000);</code></p>
<p style="padding-left:40px"><code> heating_times++;</code><br><code> if(System_Status){</code><br><code> PidCtrl();</code></p>
<p style="padding-left:40px"><code> if(heating_times >= heating_sum_time){</code><br><code> System_Status = 0;</code><br><code> heating_times = 0;</code><br><code> Setting_Element[2].value = 0;</code><br><code> }</code><br><code> }</code><br><code> // Serial.println(PT1000);</code><br><code> // Serial.println(temperature_PT1000);</code><br><code> </code><br><code>}</code></p>
<p style="padding-left:40px"><code>unsigned char ITtimes=0; // 用于屏幕刷新的计数器</code></p>
<p style="padding-left:40px"><code>void setup() {</code><br><code> // put your setup code here, to run once:</code><br><code> // IO Setting</code><br><code> pinMode(OUT,OUTPUT);</code><br><code> pinMode(FAN,OUTPUT);</code><br><code> pinMode(PT1000_IN,INPUT);</code><br><code> pinMode(UIN_IN,INPUT);</code></p>
<p style="padding-left:40px"><code> // Serial</code><br><code> Serial.begin(115200);</code></p>
<p style="padding-left:40px"><code> // SHT30</code><br><code> Wire.begin(SHT30_SDA,SHT30_SCL);</code><br><code> if (!sht31.begin(0x44)) {</code><br><code> while (1) {</code><br><code> Serial.println("SHT31 sensor not found!");</code><br><code> }</code><br><code> }</code></p>
<p style="padding-left:40px"><code> // U8G2</code><br><code> u8g2.begin();</code><br><code> u8g2.enableUTF8Print();</code><br><code> u8g2.setFont(u8g2_font_wqy14_t_gb2312a);</code></p>
<p style="padding-left:40px"><code> button.reset();//清除一下按钮状态机的状态</code><br><code> button.attachClick(Click1);</code><br><code> button.attachLongPressStart(longPressStart);</code></p>
<p style="padding-left:40px"><code> // 定时器初始化</code><br><code> // 定时器0</code><br><code> timer0 = timerBegin(0,80,true); // 初始化定时器-使用定时器1</code><br><code> timerAttachInterrupt(timer0,onTimer0,true); // 绑定定时器中断服务函数</code><br><code> timerAlarmWrite(timer0,Ts*1000,true); // 设置中断 间隔为采样周期</code><br><code> timerAlarmEnable(timer0); // 启动定时器</code><br><code>}</code></p>
<p style="padding-left:40px"><code>void loop() {</code><br><code> // put your main code here, to run repeatedly:</code><br><code> EncoderRead();</code><br><code> button.tick();</code></p>
<p style="padding-left:40px"><code> if(FLAG_timIT0){</code><br><code> FLAG_timIT0 = 0;</code></p>
<p style="padding-left:40px"><code> dataRead();</code><br><code> if(System_Status){</code><br><code> analogWrite(FAN,Setting_Element[3].value);</code><br><code> }</code><br><code> else{</code><br><code> analogWrite(FAN,0);</code><br><code> analogWrite(OUT,0);</code><br><code> }</code><br><code> </code><br><code> ITtimes++;</code><br><code> if(!List_Level){</code><br><code> if(ITtimes >= 4){</code><br><code> ITtimes = 0;</code></p>
<p style="padding-left:40px"><code> u8g2.clearBuffer();</code><br><code> u8g2.setCursor(0, 15);</code><br><code> u8g2.print("箱内温度: "+String(temperature)+"℃");</code><br><code> u8g2.setCursor(0, 31);</code><br><code> u8g2.print("箱内湿度: "+String(humidity)+"%");</code><br><code> u8g2.setCursor(0, 47);</code><br><code> u8g2.print("输入电压: "+String(voltage_UIN)+"V");</code><br><code> u8g2.setCursor(0, 63);</code><br><code> if(UIN_Error){</code><br><code> u8g2.print("系统状态: 电压过低");</code><br><code> u8g2.drawHLine(0, 63, 128);</code><br><code> }</code><br><code> else{</code><br><code> if(System_Status){</code><br><code> u8g2.print("系统状态: 加热中");</code><br><code> }</code><br><code> else{</code><br><code> u8g2.print("系统状态: 待机");</code><br><code> }</code><br><code> }</code><br><code> u8g2.sendBuffer();</code><br><code> }</code><br><code> }</code><br><code> else{</code><br><code> if(ITtimes >= 1){</code><br><code> ITtimes = 0;</code></p>
<p style="padding-left:40px"><code> u8g2.clearBuffer();</code><br><code> for(unsigned char i=0; i<=3; i++){</code><br><code> u8g2.setCursor(0, (i+1)*16-1);</code><br><code> u8g2.print(Setting_Element[i].name+String(Setting_Element[i].value)+Setting_Element[i].unit);</code><br><code> if(Choose_Targrt == i){</code><br><code> if(Choose_Status){</code><br><code> u8g2.setCursor(112, (i+1)*16-1);</code><br><code> u8g2.print("*");</code><br><code> }</code><br><code> u8g2.drawHLine(0, (i+1)*16-1, 128);</code><br><code> }</code><br><code> }</code><br><code> u8g2.sendBuffer();</code><br><code> }</code><br><code> }</code><br><code> }</code><br><code>}</code></p>
</div>
评论(30)