65.9K
CodeProject 正在变化。 阅读更多。
Home

再也不用买车库门遥控器了:用你的 Android 手机(通过蓝牙)打开车库门

starIconstarIconstarIconstarIconstarIcon

5.00/5 (26投票s)

2016年7月27日

CPOL

37分钟阅读

viewsIcon

90210

downloadIcon

1256

本文介绍了如何构建一个设备,将其添加到您现有的车库门上。该设备包含一个atmega328微控制器、一个蓝牙模块(hc-05)和一个继电器模块,允许您通过任何已配对的Android设备打开车库门。

引言

创建不仅仅基于软件的产品所面临的挑战是,您最终不得不使用多种技术。然而,这也可以是最有趣的部分。

这是一个关于该项目完整概述的粗略图。它展示了所有必需的组件,应该能让您对该项目的工作原理有一个基本的了解。

如果您阅读并完成了整篇文章,您将拥有一个可用的设备,它将允许您(以及任何您提供Android应用程序的人)通过蓝牙打开您的车库门。

Fritzing电路

如果您了解fritzing.org上那个出色的应用程序,那么您就知道可以使用它来绘制和测试您的电路。我已将完成电路板的原理图添加到这里:http://fritzing.org/projects/bluetooth-garage-door-opener[^]

在该网站上,您可以获取电路文档并根据您的需求进行修改和测试。

最终的原理图展示了电子设备的构建是多么简单,以及您实际需要多么少的组件。

所需零件清单

我提供了所有零件的清单,并在文章中推荐了购买地点,然后在本文末尾将它们列在一起,方便您参考。

它每天都打开我的车库门

这就是最终产品的样子——它仍然是面包板上的原始电路,但它工作得非常好。我每天都依靠它打开我的上翻式车库门。

main circuit and components

使用中的视频演示

这是一个YouTube视频,您可以看到它是如何工作的。这不是一个很好的视频,但它能让您了解它的原理,并且您可以看到当我按下Android应用程序上的按钮时继电器被激活。

再也不用购买车库门遥控器:使用您的Android手机(通过蓝牙)打开车库门 - YouTube[^]

不幸的是,我的视频显示我从屋内打开车库门。嗯,这可能会让您认为蓝牙的距离不会很远。

蓝牙范围:它能从合理的距离工作吗?

我的廉价手机和廉价蓝牙模块的首次蓝牙测试让我印象深刻。它通过车库的砖墙和车库门的金属,以及至少在车库外20英尺的距离上都能正常工作。这真是太棒了。

我希望通过本文教会您很多知识

在这篇文章中,我们将

  1. 研究一些基本的电学/电子学概念。
  2. 学习如何连接一个使用蓝牙模块(HC-05)、AVR atmega328和继电器模块(易于使用的电子开关)的简单电路。
  3. 了解如何重新利用旧的设备充电器为电路供电。
  4. 学习编写一些基本的AVR-C语言(Atmel AVR芯片使用的C语言)。
  5. 发现如何连接芯片编程器(硬件)将您的程序烧录到ATMega芯片的内存中。
  6. 使用AVRDude(软件)和GNU工具链编译和编程我们的Atmel芯片。
  7. 检查代码以创建一个Android应用程序,该应用程序将允许用户通过蓝牙向另一个设备发送数据。
  8. 在我尝试分解问题并创建解决方案时,回顾一下发现/设计过程。
  9. 提供我项目中使用的确切硬件项目的链接,以便您了解可用性和成本。

我认为这是一个学习如何将硬件和软件知识结合起来的绝佳入门项目,因为当您完成本文后,您将拥有一个可以为您省钱的设备*。

*通常,需要打开车库门的人越多,您就必须购买越多的遥控器。然而,使用蓝牙解决方案,只需安装Android应用程序并让用户配对其设备即可添加新用户。无需额外的硬件或成本。++

++您可能会认为这是一个安全问题,因为它听起来好像任何人都可以将他们的设备与您的车库门配对并打开它,但是,您必须按下设备上的一个物理按钮才能初步配对新设备,然后该人必须输入一个4位安全码。

背景

我最近搬家了,发现我的新家有一个非常旧的顶置式车库门开启器。然而,前主人没有给我们提供无线遥控器。通常你可以购买一个通用的无线遥控器,但这些遥控器太旧了,你必须购买原装的LiftMaster遥控器才能与它们配对。这些遥控器很难找到,而且当然比通用遥控器更贵。每个大约30美元(现在可能便宜一些)。

这一切都让我很恼火,因为每次都被迫以20美元的价格购买一个单独的遥控器,这种想法简直荒谬。我们都随身携带着功能强大得多的设备(手机、平板电脑等),这些设备应该拥有控制简单车库门所需的所有技术。

一定有办法

我不是硬件大师,但我从1995年左右就开始开发软件。不过我想,一定有更好的方法来控制我的车库门。起初,无线车库门控制的想法似乎有些难以逆向工程。我的意思是,那是不是意味着我需要了解所有关于射频(R/F)之类的废话?不。

我真正需要知道的只是如何远程激活一个开关。

远程激活开关

车库门开启器本质上只是墙上的一个开关,对吗?我知道开关连接到安装在天花板上的电机,当我按下开关时,电机就会启动。所以,我需要知道的只是如何替换开关或远程激活它。当然,还有一个额外的限制是,我希望我的墙壁开关也能继续工作。

我做的第一件事是检查我的问题

我做的第一件事是走到车库,看了看墙上的开关。它很旧,非常丑陋。

我用高亮显示了输入线(来自车库门电机——上方)和用户按下以打开或关闭车库门的瞬时开关(下方)。

momentary switch on wall

只需按下那个扁平的面板,顶置电机就会启动。嗯,我知道这只是一个断开的开关,当我按下它时,我将端子连接在一起并完成电路。

这很简单。

于是我决定把开关从墙上拆下来看看它是怎么工作的。如果我能增加几根电线(每侧各一根)并将它们连接在一起以完成电路,那么我想我就有了一个开始。

触电身亡怎么办?

这绝对是一个担忧。免责声明:我不是持证电工。请不要拆卸您的开关,以免意外触电。

车库开关相对安全的线索

有一个线索让我觉得捣鼓车库门开关可能是安全的。电路中导线的规格可以指示它所承载的电压和电流大小。这只是一条经验法则,并非任何形式的电气建议。再次强调,请不要做您不确定的事情。我不想让您受伤。

然而,我们大多数熟悉车库门开启器的人都知道,通常有两根电线从天花板上的电机连接到开关。您可能已经注意到这些电线非常细。

这可能表明它们不承载太多电流和/或电压。而且,如果您在互联网上搜索“瞬时开关车库门”,您会发现大多数情况下这些电线只承载大约12V(伏特)。

我找到了一个原理图,显示了这一点:DIY:将3V(3伏)车库门开启器遥控器集成到您的车辆(新手友好) - 丰田FJ酷路泽论坛[^]

momentary switch schematic

第一步 - 添加两根电线

我的第一步是添加两根电线,以便将电路延伸到我的新远程控制开关。当我把开关从墙上取下来并查看其背面时,我的第一步看起来如下。

behind switch panel

您可以看到(来自车库门电机的)输入线,然后我通过简单地松开螺丝,将电线缠绕在上面,然后重新拧紧螺丝,将两根线连接到相同的螺丝上。

添加完成后,将面板放回墙上,它看起来像下面这样

added wires

然后我可以将这两根电线接触在一起,车库门电机(以下简称GDM)就会被激活。或者,如果GDM已经激活,将两根电线接触在一起就会使其停止激活。

这似乎是一个非常简单的步骤,我想它确实是,但它也是一个重要的步骤,因为我知道这意味着如果我能以某种方式远程控制这两根电线的连接(完成电路),那么我就能得到我想要的东西。我需要某种电子激活的开关。

电子激活开关

在我的脑海深处,有一点信息是我在编程作者传奇人物Charles Petzold撰写的精彩书籍中读到的:《代码:计算机硬件与软件的隐藏语言》电子书 - Amazon.com[^]

电子继电器

在许多其他有趣的事情中,Petzold解释了继电器基本上是由电磁铁控制的开关。太棒了!这正是我需要的。

继电器是如何工作的?

最简单继电器的基本原理是这样的

  1. 当电压施加到继电器主电路时,电磁铁被激活
  2. 当电磁铁被激活时,它将金属杆(开关)从其常开(断开)位置拉到闭合位置。
  3. 当杠杆移至闭合位置时,次级电路完成,电流可以在该电路中流动(这将是我们的GDM的激活)。

电磁铁:绕在铁芯上的线圈

电磁铁可以通过将一块铁用铜线缠绕成线圈来轻松制造。当电流通过铜线时,会产生电磁场。这基本上就是继电器的制造方式。最简单的继电器由一个线圈和一块金属组成,这块金属在一个位置静止,当电压施加到线圈上且磁场移动金属开关时,它会移动到闭合位置。

请记住,我的解释是外行人的解释,所以那些拥有电子工程学位的专家们请对我宽容一些。:)

这是一个简单的继电器电路图,类似于我所说的。SPST表示单刀单掷。这只是意味着有一个单开关以一种方式切换。

relay circuit  这张图来自 (https://upload.wikimedia.org/wikipedia/commons/6/67/Relay_symbols.svg)。

更多继电器详情:我想要一个简单的

在电路中创建实际的继电器还有许多细节。即使您购买的是仅包含继电器单元的模块化类型,您也必须添加一些二极管以确保开关正常工作。这就是为什么在这个项目中我购买了一个完整的预制继电器电路模块。它们包含了所有使继电器正常工作的二极管。此外,它们包含了您轻松连接主电路和次级电路所需的一切,并且使用起来非常酷且方便。

继电器电路模块:价格便宜且易于使用

我在这个项目中使用的那个看起来像

relay module 1relay module 2

我是在亚马逊上买的,如果您喜欢,也可以在那里购买(Amazon.com: Tolako 5v Arduino继电器模块(兼容官方Arduino板)[^])

电路板中间的大蓝色盒子是实际的继电器(产生磁场并移动开关的线圈)。

另外,请注意,该设备作为“用于Arduino”销售。这是因为大多数编程AVR ATMega芯片的人都使用Arduino板。我们虽然不使用,但它工作正常。他们本可以将其营销为用于AVR芯片,那样也会很好,但Arduino当然拥有巨大的影响力。

输出电路

第一张视图显示了输出电路。它们是我们的电线将连接的三个端口,每个端口都有一个螺丝,允许您牢固地连接输出电线,无需焊接。这就是我们将GDM电线连接到的电路。看一下我将两根电线添加到开关的原始图片。这两根电线将连接到这三个输出端口中的两个。您可以在完成项目的第一个图片中看到这一点。这就是最终在我们想要激活GDM时将被打开的电路。

输入电路

然而,要使用继电器模块,您还必须提供一个输入电路。这个电路将决定GDM是否应该被激活。随着我们继续,我们将了解更多。您可以在上面继电器模块的第二个视图中看到输入电路的3个引脚。

为什么继电器模块上有三个输入引脚而不是两个?

继电器模块的工作方式非常简单。您将5到12伏的正电压施加到+(正)引脚,并将地线连接到-(负)引脚。然后将一根线连接到另一个同样提供5到12伏电压的设备。这就是此继电器模块上标记为IPP(可能代表输入端口?)的引脚。当5伏电压施加到该引脚时,线圈将被激活,电磁铁将导通,开关将打开,从而完成我们输出端的电路。

为什么也有三个输出端口?

好吧,你抓到我了。我上面没有完全讲完继电器的故事,因为我试图保持简单。有些继电器实际上有两个输出电路。我们的模块实际上有两个输出电路。这就是为什么我们有三个输出端口。

中间端口:公共

中间的一个是两者共用的,所以你总会有一个线在中间端口,它被称为公共端。

然后,其他每个端口(左和右)都有自己的名称。

常开

当IPP引脚没有电压(或低于5v)时,NO(常开)端口是断开的。

常闭

当IPP引脚没有电压(或低于5v)时,NC(常闭)端口是接通的。

然后,当5v电压施加到IPP引脚时,NO闭合,NC打开,因为开关翻转了。

这种类型的开关被称为SPDT(单刀双掷),因为它可以在两种不同的方式之间切换。

电路图如下所示

single pole double throw

在上一张图片中,我们将原理图视为电路的非供电版本。因此,您可以看到B到C电路是NC(常闭或无电源接通)电路,而A到C电路是NO(常开或无电源断开)电路。

所以现在我们有了解决这个问题的主要组件。让我们把它连接到一个非常简单的电路中,这样您就可以看到它的工作原理。我们将把它设计成当电压施加到IPP时,开关就会翻转,输出端的LED就会亮起。

首先,我将绘制简单的电路图,然后向您展示它工作的视频。

继电器代表三个独立的电路

我们的继电器模块实际上有三个独立的电路。

  1. 有一个输入电路。这个电路影响哪个输出电路接通。
  2. 有一个NC - 常闭输出电路。当没有电压施加到IPP时,该电路接通。(您可以在下一个粗略绘制的图像中看到,没有电压施加到IPP,因此NC(输出)电路上的LED亮着。)
  3. 最后是NO - 常开输出电路。

现在,如果我们将输入电路上的开关翻转为闭合状态,那么输出电路上的开关也将翻转,NC电路将变为开路,LED将熄灭,而NO电路将闭合,从而点亮图顶部的LED。

这是一个快速视频,展示了实际发生的情况。请记住,有一个输入电路和一个输出电路,这样就说得通了。

继电器实际运行的视频

电子学 - 使用继电器模块:输入和输出电路[^](仅52秒。)

我们是不是在继电器上花了太多时间?

也许您认为我们在这个继电器模块上花了太多时间。然而,请考虑这是一个基础组件,一旦您了解了它的工作原理,它将为您开启一个控制的世界。您可以在未来的所有项目中都使用它。

此外,这是我们项目的关键。我们需要一种方法来电子翻转开关,现在我们可以做到了。

控制几乎任何电器设备

一旦您学会了如何通过蓝牙控制您的车库门,您就可以使用相同的电路控制几乎任何其他可以想象到的电器设备。

哪个组件将决定何时向继电器施加电压?

然而,您可能想知道如何决定何时向继电器施加电压。正如您在视频中看到的,我正在手动(使用我手中的一根电线)向输入引脚施加5V电压。

发送信号激活

我们知道在我们的例子中,我们希望向继电器发送某种信号,告诉它激活,以便开关翻转,GDM启动。

我们可以连接一些东西,即使我们离得很远,我们也可以按下一个按钮,然后5v的电压就会施加到导线上,这根导线会连接到继电器模块上的IPP,然后它会激活磁性线圈,GDM就会启动。

但这显然是一个有线解决方案,我们不想要。在这种情况下不实用。这基本上就是我们墙壁开关的作用。此外,我们知道我们想要接收一个无线信号来激活GDM。

啊,蓝牙是一种无线信号。我经常看Adafruit Industries,独特有趣的DIY电子产品和套件[^]的视频,并关注一些不错的组件,我相信我见过一些廉价的蓝牙产品,所以那可能可行。

进入蓝牙

我正试图让这个项目尽可能便宜和简单。我开始四处搜索,发现一个极其简单(尽管文档不那么出色)的蓝牙模块,它似乎是多家公司制造的一种事实标准。

HC-05蓝牙组件(事实标准)

这就是我最终购买的那个。您可以在亚马逊上以约8.00美元的价格购买:Amazon.com: HC-05无线蓝牙串口收发模块从机和主机[^] 这里您可以看到正面和背面视图。

 

设备上的引脚提供功能访问

背面视图很好,因为我们能了解到一些关于设备及其工作原理的信息。我们可以看到,要让模块通电,只需在标记为VCC(电压)的引脚上提供3.6V至6V的电压,并将GND(地)引脚连接到地线以形成一个完整电路。

蓝牙模块易于使用(大部分)

这意味着如果我们将这个模块插入面包板,并添加一个提供3.6v-6v电源的电源,它就会开始广播蓝牙信号,以便其他设备可以连接。

真正的问题:我们如何与蓝牙设备通信?

然而,一旦模块通电并广播,并且设备连接后,我们想知道的是如何与蓝牙设备通信。我们如何接收来自设备的消息并为继电器供电,以便激活GDM?我们将看到如何做到这一点。但首先,让我们继续对蓝牙引脚提供的功能进行基本调查。但在此之前,让我提一下这些各种设备上的电压,以及为什么它们对于我们在购买组件时要注意是很重要的。

关于设备电压的注意事项

请注意,我们的继电器模块指示它在5v - 12v范围内工作,而蓝牙模块在3.6v - 5v范围内工作。这一点很重要,因为我们希望尝试使用某种电源为两个设备供电。当我们开始讨论Atmel ATMega328芯片时,我们还会了解到它的工作电压范围为1.8v - 5.5v。

好了,现在回到我们的HC-05蓝牙模块。

让我们连接它,连接一个设备,看看我们能做些什么。

蓝牙模块上电与设备配对

以下是配对设备的基本步骤(来自Google - 连接到蓝牙 - Nexus帮助[^])。这些HC-05模块的默认密码是:1234。

 

从蓝牙模块发送和接收数据

现在我们已经启动了它,并且有一个设备与之配对。我们如何与它通信?我们怎么知道我们正在与它通信?

蓝牙模块真正做的所有事情:发送和接收数据

获取蓝牙模块接收到的数据是具有挑战性的部分。基本上,蓝牙模块只做两件事

  1. 通过无线接收数据,并将其写入其串行发送引脚(Tx)。此数据以一系列电压的形式写入该引脚,类似于摩尔斯电码。
  2. 然后,当有东西向蓝牙模块的Rx引脚写入数据(施加一系列电压)时,它会将该数据转换为无线信号并发送出去。

这一切都意味着,如果你能以某种方式知道Tx引脚何时有电压,那么你就能知道有消息要读取。而且,如果你想通过蓝牙发送消息,你需要向Rx引脚写入电压。

我们真正想要的只是数据

问题是我们无法获取蓝牙模块正在接收的数据。您必须思考一下。我们如何读取Tx引脚上的电压?嗯,我们可以将Tx引脚直接连接到继电器的IPP(输入端口)。但这将意味着,蓝牙模块Tx引脚上接收到的每一位数据都会以每秒多次脉冲的方式激活输入端口和继电器。反过来,这将导致我们的GDM每秒多次激活和停用。这对我们不起作用。

我们需要处理器的原因

我们真正需要的是能够处理传入数据(通过蓝牙传入的数据)的东西。我们需要一种编写程序的方法,该程序可以检查数据并决定应该做什么。由于我们无法为蓝牙模块编写任何程序,也无法处理它发送和接收的数据,因此我们需要另一个组件来完成这项工作。这个组件就是我们项目的主要微处理器:ATMega328PU。

Atmel ATMega系列芯片

我可以告诉您这些芯片的所有历史和规格,但我们还是专注于将芯片视为一个产品开发人员,他正试图以最便宜、最快的方式完成一个产品。这才是对我们重要的。首先,为什么ATMega芯片会越来越受欢迎?

AVR芯片最初于1996年开发,是首批芯片之一,并且是...

引用

“...首批使用片上闪存进行程序存储的微控制器家族之一,而不是当时其他微控制器使用的单次可编程ROM、EPROM或EEPROM。”

摘自Atmel AVR - 维基百科,自由的百科全书[^]

这项技术意味着这些芯片可以比以前的芯片更容易地将程序写入其内存中。

Arduino开发板

这为后来的开发者生产Arduino开发板奠定了基础,Arduino开发板是开源硬件(任何人都可以自己制造和销售Arduino板)。2005年,第一批Arduino板发布,它们为业余爱好者提供了一种极其廉价(30-40美元)的方式来开始嵌入式编程。

创建Arduino的团队选择基于Atmel芯片,原因有很多,包括:

  1. 低价
  2. 易于上传程序(闪存)
  3. 易于编写程序
  4. 提供了一套良好的内置功能(串行通信等)
  5. 表现良好

以前,如果一个业余爱好者想基于微处理器做一个简单的项目,仅仅为了开始编程芯片,可能就需要投入数百美元。Arduino和Atmel芯片显著降低了这一价格。此外,由于Arduino开发板是开源的,任何人都可以制造和销售它们,这进一步降低了价格。

ATMega328拥有一切我们所需

低价

我在亚马逊上以仅10.99美元的价格购买了两颗这样的芯片:Amazon.com: 2个全新Atmega328p-pu芯片,带Arduino UNO引导程序[^]。

简易串口通信

芯片的功能必须通过其引脚易于访问,而ATMega328内置了串行通信功能,并通过两个引脚:发送(Tx)和接收(Rx)易于访问。以下是芯片引脚图以及这些引脚的名称,以便您可以看到串行引脚。(图表来自Atmel文档:http://www.atmel.com/Images/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Summary.pdf[^])

atmega328 pin diagram

您可以看到我用红色框高亮显示了上图中标注为TXD和RXD的两个串行通信引脚。

以下是一个28引脚ATMega328P芯片的模样

非常容易连接到蓝牙

正如我们将看到的,这些引脚使得将我们的芯片连接到蓝牙模块变得极其容易,这样我们就可以从蓝牙读取数据并通过蓝牙发送数据。只需将蓝牙的Tx连接到芯片的RXD,将蓝牙的Rx连接到芯片的TXD即可。

让我们将电源连接到ATMega芯片和蓝牙模块,然后编写一个C程序,将其烧录到芯片中,该程序将从蓝牙设备获取数据。

连接闪存编程器

我们首先需要做的是连接我们的电路板,以便将程序烧录到芯片中——将我们的程序写入ATMega芯片的闪存。

通常我们会在这里讨论一些Arduino编程板。然而,我比较节俭(便宜),并且我想直接使用芯片的底层,用纯C语言编程,所以我选择使用不同的设备。

我建议您购买以下闪存编程器,它非常好用且价格便宜(10.50美元)

Amazon.com: Gikfun USBASP AVR编程器适配器10针USB电缆[^]

flash programmer

设置您的闪存编程器

获取驱动程序

您将此设备连接到USB端口并安装可在以下网址获取的驱动程序:

USBasp - Atmel AVR控制器USB编程器 - fischl.de[^]

获取并安装AVRDude

接下来,您安装AVRDude,这是一款软件,它将使用GNU C编译器编译您的C程序,然后将程序烧录到芯片的内存中。

您可以在以下网址获取AVRDude(免费且开源):Index of /releases/avrdude[^]

获取最新版本,下载并解压,然后您就可以在命令行运行AVRDude了。

设置环境的挑战

我明白设置这个编程环境存在一些挑战,但为了让这篇文章更短,我不会详细介绍所有这些。稍后我会在我的博客上添加一些文章,为那些在此过程中遇到困难的人提供帮助。请查看我的博客着陆页顶部:RAD Dev US - 博客 - Roger Deutsch的开发网站[^],了解更多详情。注意:这篇文章发布时这些文章还不可用,因为我需要一些时间来撰写它们。

获取设置的极好资源

我为了完成这一切并开始编程Atmel芯片而阅读的书是:《AVR编程:学习为硬件编写软件》作者Elliot Williams,电子书 - Amazon.com[^] 您不必读完全书,尽管它是一本写得非常好的书。如果您需要更多帮助,前两章将帮助您完成所有设置。

我假设您已经设置好环境并连接完毕,准备将程序烧录到芯片中。

用于从蓝牙模块读取字节的C程序

这是我用来读取蓝牙模块传入字节,然后根据数据决定我们应该做什么的简单程序。

#include <avr/io.h>
#include <util/delay.h>
#include "pinDefines.h"
#include "USART.h"

int main(void) {
  char serialCharacter;
  DDRB |= 0b0000001; 
  initUSART();

  while (1) {
    serialCharacter = receiveByte();
    transmitByte(serialCharacter);
    if (serialCharacter == 'y')
    {
        PORTB = 0b00000001;
    }
    if (serialCharacter == 'n')
    {
        PORTB = 0b00000000;
    } 
    _delay_ms(100);
  } 
  return 0;
}

仔细检查AVR C程序

让我们逐步检查代码并解释这个简单代码的作用。这段代码来自于Elliot Williams(前面提到的AVR编程书的作者)代码的修改版本,可以在他的GitHub上找到:AVR-Programming/serialLoopback.c at master · hexagon5un/AVR-Programming · GitHub[^]。

将整个项目打包成一个Zip文件

您可以下载整个项目,它已很好地打包在一个文件夹中,位于本文顶部(ActivateDoor.zip)。该zip文件还包含项目的makefile,如果您的GNU C工具链设置正确(如果您安装了WinAVR,则已正确设置),那么您将能够输入:c:\>make,项目将构建并输出activateDoor.hex(这是上传到ATMega328P芯片的文件)。

包含文件

您在代码中看到的前四行是该程序使用的库的引用。括号中显示的那些是AVR-C标准库或C标准库的一部分。它们是您的WinAVR安装和GNU C工具链的一部分。

另外两个(pinDefines.h和USART.h)是这个程序的附加组件。我从Elliot Williams的github获得了这些文件,因为它们提供了我们在ATMega328P上读写串行引脚(Tx和Rx)所需的一些功能。

使用makefile(同样由Elliot Williams提供)也有帮助,因为如果我们键入

c:\ActivateDoor>make flash 

那么GCC编译器将遵循make脚本,构建可执行文件(.hex文件),并一次性将其烧录到芯片内存中。这个过程并非总是那么容易,所以我会在我的网站上写一些补充博客文章,详细说明可能出现的陷阱和问题,希望能帮助您解决任何问题。

代码在main()函数中做的第一件事是设置一个变量来保存我们将从RXD引脚读取的字符。这将是有人通过蓝牙发送给我们的值。

设置输出引脚

接下来你看到那行奇怪的代码

DDRB |= 0b0000001;

这只是意味着将PORT B引脚准备好用于输出。这行代码使用位运算符将Port B的第一个位设置为具有电压。这指示芯片该引脚可用于写入。DDRB位1等于PB0(上面显示引脚标签的图中的引脚号14)。再次强调,设置此值只是让芯片知道它将用于输出。它尚未设置值。我们稍后会看到。

初始化串口引脚

我们还必须准备好串行引脚用于发送和接收,幸运的是,这段代码已经为我们编写好了,所以我们不必去琢磨它。usart.h库中的代码以及initUSART()的实际实现都可以在项目压缩包中包含的usart.c文件中找到。我们不必过多考虑它,因为所有这些工作都已为我们完成。

现在,在我解释接下来出现的无限while循环之前,让我们退一步思考一下我们正在使用的芯片是一台完整的计算机这个事实。我的意思是这样的。

AVR芯片作为一台完整计算机的概述

如果您将我们的ATMega328P芯片连接其引脚,使VCC(图中的引脚7)连接到5v,地线引脚(图中的引脚8)连接到地线,芯片就会开始运行已烧录到其内存中的任何程序。没错,即使没有连接任何其他东西,芯片也会开始处理。然而,芯片的内存中可能没有烧录程序。而且,即使有,如果其输出引脚没有连接任何东西,您也无法知道它在做任何事情。

只要有电,它就会运行程序

我的基本观点是,只要有电,芯片就会运行程序。这就是为什么我们用while语句将程序放入一个无限循环中,类似于下面这行:

while (1) { //做一些事情... }

这只是意味着只要为真就一直循环这些行。这只是创建一个程序循环,只要芯片有电就会运行。

我们循环中的第一行是

serialCharacter = receiveByte();

我们正在调用一个预先编写的usart函数,并要求它获取任何接收到的字节(字符)并将其存储在我们的char变量中。

代码中的下一行有点奇怪。

transmitByte(serialCharacter);

然后我们使用另一个库函数将该字符直接传输出去。这仅仅是因为我试图确保我可以看到我输入的字符在我用来测试程序的终端屏幕上回显给我。

有实际作用的有趣代码

最后,我们来看实际执行操作的有趣代码。它是我们整个系统的核心,也是我们与Android程序连接的方式。(稍后,我们将看到我们的Android程序如何向蓝牙模块发送字符值。)

当字符传入时,我们检查它的值。如果它是字母Y,我们打开PB0(引脚14)上的电压;如果它是N,我们关闭PB0上的电压。

   if (serialCharacter == 'y')
    {
        PORTB = 0b00000001;  // set voltage high (5v) on PB0
    }
    if (serialCharacter == 'n')
    {
        PORTB = 0b00000000;  // set voltage low (less than 5v (0v)) on PB0
    } 

PB0(引脚14)直接连接到继电器上的输入端口

现在您看到这段代码,您就可以了解整个工作原理了。由于PB0通过导线连接到继电器上的输入端口,它控制着继电器何时切换。

当然,当继电器切换时,输出电路被激活,ODM(顶置式车库门电机)上的开关闭合,电机启动。

Android应用,我们需要你

现在,我们只需要一个Android应用程序,它允许我们与蓝牙模块配对,以便它可以发送值来设置PB0高电平或低电平,从而激活/停用开关。

为了使蓝牙Android应用程序正常工作,我完全依赖于Google官方文档:蓝牙 | Android开发者[^]

您可以在本文顶部下载Android应用程序,并使用Android Studio构建它。

下载APK - 安卓安装包

或者,如果您愿意,可以直接从我的网站将应用程序下载到您的手机或平板电脑上进行安装。

只需将您的设备浏览器指向:http://raddev.us/android/btfinder.apk[^] 一旦下载,您只需点击文件即可轻松安装。它只请求控制/设置蓝牙的权限,因此侵入性不强。

Android应用:粗略版本

我本来打算为这篇文章清理应用程序的用户界面,但我决定给您应用程序的原始版本,这样您就可以更接近我所做的开发细节。

该应用看起来如下

基本上,该应用程序会在顶部加载一个已配对蓝牙设备的列表。

连接到您的蓝牙模块,在您给它通电后,您只需点击它在顶部列表中出现的位置。

当您点击列表中的项目时,应用程序会向蓝牙设备发送一些测试数据,并提供一条消息告知您是否成功。

无论成功与否,它都会在底部可滚动列表中打印一条消息,以便您了解状态。

某种程度上是手动操作

如果初始连接成功,您将点击[Yes]按钮发送“y”以激活继电器。但是,现在您需要手动停用继电器,因此在您点击[Yes]按钮后,请继续点击[No]按钮。

每次点击按钮,新的状态都会写入底部可滚动列表视图,以便您知道应用程序已执行该操作。

安卓开发挑战:没有模拟蓝牙

开发蓝牙应用程序的主要挑战之一是Android模拟设备上没有提供蓝牙仿真。这意味着测试应用程序的唯一方法是将其发送到设备,运行应用程序并查看发生的情况。这就是为什么我将所有这些状态消息写入可滚动列表视图的原因。

当您启动应用程序时,它看起来会像这样:(当然这是在模拟器上运行的,但想象一下每个测试项目都是一个蓝牙设备)

其中一个项目很可能命名为HC-05(我们的蓝牙模块)。

接下来,您只需点击顶部列表中的项目,应用程序就会尝试连接到设备并发送一些数据进行测试。

它会在模拟器上失败,但至少会给你一些输出,让你知道。

如果您在真实设备上运行应用程序并成功连接,它将看起来像这样

最后,成功连接后,您点击[Yes]按钮,PB0引脚将变为高电平(设置为5v),继电器将激活。

为了让它更简短(太晚了:)),这是ConnectThread.java类中写入“y”和“n”的代码。

public void writeYes() {
    try {
        byte [] outByte = new byte[]{121};

        mmOutStream.write(outByte);
        logViewAdapter.add("Success; Wrote YES!");
        logViewAdapter.notifyDataSetChanged();

    } catch (IOException e) { }
}

public void writeNo() {
    try {
        byte [] outByte = new byte[]{110};
        mmOutStream.write(outByte);
        logViewAdapter.add("Success; Wrote NO");
        logViewAdapter.notifyDataSetChanged();

        mmOutStream.write(outByte);
    } catch (IOException e) { }
}

您可以看到,在`writeYes()`方法中,我们将`outByte`设置为小写字母“y”的ASCII值121。在`writeNo()`方法中,我们将`outByte`设置为小写字母“n”的ASCII值110。就是这么简单。

您还可以看到,该应用程序会写入一条简短消息,告知您它已将字节写入流中,该流通过蓝牙信号输出。

所需组件快速清单

  1. 蓝牙模块 (HC-05) - Amazon.com: HC-05无线蓝牙串口收发模块主从一体[^]
  2. AVR芯片:ATMega328P - Amazon.com: 2个全新Atmega328p-pu芯片,带Arduino UNO引导加载程序[^]
  3. 继电器模块 - Amazon.com: Tolako 5v Arduino继电器模块(兼容官方Arduino板)[^]
  4. 用于轻松构建电路的面包板 - Amazon.com: Frentaly® 3x 无焊面包板,400个连接点[^]
  5. 各种电线
  6. 用于电源状态的LED
  7. 220欧姆电阻(与LED串联使用)
  8. 22 pF 陶瓷电容器,用于平稳电源
  9. 电源适配器/变压器,以便您可以轻松插入交流电源 - 我使用了旧的摩托罗拉Razr充电器,并将其重新利用,但您需要一个输出5v和大约850mA电流的适配器。- Amazon.com: 摩托罗拉 SPN5202B 5V 850mA 交流适配器电源,适用于摩托罗拉 RAZR[^]

兴趣点/注意事项

我撰写本文的初衷是向您展示,即使您对所有这些不同组件(AVR芯片、蓝牙、Android)的经验很少,您也能构建这个项目。我仍然相信,如果您按照本文中的步骤操作,您就能做到。

困难在于设置,不一定是项目的细节

我发现这个项目的细节极其简单。总的来说,这是一件非常容易的事情。您最可能遇到的挑战将与设置您的构建系统有关。安装WinAVR、构建您的AVR-C程序,然后将这些程序烧录到您的AVR芯片中可能极其困难,所以不要因为认为您正在做一件简单的事情却出了问题而感到沮丧。这根本不简单。而且它可能极其令人沮丧,因为您可能只是设置了一个小细节不正确,但所有东西似乎都无法工作。

不要放弃

即使遇到困难,也不要放弃。你学到的所有东西都会帮助你完成下一个项目。

正如我所提到的,我将尝试在我的网站(RAD Dev US - 博客 - Roger Deutsch的开发网站[^])上撰写一些文章,进一步详细说明这些事情并提供帮助。

如果您需要帮助,请评论和提问

我希望您能看到我在撰写这篇文章上付出了很多努力。我希望如果您需要帮助,您会评论并请求帮助,因为我很乐意尽我所能帮助您启动您的项目。

继电器与ODM线路连接:失败

哪一边:常开还是常闭

当我第一次将输出线连接到ODM时,我将它们连接到继电器的公共端和NO(常开)端。我以为这是正确的,因为我以为开关上没有电压,然后我们会给它施加电压。

墙壁开关停止工作?!

通过安卓应用,它完全按预期工作。然而,墙壁开关不再起作用。我还注意到墙壁开关上的LED灯不再亮了。我本应进一步调查,但我太兴奋了,因为我的应用可以工作,而且我可以通过手机开/关门。

其他遥控器也停止工作

然后我的妻子试图离开。她无法从墙壁开关打开车库门,所以她上了车,心想可以使用她通常的射频(R/F)遥控器。不行!问题是电路实际上需要一些电流来运行,这些电流由ODM提供,用于点亮墙壁上的状态LED并允许射频遥控器工作。

我猜测了一下,将我的输出线切换到NC(常闭)侧,墙壁开关LED立即亮起。墙壁开关再次开始工作,射频遥控器也恢复了。 

有趣的是,应用程序现在会暂时关闭开关,然后再次将其连接到NC侧。这与我原先设想的工作方式相反,但好消息是应用程序和所有开关现在都能完美运行。

历史

首次发布于2016年7月27日

© . All rights reserved.