本帖最后由 怀若谷 于 2022-6-13 10:27 编辑  
 
创客奶爸造物记系列: 
 
↑演示视频↑  
 
【创作背景】  
 
 
图1  
在冲泡奶粉时,适度的水温是保证营养成分最大程度保留的关键。通常奶粉罐上会有冲泡指南,其中会有关于水温的建议(如图1)。大多数婴幼儿奶粉品牌建议水温在40℃~50℃范围,那怎么得到合适温度的温水呢?人们一般会使用温奶(水)器保温、自然冷却、热水兑冷水的方式。 
 
图2  
有时为了赶时间,我会采用热开水兑冷开水的方式,但是感觉调出的温度高低不定,所以就冒出一个问题:如何能更精准地调制出合适温度的温水(该使用多少热水和冷水混合)呢?我琢磨了一段时间,发现这其实是一个很普通的物理问题,已经有现成的热量公式(见图2)可用,只要借助创客器材和技术实现智能测温和自动计算就可以解决。 
 
当然,有些朋友可能会认为热水兑冷水的方式不可取,那我们暂且抛开泡奶粉这件事吧,来解决如何调制温水的问题好了。 
 
项目制作伊始,主控板采用了Arduino Uno,使用了一块LCD12864显示屏,由于要显示的信息较多,显示效果不太理想。这时正好收到了一块DFRobot新出品的行空板,各方面的性能比Arduino Uno更优越,配备的那块2.8寸的彩屏更是让我欣喜。于是,将原来的硬件配置方案做了调整,改为使用行空板作为主控板,对原来的信息显示方式也做了重新设计。 
 
【认识行空板】  
 
图3  
行空板(见图3)是一款专为Python学习和使用设计的新一代国产开源硬件,采用单板计算机架构,集成LCD彩屏、WiFi蓝牙、多种常用传感器和丰富的拓展接口。从硬件配置及参数上看,它是一块性能非常出色的主控板,可供创作功能更加强大的创客作品。更可喜的是,它支持多种编程软件和连接方式,可以供使用者更方便地学习Python语言,还提供了入门级的图形化编程环境,即使是小学生也能快速上手。 
 
对于习惯了使用Mind+软件的朋友,需要注意一下:适用于行空板的Mind+版本暂时还未正式发布,大家可到https://wiki.unihiker.com/去下载测试版。 
 
 
【功能描述】  
图4  
 
本作品配有两个DS18B20防水温度传感器,能够同时检测两路水的温度;面板上有两个旋钮,用来设置需要调制的温水的量(体积)和温度(见图4)。 
图5  
当热水的温度高于需要调制的温度时,才会启动计算水量程序,得出需要混合的热水量和冷水量(见图5)。上面提到的三个体积值、三个温度值都会实时显示在屏幕上,并辅以条形图进行直观呈现。 
 
【制作过程】  
 
一、材料准备 
图6  
 
本项目使用了以下硬件材料(图6): 
 
1.行空板  1块  
 
2.DS18B20温度传感器(防水)  2个 
 
3.旋钮电位器  2个 
 
4.USB线 1根 
 
5.3P连接线 4根 
 
二、硬件搭建 
图7  
行空板集成了4个3Pin I/O接口,引脚分别为P21、P22、P23、P24,本项目使用的4个传感器连接的对应引脚如下(实物图见图7): 
 
旋钮电位器(蓝)——P21 
 
旋钮电位器(黄)——P22 
 
DS18B20温度传感器 ——P23 
 
DS18B20温度传感器 ——P24 
 
三、程序设计 
图8  
本项目程序采用了Mind+软件编写,软件版本为V1.7.2 RC3.0。为行空板编写程序时,需要切换到“Python模式”,在“扩展”中找到并加载“行空板”库;本项目使用了DS18B20温度传感器,还需要加载“DS18B20温度传感器”库。 
 
利用Mind+对行空板进行编程时,可以使用图形化积木模块编程,也可以使用代码编程。以下为本项目的代码示例,分为六个部分展示。 
(一)加载所需库文件
			
			
			复制代码 (二)定义函数“numberMap”(映射)#定义函数:映射 
- def numberMap(x, in_min, in_max, out_min, out_max):
 
  复制代码 (三)定义函数“calculation”(计算) 
- # 自定义函数:计算所需冷热水量
 - def calculation():
 -     ok = 0   #是否完成求解,默认值为0(否)
 -     m_hot = 0  #设热水量初始值为0mL(g),通过枚举法求解
 -     while not ((ok == 1)):  #重复执行下面的指令,直到找到答案
 -         m_hot = (m_hot + 1)   #每循环一次,热水量的值递增1mL
 -         m_cold = (m_total - m_hot)  #冷水量的值等于总水量减去热水量的值
 -         Q1 = (4.2 * (m_hot * (t_hot - t_end)))     #计算热水的放热量Q1
 -         Q2 = (4.2 * (m_cold * (t_end - t_cold)))   #计算冷水的吸热量Q2
 -         if ((abs((Q1 - Q2))) < 200):     #当Q1和Q2的数值很接近时(完全相等很难),说明求解成功
 -             ok = 1                 #是否完成求解标记,设为1(是)
 -     M1.config(text=(str(m_hot) + str("mL")))    #更新热水量的数值
 -     SQU20.config(h=(-0.7 * m_hot))              #更新热水量对应的矩形高度
 -     M2.config(text=(str(m_cold) + str("mL")))   #更新冷水量的数值
 - SQU30.config(h=(-0.7 * m_cold))              #更新冷水量对应的矩形高度
 
  复制代码 (四)初始化设置 
- Board().begin()  #主控板初始化
 - u_gui=GUI()      #实例化GUI
 - p_p21_analog=Pin(Pin.P21, Pin.ANALOG)   #设置P21为模拟输入引脚,连接旋钮电位器1
 - p_p22_analog=Pin(Pin.P22, Pin.ANALOG)   #设置P22为模拟输入引脚,连接旋钮电位器2
 - ds1_hot = DS18B20(Pin((Pin.P23)))  #设置P23为对象为ds1_hot,连接DS18B20,用来检测热水温度
 - ds1_cold = DS18B20(Pin((Pin.P24))) #设置P24为对象为ds1_cold,连接DS18B20,用来检测冷水温度
 
  复制代码
  
(五)设置用户界面 
- #设置用户界面
 - BG=u_gui.draw_image(image="bg.png",x=0,y=0) #设置背景图片
 - WORD0=u_gui.draw_text(text="温水调制助手",x=54,y=5,font_size=15, color="#000000")
 - WORD10=u_gui.draw_text(text="调制水量",x=5,y=235,font_size=12, color="#FFFF00")
 - WORD11=u_gui.draw_text(text="调制温度",x=5,y=275,font_size=12, color="#FFFF00")
 - BG10=u_gui.fill_rect(x=6,y=255,w=64,h=17,color="#FFFFFF")
 - M0=u_gui.draw_text(text="0mL",x=8,y=250,font_size=13, color="#000000")
 - BG11=u_gui.fill_rect(x=6,y=297,w=64,h=17,color="#FFFFFF")
 - T0=u_gui.draw_text(text="0℃",x=13,y=290,font_size=15, color="#000000")
 - SQU10=u_gui.fill_rect(x=13,y=230,w=25,h=-10,color="#00FF00")
 - SQU11=u_gui.fill_rect(x=39,y=230,w=25,h=-10,color="#FF6666")
 - WORD20=u_gui.draw_text(text="热水水量",x=85,y=235,font_size=12, color="#FFFF00")
 - WORD21=u_gui.draw_text(text="热水温度",x=85,y=275,font_size=12, color="#FFFF00")
 - BG20=u_gui.fill_rect(x=86,y=255,w=64,h=17,color="#FFFFFF")
 - M1=u_gui.draw_text(text="0mL",x=86,y=250,font_size=13, color="#000000")
 - BG21=u_gui.fill_rect(x=86,y=297,w=64,h=17,color="#FFFFFF")
 - T1=u_gui.draw_text(text="0℃",x=88,y=290,font_size=15, color="#000000")
 - SQU20=u_gui.fill_rect(x=93,y=230,w=25,h=-1,color="#00FF00")
 - SQU21=u_gui.fill_rect(x=119,y=230,w=25,h=-1,color="#FF0000")
 - WORD30=u_gui.draw_text(text="冷水水量",x=165,y=235,font_size=12, color="#FFFF00")
 - WORD31=u_gui.draw_text(text="冷水温度",x=165,y=275,font_size=12, color="#FFFF00")
 - BG30=u_gui.fill_rect(x=166,y=255,w=64,h=17,color="#FFFFFF")
 - M2=u_gui.draw_text(text="0mL",x=168,y=250,font_size=13, color="#000000")
 - BG31=u_gui.fill_rect(x=166,y=297,w=64,h=17,color="#FFFFFF")
 - T2=u_gui.draw_text(text="0℃",x=166,y=290,font_size=15, color="#000000")
 - SQU30=u_gui.fill_rect(x=173,y=230,w=25,h=-1,color="#00FF00")
 - SQU31=u_gui.fill_rect(x=199,y=230,w=25,h=-1,color="#FFCCCC")
 
  复制代码
  
以上代码执行后可以呈现如图9所示样式的用户界面,在后面的程序运行中只要对某些对象的参数值进行更新操作即可。 
 
  
 
图9  
 
(六)循环执行部分 
-  #循环执行
 - while True:       
 - t_hot = ds1_hot.temp_c()     #读取ds1_hot对应的温度值,赋给变量t_hot
 -     t_cold = ds1_cold.temp_c()   #读取ds1_cold对应的温度值,赋给变量t_cold
 -     T1.config(text=(str(t_hot) + str("℃")))   #更新热水温度值
 -     T2.config(text=(str(t_cold) + str("℃")))  #更新冷水温度值
 -     SQU21.config(h=(-2 * t_hot))    #更新热水温度对应的矩形高度
 -     SQU31.config(h=(-2 * t_cold))   #更新冷水温度对应的矩形高度
 - 
 -     #读取P21的模拟值,通过映射及乘10处理,转换为20-200的整十数,该数值为调制水量
 -     m_total = (10 * (round((numberMap(p_p21_analog.read_analog(), 4095, 0, 2, 20)))))
 -     #读取P22的模拟值,通过映射及乘2处理,转换为36-60的2倍数,该数值为调制温度
 -     t_end = (2 * (round((numberMap(p_p22_analog.read_analog(), 4095, 0, 18, 30)))))
 -     M0.config(text=(str(m_total) + str("mL")))  #更新调制水量的数值
 -     SQU10.config(h=(-0.7 * m_total))            #更新调制水量对应的矩形高度
 -     T0.config(text=(str(t_end) + str("℃")))    #更新调制温度的数值
 - SQU11.config(h=(-2 * t_end))                #更新调制温度对应的矩形高度
 - 
 -     if (t_hot > t_end):         #当热水温度高于调制温度时,调用函数calculation进行求解
 -         calculation()
 -     time.sleep(0.3)    #等待0.3秒
 
  复制代码
  
四、结构设计及加工 
(一)绘制图纸 
图10  
使用LaserMaker软件绘制结构和造型图纸(图10)。其中主机部分设计为类似手机外形,面板和底板采用亚克力材料,侧边为多个椴木板边框叠加而成;盛水部分为一个留有两个圆口的长方体盒子,用来放置两个量筒,还设计了一个配套的测温探头固定装置。 
 
(二)切割加工 
图11  
使用激光切割机分别对椴木板和亚克力板材料进行切割加工(图11),使用的加工工艺有切割、浅雕和描线等。切割好的全部部件如图12、图13所示。 
 
图12  
图13  
 
五、成品组装 
 
图14 1.将DS18B20温度传感器主固定在底板上;在底板四角装上双通尼龙柱(图14) 
 
图15 2.将7个侧边部件叠放整齐,钉入4个木楔使之成为一体(图15) 
 
图16 3.使用热熔胶将侧边框与底板粘合起来(图16) 
 
图17 4.在底板上,从下而上插上3根长螺丝,螺母不拧紧,稍留间隙(图17) 
 
图18 5.放上行空板,将底板上的3根螺丝拧进行空板背面的安装螺丝孔(图18) 
 
图19 6.将旋钮电位器安装在面板上(图19) 
 
图20 7.合上面板,将4根螺丝插进螺丝孔,与双通尼龙柱连接紧固(图20) 
 
图21 8.组装盛水部分的盒子(图21) 
 
图22 9.放进两个小量筒(图22) 
 
图23 10.将DS18B20的金属探头固定在8字形板件上(图23) 
 
六、调试优化 
图24 在量筒中分别倒入热水和冷水,测试设备是否工作正常(图24)。测试过程中,先看看测温功能是否正常;然后转动旋钮,观察调制水量和调制温度是否能及时随之变化;不断改变调制水量和调制温度,观察能否及时准确地计算出对应的热水量和冷水量;检查用户界面的显示效果。 
 
及时记录下测试过程中发现的问题,进行分析并通过修改程序解决,以实现预定的全部功能。 
 
【总结反思】 图25 经过多次测试后,感觉这个设备运行良好,是一件较完美的创客作品。但是,也存在一些需要改进的地方。 
 
项目中用到的这种DS18B20温度传感器,最高显示温度为85℃,所以对于这个项目来说还是难以胜任的,开水的温度是100℃,即使是热水瓶里的水,很长一段时间内温度都在85℃以上。所以,真正要使用的话,还需要换用其他温度传感器。 
 
使用了集成IO接口的主控板制作创客作品时,不用再加扩展板,外型能够做到更加精致小巧。如果使用3D打印技术结合激光切割来完成这个项目的造型和结构设计,我想会更加理想。当然,那得花费更多的时间。 
 
图26  
这是我第一次使用Python代码来制作项目,期间遇到了不少困难,最后通过找资料、看教程、对照图形化指令等途径顺利完成任务,算是一次难得的学习之旅!使用代码编程时,会让我们看到更深入的东西,比如图形化编程环境下的“映射”积木(图),拖拽并填入5个参数就完了;而在纯代码环境下,则需要掌握它的算法,为其编写函数,然后再调用。在Python学习风潮日益盛行的今天,作为一个创客教育者,需要与时俱进! 
 
 
 
 
 
 |