有在家庭自动化中使用GSM模块的经验

小屋很冷,您想在抵达前几个小时打开加热器,或者担心在您不在的情况下紧急关闭乡间别墅的供暖系统。 所有这些问题都可以使用GSM模块解决,该模块可以发送和接收SMS消息并对它们进行响应,从而打开和关闭必要的负载。 从理论上讲,一切都很简单,实际上,在实现这种设备的方式上存在很多陷阱。

图片

我的计划是制造一种简单且便宜的设备,该设备配备两个温度传感器,一个湿度传感器,一个GSM模块,以及一个固态继电器和一个用于连接负载的插座。 照片中可以看到最终发生了什么。 选择BME280气候传感器作为温度和湿度传感器;不使用其压力通道。 在照片中,您可以在主模块左侧的透明盖下看到它。 这种布置减小了壳体内部的发热对传感器读数的影响。 作为盖子,使用具有两个通风孔的中国塑料试管。 第二个温度传感器是远程的,由DS18B20制成。 它位于金属探针内部,通过电缆通过耳机的常规音频插孔与电缆连接到外壳。 该探头设计用于直接测量加热系统的温度。 主体体积由一个固态继电器(我选择了功率更大的继电器)和一个从220V到5V的转换器为电路供电的空间占据。 用于连接负载的插座安装在外壳的背面,在照片中看不到。 基于SH1106控制器的OLED显示屏显示传感器读数,并显示负载是否接通。 为了控制整个系统,在3.3V 8MHz版本中使用了Arduino Pro Mini模块。 我不是这个平台的忠实拥护者,但是如果您需要快速做一些简单的事情,那么丰富的库,包括作者精心研究的库,便是她的最佳选择。

SIM800L GSM模块位于单独的金属外壳中,以减少对电路其余部分产生的干扰。 如实践所示,干扰不会减少很多。 从根本上讲,通过屏蔽电缆将外部天线连接到同轴连接器可以减少这些干扰,在上面的照片中它是在前台。 但是我们稍后将详细讨论。

图片

关于GSM模块的使用,包括在集线器上,已经写了很多文章,所以我将避免重复,并谈论我在该主题的出版物中没有看到的内容,即如何基于该模块制造可靠的设备。

在我经常拜访的车库中,最近在入口处设置了障碍物,当您拨打一定数量的电话时该障碍物会打开。 显然,它是在类似的GSM模块上制成的。 我很惊讶获得这个数字来打开它有多么困难。 现在我知道很多原因了。 这些知识使我花了几个月的实验,并花了很多钱在上面。 我希望现在这些知识可以为其他人服务。 考虑一下要注意的重要事项,从明显的硬件问题转移到不太明显的软件问题。

正确执行的第一件事是插入SIM卡。


对我来说,显而易见的是,SIM卡插入时带有向前倾斜的角。 一个星期以来,我一直试图理解为什么模块不希望在网络上注册,同时在终端中掌握命令。 结果,在某个英语论坛上,我发现您需要插入一个带有斜角的后背。 奇怪的是,它通常以这种方式插入。

为了工作良好,您需要吃得饱。


GSM模块的电源要求非常具体。 它基于为按键式手机设计的微芯片制造,并设计为直接由锂电池供电。 因此,5V对他来说足够了,而3.3V不足。 另外,在最大功率的传输模式下,它可以消耗高达2A的电流。 如果电源无法提供所需的电流,则在尝试在网络上注册时,GSM模块可能会重新启动,并在无休止的循环中继续重新启动。 峰值消耗时间通常持续不到一秒钟,因此很容易在峰值负载期间使用具有能量存储功能的低电流稳定器。 作为这样的驱动器,可以使用锂电池。 同时,重要的是要确保断开连接的可能性,并且重要的是不要忘记使用它,否则断开设备与网络的连接将导致电池深度放电并永久损坏。 另一种选择是用电离电阻(超级电容器)更换电池。 他不怕深度放电。 但是他也有可靠性方面的问题。 电离电阻的一个单元通常额定电压为2.5至3V。 设计用于更高电压的电离电阻由几个单元组成(通常为2个)。 但是,在这种情况下,电池中的电压不平衡可能会导致电池损坏。 由于单元电容的差异或漏电流的差异,容易获得这种不平衡。 还应考虑离子电阻的内部电阻参数。 在高电流下具有高内部电阻的电离电阻是没有用的,而具有低电阻的电离电阻并不比电池便宜。 我的电离电阻器由于电池不平衡而突然死亡后,我刚使用了一个220V至5V足够功率的转换器。 为了降低所需GSM模块的电压,我在转换器和模块之间放置了一个常规的硅二极管。 在这样的二极管上,通常会下降0.7V,因此模块会获得必要的4.3V。 在二极管之后,放置一个大容量的电解电容器很有用。 当变送器突然打开时,它将消除电压骤降。

远离发射天线。


即使我为GSM模块提供了所需的电源,重启症状也会定期出现,但这一次Arduino重启了。 使用示波器观察其功率表明此处不需要功率。 显然,发射机创建了模块,因为该问题更经常出现,基站信号的接收条件越差。 如果我们记得模块的发射器能够向天线传送2瓦特,那么来自发射天线的这种根本干扰效应就可以完全解释。 这样的功率可以在5分钟内烧开一毫升的水,或者将您的耳朵加热几度。 为了解决这个问题,已经尝试了各种方法。 首先,我连接了一个外部天线,该天线位于外壳外部,并通过短同轴电缆连接至模块。 但是,这没有得到预期的效果。 然后,我将模块放在单独的金属盒中,天线从外面固定在金属盒中。 情况有所好转,但不多。 从根本上改善了这种情况,因为天线与足够长的同轴电缆相连,因此仅在距离设备一定距离的情况下才拆除天线。

从物理上的原因很容易理解为什么会发生这种情况。 典型的天线是四分之一波引脚,即偶极天线的一半。 但是,要产生电场,偶极子的一半是不够的,您需要后一半,那么天线的负电荷和正电荷元件之间将出现电场。 对于普通的鞭状天线,另一半是地球的表面或仪器的身体,或特殊的导电“天平”。 但是对于营销人员来说,这一切都太复杂了,因此我们通常只出售普通天线的一半。 她如何工作? 非常简单-另一半是天线所连接的电缆。 它被屏蔽的事实不会改变任何东西。 编织物的外表面起偶极子天线后半部分的作用。 在这种情况下,尽管电缆似乎被屏蔽了,但很容易对附近的电线产生干扰。 好吧,例如,如果没有电缆,我们将模块隐藏在金属丝网中,天线从中伸出? 如果屏幕较大(与波长相比),则其工作方式类似于发射器的后半部分;如果屏幕较小,则与该模块连接的其他电线也可以发光。 下图说明了上述内容(为清楚起见显示了优缺点,实际上,天线元件的电荷随载波频率而改变符号)。

图片

“右侧”天线显示在左侧;其引入电缆不产生干扰。 中间的图像显示您通常购买的天线。 此处,引入电缆是发射器的一部分,并且会干扰附近穿过的电线。 右图显示了信号源何时隐藏在紧凑的屏蔽外壳中。 在这里,任何带入这种外壳的电线都是发射器的一部分。

道理是,保护自己免受发射天线干扰的唯一可靠方法是,通过将其与足够长的同轴电缆连接,使其远离电子设备的其余部分。 足够多长时间? 用波长测量距离是很自然的,在这种情况下,最大距离是30厘米,这是分配天线的最小距离,但越远越好。

并非所有串行端口都同样有用。


在每个人都普遍使用的简单AVR微控制器中,只有一个硬件串行端口,用于下载程序。 因此,串行端口的软件实现是非常流行的解决方案。 我要证明一个说法,许多人会认为这是意外的-为了管理GSM模块,串行端口的软件实现根本不合适。

问题的实质是,串行端口的软件实现在发送或接收下一个字符的整个过程中都禁止中断。 好像很多人一样,这是不好的。 例如,用于读取达拉斯半导体温度计的1-Wire协议的实现还禁止在传输一位(即65微秒)时中断。 当然,这也不是太好。 如果系统具有其他中断处理程序,则它们将不能提供少于这65微秒的中断响应时间。 如果中断请求被拒绝时到达,则仅在再次解决中断后才会处理。 例如,硬件串行端口使用中断将下一个接收到的字符放入接收器缓冲区。 如果下一个字符到来,直到处理上一个字符的中断,则它将丢失。 这意味着硬件串行端口将无法以大于115200位/秒的速度运行。 对于串行端口的软件实现,情况会更糟。 对于其操作,对中断的响应时间必须小于一位的传输时间。 这将我们限制为每秒9600位的速度。

一个更严重的问题是串行端口软件本身禁止中断。 此外,禁止它们的时间(一个字符的发送或接收时间)总是比相同软件串行端口的接收器正确操作所需的最大中断处理时间长约10倍。 也就是说,它总是对其自身造成一定程度的干扰,以致于它同时无法接收和发送数据。 当然,在大多数情况下,这不是必需的。 在大多数情况下,但在我们情况下不是GSM模块。 对于我们,他可以出乎意料地主动开始传输数据(例如,在收到SMS消息时)。 并且在使用串行端口的软件实现的情况下,这很容易导致与模块的通信协议失败。 因此,我只是将相同的硬件串行端口应用于Arduino编程以及与GSM模块的通信。 当然不方便,但这是制造可靠设备的唯一方法。

异步协议-异步处理程序


异步协议是这样一种协议,其中交换的一侧可以开始意外地将信息传输到另一侧,即与其消息没有任何同步。 这正是与GSM模块的通信协议。 它定期响应来自Arduino的请求,但是它也可能开始传输自己的内容,例如,通知接收到的SMS消息。 这造成了一个真正的问题,因为我所知道的与Arduino模块一起使用的所有库都没有考虑到协议异步性。 想象一下,Arduino向模块发送了一条命令,并且模块同时传输了有关接收到的SMS消息的信息。 该信息将被接受,而不是响应命令。 结果,该库将响应该命令返回一个错误(最好的情况是,最坏的情况都将“挂起”),有关接收到的SMS的消息将丢失。

这很容易解决-您只需要编写自己的异步协议处理程序即可。 异步处理程序仅对模块对其命令的响应做出必要的最低要求。 结果,模块对每个命令回答“确定”或“错误”。 这就是解决问题的全部方法。 来自模块的所有其他行都将被处理,无论它们是响应命令还是单独响应。 这些行的含义始终可以通过它们的开头来确定。 如果该行以+ CSQ开头,则它包含有关信号质量的信息。 如果启动+ CMT,则这是有关收到的SMS的信息,其中包含发送者的地址。 第一行是作为对AT + CSQ命令的响应的一部分发送的,而第二行是主动发送的,但是对我们而言,这种区别绝对是微不足道的。 模块将收到的SMS消息直接发送到串行端口。 这样可以避免从内存中读取它们并随后删除它们。 为了使我们能够识别来自模块的常规消息流中的SMS消息,它们必须以#符号开头,否则该消息将被忽略。

作者创建的实现上述方法的库位于此处

为了接收以特定字符序列开头的行,客户端将创建一个特殊对象-陷阱。 他可以创建任意数量的此类陷阱。 从模块收到的行(OK,ERROR除外)没有落入任何陷阱,这些行仅被忽略。 由于这样的体系结构不需要完全分析模块对许多不同类型的命令的响应,因此该库代码比我所知道的任何库都紧凑许多倍。

结果如何?


结果是该设备可以在覆盖率较差的区域可靠地工作,甚至比普通电话还要好。 下面是它的完整轮廓。

图片

对于那些感兴趣的人,有到github的链接,您可以在其中找到项目的源代码以及可以通过SMS消息发送到设备的命令的描述。

github.com/olegv142/GsmMon

Source: https://habr.com/ru/post/zh-CN460745/


All Articles