如何构建一个 Arduino 驱动的智能家居。






4.98/5 (62投票s)
连接(激光切割)模型房屋到互联网,并控制它的灯和门!
目录
- 概述
- 项目视频
- 原型
- Arduino 代码
- 循环
- 向 Arduino 发送消息
- 简单的移动网站
- 激光切割房屋模型
- 组装和粘合
- 焊接原型板
- 测试原型板
- 制作线缆
- 安装 LED
- 安装伺服电机
- 制作窗户
- 安装原型板
- 安装 Arduino 板
- 安装电池盒
- 最终组装
- 常见问题解答
概述
现在你也可以拥有一个智能家居了!在本教程中,你将激光切割自己的模型房屋,将其连接到互联网,并构建一个移动网站来控制它!
这是我们项目的高层概览。我们将使用 PubNub,因此无需编写 Web 服务器代码。
项目设置如下
- 右侧是一个移动网站,它将消息发送到 PubNub 频道。
- 左侧是一个具有互联网连接的 Arduino 微控制器。它连接到与移动网站相同的 Pubnub 频道并监听消息。
- 当房屋收到来自频道的消息时,它会打开一个数字引脚。
- Arduino 的数字引脚连接到一个芯片,该芯片为 LED 和伺服电机供电。
- 额外的芯片为伺服电机提供电阻、接地和电源。
Web 应用和 Arduino 都通过 PubNub 网络进行通信,使用发布/订阅协议相互发送小型消息字符串。
项目视频
PubNub 物联网模型房屋 在 Vimeo 上。
原型
创建面包板原型。
对于面包板原型,您需要
零件 | 数量 | 此处使用的 | 零件 |
Arduino | 1 | Uno (Rev 3) | Arduino Uno Rev 3 |
以太网盾 | 1 | Seedstudio | Seed Studio 以太网盾 V1 |
LED | 4 | 超亮白 | Linrose BCMD333UWC-5PK Brite White T1-3/4 LED |
伺服电机 | 2 | 塑料 | HOSSEN Mini SG90 Micro 9g 伺服电机 |
电池盒 | 1 | Philmore 四节 AA 电池盒带插头 | |
电池 | 4 | Fry's 品牌 | AA |
跳线 | 20 | Sparkfun | 跳线 - 30 件装 - 零售 RTL-11242 ROHS |
面包板 | 1 | Sparkfun |
面包板 - 半透明自粘(透明) |
我在面包板上进行了电路原型设计。这是一个非常简单的电路,唯一应该引人注目的是额外的电池组。注意它与 Arduino 共享接地!
按照图示连接跳线。您可以使用简单的代码测试您的设置。尝试 闪烁示例 和 伺服电机示例。
- 我们将通过 USB 为 Arduino 供电,而不是使用上面所示的 9V。
- 图中没有显示以太网盾。我使用了 SparkFun 的以太网盾 v2,但任何版本都可以。您需要有一个互联网盾,否则您的项目将无法连接到互联网!
- 请务必为您的 LED 添加电阻。具体的电阻值将根据您使用的 LED 类型而有所不同,但您可以使用 这个方便的计算器 来确定您需要的电阻。
- 如果您没有 4xAA 电池盒,您可以将伺服电机直接连接到 5V 引脚。但是,当伺服电机连接负载时,这将不足以提供功率。您之后必须添加一个电池组,否则以太网盾将没有足够的功率。
Arduino 代码
让我们开始编码吧。
下面我们包含库并启动主 setup() 函数。此代码很大程度上基于 PubNub Arduino 示例。
您需要下载 PubNub Arduino 库并将其导入到您的项目中。
- PubNub 库使用
Ethernet.h
,但我们不需要过多使用它。 - 我们还需要为 PubNub 库提供发布和订阅密钥。目前我们将使用默认的
demo
密钥。
接下来,我们定义一个要连接的频道。在这种情况下,它是 iot_house
。这是 Arduino 代码将监听消息的 PubNub 频道。
#include <JsonArray.h> #include <JsonHashTable.h> #include <JsonObjectBase.h> #include <JsonParser.h> #include <Bridge.h> #include <HttpClient.h> #include <Servo.h> HttpClient client; Servo frontDoor; Servo garageDoor; int lightLeft = 11; int lightRight = 10; int lightRoom = 9; int lightGarage = 8; int servoDoor = 7; int servoGarage = 6; bool asyncdemo = false; void setup() { // Bridge takes about two seconds to start up // it can be helpful to use the on-board LED // as an indicator for when it has initialized Bridge.begin(); client.setTimeout(2000); pinMode(lightLeft, OUTPUT); pinMode(lightRight, OUTPUT); pinMode(lightRoom, OUTPUT); pinMode(lightGarage, OUTPUT); blink(300, 5); frontDoor.attach(servoDoor); garageDoor.attach(servoGarage); reset(); }
频道就像一个 IRC 房间,一旦 Arduino 代码连接,它就可以接收来自任何其他设备的消息,例如电脑、手机,甚至另一个 Arduino!
循环
代码使用键值语法来处理消息。当它收到消息时,它会触发一个与键同名的函数,并将值转换为布尔值,并将其作为唯一参数发送到函数。
每次处理循环时,Arduino 会通过互联网连接到 PubNub,并询问 PubNub API 是否有新消息。如果存在,PubNub 将做出响应,但如果不存在,连接将保持打开状态。在短暂超时后,PubNub 将以空数组响应,loop()
将解除阻塞并重新开始。
如果存在消息,我们会将它们作为键值对进行处理。查看我们此处总结的循环语句底部的 if/then 语句
void loop() { Serial.println("subscribe called"); String sub = "demo"; String pub = "demo"; String chan = "pubnub_iot_house"; String url = "http://pubsub.pubnub.com/subscribe/" + sub + "/" + chan + "/0/" + timetoken; char sub_buff[200]; char next_char; String thejson; Serial.println(url); client.getAsynchronously(url); // Wait for the http request to complete while (!client.ready()) { if(asyncdemo) { pingpong(1); off(); } } while (client.available()) { next_char = client.read(); Serial.print(next_char); if(String(next_char) == '\0') { break; } else { thejson += next_char; } } Serial.println("the json is"); Serial.println(thejson); int firstParen = thejson.indexOf('('); int lastParen = thejson.lastIndexOf(')'); String thejson2 = ""; for(int i = 0; i < thejson.length(); i++){ if(i == lastParen) { Serial.println("last paren"); break; } if(i > firstParen) { thejson2 += thejson[i]; } } Serial.println(thejson2); thejson2.toCharArray(sub_buff, 200); JsonParser<32> parser; JsonArray root = parser.parseArray(sub_buff); if (!root.success()) { Serial.println("fail"); } else { timetoken = root.getString(1); JsonArray messages = root.getArray(0); Serial.print("array len "); Serial.print(messages.getLength()); Serial.println(); if(messages.getLength() < 0) { Serial.println("no data"); } for(int i = 0; i < messages.getLength(); i++){ JsonHashTable message = messages.getHashTable(i); if (!message.success()) { Serial.println("fail"); } String name = message.getString("name"); String valueString = message.getString("value"); Serial.println(name + ":" + valueString); boolean value = false; if(valueString == "1") { value = true; } if(name == "door") { door(value); } if(name == "garage") { garage(value); } if(name == "lightLeft") { light(lightLeft, value); } if(name == "lightRight") { light(lightRight, value); } if(name == "lightRoom") { light(lightRoom, value); } if(name == "lightGarage") { light(lightGarage, value); } if(name == "blink") { blink(100, valueString.toInt()); } if(name == "pingpong") { pingpong(valueString.toInt()); } if(name == "demo") { demo(); } if(name == "async") { asyncdemo = value; } } } Serial.flush(); }
这是 完整代码。将此代码加载到您的 Arduino 中。
向 Arduino 发送消息
让我们试试!运行代码并检查您的串行输出。如果一切看起来都不错,让我们尝试向 Arduino 发送消息。
我们将使用 PubNub 开发者控制台 将消息发布到我们的频道。输入相同的 demo
密钥和 iot_house
频道。
正如 您在视频中看到的,我们将使用 “garage:0”
或 “lightLeft:1”
来关闭车库和打开左侧灯。
简单的移动网站
现在 Arduino 已经工作正常,让我们构建网站。我们将构建一个 UI 来控制 Arduino 电路。我们将使用
- jQuery
- jQuery mobile
- PubNub Javascript SDK
这个 Web 应用非常简单。还记得我们在面包板上的键值语法吗?我们将使用它作为 html id
。open
和 close
按钮具有 value=""
属性,它们充当我们要发送到 PubNub 的值。
<div class="ui-grid-a toggle" id="door"> <legend class="ui-block-a">Front Door:</legend> <div class="ui-block-b"> <button type="button" class="ui-shadow ui-btn ui-corner-all ui-btn-inline" value="1">Open</button> <button type="button" class="ui-shadow ui-btn ui-corner-all ui-btn-inline" value="0">Close</button> </div> </div>
所以我们的 Javascript 将等待点击 button
元素,并将命令作为键值对广播。
例如,如果您单击上面的按钮,它将广播 door:1
或 door:0
,具体取决于您单击的按钮。
<script>
$(function() {
var channel = "iot_house";
var pubnub = PUBNUB.init({
publish_key: 'demo',
subscribe_key: 'demo'
});
$('button').click(function(){
var value = $(this).val();
var module = $(this).parent().parent().attr('id');
pubnub.publish({
channel: channel,
message: {
name: module,
value: value
}
});
});
});
</script>
在此处获取 完整代码。将所有这些都连接好后,就可以激光切割房屋了!
激光切割房屋模型
使用 这个来自“辛普森一家”的房屋 CAD 文件。它设计得非常好,只需 15 美元。车库门和前门都有铰链,非常适合我们的项目。
我在 ATX Hackerspace 上参加了一个为期 2 小时的课程,学会了如何使用激光切割机。您可以在当地的黑客空间或 TechShop 找到激光切割机。
- 我将激光文件导入到 inkscape 中,并在相当强大的设置下运行了激光。
- 我的供应商提供了一些额外的 Eucaboard,但它非常厚,难以切割。
- 此文件为卡扣式。
- 您需要测量屋顶上孔的高度,并将您的项目缩小,直到它们与材料的厚度相匹配。这款特定的激光模型是为 3mm 厚度设计的。
我浪费了半块板,因为 Corel Draw 在打开每个文件时都会确定缩放设置。显然,我以不同的比例切割了所有 4 个激光文件,所以所有部件都不匹配!
组装和粘合
粘合房屋的小部件,如窗户、烟囱和门。我使用了哥俩好胶。
事实证明,哥俩好胶很 messy,因为它会随着时间的推移而膨胀。这产生了大量的巨大实心胶块,完全破坏了房屋的美观。请少量使用。
我使用 Dremel 工具来去除多余的胶水。花了我一段时间,但我确实 提升了我的 Dremel 技能。
暂时不要将整个项目粘合在一起,我们还有工作要做。
焊接原型板
这部分比看起来容易。我们要做的是让之前在面包板上制作的电路板变得更永久。它与上面 Arduino 图中显示的电路完全相同。
我们所要做的就是使用电线和焊锡将电路板固定在一起。我们还将在两侧添加母头连接器,以便我们可以更换 LED、伺服电机并断开 Arduino。请看下面的图。
注意另一侧的母头连接器和电阻。这些母头连接器使我们能够通过在下一步将公头连接器焊接到电线上来创建“插头”。
该电路也可以构建在 Arduino 原型板上,这将使项目更稳定并消除跳线的需要。
测试原型板
板子焊接好后,尝试将其集成到您的电路中。将 Arduino 的数字引脚路由到右侧,将 LED 和伺服电机放在左侧。
这是电路板全部连接好后外观的预览。Arduino 在右侧(缺少以太网盾),我们的原型板在左侧。
一旦您确定它正常工作,就用热胶枪将焊点完全包裹起来。这将防止它们磨损。别担心,如果事情出了问题,很容易将胶水切割掉并重新开始。
制作线缆
您可能想知道,为什么我们在电路未完成之前就构建并组装了房屋?原因在于电线。我们构建了房屋,以便对电线的长度有一个概念。
考虑您想放置 LED 和伺服电机的位置。测量比您需要的电线稍长一些。
您需要使用细线规的电线。我喜欢对它们进行颜色编码和编织。
剥开电线末端,并在两端焊上接头插针。
您可以在桌子的角落处掰断接头插针,以获得所需的数量。
这些是我制作的一些电线。第一根是简单的 LED 电线,带电源和接地。
第二根是伺服电机延长线,带电源、数字引脚和接地。这使得我们可以够到车库旁的伺服电机。
最后一个称为“双接头插针”,我们将其直接插入母头伺服电机插座。这允许我们将伺服电机直接插入原型电路板。前门离电路板很近,所以我们不需要做任何定制布线。
您可以将 LED 直接焊接到电线上。用电工胶带包裹它们,并在暴露的电线之间插入一条带状物,以免它们短路。
制作好电线后,进行测试。将它们连接到面包板,看看它们是否工作。如果它们正常工作,请继续下一步!
安装 LED
使用与 LED 尺寸匹配的钻头,在房屋墙壁上钻一个孔。我在当地的 Fry's Electronics 找到了一些方便的塑料 LED 支架,所以我用它们来固定 LED。
LED 支架是 Linrose B4304MC 1/4" 安装夹,适用于 1/34" (5mm)。
LED 支架正好装入孔中,LED 卡入支架。太棒了!
安装伺服电机
对于车库门伺服电机,我使用了装修常用的小钉子将塑料伺服电机臂固定在车库门上。我砍掉了车库门上的铰链,想法是让伺服电机臂取而代之。
您可以看到木头开始有点裂开了,但它会固定住。
然后使用 Dremel 或钻头在房屋右侧切出一个孔以安装伺服电机。一旦孔足够大可以穿过,尝试连接车库门并调整直到其平稳旋转。
我能够对前门使用与车库类似的方法。我将伺服电机臂粘在前门上,然后直接将伺服电机粘在上面!伺服电机松散地用胶带固定在内墙上。请参见上面的 GIF。
制作窗户
我们需要漫射窗户的光线,以使房屋内的灯光看起来逼真。我使用了来自海报框架的透明亚克力。我不确定在哪里可以获得这个,因为我手头正好有。
将亚克力板切成正方形,然后粘在窗户结构后面。我在这里使用了强力胶。
取一些纸巾并切成小方块。在纸的每个角落滴一小滴强力胶。这将使其粘附在塑料上。现在我们有了逼真的窗户!
看看 GIF 中光线的折射效果。
安装原型板
将原型板安装在房屋背面。我使用了较长的螺钉,并在电路板和墙壁之间粘合了一些泡沫材料,使其牢固。
我使用了一个柔性螺丝刀伸入房屋内部。
安装 Arduino 板
使用小螺钉将 Arduino 安装到房屋上。我将其安装在大房间的后角,并钻了孔以访问端口。确保您仍然可以够到 Arduino 和以太网端口上的所有按钮。
另外请注意 Arduino 上方的走线孔。这是为了穿过电线。在安装电路板之前,请确定这些孔的位置。
安装电池盒
找一个合适的位置安装电池盒。我选择了右侧的小房间。将电池盒连接到原型板,然后为其供电!
最终组装
再测试一次移动网站和房屋!然后,拆开所有东西,以便我们可以将它们粘合在一起而不会弄坏任何东西。
用胶水描边房屋的边缘。我再次使用了哥俩好胶。
将所有部件夹在一起,等待几个小时,然后用 Dremel 工具去除多余的胶水。
恭喜!您拥有了自己独特的 IOT 房屋。
常见问题解答
其中一个 LED 不亮
顺着 LED 的电线找到插头。确保它连接正确,并且接地线(黑色)在顶部。
拔下另一个确认工作的 LED,然后将损坏的 LED 插入其插头。如果 LED 点亮,则故障不在电线或 LED 中。附带的万用表在这里很有用。
检查跳线。确保它们从 11 开始并连接到 6,并且已正确插入。
如果跳线没问题,则故障在原型(黄色)电路板中。拔下所有东西,然后使用附带的柔性螺丝刀将电路板从房屋上卸下。使用附带的钳子刮掉热胶,露出焊接元件。按压元件以确定是否有连接松动。如果有,请使用附带的焊铁修复连接。
其中一个伺服电机不工作
顺着伺服电机的电线。确保伺服电机已插入,接地线(黑色)在顶部。通过类似上一段中 LED 的方式进行调试。
触摸伺服电机。如果它在接收命令时振动但无法转动,则可能是 a) 已经处于正确位置或 b) 卡住。通过使用伺服电机支架强制伺服电机齿轮,可以解决伺服电机卡住的问题。
否则,请更换伺服电机。
两个伺服电机都不工作,但 LED 工作正常。
确保您已将电池放入 AA 电池盒中。如果存在,请尝试更换它们 - 它们可能已经没电了。确认电源插头与电池盒到原型(黄色)板底部连接牢固。
这是辛普森一家的房子吗?
是的,是。
您使用了什么材料?
Eucaboard。
伺服电机发出很大的咔哒声或发热。
伺服电机负载过大。尝试重新定位伺服电机。确保伺服电机在安装前处于“关闭”状态,如视频中所述。请参阅“伺服电机不工作”。