使用一台28BYJ-48步进电机和一个ULN2003驱动板构建一个天气数据雕塑
这个项目旨在为我学校物理计算课程的数据变化进行可视化。项目必须围绕“培育光明”这一主题展开。老师允许我自由诠释这一主题,因此我选择了更直接的方式。我希望将“培育光明”表现为世界中的物理亮度,即当外界光线更明亮时(例如在夏季),生命感也更加明显。
雕塑的创意是一棵树,树上长出“果实”(用灯光表示),会根据芝加哥的天气变化颜色和亮度。此外,我在盒子侧面添加了一道彩虹,会在我的盒子“天空”中旋转。项目接近尾声时,我还加入了动物和一个迷你篝火等额外细节。
使用 OpenWeather API
在本项目中,我使用了 OpenWeather API 来获取数据,该 API 从芝加哥市中心以南几英里处的一个气象站获取信息。为了获取数据,我在 Particle IDE 中创建了一个 webhook 集成,通过我的 API 端点来调用数据。为了获得 API 端点,我访问了 openweathermaps.org 并注册了一个 API 密钥。
我创建了API端点后,便前往Particle的IDE并创建了一个GET类型的Webhook。
我的API端点返回了一个包含大量我无需使用的值的JSON对象。
为了解决这个问题,我使用了一个自定义的响应模板,以易于使用的格式从JSON中提取所需的数据。该模板是
{"w":"{{weather.0.main}}", "t":{{main.feels_like}}, "ws":{{wind.speed}}}
它只提取了天气信息,包括天气类型(例如:“多云”、“晴天”、“雨天”等)、“体感温度”以及风速。
在我的项目中,我的回调函数每10秒运行一次。这意味着每隔10秒,我的Particle Photon就会发布getWeatherInfo回调,并从API端点获取JSON数据。我创建了一个extractInfo函数,以便每次回调运行时都能使用API返回的JSON数据。
在我的项目中,我使用了一台28BYJ-48步进电机和一个ULN2003驱动板。
设置
为了设置我的电机,我将驱动板上的IN1、IN2、IN3和IN4引脚分别连接到Photon上的D1、D3、D4和D5引脚。我没有使用D2,因为我的LED是通过D2引脚进行寻址的。
以下是用于设置我电机的全局变量。
由于电机转速取决于从我的API端点获取的风速,因此我在extractInfo函数中设置了电机的速度,这样每次webhook运行时,都会更新电机速度以匹配当前的风速。
为此,我创建了一个风速处理函数,将JSON数据转换为电机的速度值,通过限制风速数值并将其映射到对应的速度值来实现。
然后在我的 extractInfo 函数中,我添加了这行代码。
灯光
本项目中我使用的LED是AdaFruit的NeoPixel散射5毫米通孔LED,总共使用了5颗LED来代表我树上的“水果”。
设置
每个LED都通过我的Photon上的相同引脚D2进行寻址,并通过公对母跳线连接。每个通孔LED有4个引脚,从左到右依次为数据输入、电源、地和数据输出。对于每个LED,我使用公对母跳线将电源引脚连接到面包板的正极,将地引脚连接到面包板的负极。数据引脚是AdaFruit实现所有LED可通过同一引脚进行寻址的关键。对于数据输入和输出引脚,我首先在Photon的D2引脚与最左侧LED的数据输入引脚之间连接一条公对母跳线,然后将该LED的数据输出引脚与右侧相邻LED的数据输入引脚之间也连接一条公对母跳线。我继续这样操作,直到所有LED都相互连接完成。
以下是用于设置灯光的全局变量。
需要注意的是,这些变量中的许多与灯光本身的设置(如头、脉冲相位、precipLastMove、precipInterval 和 flip)无关。相反,它们在程序后续部分被用来编码灯光的实际模式(我稍后会详细说明)。与我的电机类似,灯光的亮度由我 JSON 中的“感觉温度”决定。因此,我在 extractInfo 内部也设置了灯光的亮度,这样每次 webhook 运行时,灯光的亮度都会被更新。
为此,我创建了一个温度处理函数,将JSON数据转换为灯光的亮度值,通过限制温度值并将其映射到亮度值来实现。
然后在我的 extractInfo 函数中,我添加了这行代码。
3D打印
为了我项目中的移动彩虹,我制作了一个小杆子,可以安装在步进电机的末端,使其能够自由旋转。我使用Tinkercad制作了这个模型。
编码模式/运动
我的项目有三种不同的视觉呈现方式:一种适用于晴朗天气,一种适用于多云天气,还有一种适用于任何降水情况。
晴朗
我的第一个图案是晴天模式。在这个模式中,我设计了一个快速移动的灯光,通过LED之间来回闪烁,形成一条在LED上发光的轨迹。每一帧中,我的代码会点亮4个LED(以头部变量为中心)。关键点在于,每个位于“头部”LED之后的位置的LED(t = 0, 1, 2, 3)都会以25%的增量逐渐变暗。
点亮LED后,头部变量每次调用都会增加一个像素,从而使光迹不断循环。
这会形成一个明亮的主LED灯,当后续LED点亮时,颜色逐渐变暗至接近黑色。该颜色为温暖的橙色/琥珀色,以代表太阳的光芒。
多云
我的第二个图案是为阴天天气设计的。这个图案中,我制作了一个缓慢呼吸的LED灯,其亮度会逐渐变暗又变亮。我用正弦波(相位为pulsePhase)来控制LED的灰度,在20到170之间平滑地摆动。由于灰度颜色需要红、绿、蓝三色都相同才能呈现,因此最终效果是一种缓慢闪烁的白灰色灯光。
降水
我的第三个也是最后一个图案用于表示降水。在这个图案中,我通过创建两个交替的组来模拟降雨效果,这些组会来回闪烁。偶数索引的LED和奇数索引的LED在每一帧之间交替显示亮色和底色。我的precipInterval变量控制它们切换的速度。
此外,灯光的颜色会根据降水类型发生变化。当天气类型为“雨”时,灯光呈深蓝色;为“细雨”时,颜色稍显柔和的蓝色;“雷暴”时,灯光变为黄色调的紫色,象征闪电和雷声;而“降雪”时,灯光则呈现近乎白色的蓝调。
总结
在将电子元件与雕塑结合之前,我首先需要通过焊接,把元件从面包板转移到实验板上。完成所有元件的焊接后,我开始着手制作雕塑。我使用棕色的干性空气干燥黏土,在灯周围塑造成一个空心的树干。树干完成后,我在灯周围摆放了一团人造苔藓,以营造出树木的叶片效果。接着,我将LED灯插入苔藓中,从而形成之前提到的“果实”。
完成树木后,我添加了草地、动物和篝火作为景观。此外,我还用纸张涂色并粘贴在3D打印的杆子上,制作出彩虹,并将其固定在盒子侧面,以便可以自由旋转。
本文编译自hackster.io





