LoRa网关、节点性能常用数据整理和统计

本文包含一些用到的一些LoRa网关、节点相关的参数,供方案设计人员参考。LoRa网关处理能力1个1301芯片,8个上行通道,24小时可以接收约150万个数据包。每个设备每小时上报一次,可以处理约62500个设备。下面见官方资料What is the capacity of LoRa gateway? How many nodes can be connected to a single gate...了解详情

LoRa点对点系统9 下载源代码与前路思考

1 源代码下载地址源代码可以从以下链接下载http://download.csdn.net/detail/jiangjunjie_2005/96634522 开发环境与工具硬件平台:锐米LoRa终端http://www.rimelink.com/pd.jsp?id=2测试套件:USB转串口 + LoRa终端转接板https://shop140974727.taobao.com/?spm=2013.1.1000126.d21.DL6hVR仿真器:  ST LINK V2https://item.taobao.com/item.htm?spm=2013.1.20141002.4.Sj743Y&scm=1007.10009.31621.100200300000004&id=540446816750&pvid=8a31520e-d2bd-4a21-b940-aa421c82d92dIDE环境:IAR for STM8 http://www.rimelink.com/nd.jsp?id=33&_np=105_3153 评估软件3.1 下载评估软件下载评估软件链接:http://www.rimelink.com/nd.jsp?id=38&_np=105_3153.2 使用评估软件使用该软件请参考《锐米LoRa终端评估软件操作手册》,链接地址为:http://www.rimelink.com/nd.jsp?id=38&_np=105_315思考题:路往何方1 点对点系统局限性LoRa点对点系统在现实中有少量的应用场景,如:使用手持机“点名”抄能源表计(电/水/气/热表计),远程控制阀门等。当然,它的局限性是很明显的:1. 没有避免冲突机制:没有LBT(Listen BeforeTalk)机制,如果2个节点同时发送,无线电信号将受损,导致通信失败;2. 接收节点无法低功耗:接收节点必须随时等待发送节点的信号,无法休眠;3. 无法自动组网:解决不了避免冲突和低功耗侦听,组网也就成了空中楼阁。2  LoRa+mesh可行吗?在FSK调制的微功率射频时代,mesh是主流方案,表面看,它具备:多跳延伸通信距离,多路径保证通信链路健壮性,避免冲突,低功耗侦听等优点;然而,深入研发的工程师都知道它有以下缺陷:1. 延时大:当一个数据包经过几跳传输后,实时性就很难保证;2. 不可靠:跳跃转发越多,丢失数据包的机率就越大,尤其是通信链路受干扰或信号微弱的情况下;3. 耗电大:mesh网中负责转发的节点能耗很大,最终整体网络将陷入瘫痪;4. 很复杂:多跳转发和多径路由,本身就复杂,这给开发和维护带来困难。也正因为上述缺陷,像ZigBee一直没有占据主导地位;LoRa是从物理层面(调制技术)实现了长距离和低功耗,因此它的“基因良好”,天生就可以绕过上述4个坑。除非常特殊的场景(如:军用或救灾),一般LoRa是不需要mesh组网的。锐米通信于2年前研发过一个LoRa+mesh的网络系统,后来团队发现,应用于产品不合适;当然,对于科研机构,该系统可能具备研究价值。如果您对于该系统感兴趣,我们提供源代码。申请Email:sales@rimelink.com3  星型网关LoRa因为长距离的优势,使用星型网络成为最佳的选择,它具备很多优势:1. 延时小:因为是单跳,一次性传播,延时是可控的;2. 高可靠:那怕链路受干扰或信号微弱,借助LoRa抗干扰优势,星型网络仍能提供可靠的通信;3. 能耗低:双方可以协商唤醒时刻,空闲时休眠,实现低功耗;4. 简单化:星型网在网络拓朴中非常简单,可以大幅降低开发和维护成本。锐米通信开发的第2代LoRa系统,就是星型网络,它除了低功耗和长距离还,特别擅长超低功耗唤醒技术。了解更多详情,请链接:http://www.rimelink.com/nd.jsp?id=44&_np=105_315了解详情

LoRa点对点系统8 测试

1 测试环境1.1 测试工具PC机2台;锐米LoRa终端2个;USB转串口套件2个;锐米LoRa终端评估软件;1.2 搭建平台如下图所示,2个LoRa终端,分别通过USB转UART连接2台PC,终端之间通过LoRa无线通信。这样一来,PC#i发送的数据,PC#j能远程接收;反之,亦然。2 集成测试2.1 测试目的将LoRa终端和PC评估软件联合测试,使它们能够正常运行。2.2 测试内容
步骤方法结果
使用PC评估软件,遍历测试LoRa终端的接口协议;
发送RF数据包,Comm2Trm和Network进程正常工作;
接收RF数据包,Comm2Trm和Network进程正常工作;
设置参数,2个进程和SystSettings模块正常工作;
3 功能测试3.1 测试目的功能测试指按产品说明书,逐项测试列举的功能。3.2 测试内容
测试对象测试内容测试结果
读取软件版本使用PC评估软件,读取LoRa终端的软件版本
发送数据发送字节从1到247,都能够正确发送
配置射频参数...
了解详情

LoRa点对点系统7 剖析核心代码

1 引言在LoRa点对点系统中,核心是Network进程的处理代码,它除了响应用户发送无线数据包外,还需要驱动射频和响应多种中断信号。为此,我们列出该进程的逻辑,并且剖析它的代码。2 核心代码逻辑有2个特别注意的地方:1. 如果RF_Rx_Error,需要重新启动RF接收功能,以避免引发宕机错误;2. RF缓冲区中有多个数据包时,给自身发poll消息,让其他进程有机会运行。3 剖析核心代码PROCESS_THREAD(NetworkProcess, ev, data){/*ATTENTION: stack variables can NOT cross any “XX_YIELD()”. */uint8_t    byDataSize;uint16_t    wCalcCRC16;uint16_t    wSrcCRC16;PROCESS_BEGIN();SX1278Receive(0);while(TRUE){PROCESS_YIELD();if (NETWORK_EVENT_TX_RF_PACKAGE == ev)                                                      1{/* Make RF package as well as TX it. */wCalcCRC16= util_CRC16( s_stTxRFPackage.a_byBuf,s_stTxRFPackage.byRFTxSize );*(uint16_t *)&s_stTxRFPackage.a_byBuf[s_stTxRFPackage.byRFTxSize] =wCalcCRC16;SX1278SetSleep();                                                                                                       2SX1278Send( s_stTxRFPackage.a_byBuf,s_stTxRFPackage.byRFTxSize +sizeof(uint16_t));                               3/* Waiting until TX is done. */PROCESS_YIELD_UNTIL( RF_Tx_Done == s_tRFResult ||RF_Tx_Timeout ==s_tRFResult );                                  4/* Enable RF_RX. */SX1278Receive(0);                                                                                                       5}else                                                                                                                                6{if (RF_Rx_Error == s_tRFResult){/*EXPLAIN: Restore the RX of RFif Rx-Error or frame is NOT integrity. */SX1278SetSleep();                                                                                                     7SX1278Receive(0);}/* EXPLAIN: process all received packets for simplicity. */if (!IsRadioBufEmpty()){/* Fetch data from RF buffer, CheckCRC16. */s_stParseRFBuf.bySize = GetRadioBuf(s_stParseRFBuf.a_byBuf,RF_FIFO_SIZE); 8if (sizeof(uint16_t) < s_stParseRFBuf.bySize){byDataSize = s_stParseRFBuf.bySize – sizeof(uint16_t);wSrcCRC16 = *(uint16_t *)&s_stParseRFBuf.a_byBuf[byDataSize];wCalcCRC16 = util_CRC16(s_stParseRFBuf.a_byBuf, byDataSize);if (wSrcCRC16 == wCalcCRC16)                                                                             9{/* Deliver data to Comm2Trm-Process */comm2trm_RxRFPackage(s_stParseRFBuf.a_byBuf, byDataSize);                     10}else{/*EXPLAIN: Restore the RX of RF if Rx-Error orframe is NOT integrity. */SX1278SetSleep();                                                                                                11SX1278Receive(0);}}/*if*//* Check whether some packages still stay in buffer. */if (!IsRadioBufEmpty())                                                                                               12{/* Don’t disturb the scheduling ofother processes. */process_poll(&NetworkProcess);}}/*if (!IsRadioBufEmpty())*/}}/*while(TRUE)*/PROCESS_END();}Line#1:用户需要发送RF数据包;Line#2:将处于持续接收的RF设置休眠状态;Line#3:通过SX1278发送该RF数据包;Line#4:阻塞进程,直到RF发送数据包完毕;Line#5:将RF切换到持续接收模式;Line#6:射频中断服务程序发来消息:接收到数据包,或,接收错误;Line#7:RF接收出错,重新启动RF接收功能,避免宕机错误;Line#8:从RF缓冲区复制数据包到解析工作区;Line#9:检查接收数据包的CRC16是否正确;Line#10:交付接收数据给Comm2Trm进程;Line#11:如果数据包的CRC16错误,重新启动RF接收功能,避免宕机错误;Line#12:如果RF缓冲区还有数据包,给自身发poll消息,允许Contiki调度其他进程运行。了解详情

LoRa点对点系统6 源代码结构

1 源代码结构main.c      基于C语言系统的入口函数main.h      系统的全局配置文件Application  应用程序,以Contiki系统的protothread方式组织Contiki      Contiki操作系统Driver       驱动:ST官方驱动库和MCU外设驱动文件Project      IAR环境下所有工程文档RF         SX1278射频芯片驱动代码2 使用源代码在源代码文件main.h中,有如下宏编译语句:#define CUR_PRODUCT    iWL882A#define REL_VER    1 /* 0=debug; 1=release */#define CUR_VER    “LoRaP2PTW V1.0.00 2016-10-20” /*current version */它们代表如下含义:CUR_PRODUCT:当前LoRa终端的硬件版本号,目前出厂为iWL882A;REL_VER:0=debug版本,串口支持shell命令;1=release版本,串口与评估软件通信;CUR_VER:软件版本号,其中“LoRaP2PTW”不能更改,因为评估软件依赖该版本编号来识别产品种类;3  Main入口函数void main(void){/* Initialize hardware */chip_Init();                                                                                                   1SX1278InitPins();                                                                                        2rtimer_init();                                                                                                 3ss_Init();                                                                                                       4cpc_Init();                                                                                                        5#if (!REL_VER)dp_Init();                                                                                                      6#endif/* EXPLAIN: enable INT before initialize process! */HAL_ENABLE_INTERRUPTS();                                                                 7/*Initialize contiki system */process_init();                                                                                              8/* Start process of user */comm2trm_Init();                                                                                          9network_Init();                                                                                            10#if (!REL_VER)monitor_Init();                                                                                             11#endifwhile (1){while (0 < process_run())                                                                       12{null();                                                                                                  13}/* EXPLAIN: Set MCU to low power mode if have nothing to do. */wfi();                                                                                                       14}}Line#1:初始化MCU时钟和引脚等;Line#2:初始化连接SX1278的SPI总线和中断控制线;Line#3:初始化rtimer(高精度实时时钟);Line#4:初始化SystSettings(系统参数)模块;Line#5:初始化通信串口,它连接PC;Line#6:如果是Debug版本,初始化调试串口;Line#7:使能MCU硬件中断;Line#8:初始化Contiki的进程模块;Line#9:初始化comm2trm模块,同时启动comm2trm进程;Line#10:初始化network模块,同时启动network进程;Line#11:如果是Debug版本,初始化monitor模块,同时启动monitor进程;Line#12:Contiki主循环函数,根据post和poll消息,调用对应的进程;Line#13:空语句,为代码可读性而添加;Line#14:节能指令,如果MCU空闲则进入WFI模式,可以被任意中断唤醒。了解详情

LoRa点对点系统5 数据结构与算法

1 Comm2Trm进程1.1处理UART数据帧为节省内存,接收与处理UART数据“复用”了缓冲区,如下图所示:UART驱动:#1:一个接一个将接收的UART数据存储到缓冲区;#2:接收一完整UART帧后,发消息给进程通知处理;Comm2Trm进程:#3:给缓冲区加锁,解析UAR帧;#4:组织UART回应帧;#5:通过UART发送回应帧,给缓冲区解锁。为什么要给缓冲区加锁和解锁呢?如下图的时序逻辑所示:进程“锁定”缓冲区期间UART驱动无法向缓冲区中写数据,因此也不会“竞态打扰”进程处理该数据帧。1.2 发送RF数据包#1:UART一个接一个输入数据到缓冲区COMM_TRM_DATA;#2:当接收一完整帧结束后,UART_ISR给进程poll消息;#3:进程解析和处理该UART数据帧;#4:进程拷贝用户数据到缓冲区TxDataBuf;#5:Network进程从缓冲区TxDataBuf提取数据,通过RF发送。1.3 接收RF数据包#1:Network进程存储接收数据到缓冲区RxDataBuf;#2:Network进程post消息给Comm2Trm进程;#3:Comm2Trm进程组织该数据为UART帧;#4:进程通过UART口发送该数据帧。2 Network进程2.1发送RF数据包#1:从Comm2Trm进程提取发送数据到packetbuf;#2:基于packetbuf组织RF数据包;#3:通过RF发送packetbuf中的RF数据包;2.2接收RF数据包#1:RF接收的数据包存入RadioBuf,并poll进程;#2:进程从RadioBuf拷贝数据包到ParseRFBuf;#3:进程解析该RF数据包;#4:提取用户数据,交付给Comm2Trm进程;2.3 逻辑流程3 SystSettings模块为简化设计,定义了NetSettings_t数据结构,它的“主本”存储在SystSettings模块的EEPROM中,Comm2Trm和Network这2个进程各自拥有一个“副本”。1.上电时,Comm2Trm和Network这2个进程各自从“主本”拷贝“副本”;2.任意一方修改“NetSettings_t”的副本数据,必须:①存储到“主本”之中;②通知“另一方”同步更新副本数据。了解详情

LoRa点对点系统4 进程通信

1 Comm2Trm进程1.1 接收RF数据包,发送给PCt0时刻:Network进程通知Comm2Trm进程(简称进程),接收到RF数据;t1时刻:进程封装数据为UART帧,通过UART端口发送;t2时刻:UART端口启动发送;t3时刻:UART发送完毕,ISR执行扫尾工作(清除硬件中标标识等);1.2 接收PC数据帧,通过RF发送t4时刻:UART接收到来自PC的UART数据帧,poll进程;t5时刻:进程提取UART帧中用户数据,通知Network进程;t6时刻:Network进程通过RF发送该数据帧。2 Network进程2.1 接收PC数据帧,通过RF发送t0时刻:Comm2Trm进程通知Network进程(简称进程),接收到UART数据;t1时刻:进程封装数据为RF包,通过RF端口发送,阻塞自身;t2时刻:RF启动发送;t3时刻:RF发送完毕,ISR执行扫尾工作,通知进程;t4时刻:进程恢复运行,切换RF到RF模式;2.2 接收RF数据包,发送给PC接收RF数据包,发送给PC。t5时刻:RF接收到数据包,poll进程;t6时刻:进程处理该RF数据包,通知Comm2Trm进程;t7时刻:Comm2Trm进程了解详情

LoRa点对点系统3 与PC接口

1 通信介质UART口:115200波特率、8位数据位、1位停止位、无校验。2 通信模式设置和读取参数遵循主从方式,PC为主,Node为从。通信由PC发起,Node根据相应的命令进行响应,如下图所示。当Node接收唤醒通信数据帧时,它以“异步方式”发送给PC,如下图所示。3 通信帧格式PC与Node通信帧采用变长格式,如下图所示。大部分设备可以很好地处理以“回车符”结尾的数据帧,因此协议中的Tail等于0x0D(换行符)。4 通信帧种类没有额外说明,数据格式均为“大端”,即:4字节整数0x12345678在内存中(自低向高)存储顺序为:0x12、0x34、0x56、0x78。
帧含义Typ数据域实例
字节数据解释
读取软件版本(PC->No0x0
回应软件版本(Node->0x8软件版本号(字符串,以’\0’结尾2“LoRaP2P V1.0.0 16-10-20”
发送数据(PC->No0x0实际发送数据,最大字节=24数据帧(十六进制):12 34发送2字节数据:...
了解详情

LoRa点对点系统2 软件模块划分

1 任务逻辑图如下图所示,软件系统包括2个进程:Network和Comm2Trm,它们分别控制LoRa射频和UART口,数据模块SystemSettings用于保存系统参数。2 数据流图2.1 发送数据#1:PC将用户数据帧通过UART交付给LoRa终端;#2:Comm2Trm进程接收该UART数据帧;#3:Comm2Trm进程抽取用户数据,通知Network进程发送;#4:Network进程封装用户数据为RF数据包,通过LoRa射频发送。2.2 接收数据#1:LoRa射频接收RF数据包,通知Network进程处理;#2:Network进程提取用户数据,通知Comm2Trm进程;#3:Comm2Trm进程将用户数据封装成UART帧,并通过UART发送;#4:PC接收UART帧,打印用户数据。2.3 设置参数#1:PC将参数帧通过UART交付给LoRa终端;#2:Comm2Trm进程接收该UART参数帧;#3:Comm2Trm进程提取参数,写入SystemSettings;#4:Comm2Trm进程通知Network进程更新参数。了解详情

LoRa点对点系统1 需求分析

1 引入为更进一步了解LoRa终端和Contiki系统,我们设计一个P2P(Point to Point)系统。虽然该系统简单,我们还是采用软件工程的方法来实现,借此展示一个嵌入式产品的开发过程。2 连接设备如下图所示,2个LoRa终端,分别通过USB转UART连接2台PC,终端之间通过LoRa无线通信。这样一来,PC#i发送的数据,PC#j能远程接收;反之,亦然。当然,这2个终端也可以连接到同一台PC,只是不能体现LoRa远距离通信的功能。3 通信时序这4个设备的一次通信时序如下图所示:#1:PC#i接收用户数据;#2:PC#i将用户数据封装成UART帧#i,并交付给LoRa终端#i;#3:LoRa终端#i抽取用户数据,封装成RF数据包#i,通过LoRa射频发送;#4:LoRa终端#j接收到RF数据包#i,抽取用户数据,封装成UART帧#i;#5:LoRa终端#j将UART帧#i交付给PC#j。#6:PC#j打印用户数据。了解详情

LoRa开发8: 下载源代码

1 源代码下载地址源代码可以从以下链接下载http://download.csdn.net/detail/jiangjunjie_2005/96571612 开发环境与工具硬件平台:锐米LoRa终端http://www.rimelink.com/pd.jsp?id=2测试套件:USB转串口 + LoRa终端转接板https://shop140974727.taobao.com/?spm=2013.1.1000126.d21.DL6hVR仿真器:  ST LINK V2https://item.taobao.com/item.htm?spm=2013.1.20141002.4.Sj743Y&scm=1007.10009.31621.100200300000004&id=540446816750&pvid=8a31520e-d2bd-4a21-b940-aa421c82d92dIDE环境:IAR for STM8  http://www.rimelink.com/nd.jsp?id=33&_np=105_3153 编译对应的进程void main(void){//   process_start(&TxRandData, NULL);//   process_start(&RxPrintSNRRSSI, NULL);process_start(&PingPong, NULL);}在源代码main.c中,屏蔽不需要的进程,仅允许编译一个进程,即可将LoRa终端设置成对应的系统。如上例所示,编译了PingPong进程。4 源代码结构main.c        基于C语言系统的入口函数main.h        系统的全局配置文件Application  应用程序,以Contiki系统的protothread方式组织Contiki        Contiki操作系统Driver         驱动:ST官方驱动库和MCU外设驱动文件Project        IAR环境下所有工程文档RF              SX1278射频芯片驱动代码了解详情

LoRa开发7:PingPong系统

1 引言前2章介绍了SX1278的发送和接收,在此基础上,我们设计一个有趣的PingPong系统,更好地理解LoRa终端的收发逻辑。该系统将LoRa终端自动定义成2种角色:master和slave。master主动发送ping数据帧,接收pong数据帧;slave如果接收到ping数据帧,回应pong数据帧。2 整体逻辑流程如上图所示,当LoRa终端上电后,在(2 * PingPongPeriod)周期内没有接收到ping数据帧,它就认为自己是master。Master节点每隔(1 * PingPongPeriod)周期主动发送ping数据帧,然后启动RF接收,可能接收到pong回应帧(正常通信),也可能接收超时(slave没有上电或通信失败)。同理,当LoRa终端上电后,在(2 * PingPongPeriod)周期内接收到ping数据帧,它就认为自己是slave。Slave节点启动RF接收,如果接收到ping数据帧,它将发送pong回应帧。一个节点从上电,判断自身角色,根据角色处理逻辑,如下流程图所示。3 代码剖析PROCESS_THREAD(PingPong, ev, data){#definePING    “ping, this is MASTER ofrime node.”#definePONG    “pong, this is SLAVE of rimenode.”#definePING_SIZE    34#definePONG_SIZE    33staticbool    s_bIsMaster;staticuint16_t    s_wPingPongPeriod;staticint32_t    s_lTxCnt = 0;staticint32_t    s_lRxCnt = 0;PROCESS_BEGIN();InitSetLoRa();s_wPingPongPeriod =SX1278GetTimeOnAir(4) + SX1278GetTimeOnAir(4) + 15;                   1/*Determine MASTER or SLAVE by RX “ping”. */SX1278Receive(2 * s_wPingPongPeriod);                                              2PROCESS_YIELD(); /* Yield until receive or timeout. */                          3SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */       4if(GetCompareRxFrame(PING, PING_SIZE))                                           5{s_bIsMaster = FALSE;}else{s_bIsMaster = TRUE;}if(s_bIsMaster) /* Is MASTER */{while (1){/* TX “ping” */++s_lTxCnt;SX1278Send(PING, PING_SIZE);                                                          6PROCESS_YIELD_UNTIL( (RF_Tx_Done == s_tRFResult) ||(RF_Tx_Timeout ==s_tRFResult) );          7/* RX “pong” */SX1278Receive(s_wPingPongPeriod);                                                  8PROCESS_YIELD(); /* Yield until receive a frame or timeout. */SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */if (GetCompareRxFrame(PONG, PONG_SIZE))                                    9{++s_lRxCnt;RIME_DBG( RIME_DBG_ON,“TxCnt=%ld, Rx Cnt=%ld, SNR=%d, RSSI=%d.\r\n”,s_lTxCnt, s_lRxCnt, s_chPacketSnr,s_nPacketRssi );   10}}}else /* Is SLAVE */{while (1){/* RX “ping” */SX1278Receive(0);                                                                                  11PROCESS_YIELD(); /* Yield until receive a frame or rx error. */SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */if (GetCompareRxFrame(PING, PING_SIZE))                                          12{/* TX “pong” */++s_lTxCnt;SX1278Send(PONG, PONG_SIZE);                                                      13PROCESS_YIELD_UNTIL( (RF_Tx_Done ==s_tRFResult) ||(RF_Tx_Timeout == s_tRFResult) );         14++s_lRxCnt;RIME_DBG( RIME_DBG_ON,“Tx Cnt=%ld, RxCnt=%ld, SNR=%d, RSSI=%d.\r\n”,s_lTxCnt, s_lRxCnt,s_chPacketSnr, s_nPacketRssi );}}}PROCESS_END();}Line#1:计算PingPong通信空中时间,添加15ms做为收发准备时间;Line#2:启动接收功能,超时时长为2倍PingPong通信空中时间;Line#3:阻塞进程,直到接收数据帧或超时;Line#4:设置SX1278为休眠,否则它将处于持续接收状态(那怕超时亦如此);Line#5:GetCompareRxFrame()复制数据帧到解析工作区,比较是否为ping帧;Master节点逻辑Line#6:master节点发送ping数据帧;Line#7:阻塞进程,直到发送ping数据帧完毕;Line#8:启动接收功能,超时时长为PingPong通信空中时间;Line#9:比较是否为pong回应帧;Line#10:打印发送和接收数据帧个数,SNR和RSSI值;Slave节点逻辑Line#11:启动持续接收功能,为0表明关闭超时功能;Line#12:比较是否为ping数据帧;Line#13:slave节点发送pong回应帧;Line#14:阻塞进程,直到发送pong回应帧完毕;了解详情

LoRa开发6:接收数据帧

1 引言接收LoRa数据帧比发送稍复杂一些,接收是一个异步动作—-不知道下一帧什么时候到来;因为干扰或信号微弱等,接收可能会出错;甚至,当多次接收错误后,RF可能会宕机—-再也无法接收任何数据帧。本章,我们继续基于Contiki和SX1278,开发接收数据帧的代码。2 整体逻辑流程接收数据帧的整体逻辑流程如下所示,特别注意的是,添加了处理异常的代码:如果RF接收错误(硬件自检payloadcrc16失败)或数据帧错误(用户CRC16失败),进程会重启动RF的接收,以防止陷入宕机(根据我们多年的经验,这种缺陷是可能发生的)。3 进程时序t0时刻:进程启动RF接收;t1时刻:SX1278接收到数据帧,中断服务程序poll进程;t2时刻:进程检验数据帧的CRC16,闪烁LED,打印计数、SNR和RSSI;4 代码剖析PROCESS_THREAD(RxPrintSNRRSSI, ev, data){/*ATTENTION: stack variables can NOT cross any “XX_YIELD()”. */bool    bFrameOK;                                                                                                            1RF_FRAME_RAND_DATA    *p_stFrameData;staticint32_t    s_lRxRandCnt = 0;PROCESS_BEGIN();                                                                                                       2InitSetLoRa();                                                                                                                   3SX1278Receive(0);/* Explain: 0 means RX forever */                                                      4while(1){PROCESS_YIELD(); /* Yield until receive aframe. */                                                     5bFrameOK = FALSE;if (RF_Rx_Done == s_tRFResult)                                                                                   6{/* Check CRC16 of this received frame. */s_stParseRFBuf.bySize = GetRadioBuf(s_stParseRFBuf.a_byBuf,RF_FIFO_SIZE);  7p_stFrameData = (RF_FRAME_RAND_DATA *)s_stParseRFBuf.a_byBuf;if ( p_stFrameData->wCRC16 ==util_CRC16( p_stFrameData,GET_ST_FLD_OFFSET(RF_FRAME_RAND_DATA, wCRC16)) )                         8{bFrameOK = TRUE;chip_LEDToogle();++s_lRxRandCnt;RIME_DBG( RIME_DBG_ON,“Rx Rand Cnt=%ld, SNR=%d,RSSI=%d.\r\n”,s_lRxRandCnt, s_chPacketSnr, s_nPacketRssi );                         9}}/*EXPLAIN: Restore the RX of RF if Rx-Error or frame is NOT integrity.*/if(!bFrameOK)                                                                                                              10{SX1278SetSleep();SX1278Receive(0);}}PROCESS_END();                                                                                                         11}Line#1:小心!在Contiki系统自动变量不能跨越阻塞语句,详细原因请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/44725997Line#2:Contiki进程的第一条语句,详解请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/44600365Line#3:初始化SX1278,详解请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/52824184Line#4:启动RF接收,参数为0代表关闭超时定时器,即持续接收;Line#5:阻塞进程,等待RF中断唤醒;Line#6:判断RF是否接收一帧数据;Line#7:从RF缓冲区复制数据帧到解析工作区;Line#8:检测数据帧的CRC16是否正确;Line#9:打印接收次数、SNR和RSSI,RIME_DBG()的原理和使用,请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/51869953Line#10:如果接收错误或数据帧CRC16错误,重启动RF接收,防止宕机;Line#11:Contiki进程的最后一条语句,详解请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/44600365了解详情

LoRa开发5:发送随机数据

1 引言学习需要循序渐进,做开发也不例外。在LoRa终端开发中,最简单的代码是通过SX1278发送数据帧。因此,我们先从发送开始,了解初始化SX1278和建立Contiki进程的入门知识。2 整体逻辑流程发送数据帧的整体逻辑流程如下所示,很明显,进程是一个无限循环:生成随机数据帧-> 发送 -> 生成随机数据帧 ->…3 初始化SX1278初始化SX1278的代码清单如下,它主要完成射频参数的配置。static void InitSetLoRa(void){SX1278Init(&s_stRFEvents);                                                   1SX1278SetFreq(RADIO_FREQ);                                             2SX1278SetPAOutput(PA_OUTPUT_PIN_BOOST);                3SX1278SetTxPower(20);                                                          4SX1278SetPreambleLen(6);                                                     5SX1278SetLowDatarateOptimize(FALSE);                               6SX1278SetFixLen(FALSE);                                                       7SX1278SetCrcOn(TRUE);                                                         8SX1278SetRxContinuous(TRUE);                                             9SX1278SetBandwidth(RF_BW_500000);                                10SX1278SetSpreadingFactor(RF_SF_7);                                  11SX1278SetCodingRate(RF_FEC_4_5);                                   12SX1278SetLoRaSettings();                                                      13SX1278SetTxTimeout(SX1278GetTimeOnAir(255) + 10);       14return;}Line#1:传递一个回调函数指针数组给SX1278驱动,这样一来,当射频中断发生时,可以让调用者执行必需的动作 (一般用于给进程发消息)。该原理的解释,请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/52798757Line#2:设置频率为470MHz;Line#3:使用PA(Power Amplifier,功率放大器)引脚输出;Line#4:设置发射功率为最大值20dBm;Line#5:设置preamble(前导码,用于接收同步)长度为6,根据我们多年的测试经验,6是最小值,低于该值将会导致接收误码率上升;Line#6:关闭低速率优化功能:当symbol驻空时间超过16ms时,打开此选项可以提高LoRa链路健壮性。注意:发送和接收双方必须设置一致!Line#7:允许发射数据帧长度可变;Line#8:使能SX1278对接收数据帧payload进行CRC16校验;Line#9:使能持续接收;Line#10:设置BW为500kHz;Line#11:设置扩频因子为7,即1symbol(每bit用户payload),LoRa扩频到2^7=128 chip(实际发射信号);Line#12:设置前向纠错码,每发送4symbol,添加1symbol纠错码;Line#13:将设置参数写入SX1278寄存器(批量操作提高效率);Line#14:设置发送超时为最大值(使用MCU定时器避免SX1278发送宕机);4 进程时序t0时刻:进程生成随机数据帧,并发送;t1时刻:SX1278启动发送;t2时刻:SX1278发送完毕,中断服务程序poll进程;t3时刻:进程打印发送次数,再次生成随机数据帧和发送;5 代码剖析PROCESS_THREAD(TxRandData, ev, data){/*ATTENTION: stack variables can NOT cross any “XX_YIELD()”. */RF_FRAME_RAND_DATA    *p_stFrameData;                                                            1staticint32_t    s_lTxRandCnt = 0;PROCESS_BEGIN();                                                                                                    2InitSetLoRa();                                                                                                                3while(1)                                                                                                                         4{/* Makethe frame of random data, TX it. */p_stFrameData= (RF_FRAME_RAND_DATA *)s_abyTxRFBuf;MakeRandData(p_stFrameData->a_byBuf, sizeof(p_stFrameData->a_byBuf));        5p_stFrameData->wCRC16= util_CRC16( p_stFrameData,GET_ST_FLD_OFFSET(RF_FRAME_RAND_DATA, wCRC16));                         6SX1278Send(s_abyTxRFBuf, sizeof(RF_FRAME_RAND_DATA));                            7/* Block process until Tx Done or timeout. */PROCESS_YIELD_UNTIL( (RF_Tx_Done == s_tRFResult) ||(RF_Tx_Timeout == s_tRFResult) );                              8++s_lTxRandCnt;RIME_DBG(RIME_DBG_ON, “Tx Rand Cnt=%ld\r\n”, s_lTxRandCnt);                      9}PROCESS_END();                                                                                                        10}Line#1:小心!在Contiki系统自动变量不能跨越阻塞语句,详细原因请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/44725997Line#2:Contiki进程的第一条语句,详解请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/44600365Line#3:初始化SX1278;Line#4:一般而言,进程都是无限循环;Line#5:生成随机数据;Line#6:计算CRC16,宏GET_ST_FLD_OFFSET()用于取结构体中域的偏移;Line#7:发送随机数据帧;Line#8:阻塞进程,直到发送数据帧结束或超时;Line#9:打印总发送次数,RIME_DBG()的原理和使用,请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/51869953Line#10:Contiki进程的最后一条语句,详解请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/44600365了解详情

LoRa开发4:移植Contiki

1  LoRa终端需要OS吗?尽管工程师有很多理由拒绝在LoRa终端上使用OS(Operating System操作系统):“它很复杂”,“没必要”,“内存太小”,“有学习成本”,“要改变编程思维”,“可能不稳定”……然而,基于以下理由,我们强烈推荐移植一个小型OS:降低复杂度LoRa终端的复杂度其实比我们想象的要高:它需要驱动SX1278,这需要处理很多事件,如接收数据超时,接收数据错误等;它需要实现网络算法,申请入网,主动上报,低功耗唤醒,断网续连等;它需要管理本地设备,采集传感器数据,控制阀门等。使用OS,可以将上述任务分解成多个进程,开发者专注于每个进程的实现,可以有效降低复杂度。复用组件LoRa终端一定有这样的需求:射频CAD侦听到唤醒信号后,快速通知进程接收数据帧;需要一个软定时器来灵活地延时和唤醒……这些系统组件,OS都提供,要知道,这些丰富的组件可是经过严格测试的。复用成熟稳定的组件是提高软件生产力的有效手段,这方面,操作系统功不可没。提高CPU效率当LoRa终端“等待射频发送数据包完成”前,它无事可干;而其他进程希望得到CPU运行权,不用担心,操作系统会完成调度,它会将“因等待而无事可干”的进程阻塞,而将CPU分配给“具备运行条件”的进程享用。移植性更好有一天,因为某种原因(需要更强大的计算能力,需要更低成本等)需要更换LoRa终端的MCU,有操作系统支撑的系统就轻松多了,因为应用软件调用的是操作系统的API,它很少与硬件层直接打交道;基本上,只要将操作系统移植到“新MCU平台”,软件系统就OK了。2  Contiki是一个怎样的OS?Contiki是少有能同时实现2个目标的操作系统:对内存要求极低,同时支持进程阻塞机制。8位单片机的RAM极为宝贵,几KB都是很大了,一般的RTOS(FreeRTOS或uc/os-ii等)无法运行,而Contikil可运行良好;有些操作系统,如OSAL也在极少的RAM上可以运行,但是这种基于“状态机”开发的机制,让代码很难理解,程序执行流在状态中来回判断和切换,让逻辑更复杂。节能内存Contiki有一个巧妙的机制来实现进程的调度:当进程被阻塞时,OS记录该进程的下一C语言行号;当进程继续运行时,从记录的C语言行号继续运行。这种机制从2个方面极大节省内存:所有的进程共享一个栈,没有上下文机切换。甚至在小于1KB内存的MCU上,Contiki都可以良好地运行。进程可以阻塞在Contiki系统中可以实现如下语句,进程发送无线电数据包,然后阻塞自己,直到发送完毕。这种“优雅”的机制,非常符合程序员思维,同时降低了开发的复杂度。SX1278Send(packetbuf_dataptr(),packetbuf_datalen());PROCESS_YIELD_UNTIL(RF_Tx_Done ==s_tRFResult);移植简单如果仅使用Contiki的内核,只需要移植clock.c,即从MCU中找一个定时器来给etimer进程提供时钟源。如果使用Contiki的网络协议栈,需要按radio.c实现无线收发函数。丰富的网络协议栈针对无线通信,Contiki提供3种MAC协议,还有RIME通信原语和RPL路由协议;针对TCP/IP,Contiki提供uIP协议栈,它支持IPv4和IPv6。3 怎样移植Contiki?移植一个操作系统是指将它运行在给定的硬件平台。因为Contiki是非可剥夺的OS,不用实现上下文切换(CPU的寄存器保存与恢复),因此它的内核移植特别容易,一般是实现2个定时器:etimer和rtimer。如果站在3万英尺的高度,一个基于Contiki嵌入式系统的层次结构如下所示。考虑2种情况,首先需要升级Contiki更高版本的软件,其次需要将Contiki移植到不同的硬件平台。为了尽可能地减少升级和移植的工作量,增加了ports文件夹,ports目录中文件与core目录中文件低耦合。3.1 移植Contiki内核如果仅仅只移植Contiki的内核,那么还是比较容易的,一般说来只需要修改2个文件:clock.c和contiki-conf.h。clock.c有2个函数需要适配对应硬件平台:void clock_init(void); 设置一定时器,每秒产生CLOCK_SECOND个tick;void SysTick_handler(void); tick中断时递增时间,检测是否有超时事件;contiki-conf.h:设置contiki系统的一些参数,如:CLOCK_CONF_SECOND=100;3.2 移植rtimer3.2.1 rtimer用途Contiki系统引入rtimer可以满足精准定时的需要,一些对时间极为敏感的模块(如MAC协议)依赖于rtimer。和etimer的粗粒度(常见为100Hz)不同,rtimer是细粒度(常见为1kHz)定时器。3.2.2 rtimer移植移植rtimer比较容易,基于MCU实现rtimer-arch.c和rtimer-arch.h。需要特别注意,大多数定时器(尤其是8位MCU)位宽为16位,即MAX=65535, rtimer的频率定为1kHz比较合理,它既可以保证比较好的精度(1ms),又具备65秒的满量程,这可以适应大多数的应用需要。另外,大多数应用需要随机撤销和重启动rtimer,它可以通过添加2个函数来实现:rtimer_arch_disable_irq()和rtimer_arch_enable_irq()。关于rtimer更多的原理与应用介绍,请链接:http://blog.csdn.net/jiangjunjie_2005/article/details/449478994 怎样应用Contiki?Contiki是标准ANSI C语言开发,调用API函数和系统组件和一般的OS无异。在进程函数中开发,以下三点需要注意:1.       自动变量不能跨越阻塞语句2.       不能使用switch语句3.       执行语句位于PROCESS_BEGIN()和PROCESS_END()之间详细了解该规则,请参考《Contiki开发要点》:http://blog.csdn.net/jiangjunjie_2005/article/details/44725997从一个入门级的Contiki进行代码,请参考《Contiki开发5:Hello, Contiki》:http://blog.csdn.net/jiangjunjie_2005/article/details/51921568了解详情

LoRa开发3:终端驱动设计

1 引言从表面看,终端驱动就是MCU通过读写SX1278的寄存器,实现射频收发功能。然而,一个优秀的驱动设计,至少满足以下设计目标;最具喜挑战的是,有些目标是相互抵触的。提供机制:区分策略和机制,驱动仅提供机制,由用户进程实现策略;接口简单:接口越简单,驱动越好使用,另外,更好实现“高内聚、低耦合”;提高效率:最大化硬件设备性能,是驱动的重要使命;节能内存:内存复用和指针传递等方法可以节省MCU宝贵的内存;...了解详情

LoRa开发2:终端硬件平台

1 硬件基本框图一般而言,LoRa终端主要部件包括:MCU,SX1278,TCXO,RF_SWITCH,它们的功能如下表
部件功能
MC驱动SX1278,实现无线网络协议,与用户系统交互等
SX127完成LoRa无线信号的接收与发送
TCX为SX1278高频电路提供精确时钟
RF_SWITC为半双工的SX1278切换输入或输出状态
一个LoRa终端硬件框图如下所示在实际工程应用中,为更好地移植射频...了解详情

LoRa开发1:LoRa设计10问

引言近2年来,LoRa技术在国内受重视,从高校到企业,再到自主创业者,都在了解和研究。作为从事LoRa研发3年,推出2代LoRa网关的锐米通信,接触许多问询LoRa技术的客户。为此,我们解释一些LoRa技术的常见问题。1问:LoRa是什么?答:LoRa是Long Range(长距离)的简称,是一种长距离、低功耗无线通信技术。2009年法国公司Cycleo设计出一种优异的扩频通信算法,后来,该公司被美国semtech公司收购,后者于2013年推出LoRa芯片。目前,semtech公司是LoRa芯片唯一供应商。2问:LoRaWAN是什么?答:LoRaWAN是LoRa Wide Area Network(LoRa广域网)的简称,是基于LoRa技术的一种通信协议。它主要包括三个层次的通信实体:LoRa终端、LoRa网关和LoRa服务器。LoRaWAN是一个较庞大的体系结构,支持CLASS A / B / C三种终端,使用LoRa MAC协议为网关和终端提供防冲突通信和同步机制,有4种服务器角色,分别担任:网络连接、应用管理、接入控制和用户数据。它的层次关系如下:3问:LoRa有什么优点?答:最大的优点是长距离传输,采用扩频增益,它的传输距离约FSK的3倍;其次是低功耗,尽管它通信距离空旷能达到5km,仍保持良好的节能特性;再次,它工作在免费ISM频段,这为普通民众使用该无线网络打开了一道便捷之门,极大降低网络铺设成本。4问:LoRa有哪些缺点?答:第一个缺点,传输速率低,因为扩频调制后的通信带宽窄,一般只适合传感器网络;第二个缺点,硬件价格高,推出市场的时间不长,没有大规模应用,成本没有被摊薄;第三个缺点,LoRaWAN核心技术(通信协议和算法)需要缴纳会费才能获取,这提高了研发成本和难度。5问:LoRa与常见无线技术的区别?答:确实,我们身边的无线技术已经很多了:3G/4G、WiFi、蓝牙和ZigBee,为什么还需要LoRa这种无线技术呢?其实,每种无线技术都只能适应特定通信场景,需要配合使用才能构建高效率、低成本的网络。打个比方,现代化的军事组织,单兵武器都是配合使用,才能达到最佳火力配制。
无线技术类比武器距离...
了解详情