使用taskBus串口操作LORA设备收发消息并获取LORA波形
发布时间:2026/9/28 20:10:23来源:尧图网络
LORA是一种低功耗物联网协议最近5年越来越得到业界的关注。正好最近在给taskBus添加串口、原始TCP\UDP三类接口以便更好的和物联网设备进行M2M交互这为LORA模块测试提供了便利。下一篇我们通过Octave研究数学结构2026年我们根据数学模型驱动AI实现了堪用的B210收发模块。文章目录1. 硬件环境搭建2 在 taskBus 中操作LORA设备3. 传输速率测试4. 监测并获得波形和频谱5. 相关资料1. 硬件环境搭建LORA模块一般几十元到100多元不等。如果只是为了研究传输特性比如距离、速率则不需要购买很复杂的版本或者中继、云服务。笔者使用的是一款RS485的LORA模块配合RS485转USB的连接线构成了测试LORA的最小环境。当然为了能够通信一次要买至少2个。由于是在室内临时使用所以即使买的是支持上槽的也没有和室外板箱结合。笔者简单的把旧诺基亚的充电器、RS485连接线连上模块一起放在包装盒里如下图所示具体接线旧诺基亚充电器引出5v和GND用万用表测一下极性直接接到LORA模块的正负极上作为供电。供电一旦成功指示灯就亮了。产品建议5-12V为了室内小功率测试5V足够了。需要注意的是如果有条件用9V还是更好5V时误码率比较高。RS485的T/R和T/R-线连接LORA的AB-。这里有一个坑笔者手头的485模块上面A叫做T/RB-叫做T/R-和公司的不一样。公司的名字也叫 A、B-和LORA模块一样。二者没有区别只是叫法不同。在windows下安装合适的RS485驱动。注意要咨询客服RS485的芯片很多同样外形的转接口型号很杂一定要安装正确。笔者询问客服后试了4种芯片的驱动才成功。笔者安装的是MS3020芯片的驱动。全部连接正确后串口调试助手登入能够执行AT指令就成功了。笔者测试的型号CW-4A82其测试状态截图(软件是老板附送的写的很棒:2 在 taskBus 中操作LORA设备taskBus的串口模块可以直接连接键盘(console模块我们迫不及待的在两个机器上测试消息收发了。按照产品手册最简便的方法是使用透明模式连接键盘到LORA:两台设备均能收发。在初步测试时感觉到延迟挺大的应该是默认速率比较低。默认的配置参数单位取值带宽KHz512中心频率MHz433比特率bit/s2400串口速率bit/s9600在测试中LORA设备位于COM3COM4我们分别为两个串口连接键盘这样构成了点到点的消息收发最简实验。3. 传输速率测试可以进一步开发一个发送数据包的小程序测试LORA单路的时延和发送能力。测试数据包采用2台设备A设备发B设备收。包由一个简单的C语言程序产生具备一定的长度。通过统计每秒成功发送并接收的包数来计算真正的通信流量。#includeQCoreApplication#includeQFile#includeQVector#includeQThread#includecstdio#includecstdlib#includethread#includeatomic#includectime#includecmdlineparser.h#includetb_interface.hintmain(intargc,char*argv[]){QCoreApplicationa(argc,argv);//...retdo_function(args);//...returnret;}intinstance0;intsub_input0,sub_output0;std::atomicintsend_count0,lost_count0;std::atomiclonglongtotal_bytes;std::atomicboolrecievedtrue,finishedfalse;constintmsglen64;voidsend_loop(){if(sub_output0){intsleep_cnt0;while(!finished){staticunsignedchardata[msglen]{0xc3u,0xa5u,0xe7u,0x96u};staticclock_t*clk(clock_t*)data[4];staticunsignedint*check(unsignedint*)data[msglen-4];if(recieved){recievedfalse;sleep_cnt0;*clkclock();//Checksumunsignedintsum0;for(inti0;imsglen-4;i){if(i44)data[i]i8;sum(unsignedchar)(data[i]);intpsum0x80000000u?1:0;sum1;sum^p;}*checksum;TASKBUS::push_subject(sub_output,instance,msglen,(unsignedchar*)data);send_count;total_bytesmsglen;}else{sleep_cnt;QThread::msleep(10);//20 secondsif(sleep_cnt2000){sleep_cnt0;lost_count;recievedtrue;}}}}}voidrecv_loop(){//Begin recievelonglongdelay0;clock_t first_clk-1;unsignedcharmsg[msglen]{0};intmsg_pos0;longlongsucceed_cnt0,failed_cnt0;staticclock_t*clk(clock_t*)msg[4];staticlonglong*cnt(longlong*)msg[48];staticunsignedint*check(unsignedint*)msg[msglen-4];intfailed_header0;while(falsefinished){subject_package_header header;vectorunsignedcharpackagedtapull_subject(header);if(is_valid_header(header)false){if(failed_header16)finishedtrue;continue;}if(is_control_subject(header)){//收到命令进程退出的广播消息,退出if(strstr(control_subject(header,packagedta).c_str(),functionquit;)!nullptr)finishedtrue;}elseif(header.subject_idsub_inputpackagedta.size()){staticunsignedcharhead_msg[]{0xc3u,0xa5u,0xe7u,0x96u};intlenpackagedta.size();for(inti0;ilen;i){msg[msg_pos]packagedta[i];switch(msg_pos){case0:case1:case2:case3:if(msg[msg_pos]head_msg[msg_pos])msg_pos;else{if(msg_pos)--i;msg_pos0;}break;default:msg[msg_pos]packagedta[i];msg_pos;if(msg_posmsglen){recievedtrue;//Checksumunsignedintsum0;for(intj0;jmsglen-4;j){sum(unsignedchar)(msg[j]);intpsum0x80000000u?1:0;sum1;sum^p;}if(*checksum){succeed_cnt;if(first_clk-1)first_clk*clk;delayclock()-*clk;}else{failed_cnt;fprintf(stderr,CHECKSUM Failed.\n);}longlongavgdelaydelay/(succeed_cnt1e-13);doubletmCost(*clk-first_clk)*1.0/CLOCKS_PER_SEC1e-10;doublespeedtotal_bytes*1.0/(tmCost1e-13);fprintf(stderr,Send:%lld, succeed:%lld, Average delay %d clocks, total Speed %.2lf B/s.\n,(longlong)send_count,succeed_cnt,(int)avgdelay,speed);fflush(stderr);msg_pos0;}break;};}}}}intdo_function(constcmdlineParserargs){boolbInfofalse,finishedfalse;//1. parse cmdlineinstanceargs.toInt(instance,0);sub_inputargs.toInt(data_in,0);sub_outputargs.toInt(data_out,0);if(instance0)return-1;srand(time(0)instance*16);std::this_thread::sleep_for(std::chrono::milliseconds((instance*11711)%2000));//Begin send,recvstd::threadth_send(send_loop);std::threadth_recv(recv_loop);th_send.join();th_recv.join();//3.exitreturn0;}测试表明默认状态下LORA是一种半双工的IO通信。也就是说终端在发送数据的时候无法接收数据。同时由于存在空闲率如250ms两个包之间不是完全连续的是有空隙的这些因素都导致实际速率远达不到2400bps, 实测约560~600bps左右。被测试产品在默认出厂配置模式下单个包最大64字节512bit。超过64字节的包会分片到下一次。从包送入串口到从串口返回包全路径延迟约900ms。两台设备若同时进行双向收发则碰撞后无法解析完整的包。这也从侧面说明了LORA用于双终端乒乓通信并不是最佳的实践。这些设备更适合多发1收的情况。4. 监测并获得波形和频谱用taskBus可以直接驱动USRP B210采集433MHz的频谱。在5MHz采样率下采用Audacity可以导入RAW格式的数据降速设置采样率如44100后可以听到每个符号的鸟叫频谱(chirp)和清晰的边界。这种鸟叫信号直接进行解调即可获得线性的三角波。我们用Octave直接处理上面的波形求取角度和角度差分而后得到频率clc;clear;fidfopen(d:\\lora\\lora.wav,rb);%读取数据raw_iq_1dfread(fid,int16);fclose(fid);%组装为IQ复平面坐标raw_iqraw_iq_1d(1:2:end)1j*raw_iq_1d(2:2:end);%测相位角anglesangle(raw_iq);%求差分瞬时频率也就是转速freqsangle(raw_iq(2:end))-angle(raw_iq(1:end-1));% 2pi环绕去除freqs(freqs-pi)freqs(freqs-pi)2*pi;freqs(freqspi)freqs(freqspi)-2*pi;% 画图plot(freqs);前面规整的应该是同步序列可以看到5MHz采样500KHz情况下经过chirp线性调频扩频后的符号长度约为 (85984-65520 )/102046也就是每个符号在500KHz采样率下占2048个点符合 SF11的配置, 1个符号对应11比特有2048种状态。LORA的状态取决于线性调频的起点但是由于存在收发的频率、时钟误差在存在漂移的情况下正确解析出符号不是简单的事情。对于SF较小的情况FFT的误差大一点问题不大。对 SF10\11\12来说如SF11,2048点FFT只要错位1个频率位置符号就漂移了。下个月我应该能学习完LORA的解析技术在下一篇文章将介绍如何还原本节的信息。5. 相关资料LORA的上位机COM测试用例参考https://gitcode.com/colorEagleStdio/taskbus_course/tree/master/src/a4_lora
网站建设高端定制企业官网