Difference between revisions of "Tutorial:LoRa"
From MobiNetS
| (24 intermediate revisions by one other user not shown) | |||
| Line 1: | Line 1: | ||
This page shows the tutorial for LoRa experiments. | This page shows the tutorial for LoRa experiments. | ||
===LoRa basics=== | |||
===Platform and programming environments=== | ===Platform and programming environments=== | ||
===Arduino + Lora=== | |||
*Lora is a wireless communication module,we also need a ''MCU'' to contral it like Raspberry | *Lora is a wireless communication module,we also need a ''MCU'' to contral it like '''Raspberry Pi(树莓派)'''、'''Arduino''' and so on. (Here we choose Arduino). | ||
*[http://mobinets.org/index.php?title=Tutorial:Arduino&action=edit&redlink=1 More about '''Arduino'''] | *[http://mobinets.org/index.php?title=Tutorial:Arduino&action=edit&redlink=1 More about '''Arduino'''] | ||
*'''Lora''' | *'''Lora''' | ||
===Lora通信实例=== | |||
#使用Arduino进行Lora开发,首先需要环境配置: | |||
*'''下载和安装Arduino IDE''' [[https://www.arduino.cc/en/Main/Software Arduino下载]] | |||
*'''在IDE中添加开发板''' 我们要在IDE上编写代码烧录到板子上运行,首先需要把板子信息加载到IDE里面,这样,IDE才能识别到开发板。以我们使用的Dragino开发板为例: | |||
具体步骤: | 具体步骤: | ||
在PC上打开IDE --> 点击'''File''' --> '''preference'''-->在'''Additional Boards Manager URLs'''里添加以下URL:'''http://www.dragino.com/downloads/downloads/YunShield/package_dragino_yun_test_index.json''' | 在PC上打开IDE --> 点击'''File''' --> '''preference'''-->在'''Additional Boards Manager URLs'''里添加以下URL:'''http://www.dragino.com/downloads/downloads/YunShield/package_dragino_yun_test_index.json''' | ||
转到tools --> Boards --> Boards Manager,找到Dragino信息并安装它 | 转到tools --> Boards --> Boards Manager,找到Dragino信息并安装它 | ||
这样,我们的Dragino开发板就成功的关联到了IDE里面,可以打开IDE --> Tools的开发板,就能找到Dragino | 这样,我们的Dragino开发板就成功的关联到了IDE里面,可以打开IDE --> Tools的开发板,就能找到Dragino | ||
# | |||
# | #*要使用Lora通信,需要调用Lora的库文件,当然,我们有现成的库可以用。点击下载[[http://www.airspayce.com/mikem/arduino/RadioHead/ RadioHead]],将其拷贝到Arduino安装目录下的'''libraries'''里面(我的是在 ''C:\Program Files (x86)\Arduino\libraries''),就可以从IDE当中直接导包,使用里面提供的接口 | ||
#*用数据线将开发板连接到电脑,打开IDE --> Tools --> 开发板 --> 选择Arduino/Genuino UNO(因为我们使用的是UNO型号的板子),然后:Tools --> 端口(选择开发板连接的端口)。下面是Lora通信的示例代码: | |||
#include <SPI.h> | '''Client:''' | ||
#include <RH_RF95.h> | #include <SPI.h> //lora跟Arduino之间使用的是SPI通信方式 | ||
#include <RH_RF95.h> //lora的库文件,提供了关于设置lora发射参数等一系列函数 | |||
RH_RF95 rf95; | RH_RF95 rf95; | ||
float frequency = 433.0; | float frequency = 433.0; //在国内,ISM频段只有433MHz可用,这里需要注意,如果我们买的是868M或者915M的lora板子,是无法使用的 | ||
void setup() | void setup() | ||
{ | { | ||
Serial.begin(9600); | Serial.begin(9600); //设置波特率,为了Arduino开发板跟电脑端的串口通信使用,有时候使用串口助手发现电脑端显示的全是乱码,就很有可能是波特率设置的不一样。 | ||
while (!Serial) ; // Wait for serial port to be available | while (!Serial) ; // Wait for serial port to be available | ||
Serial.println("Start LoRa Client"); | Serial.println("Start LoRa Client"); //串口打印函数 | ||
if (!rf95.init()) | if (!rf95.init()) | ||
Serial.println("init failed"); | Serial.println("init failed"); | ||
// Setup ISM frequency | rf95.setFrequency(frequency); // Setup ISM frequency | ||
rf95. | rf95.setTxPower(13); // Setup Power,dBm | ||
rf95.setSpreadingFactor(7); // Setup Spreading Factor (6 ~ 12) | |||
rf95. | |||
// Setup BandWidth, option: 7800,10400,15600,20800,31200,41700,62500,125000,250000,500000 | // Setup BandWidth, option: 7800,10400,15600,20800,31200,41700,62500,125000,250000,500000 | ||
//Lower BandWidth for longer distance. | //Lower BandWidth for longer distance. | ||
| Line 44: | Line 42: | ||
// Setup Coding Rate:5(4/5),6(4/6),7(4/7),8(4/8) | // Setup Coding Rate:5(4/5),6(4/6),7(4/7),8(4/8) | ||
rf95.setCodingRate4(5); | rf95.setCodingRate4(5); | ||
} | //如果我们需要修改lorat通信参数,只需要一行代码,非常方便 | ||
} //setup函数体只执行一遍,执行完了过后,开始进入到loop函数里面 | |||
void loop() | void loop() | ||
| Line 50: | Line 49: | ||
Serial.println("Sending to LoRa Server"); | Serial.println("Sending to LoRa Server"); | ||
// Send a message to LoRa Server | // Send a message to LoRa Server | ||
uint8_t data[] = "Hello, this is device 1"; | uint8_t data[] = "Hello, this is device 1"; //lora需要发射的数据,都是存放在一个字符数组里面 | ||
rf95.send(data, sizeof(data)); | rf95.send(data, sizeof(data)); //发送函数 | ||
rf95.waitPacketSent(); | rf95.waitPacketSent(); //等待数据发送完成 | ||
// Now wait for a reply | // Now wait for a reply | ||
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; | uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; | ||
uint8_t len = sizeof(buf); | uint8_t len = sizeof(buf); | ||
delay(1000); | if (rf95.waitAvailableTimeout(3000)) | ||
{ | |||
// Should be a reply message for us now | |||
if (rf95.recv(buf, &len)) | |||
{ | |||
Serial.print("got reply: "); | |||
Serial.println((char*)buf); | |||
Serial.print("RSSI: "); | |||
Serial.println(rf95.lastRssi(), DEC); | |||
} | |||
else | |||
{ | |||
Serial.println("recv failed"); | |||
} | |||
} | |||
else | |||
{ | |||
Serial.println("No reply, is LoRa server running?"); | |||
} | |||
delay(1000); //延迟1000毫秒,通过修改这里的值,我们可以控制发包间隔 | |||
} | } | ||
'''Server:''' | |||
#include <SPI.h> | #include <SPI.h> | ||
#include <RH_RF95.h> | #include <RH_RF95.h> | ||
| Line 77: | Line 93: | ||
if (!rf95.init()) | if (!rf95.init()) | ||
Serial.println("init failed"); | Serial.println("init failed"); | ||
rf95.setFrequency(frequency); | rf95.setFrequency(frequency); | ||
rf95.setTxPower(13); | rf95.setTxPower(13); | ||
// Defaults BW Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on | // Defaults BW Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on | ||
| Line 89: | Line 103: | ||
{ | { | ||
if (rf95.available()) | if (rf95.available()) | ||
{ | { | ||
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; //开辟一个buffer便于接收lora数据 | |||
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; | |||
uint8_t len = sizeof(buf); | uint8_t len = sizeof(buf); | ||
if (rf95.recv(buf, &len)) | if (rf95.recv(buf, &len)) | ||
| Line 100: | Line 113: | ||
Serial.println((char*)buf); | Serial.println((char*)buf); | ||
Serial.print("RSSI: "); | Serial.print("RSSI: "); | ||
Serial.println(rf95.lastRssi(), DEC); | Serial.println(rf95.lastRssi(), DEC); //调用现成的接口可以直接获取lora信号的RSSI值 | ||
// Send a reply | // Send a reply | ||
| Line 116: | Line 129: | ||
} | } | ||
=== | ===Change lora parameters online=== | ||
当我们需要修改lora节点的通信参数,但是却无法手动去更改的时候(比如节点已经布置到各个区域,不可能再一个一个去现场修改),我们就需要在网关处发送命令,让节点收到命令后自己修改掉参数。 | |||
要实现这样的功能,主要需要两点: | |||
*'''arduino板子的软重置'''。我们修改了参数,需要重启一下板子,以新的参数进行通信。这里arduino为我们提供了一个函数:'''resetFunc().''' 当程序执行到这里的时候,板子会重新启动 | |||
*'''一块掉电后仍能保存数据的区域'''。光是能重启,那么板子还是原来的参数,我们要修改参数,通过网关发射参数过去后,节点收到参数,需要保存在一个区域,掉电了后,这里的数据还在。所以重启后读这里面的数据,就能读到新的参数。这块掉电保存的区域,在Arduino里叫做'''EEPROM''',我们使用的UNO型号的Arduino开发板,EEPROM的大小为 1KB,但是我们就放几个参数是完全够用的。 | |||
*下面例程代码: | |||
**'''Client''' | |||
#include <SPI.h> | |||
#include <RH_RF95.h> | |||
#include <EEPROM.h> //需要用到EEPROM | |||
void(*resetFunc)(void) = 0; //将函数入口设为0, | |||
RH_RF95 rf95; | |||
float frequency = 433.0; | |||
int TxPower; | |||
int SpreadingFactor; | |||
int CodingRate4; | |||
const unsigned int Buffer_len = 15;//接收要修改的参数的长度:"Reset,传输功率,扩频因子,码率," 。网关按照这样的格式发命令给节点 | |||
struct | |||
{ | |||
char Buffer[Buffer_len]; | |||
bool isGetCommand; //是否获取到command数据 | |||
bool isParseData; //是否解析完成 | |||
char TxPower[3]; //发送功率 12-20 | |||
char SpreadingFactor[3]; //扩频因子 7-12 | |||
char CodingRate4[2]; //码率5-8 | |||
} Command; | |||
void setup() //初始化内容 | |||
{ | |||
Serial.begin(9600); //定义波特率9600 | |||
Serial.println("Wating..."); | |||
Command.isGetCommand = false; | |||
Command.isParseData = false; | |||
if (!rf95.init()) | |||
Serial.println("init failed"); | |||
TxPower = EEPROM.read(0); //先读取传输功率,来判断是否写入过参数 | |||
if (TxPower == 0||TxPower == 255) //如果还没有写入,设置默认的通信参数 | |||
{ | |||
TxPower = 20; //初始化传输功率为13 | |||
SpreadingFactor = 12; | |||
CodingRate4 = 5; | |||
} | |||
else | |||
{ | |||
SpreadingFactor = EEPROM.read(1); | |||
CodingRate4 = EEPROM.read(2); | |||
} | |||
rf95.setFrequency(frequency); | |||
rf95.setTxPower(TxPower); | |||
Serial.println(TxPower); //检查一下传输功率 | |||
rf95.setSpreadingFactor(SpreadingFactor); | |||
Serial.println(SpreadingFactor);//检查一下扩频因子 | |||
rf95.setCodingRate4(5); | |||
Serial.println(CodingRate4); | |||
rf95.setSignalBandwidth(125000); | |||
} | |||
void loop() | |||
{ | |||
Send_Message(); //发送数据 | |||
Command_Get(); //接收命令 | |||
Command_Parse();//解析数据 | |||
} | |||
void Send_Message() | |||
{ | |||
Serial.println("Sending to lora Server"); | |||
uint8_t data[] = "Hello,this is device 1"; | |||
rf95.send(data,sizeof(data)); | |||
rf95.waitPacketSent(); | |||
} | |||
void Command_Get() | |||
{ | |||
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; | |||
uint8_t len = sizeof(buf); | |||
if (rf95.waitAvailableTimeout(3000)) | |||
{ | |||
// Should be a reply message for us now | |||
if (rf95.recv(buf, &len)) | |||
{ | |||
Serial.print("got reply: "); | |||
Serial.println((char*)buf); | |||
if(buf[0] == 'R') //Reset | |||
{ | |||
memcpy(Command.Buffer, buf, Buffer_len);//将lora传过来的数据拷贝到结构体buffer里面,15位 | |||
Command.isGetCommand = true; //如果收到Reset命令,就表示得到了数据 | |||
} | |||
} | |||
else | |||
{ | |||
Serial.println("recv failed"); | |||
} | |||
} | |||
else | |||
Serial.println("No message"); | |||
} | |||
void Command_Parse() | |||
{ | |||
char *subString; | |||
char *subStringNext; | |||
if (Command.isGetCommand) | |||
{ | |||
Command.isGetCommand = false; | |||
Serial.println("**************"); | |||
for (int i = 0 ; i <= 3 ; i++) //将命令切分,依次放入对应的数组中 | |||
{ | |||
if (i == 0) | |||
{ | |||
if ((subString = strstr(Command.Buffer, ",")) == NULL) | |||
Serial.println("error1"); //解析错误 | |||
} | |||
else | |||
{ | |||
subString++; | |||
if ((subStringNext = strstr(subString, ",")) != NULL) | |||
{ | |||
switch(i) | |||
{ | |||
case 1:memset(Command.TxPower,'\0',3);memcpy(Command.TxPower, subString, subStringNext - subString);break; //获取传输功率 | |||
case 2:memset(Command.SpreadingFactor,'\0',3);memcpy(Command.SpreadingFactor, subString, subStringNext - subString);break; //获取扩频因子 | |||
case 3:memset(Command.CodingRate4,'\0',2);memcpy(Command.CodingRate4, subString, subStringNext - subString);break; //获取码率 | |||
default:break; | |||
} | |||
subString = subStringNext; | |||
Command.isParseData = true; | |||
} | |||
else | |||
{ | |||
Serial.println("error2"); //解析错误 | |||
Command.isParseData = false; | |||
} | |||
} | |||
}//for | |||
}//if (Command.isGetCommand) | |||
if(Command.isParseData) //如果解析完成,就执行更新函数 | |||
{ | |||
Command.isParseData = false; //解析完成,标志位置位假,并且重启 | |||
reset_f(); //解析完成,写入参数并重启 | |||
} | |||
} | |||
void reset_f() | |||
{ | |||
EEPROM.update(0,atoi(Command.TxPower)); //将TxPower更新到第一个位置 | |||
delay(300); | |||
EEPROM.update(1,atoi(Command.SpreadingFactor)); //将SpreadingFactor更新到第二个位置 | |||
delay(300); | |||
EEPROM.update(2,atoi(Command.CodingRate4)); //将CodingRate4更新到第三个位置 | |||
delay(300); | |||
resetFunc(); //将修改的参数写入了EEPROM,然后重置。 | |||
} | |||
**'''Server''' | |||
#include <SPI.h> | |||
#include <RH_RF95.h> | |||
RH_RF95 rf95; | |||
float frequency = 433.0; | |||
bool send_flag; | |||
void setup() | |||
{ | |||
Serial.begin(9600); | |||
while (!Serial) ; // Wait for serial port to be available | |||
Serial.println("Start Sketch"); | |||
if (!rf95.init()) | |||
Serial.println("init failed"); | |||
send_flag = false;//初始设置为0,如果要发送修改参数,就将flag设置为1 | |||
rf95.setFrequency(frequency); | |||
rf95.setTxPower(20); | |||
rf95.setSpreadingFactor(8); | |||
rf95.setSignalBandwidth(125000); | |||
rf95.setCodingRate4(5); | |||
// Defaults BW Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on | |||
Serial.print("Listening on frequency: "); | |||
Serial.println(frequency); | |||
} | |||
void loop() | |||
{ | |||
if (rf95.available()) | |||
{ | |||
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; | |||
uint8_t len = sizeof(buf); | |||
if (rf95.recv(buf, &len)) | |||
{ | |||
Serial.print("got request,"); | |||
Serial.print((char*)buf); | |||
Serial.print("RSSI,"); | |||
Serial.print(rf95.lastRssi(), DEC); | |||
Serial.print(","); | |||
Serial.print("SNR,"); | |||
Serial.println(rf95.lastSNR(), DEC); | |||
} | |||
else | |||
{ | |||
Serial.println("recv failed"); | |||
} | |||
} | |||
if(send_flag == true) | |||
{ | |||
send_flag = false;//如果手动修改了flag为1,则说明要发送命令了 | |||
uint8_t data[] = "Reset,16,8,6,"; //要发送的参数 | |||
rf95.send(data, sizeof(data)); | |||
rf95.waitPacketSent(); | |||
Serial.println("Sent a commamd"); | |||
} | |||
} | |||
===Sensory data measurement=== | ===Sensory data measurement=== | ||
===Data collection via USB cables=== | ===Data collection via USB cables=== | ||
Latest revision as of 15:52, 14 April 2020
This page shows the tutorial for LoRa experiments.
LoRa basics
Platform and programming environments
Arduino + Lora
- Lora is a wireless communication module,we also need a MCU to contral it like Raspberry Pi(树莓派)、Arduino and so on. (Here we choose Arduino).
- More about Arduino
- Lora
Lora通信实例
- 使用Arduino进行Lora开发,首先需要环境配置:
- 下载和安装Arduino IDE [Arduino下载]
- 在IDE中添加开发板 我们要在IDE上编写代码烧录到板子上运行,首先需要把板子信息加载到IDE里面,这样,IDE才能识别到开发板。以我们使用的Dragino开发板为例:
具体步骤: 在PC上打开IDE --> 点击File --> preference-->在Additional Boards Manager URLs里添加以下URL:http://www.dragino.com/downloads/downloads/YunShield/package_dragino_yun_test_index.json 转到tools --> Boards --> Boards Manager,找到Dragino信息并安装它 这样,我们的Dragino开发板就成功的关联到了IDE里面,可以打开IDE --> Tools的开发板,就能找到Dragino
- 要使用Lora通信,需要调用Lora的库文件,当然,我们有现成的库可以用。点击下载[RadioHead],将其拷贝到Arduino安装目录下的libraries里面(我的是在 C:\Program Files (x86)\Arduino\libraries),就可以从IDE当中直接导包,使用里面提供的接口
- 用数据线将开发板连接到电脑,打开IDE --> Tools --> 开发板 --> 选择Arduino/Genuino UNO(因为我们使用的是UNO型号的板子),然后:Tools --> 端口(选择开发板连接的端口)。下面是Lora通信的示例代码:
Client:
#include <SPI.h> //lora跟Arduino之间使用的是SPI通信方式 #include <RH_RF95.h> //lora的库文件,提供了关于设置lora发射参数等一系列函数
RH_RF95 rf95; float frequency = 433.0; //在国内,ISM频段只有433MHz可用,这里需要注意,如果我们买的是868M或者915M的lora板子,是无法使用的
void setup()
{
Serial.begin(9600); //设置波特率,为了Arduino开发板跟电脑端的串口通信使用,有时候使用串口助手发现电脑端显示的全是乱码,就很有可能是波特率设置的不一样。
while (!Serial) ; // Wait for serial port to be available
Serial.println("Start LoRa Client"); //串口打印函数
if (!rf95.init())
Serial.println("init failed");
rf95.setFrequency(frequency); // Setup ISM frequency
rf95.setTxPower(13); // Setup Power,dBm
rf95.setSpreadingFactor(7); // Setup Spreading Factor (6 ~ 12)
// Setup BandWidth, option: 7800,10400,15600,20800,31200,41700,62500,125000,250000,500000
//Lower BandWidth for longer distance.
rf95.setSignalBandwidth(125000);
// Setup Coding Rate:5(4/5),6(4/6),7(4/7),8(4/8)
rf95.setCodingRate4(5);
//如果我们需要修改lorat通信参数,只需要一行代码,非常方便
} //setup函数体只执行一遍,执行完了过后,开始进入到loop函数里面
void loop()
{
Serial.println("Sending to LoRa Server");
// Send a message to LoRa Server
uint8_t data[] = "Hello, this is device 1"; //lora需要发射的数据,都是存放在一个字符数组里面
rf95.send(data, sizeof(data)); //发送函数
rf95.waitPacketSent(); //等待数据发送完成
// Now wait for a reply
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.waitAvailableTimeout(3000))
{
// Should be a reply message for us now
if (rf95.recv(buf, &len))
{
Serial.print("got reply: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC);
}
else
{
Serial.println("recv failed");
}
}
else
{
Serial.println("No reply, is LoRa server running?");
}
delay(1000); //延迟1000毫秒,通过修改这里的值,我们可以控制发包间隔
}
Server:
#include <SPI.h> #include <RH_RF95.h>
RH_RF95 rf95; int led = A2; float frequency = 433.0;
void setup()
{
pinMode(led, OUTPUT);
Serial.begin(9600);
while (!Serial) ; // Wait for serial port to be available
Serial.println("Start Sketch");
if (!rf95.init())
Serial.println("init failed");
rf95.setFrequency(frequency);
rf95.setTxPower(13);
// Defaults BW Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
Serial.print("Listening on frequency: ");
Serial.println(frequency);
}
void loop()
{
if (rf95.available())
{
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; //开辟一个buffer便于接收lora数据
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len))
{
digitalWrite(led, HIGH);
RH_RF95::printBuffer("request: ", buf, len);
Serial.print("got request: ");
Serial.println((char*)buf);
Serial.print("RSSI: ");
Serial.println(rf95.lastRssi(), DEC); //调用现成的接口可以直接获取lora信号的RSSI值
// Send a reply
uint8_t data[] = "And hello back to you";
rf95.send(data, sizeof(data));
rf95.waitPacketSent();
Serial.println("Sent a reply");
digitalWrite(led, LOW);
}
else
{
Serial.println("recv failed");
}
}
}
Change lora parameters online
当我们需要修改lora节点的通信参数,但是却无法手动去更改的时候(比如节点已经布置到各个区域,不可能再一个一个去现场修改),我们就需要在网关处发送命令,让节点收到命令后自己修改掉参数。 要实现这样的功能,主要需要两点:
- arduino板子的软重置。我们修改了参数,需要重启一下板子,以新的参数进行通信。这里arduino为我们提供了一个函数:resetFunc(). 当程序执行到这里的时候,板子会重新启动
- 一块掉电后仍能保存数据的区域。光是能重启,那么板子还是原来的参数,我们要修改参数,通过网关发射参数过去后,节点收到参数,需要保存在一个区域,掉电了后,这里的数据还在。所以重启后读这里面的数据,就能读到新的参数。这块掉电保存的区域,在Arduino里叫做EEPROM,我们使用的UNO型号的Arduino开发板,EEPROM的大小为 1KB,但是我们就放几个参数是完全够用的。
- 下面例程代码:
- Client
#include <SPI.h> #include <RH_RF95.h> #include <EEPROM.h> //需要用到EEPROM
void(*resetFunc)(void) = 0; //将函数入口设为0,
RH_RF95 rf95;
float frequency = 433.0;
int TxPower;
int SpreadingFactor;
int CodingRate4;
const unsigned int Buffer_len = 15;//接收要修改的参数的长度:"Reset,传输功率,扩频因子,码率," 。网关按照这样的格式发命令给节点
struct
{
char Buffer[Buffer_len];
bool isGetCommand; //是否获取到command数据
bool isParseData; //是否解析完成
char TxPower[3]; //发送功率 12-20
char SpreadingFactor[3]; //扩频因子 7-12
char CodingRate4[2]; //码率5-8
} Command;
void setup() //初始化内容
{
Serial.begin(9600); //定义波特率9600
Serial.println("Wating...");
Command.isGetCommand = false;
Command.isParseData = false;
if (!rf95.init())
Serial.println("init failed");
TxPower = EEPROM.read(0); //先读取传输功率,来判断是否写入过参数
if (TxPower == 0||TxPower == 255) //如果还没有写入,设置默认的通信参数
{
TxPower = 20; //初始化传输功率为13
SpreadingFactor = 12;
CodingRate4 = 5;
}
else
{
SpreadingFactor = EEPROM.read(1);
CodingRate4 = EEPROM.read(2);
}
rf95.setFrequency(frequency);
rf95.setTxPower(TxPower);
Serial.println(TxPower); //检查一下传输功率
rf95.setSpreadingFactor(SpreadingFactor);
Serial.println(SpreadingFactor);//检查一下扩频因子
rf95.setCodingRate4(5);
Serial.println(CodingRate4);
rf95.setSignalBandwidth(125000);
}
void loop()
{
Send_Message(); //发送数据
Command_Get(); //接收命令
Command_Parse();//解析数据
}
void Send_Message()
{
Serial.println("Sending to lora Server");
uint8_t data[] = "Hello,this is device 1";
rf95.send(data,sizeof(data));
rf95.waitPacketSent();
}
void Command_Get()
{
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.waitAvailableTimeout(3000))
{
// Should be a reply message for us now
if (rf95.recv(buf, &len))
{
Serial.print("got reply: ");
Serial.println((char*)buf);
if(buf[0] == 'R') //Reset
{
memcpy(Command.Buffer, buf, Buffer_len);//将lora传过来的数据拷贝到结构体buffer里面,15位
Command.isGetCommand = true; //如果收到Reset命令,就表示得到了数据
}
}
else
{
Serial.println("recv failed");
}
}
else
Serial.println("No message");
}
void Command_Parse()
{
char *subString;
char *subStringNext;
if (Command.isGetCommand)
{
Command.isGetCommand = false;
Serial.println("**************");
for (int i = 0 ; i <= 3 ; i++) //将命令切分,依次放入对应的数组中
{
if (i == 0)
{
if ((subString = strstr(Command.Buffer, ",")) == NULL)
Serial.println("error1"); //解析错误
}
else
{
subString++;
if ((subStringNext = strstr(subString, ",")) != NULL)
{
switch(i)
{
case 1:memset(Command.TxPower,'\0',3);memcpy(Command.TxPower, subString, subStringNext - subString);break; //获取传输功率
case 2:memset(Command.SpreadingFactor,'\0',3);memcpy(Command.SpreadingFactor, subString, subStringNext - subString);break; //获取扩频因子
case 3:memset(Command.CodingRate4,'\0',2);memcpy(Command.CodingRate4, subString, subStringNext - subString);break; //获取码率
default:break;
}
subString = subStringNext;
Command.isParseData = true;
}
else
{
Serial.println("error2"); //解析错误
Command.isParseData = false;
}
}
}//for
}//if (Command.isGetCommand)
if(Command.isParseData) //如果解析完成,就执行更新函数
{
Command.isParseData = false; //解析完成,标志位置位假,并且重启
reset_f(); //解析完成,写入参数并重启
}
}
void reset_f()
{
EEPROM.update(0,atoi(Command.TxPower)); //将TxPower更新到第一个位置
delay(300);
EEPROM.update(1,atoi(Command.SpreadingFactor)); //将SpreadingFactor更新到第二个位置
delay(300);
EEPROM.update(2,atoi(Command.CodingRate4)); //将CodingRate4更新到第三个位置
delay(300);
resetFunc(); //将修改的参数写入了EEPROM,然后重置。
}
- Server
#include <SPI.h> #include <RH_RF95.h>
RH_RF95 rf95; float frequency = 433.0; bool send_flag;
void setup()
{
Serial.begin(9600);
while (!Serial) ; // Wait for serial port to be available
Serial.println("Start Sketch");
if (!rf95.init())
Serial.println("init failed");
send_flag = false;//初始设置为0,如果要发送修改参数,就将flag设置为1
rf95.setFrequency(frequency);
rf95.setTxPower(20);
rf95.setSpreadingFactor(8);
rf95.setSignalBandwidth(125000);
rf95.setCodingRate4(5);
// Defaults BW Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on
Serial.print("Listening on frequency: ");
Serial.println(frequency);
}
void loop()
{
if (rf95.available())
{
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if (rf95.recv(buf, &len))
{
Serial.print("got request,");
Serial.print((char*)buf);
Serial.print("RSSI,");
Serial.print(rf95.lastRssi(), DEC);
Serial.print(",");
Serial.print("SNR,");
Serial.println(rf95.lastSNR(), DEC);
}
else
{
Serial.println("recv failed");
}
}
if(send_flag == true)
{
send_flag = false;//如果手动修改了flag为1,则说明要发送命令了
uint8_t data[] = "Reset,16,8,6,"; //要发送的参数
rf95.send(data, sizeof(data));
rf95.waitPacketSent();
Serial.println("Sent a commamd");
}
}
