在这两个帖子的第一部分中,我分享了一个建立在树莓派和铁锈之上的温馨制造者项目的过程。与其说它是一个指南,不如说它是一个故事,但它提供了一个有趣的遇到问题的年表。在第2部分中,我将介绍一些技术性内容,并对铁锈进行深入讨论。此项目的源代码可在Github上找到。
我有幸和最近搬到海边小镇的爱丽丝一家一起过暑假。蒂姆是这个家庭的族长,得知他那一系列令人印象深刻的航海工具之外,他的潮汐钟读数从来都不准确,这让他心烦意乱。这是我们如何为他做了一份令人惊喜的60岁生日礼物的故事,他永远不会忘记:
大多数人都知道卫星的引力会导致水位有规律的涨落。那些关心海洋的人可能会背诵6小时10分钟作为退潮和涨潮之间的时间。以手表或挂钟为例,大多数机械钟已经记录了每天12小时的时间。只需对传动比稍作调整,就可以轻而易举地造出一个报告12小时25分钟潮汐周期的时钟。事实上,这就是大多数装饰性潮汐钟的工作方式。
然而,我惊讶地发现潮汐可以是不对称的!而不是6个小时,潮水可能需要7个小时才能进来,5个小时才能再次退潮。当地的环境因素,如河口盆地的浅薄,可以对潮汐规律产生显著的影响。在极端的地方,如墨西哥湾,这足以将规则周期从一天四次潮汐减少到只有两次潮汐。
这对钟表匠来说是一场灾难!这种不对称性也会随着月亮周期的变化而变化,所以机械钟不可能一直走错。如果你仔细想想,这是有直觉的。水是东西。当潮汐改变时,这些东西必须去某个地方。如果有什么东西让东西很难移动,比如浅水盆地中的沙洲,它就会让东西堆积起来。物质的变化越大,比如临近大潮,堆积的情况就会越多。如果当潮汐改变时,这些东西还在那里,那么净效应将是一场不对称的潮汐。
在我看来,这是物联网驱动设备的完美应用。通过外包问题并从API获取数据,这意味着真相的来源将始终是准确的。此外,数字显示器可以准确地显示不对称的潮汐和洪水。
起初,我考虑使用Arduino,因为我的工具箱里已经有一台了,还有一个兼容的LED屏幕。最终,我选择了阻力最小的路径,因为树莓PI配备了一个集成的WiFi芯片。与Arduino不同,PI是一台运行整个操作系统的微型计算机。这是一种大锤方法,但考虑到该项目最终将掌握在不熟悉嵌入式技术的人手中,这是有优势的。如果WiFi连接中断或需要更改,登录桌面将是一种更友好的体验。
在确定了Raspberry PI的构建之后,下一项工作就是找到一个合适的显示器。考虑到潮汐变化相对较慢,使用电子墨水显示器来实现疯狂的电力效率是很有诱惑力的。如果时钟是电池供电的,这可能是必要的,然而,保持PI运行的需要意味着我们已经承诺使用插电式电源。最后,我选择了128x32像素的WaveShare 1305。它方便的帽子形状意味着没有焊接。而且,与我已经拥有的标准LED屏幕相比,OLED看起来棒极了。
在这一点上,我仍然不确定要使用哪种编程语言。虽然树莓PI可以运行编译成Linux的任何东西,但与屏幕的通信是通过PI的GPIO引脚(通用输入/输出)进行的。所有信息都通过上下设置引脚来传输,让人想起在Arduino和其他嵌入式平台上工作的感觉。尽管屏幕只有128x32(又名4096)像素,但这远远超过了PI';的40个GPIO引脚可以单独寻址的目的地。幸运的是,协议(在本例中为SPI)用于将数据打包成可通过IO引脚的有限带宽发送的压缩块。
屏幕制造商提供了3个代码示例:1个是用Python编写的,2个是用C编写的。考虑到项目的在线性质,Python是我的直接选择,但我就是不能让它工作。这两个C样本很好奇。其中一个构建在控制GPIO引脚的嵌入式Broadcom芯片的自带驱动程序之上。另一个是在wiringPI之上编写的,wiringPI是Raspbian(也就是PI风格的Linux OS)附带的,似乎是进行IO的最佳途径。然而,当我得知这个开源项目在很大程度上是一个人的努力时,我感到很难过,他后来因为开源疲惫而辞去了维护人员的职务。这是我最近经常看到的一种令人担忧的趋势。
尽管如此,当前的wiringPI示例仍然工作良好。从理论上讲,我确信用C语言完成项目的其余部分是完全可能的。不过,作为一种语言,C语言往往不包括电池。在图像处理、数据解析、获取URL和日期时间咀嚼过程中跌跌撞撞的前景并不让我感到高兴,特别是考虑到我基本的C语言经验。我更愿意在一个不需要我先造铲子的游戏坑里堆沙堡。
很长一段时间以来,我一直对锈病很好奇,它做了很好的工作,将自己确立为过去C语言是唯一可行的候选者(高性能或内存受限)的工作负载的替代方案。它在没有放弃一流的开发经验的情况下做到这一点,是它成为如此受人喜爱的语言的众多原因之一。通过包裹管理器,货物,我将有一个繁荣的生态系统的第三方图书馆(又名板条箱)在武器触手可及。事实上,我很快就找到了Rppal(Raspberry PI外围接入层),这是一个用于管理GPIO的Rust机箱。
#使用板条箱只需编辑cargo.toml文件[]image=";0.23.8";chrono=";0.4";serde={version=";1.0";,Feature=[";派生";]}serde_json=";1.0";toml=";0.5";ordered-loat=";2.0";reqwest={Version=";0.10";,Feature=[";json";]}Tokio={version=";0.2";,Feature=[";Full";]}Simple-Error=";0.1.9";[]rppal=";0.9.0";
也有很多理由不选择铁锈。离生日聚会只剩不到几个星期了;如果我们要实现惊喜,那就意味着要坚持一个非常积极的时间表。RPPAL不是布线PI的端口,SPI协议的实现细节可能在微妙但基本的方面有所不同,足以影响整个工作。铁锈公司的借阅检查器对外行来说是臭名昭著的不宽容之举(它真的有点混蛋)。如果我是一个负责任的领导,我可能会命令部队带着C长途跋涉,但黑客项目真的应该是关于个人熏陶的。所以去他妈的,能有多难呢?
这么说吧,我被打了一顿,诸如此类的事之后需要一个甜甜圈形状的坐垫。铁锈的学习曲线是出了名的陡峭,希望在如此紧凑的时间表上摸索它可能是乐观的。值得称赞的是,有很多逃生口可以让你摆脱(或陷入)麻烦。这在编写您自己的代码时很有用,但是通过使用第三方库,您可以更流利地使用惯用的Rust。
理解习惯用法很难操之过急,因为它需要广博的见识。我现在的情况好多了,但作为我的第一个接触点,我就是想不出我应该如何使用RPPAL图书馆。梳理ChangeLog揭示了一次大的重构,朝着更加惯用和类似铁锈的API方向发展。通过恢复到早先不那么惯用的版本,我发现了一张厚颜无耻的出狱卡。突破性进展,最后,一个像素标志着营业时间。
既然画好了,下一个问题就是画什么?作为回答,我打开了一个像素编辑器,进行了一个微型设计冲刺。几次迭代之后,我有了一张单独的图像,作为我的设计文档。
这就是为什么这个项目如此有趣的一个很好的例子。问题空间为抽象的每一层都留下了伸展肌肉的空间,同时又受到足够的限制,以避免成为繁重的杂务。字体呈现是另一个例子。通过使用从精灵工作表复制切片的老式技术,我不必为字体文件或字体渲染库而烦恼。
为了帮助我复制切片,我依靠图片箱。再一次,我在理解API时进行了高度的摸索,但一旦我这样做了,库的质量就给我留下了非常深刻的印象。即使生态系统在技术上仍在成熟,已经展示的质量宣布了铁锈作为一个严肃的竞争者的到来。
//加载字体精灵工作表//并映射单个字符面pub fn new()->;{let p=::new(";resources/Font-5px.png";);let img=open(P)的截断示例。展开()。To_rgb();让mut faces=::new();faces。插入(';1';,img。视图(0,0,1,5)。To_image());人脸。插入(';2';,img。查看(2,0,3,5)。To_image());人脸。插入(';3';,img。查看(6,0,3,5)。To_image());...。面孔。插入(';X';,img。查看(95、6、3、5)。To_image());人脸。插入(';Y';,img。查看(99、6、3、5)。To_image());人脸。插入(';Z';,img。查看(103、6、3、5)。To_image());{faces}}。
到目前为止,我一直在Raspberry Pi3上直接进行所有的开发。它工作得很好,但我非常想念在完整的开发环境中可以享受的生活质量功能。这个图片箱非常方便,我也开始用它来做其他的绘图操作,直到我意识到我可以用它做任何事情。这是完美的抽象层。在PI上,我可以在后台缓冲将渲染纹理复制到屏幕上,而在Windows上,我只需将其保存到位图即可。
获得对Visual Studio代码的访问权和Rust Analyser最终以我的方式倾斜了生产力的天平。铁锈分析器尤其关键,因为它会给你代码提示和类型标签。这帮助我理解了我以前是如何在各种API上绊倒脚趾的。
从现在开始,只需填写细节即可。我创建了一个简单的文本字段结构,可以对所有文本标签重复使用。简单的线条画例程帮助我画出了直边。这张图只是一系列垂直线,后端API中的每个数据点对应一条垂直线。为了在过去和未来之间创造更强烈的视觉对比,我部署了一个基本的泛洪填充算法来擦除填充,只留下水位轮廓。
找到可靠、准确的潮汐数据来源是整个项目的基石。自然界中的潮汐比天气更容易预测,所以我想我很有可能在网上找到一些免费的、开放的东西。
相反,我发现的是一条昔日辉煌和破碎的愿景的踪迹。曾经免费的数据源现在要么被关闭,要么被付费墙关闭。在某些情况下,这些收费墙陡峭得离谱。用于导航的数据确实似乎是对娱乐数据的截然不同的切割,但我们仍然无法证明这样的成本是合理的。
有趣的开源选择是XTide。它本质上是建模软件,通过提供潮汐站测量的谐波振荡,您可以计算自己的潮汐表格。如果您觉得足够勇敢,这可能是唯一完全免费的解决方案。
最后,我选择了worldtides.info。这是一项付费服务,但预付费信用允许单个用户非常经济地访问。通过节约API调用,我计算出10美元足够维持几十年!希望这不会带来厄运,但免费订阅的选择可能会持续很长时间。
WorldTides API干净且经过深思熟虑。有一个方便的网络控制台可以浏览可用的数据。API还可以指定步长。一个不错的胜利,因为我没有担心重采样或走样问题。我可以简单地要求API提供与我的图形的分辨率相匹配的示例。
在整个项目中,我一直在Raspberry PI 3B+上测试迭代。然而,以太网和USB端口上的焊接意味着它不太适合计划中的外壳。别担心,我们可以用较小的外形因子Raspberry Pi Zero W发货。假设我保留了PI 3以备将来使用,那么总体建造成本的降低是一个额外的好处。
你花10美元就能买到一台可以正常工作的电脑,这仍然让我印象深刻。当然,当你拥有了所有必要的电缆和部件时,它更像是25美元--但这仍然是一个疯狂的壮举。不过,最好希望你不要着急,因为处理器有点像土豆。但是对于这个用例来说,这已经足够了。
在我看来,替换只是在两个设备之间交换SD卡的问题。但是,运行应用程序只会产生分段故障。哦,天哪!原来Zero使用ARMv6,而后来的PI型号使用ARMv7芯片组。在一轮过度的咒骂之后,我接受了我将不得不做一些真正的软件工程的事实。
虽然Rust为您所期望的平台提供了一个非常好的跨平台编译故事,但这已经进入了泥潭。在几次失败的开始之后,我终于拼凑出了一条可靠的构建管道。基于Piers Finlayson的这个奇妙的解释,我能够使用他提供的docker图像作为GitLab构建脚本的一部分。这意味着每次我推到我的GitLab回收库时,它都会为我生成一个新的ARMv6版本。虽然不像货物运输那样方便,但也可以。
在编程的同时,我们开始为PI建造一个家园。大流行使人们无法进入制造者空间或车间,这是一项独特的挑战。但和以往一样,约束会滋生创造力。部分受到现有潮汐钟的启发,我们萌生了用钟作为便宜但好看的外壳的想法。
我们无法预测内部的每一款产品会是什么样子,考虑到迫在眉睫的最后期限,我们给了自己三款产品可供选择。我们仔细地拆卸了每一个,以衡量大小、出入和通风的便利性(我不想烧毁房子)。选出赢家后,我们小心翼翼地把另外两个放在一起,然后把它们送回亚马逊。
整个夏天,蒂姆一直在一个丰收的天文季节与我们分享宇宙奇观。“龙人”太空舱天桥上,彗星NEOWISE、土星和木星处于对立状态,后来又加入了火星的行列。你通过望远镜目镜第一眼看到木星的光环或土星的光环,这是你终生难忘的记忆。
虽然月球主题是显而易见的选择,但他60岁生日那天的星图似乎更适合向我们的夏天致敬。这是受到一些服务的启发,这些服务将日期标明日期的星图作为独特的礼物打印出来。当然,我们必须推出Illustrator并推出我们自己的彩蛋,但这样做可以让我偷偷地放入一些个性化的复活节彩蛋。
关于星座:我一直认为会有某种规范的定义来定义哪些恒星构成了一个星座。然而,在逐个仔细研究了每一个之后,来源差别很大。我不得不根据美学做出几个判断。只是为了说明它们是多么武断的概念。
在讨论了各种打印设计的方法后,印刷店建议用乙烯基背激光切割丙烯酸。外包这一部分是建造过程中最昂贵的部分之一,但也是专业的光泽将整个礼物提升为值得珍视的东西。
我要感谢爱丽丝,她不仅是这个项目的共同发起人,而且还处理了大量雇佣打印机之类的工作。特别是当第一次迭代的打印质量还有很多需要改进的时候,很多来回的事情接踵而至。有一次,爱丽丝甚至让她的一位设计师同事代表我们给商店打了电话!
当我们把文件送到打印店的时候,我们还不能确切地确定这些文件将如何组合在一起。考虑到我们将从乙烯基切脸,我包括了一些额外的半圆形切割,以防我们需要一些垫片。事实证明,这是一个非常聪明的主意,因为我不确定没有它们,一切都会怎么样。它还允许我们附上一个弯曲的回形针,以确保脸部保持直立。
我的目标之一是尽可能多地利用现有的结构。通过一点钻孔和一盒PCB支架,我能够将PI直接连接到原来的钟面上。PI 3可能会变得很热,所以我有点担心热量。一些钢锯和钻探创造了一个不错的排气口,尽管Pi Zero的弱处理器的一个好处是它运行起来相当酷。不过,小心一点也无伤大雅。
在这一点上,几乎整个家庭都参与了这个诡计。我们还把一半的工具走私出车库。考虑到锈蚀的所有障碍,并让它在Pi Zero上运行,编程还远远没有完成。我们也不想承诺锯掉时钟结构,直到我们完全知道我们将使用哪种设备。取而代之的是,我匆忙拼凑了一段简短的歌舞,解释了这个设备是什么,并对Blu-tack保持这一切抱有很大的信心。
直到最后一刻,蒂姆仍然没有注意到我们正在酝酿的东西。据他所知,我在房间里熬夜的原因是加班过多。不用说,当我们揭穿这个骗局时,他的脸亮了起来,到最后,周围有几只泪水汪汪的眼睛,即使我们需要立即收回它。
生日聚会结束后,我可以拨回一个更悠闲的节奏。在接下来的几周里,我将完成编程,研究如何在Zero上运行,并对构建进行最后的润色。总而言之,在未来很长一段时间里,我们都会记住这件事。