快速搭建远程控制灯LoRa智能灯控【51单片机篇】

[复制链接]
查看846 | 回复7 | 2024-6-17 15:56:40 | 显示全部楼层 |阅读模式
前言
今天我们来深度解析一下Lora在照明设备中的应用原理。
这里Lora的优势以及劣势我就不多加赘述了,大家可以上网搜索一下,做过或者接触过物联网设备开发的朋友应该比较清楚,无线模块在这个行业中所占的比重,无线控制其实就是A端发送一个信号,B端收到以后做出相应动作的一个过程。
· 设备组成
今天我们用的设备比较简单,就是入门级的STC主控MCU加上含一片SX1278芯片的Ra-01模块,需要两个,外加两根弹簧天线。
安信可淘宝店是默认一个Ra-01模组配送一根433MHz弹簧天线的,很方便。 推荐bug一个!
另外生成的HEX文件,用串口烧录。
如果不明白的朋友可以看我们的上一篇文章,其中有介绍这个主控的详细接线以及烧录测试流程。
【安信可LoRa模组专题①】安信可LoRa快速入门指南

1.png
一. 远程灯控(开关)
1.1原理分析
我们目前手上有两个同样的设备,烧录同样的程序,程序运行在MCU中,通过外接的SPI驱动Ra-01射频模块发射和接收数据,接收端接收到这个数据做出响应,实现一个远程控制灯开和关的方案。
1.2基本通信
首先需要两个模组间能够进行通信,代码中需要编辑发射机以及接收机;
这里我们定义出接收机和发送机的逻辑代码,完成发送和接收,这部分我直接放在了主函数中了,可以把他放在单独文件中这样就便于观察条理了。
  1. else {
  2.                         P32 = 1;
  3.                         RF_EX0_STATUS = SX1276ReadBuffer( REG_LR_IRQFLAGS);
  4.                         if (RF_EX0_STATUS > 0) {
  5.                                 if ((RF_EX0_STATUS & 0x40) == 0x40) {
  6.                                         CRC_Value = SX1276ReadBuffer( REG_LR_MODEMCONFIG2);
  7.                                         if (CRC_Value & 0x04 == 0x04) {
  8.                                                 SX1276WriteBuffer(REG_LR_FIFOADDRPTR, 0x00);
  9.                                                 SX1278_RLEN = SX1276ReadBuffer(REG_LR_NBRXBYTES);
  10.                                                 lpTypefunc.lpSwitchEnStatus(enOpen);
  11.                                                 lpTypefunc.lpByteWritefunc(0x00);
  12.                                                 
  13.                                                 for (RF_REC_RLEN_i = 0; RF_REC_RLEN_i < SX1278_RLEN;RF_REC_RLEN_i++) {
  14.                                                         recv[RF_REC_RLEN_i] = lpTypefunc.lpByteReadfunc();
  15.                                                 }
  16.                                                 lpTypefunc.lpSwitchEnStatus(enClose);
  17.                                                 recv[RF_REC_RLEN_i] = '\0';
  18.                                                 RF_RECEIVE();                                                
  19.                                                 uartSendString(recv);

  20.                                                         
  21.                                                 P17 = 0;
  22.                                         }
  23.                                 }
  24.                                 else if ((RF_EX0_STATUS & 0x04) == 0x04) {
  25.                                         if ((RF_EX0_STATUS & 0x01) == 0x01) { //表示CAD 检测到扩频信号 模块进入了接收状态来接收数据
  26.                                                 SX1276LoRaSetOpMode(Stdby_mode);
  27.                                                 SX1276WriteBuffer(REG_LR_IRQFLAGSMASK, IRQN_RXD_Value); //打开发送中断
  28.                                                 SX1276WriteBuffer(REG_LR_HOPPERIOD, PACKET_MIAX_Value);
  29.                                                 SX1276WriteBuffer( REG_LR_DIOMAPPING1, 0X02);
  30.                                                 SX1276WriteBuffer( REG_LR_DIOMAPPING2, 0x00);
  31.                                                 SX1276LoRaSetOpMode(Receiver_mode);
  32.                                         }
  33.                                         else {                          
  34.                                                 SX1276LoRaSetOpMode(Stdby_mode);
  35.                                                 SX1276WriteBuffer(REG_LR_IRQFLAGSMASK,IRQN_SEELP_Value);   //打开发送中断
  36.                                                 SX1276WriteBuffer( REG_LR_DIOMAPPING1, 0X00);
  37.                                                 SX1276WriteBuffer( REG_LR_DIOMAPPING2, 0X00);
  38.                                                 SX1276LoRaSetOpMode(Sleep_mode);
  39.                                                 //PA_SEELP_OUT();
  40.                                         }
  41.                                 }
  42.                                 else {
  43.                                         SX1276LoRaSetOpMode(Stdby_mode);
  44.                                         SX1276WriteBuffer(REG_LR_IRQFLAGSMASK, IRQN_RXD_Value);  //打开发送中断
  45.                                         SX1276WriteBuffer(REG_LR_HOPPERIOD, PACKET_MIAX_Value);
  46.                                         SX1276WriteBuffer( REG_LR_DIOMAPPING1, 0x02);
  47.                                         SX1276WriteBuffer( REG_LR_DIOMAPPING2, 0x00);
  48.                                         SX1276LoRaSetOpMode(Receiver_mode);
  49.                                 }
  50.                                 RF_REC_RLEN_i = 0;
  51.                                 SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  52.                                 Delay1s(300);
  53.                         } else {
  54.                                 P17 = 1;
  55.                         }
  56.                 }
复制代码
编辑通信内容代码
我们定义两组通信,分别为内容分别为1和2,这个对应后面逻辑中的两个按键。
  1. SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  2.                         FUN_RF_SENDPACKET("1",1);
  3.                         Delay1s(1000);
  4.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
复制代码
  1. SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  2.                         FUN_RF_SENDPACKET("2",1);
  3.                         Delay1s(1000);
  4.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
复制代码
1.3 应用层逻辑设计
如上所示,我们的通信步骤就完成了,接下来就是触发逻辑以及响应逻辑的应用层代码了,这一部分
我就需要结合我们的应用设备功能来设计,如设备组成图所示,我们的硬件资源一共有10个LED和两个按键,我们就以目前资源来来做一个按键控制灯的逻辑。
按照原理图定义IO口
  1. #ifndef __GPIO_H
  2. #define __GPIO_H

  3. #define KEY                                  P30
  4. #define KEY2                                 P31

  5. #define led                                  P16
  6. #define led2                                 P35

  7. #define UART_TX_PIN                          P31
复制代码
按键控制逻辑
  1.   if (P30 == 0) {
  2.                         P17 = 1;
  3.                         P32 = 0;
  4.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  5.                         FUN_RF_SENDPACKET("1",1);
  6.                         Delay1s(1000);
  7.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  8.                 }
  9.                 else if (P31 == 0) {
  10.                         P17 = 1;
  11.                         P32 = 0;
  12.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  13.                         FUN_RF_SENDPACKET("2",1);
  14.                         Delay1s(1000);
  15.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  16.                 }
复制代码
  1.       if(recv[0] == '1')
  2.                                                 {
  3.                                                         P35 = ~P35;
  4.                                                 }
  5.                                                 else if(recv[0] == '2')
  6.                                                 {
  7.                                                         P16=0;
  8.                                                         P35=1;
  9.                                                 }
复制代码
至此我们就完成了远程控制灯开关的逻辑编写了,很简单,我们利用提供的源码稍作修改就能做出这个效果。
二. 远程灯控(指定设备)
2.1 原理分析
上述的设备应用在实际场景中已经能做到星型组网,但是这个组网的通信方式就不是很符合灯控设备的控制逻辑。
因为在我们上述所写的代码中,这个设备是全频段通信的,也就是说同一个固件,我烧录在不同设备中,只要我按下按键,所有的设备都会响应。
所以我们接下来做的操作就是在这个代码的基础上做出修改让我们的主控可以随意控制多个设备。
一对多单个控制的话方式很多,我先来做一种最简单的方法,按键A控制发射在470频段,按键B控制发送在480频段。
2.2 主机代码
下面是我们计算好的频段
  1. unsigned char Frequency[3] = { 0x6c, 0x80, 0x00 };//470Mhz
  2. //unsigned char Frequency[3] = { 0x6c, 0x80, 0x00 };//430Mhz 频率设置
  3. //unsigned char Frequency[3] = { 0x6c, 0x80, 0x12 };//475.5Mhz 频率设置
  4. //unsigned char Frequency[3] = { 0x78, 0x10, 0x00 };//480.25Mhz 频率设置
  5. //unsigned char Frequency[3] = { 0x78, 0x20, 0x00 };//480.5Mhz 频率设置
复制代码
在按键B处定义出按键数组,表示按下按键B模块跳到480频段发送数据2
  1.   } else if (P31 == 0) {
  2.                         Frequency[0] = 0x78;
  3.                         Frequency[1] = 0x20;
  4.                         Frequency[2] = 0x00;
  5.                         SX1276LoRaSetRrequency();
  6.                     SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  7.                         FUN_RF_SENDPACKET("2",1);
  8.                         Delay1s(1000);
  9.                         SX1276WriteBuffer( REG_LR_IRQFLAGS, 0xff);
  10.                 }
复制代码
  1. #define IRQN_TXD_Value                               0xF7
  2. #define IRQN_RXD_Value                               0x9F
  3. #define IRQN_CAD_Value                               0xFA
  4. #define IRQN_SEELP_Value                             0xFF
  5. #define PACKET_MIAX_Value                            0xff
  6. extern unsigned char Frequency[3];
复制代码
2.3 从机代码

在这里,我们要单独生成480和470频段的接收机代码固件,分别烧录到我们的从机模块中,我们只要控制以下代码段就可以完成对不同频段的控制效果。(这里的从机代码,我们可以直接使用第一节中的灯控代码即可)
  1. unsigned char Frequency[3] = { 0x6c, 0x80, 0x00 };//470Mhz
  2. //unsigned char Frequency[3] = { 0x6c, 0x80, 0x00 };//430Mhz 频率设置
  3. //unsigned char Frequency[3] = { 0x6c, 0x80, 0x12 };//475.5Mhz 频率设置
  4. //unsigned char Frequency[3] = { 0x78, 0x10, 0x00 };//480.25Mhz 频率设置
  5. //unsigned char Frequency[3] = { 0x78, 0x20, 0x00 };//480.5Mhz 频率设置
复制代码
总结
第一步:我们首先要确保能够通信,然后在通信的基础上我们再来对收到的值进行判断,并且做出相对的输出结果(控制灯的方案)到这里我们完成了最主要的内容——通信部分。
第二步:然后我们考虑需要实现的一个主机控制不同的设备,这样我们可以把从机工作在不同频段,主机切换频段来完成通信。
用心做好保姆工作
回复

使用道具 举报

1084504793 | 2024-6-17 16:33:40 | 显示全部楼层
回复

使用道具 举报

jkernet | 2024-6-17 16:36:19 | 显示全部楼层
LORA有意思
回复 支持 反对

使用道具 举报

WT_0213 | 2024-6-17 16:50:03 | 显示全部楼层
回复

使用道具 举报

bzhou830 | 2024-6-18 08:43:26 | 显示全部楼层
LORA有意思
选择去发光,而不是被照亮
回复 支持 反对

使用道具 举报

wxlinus | 2024-6-18 09:40:52 | 显示全部楼层
推荐bug一个是暗示可以白嫖吗
回复 支持 反对

使用道具 举报

lazy | 2024-6-18 14:47:25 | 显示全部楼层
对我来说有点难
回复 支持 反对

使用道具 举报

爱笑 | 2024-6-19 11:43:21 | 显示全部楼层
wxlinus 发表于 2024-6-18 09:40
推荐bug一个是暗示可以白嫖吗

没有发出暗示哈哈
用心做好保姆工作
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则