0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用RUI3制作一款用于电脑的多功能LoRa®适配器

瑞科慧联(RAK) 2022-11-29 14:33 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

LoRa®和 LoRaWAN®已经成为了物联网世界的重要技术,也向人们提供了诸多易于使用的远程通信解决方案。在这过程中电脑设备却被忽略了,我们会发现带有 LoRa®模块的笔记本电脑很少见。

现在这种局面陆续得到了改善,在一些解决方案中,已经开始出现用于笔记本电脑的 LoRa®模块了。最近笔者利用瑞科慧联的低代码开发平台 RUI3 制作了一个 LoRa®USB 适配器,它可以直接连接到笔记本电脑或树莓派上。大多数时候,这个适配器可以作为收发器用于家居场景种;但它也作为一个方便测试的平台,比如:远程用笔记本电脑发送命令、记录结果等等。

poYBAGOFeB-AKC3yAABUGPoWbhU732.png

使用瑞科慧联的模块化硬件开发平台 WisBlock,让这样的应用开发变得更加简单。笔者通过 WisBlock 制作了两种适配器,一种是使用计算机上的自定义软件来管理 LoRa®模块的 AT 固件,另一种是直接在LoRa®模块上完成大部分工作。在这两种适配器中,电脑都是作为终端来使用。今天要介绍的是后一种适配器,主要就是使用 RUI3 为 LoRa®通信模块 RAK4631-R 制作一个简单的自定义固件。

一、前期准备

  • 硬件

1、选择 RAK4631-R(不同国家或地区对应频率的频段不同)。

poYBAGOFeB-Aa7o2AALW9vCoSKQ801.png(注意,这里我们也可以使用另一款通信模块 RAK3172,因为他们均支持 RUI3 编译,只要有自己所需要的功能就行。因为 RAK3172 不支持蓝牙和硬件加密,但该项目需要加密 LoRa® 数据包,而且将 AES128 添加到代码中也超出了本文的范围,所以这里我们选择了 RAK4631-R。)

2、底板:本例中,我们选择了 RAK19003,它具有最小的封装尺寸 30 mm x 35 mm。

3、USB 电缆(适用于 RAK19003 的 USBType-C)。

  • 软件

1、Arduino IDE。

2、终端应用程序,例如笔者最喜欢的 CoolTerm。当然 Arduino IDE 的串行终端,也能完成开发。

  • 工作模式

LoRa®适配器基本上需要两种工作模式:传输模式和设置模式。而 AT固件本质上是单模模式的,即它们总是处于设置模式。在设置模式中,甚至发送和接收都是命令。与此相反,默认的传输模式充当 LoRa®模块和 USB端口之间的桥梁:“无论一端输入任何内容,都将从另一端输出”。只有当用户发出特殊字符串时,适配器才会在传输和设置模式之间切换。 笔者见过一些 LoRa®模块为此提供一两个引脚来实现这一点,可以设置引脚高低电平从硬件上切换这两种模式,但这样的操作对电脑来说是不可能的。因此,用户可以使用不太可能出现的特殊字符串去切换这两种模式。然而在调制解调器时代,“$$$”经常作为特殊的字符串去使用,所以我们也可以使用该字符串实现。

二、工作流程

在常规的 LoRa®应用程序中,工作流程通常如下:

  • 初始化串口
  • 设置 Wire,然后设置 LoRa®模块(引脚分配等)
  • 设置 LoRa®配置(SF、BW、频率等)

本文使用到 RUI3,因此可直接去掉第二点,因为 API 已经配置完成、电池也配置好了。在RUI的 API中,LoRaWAN®是提供了LoRa选项区域帮助用户配置 LoRa®。并且LoRa®模块在 RAK4631-R 中是预先连通的,所以只需调用 LoRaWAN®的几行 API 设置所需的配置,就可以检查结果:

bool rslt = api.lorawan.nwm.set(0); if (!rslt) { // Do something } rslt = api.lorawan.pfreq.set(myFreq); if (!rslt) { // Do something } rslt = api.lorawan.psf.set(sf); if (!rslt) { // Do something } rslt = api.lorawan.pbw.set(bw); if (!rslt) { // Do something } // etc etc etc...

通过检查,已经设置完成了,结果与 API设定的配置是一致的。

然后设置 LoRa®回调:接收和传输。这里让用户能够以异步方式将“管理这些事件的代码”单独管理运行,而不是在主 loop() 代码中循环运行。

最后一行是为了将 LoRa®模块设置为了永久监听模式。

api.lorawan.registerPRecvCallback(recv_cb); api.lorawan.registerPSendCallback(send_cb); rslt = api.lorawan.precv(65534);

最后,就可以在 setup()中完成自己的需求了。例如:让 OLED 检查状态,或设置 LED的状态(电路板上有 2 个可用,1 个绿色和 1 个蓝色)等。到这一步一切都准备好了,一起来看看接下来会发生什么?

三、loop()

在 loop() 中,循环检查串行端口是否有字符传入,并对其进行相应的操作。稍后我会详细介绍这一点。接着还需要检查 LoRa®模块,如果有接收到数据包,则将接收数据包中的内容打印到串口上。这是两个部分之间的桥梁。在其他框架中,这通常与串口相同。接着 LoRa®模块循环监听,如果有内容,直接读取。这个功能 RUI3中并不包含,需要在上面声明的 void recv_cb(rui_lora_p2p_recv_t data) 函数中自己实现并进行,在将LoRa®模块接收的原始数据发送到 Serial 之前,可以在这个函数中决定如何处理原始数据。例如:如果需要 JSON 数据,可以将其解析之后在打印到串口。同样,如果数据是加密的,或者希望它是加密的,就可以在进一步处理之前在那进行解密。回调函数代码如下所示:

void recv_cb(rui_lora_p2p_recv_t data) { uint16_t ln = data.BufferSize; char plainText[ln + 1] = {0}; char buff[92]; sprintf(buff, "Incoming message, length: %d, RSSI: %d, SNR: %d", data.BufferSize, data.Rssi, data.Snr); Serial.println(buff); if (needAES) { // Do we need to decrypt the data? int rslt = aes.Process((char*)data.Buffer, ln, myIV, myPWD, 16, plainText, aes.decryptFlag, aes.ecbMode); if (rslt < 0) { Serial.printf("Error %d in Process ECB Decrypt\n", rslt); return; } } else { // No? Just copy the data memcpy(plainText, data.Buffer, ln); } // The easiest way to know whether the data is a JSON packet is to try and decode it :-) StaticJsonDocument<200> doc; DeserializationError error = deserializeJson(doc, plainText); if (!error) { JsonObject root = doc.as(); // using C++11 syntax (preferred): for (JsonPair kv : root) { sprintf(buff, " * %s: %s", kv.key().c_str(), kv.value().as()); Serial.println(buff); } return; // End for JSON messages } // There was an error, so this is not a JSON packet – not well-formed anyway. // Print it as a plain message Serial.println("Message:"); Serial.println(plainText); }

四、Tx(发送)

发送同样也有一个回调函数,当数据发送完成时可调用。用户也可以在那里添加东西,但它在正常使用中基本上是为了确保LoRa®模块返回到监听模式中:

void send_cb(void) { // TX callback Serial.println("Tx done!"); isSending = false; // Flag used to determine whether we're still sending something or we're free to send. api.lorawan.precv(65534); }

该回调函数需要快速的执行并使 Lora®模块返回到监听模式,不需要在其中加入长延时等待。

五、设置模式

当用户发送 $$$(后缀为 \n)时,代码会切换到设置模式。这部分稍微复杂一些,发送命令这一段会重复被使用,所以为了使用方便,大部分都是复制粘贴后,对该段进行更改其函数名,并为每个命令添加合适的代码。因此我们需要一个统一的命令结构,如下所示:

int cmdCount = 0; struct myCommand { void (*ptr)(char *); // Function pointer char name[12]; char help[48]; };

(cmdCount 马上就会派上用场)。命令的结构由指针函数、函数名和命令描述三部分组成。

下图是声明了一个命令数组:

myCommand cmds[] = { {handleHelp, "help", "Shows this help."}, {handleP2P, "p2p", "Shows the P2P settings."}, {handleFreq, "fq", "Gets/sets the working frequency."}, {handleBW, "bw", "Gets/sets the working bandwidth."}, {handleSF, "sf", "Gets/sets the working spreading factor."}, {handleCR, "cr", "Gets/sets the working coding rate."}, {handleTX, "tx", "Gets/sets the working TX power."}, {handleAES, "aes", "Gets/sets AES encryption status."}, {handlePassword, "pwd", "Gets/sets AES password."}, {handleIV, "iv", "Gets/sets AES IV."}, {handleJSON, "json", "Gets/sets JSON sending status."}, };

到目前为止一切都顺利。所以在 setup() 函数启动时,会计算可用命令的数量,以便知道我们有多少个命令。cmdCount = sizeof (cmds)/ sizeof (myCommand):这在 evalCmd函数中用于遍历命令,cmdCount即为最终统计到的命令个数。

void evalCmd(char *str, string fullString) { uint8_t ix, iy = strlen(str); for (ix = 0; ix < iy; ix++) { char c = str[ix]; // lowercase the keyword if (c >= 'A' && c <= 'Z') str[ix] = c + 32; } Serial.print("Evaluating: `"); Serial.print(fullString.c_str()); Serial.println("`"); for (int i = 0; i < cmdCount; i++) { if (strcmp(str, cmds[i].name) == 0) { // call the function cmds[i].ptr((char*)fullString.c_str()); return; } } }

在此之后,添加命令和处理它们的调用就非常容易了。让我们来看看 handleHelp (char*)命令:

void handleHelp(char *param) { Serial.printf("Available commands: %d\n", cmdCount); for (int i = 0; i < cmdCount; i++) { sprintf(msg, " . %s: %s", cmds[i].name, cmds[i].help); Serial.println(msg); } }

char *param 参数可能需要也可能不需要,因此默认发送,每个命令都可以自由使用或者直接忽略它。例如:handleFreq() 命令便要使用该参数:

void handleFreq(char *param) { if (strcmp("fq", param) == 0) { // no parameters sprintf(msg, "P2P frequency: %.3f MHz\n", (myFreq / 1e6)); Serial.print(msg); sprintf(msg, "Fq: %.3f MHz\n", (myFreq / 1e6)); displayScroll(msg); return; } else { // fq xxx.xxx set frequency float value = atof(param + 2); if (value < 150.0 || value > 960.0) { // sx1262 freq range 150MHz to 960MHz // Your chip might not support all... sprintf(msg, "Invalid frequency value: %.3f\n", value); Serial.print(msg); return; } myFreq = value * 1e6; api.lorawan.precv(0); // turn off reception while we're doing setup sprintf(msg, "Set P2P frequency to %3.3f: %s MHz\n", (myFreq / 1e6), api.lorawan.pfreq.set(myFreq) ? "Success" : "Fail"); Serial.print(msg); api.lorawan.precv(65534); sprintf(msg, "New freq: %.3f", value); displayScroll(msg); return; } }

poYBAGOFeB-AEMkXAAFueGbNSLk032.png

一切操作之后有了现在的结果,编码历时几个小时,就得到了一个功能齐全的 LoRa®USB适配器。但实际上没有用这么多时间,因为笔者重用了以前项目中的 Commands.h 代码,并且暂时跳过 AES 加密部分,把它留在示例项目中是因为它相对比较复杂,且通常不是简单项目的一部分。通常可以在项目正常运行后再添加 AES,这样就不必担心其他东西会受影响。但是,就像 Commands.h 一样,笔者已经从其他项目准备好 AES 文件,所以对它的实现也只是复制粘贴工作。

pYYBAGOFeB-ARMFAAACe1v8dqBU954.png

六、扩展

功能蔓延(feature creep)一直都是困扰开发人员的问题,但现在我们暂时可以先忽略这一点。一起来看看这个项目可以有哪些扩展:

1、OLED显示屏

由于引脚配置,显示屏要在底板背面添加,但添加起来也是很方便。学习一些如何关闭屏幕的编程代码,可以帮助节省能源和保护屏幕;

2、RTC实时时钟

可以在 JSON 数据包或类似 Cayenne LPP 的格式中为数据包添加时间戳;

3、GNSS模块

用户可以将 GPS 坐标添加到数据包中,而且如果已经在家中设置了收发器的坐标,还可以使用它们的自动计算距离(Haversine 公式)的功能。

4、固件的BLE UART路由

添加这个功能很简单。一旦设置了 BLE,代码就与串行代码几乎相同了。这样操作之后,它就不仅仅是一个用于电脑的 USB LoRa®适配器了,加上电池它可以成为手机无线 LoRa®适配器。

以上这些,这个使用 RUI3 制作的项目都能实现、也都可以拥有这些功能。如果你们感兴趣,也可以自己动手试试!

pYYBAGOFeB-Ae_OBAACtuD2MIT0208.png

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 物联网
    +关注

    关注

    2939

    文章

    47317

    浏览量

    407750
  • LoRa
    +关注

    关注

    354

    文章

    1853

    浏览量

    237195
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    STEVAL-MKI242A适配器板技术解析与应用指南

    。STEVAL-MKI242A适配器板由STEVAL-MKI109V3主板进行测试和支持,其主板包含个高性能32位微控制器。该适配器板在V~DD~ 和V~DDIO~ 电源线上配有去耦
    的头像 发表于 10-20 11:33 326次阅读
    STEVAL-MKI242A<b class='flag-5'>适配器</b>板技术解析与应用指南

    CUI 电源适配器能够符合法规要求

    作者: Pete Bartolik 在设计笔记本电脑和台式电脑时,设计人员大都倾向于在确定核心功能、性能和用户体验确定之后再选择电源适配器。但考虑到不断变化的监管影响,可以应将
    的头像 发表于 10-03 17:35 1472次阅读
    CUI 电源<b class='flag-5'>适配器</b>能够符合法规要求

    高性价比65W 适配器

    不同的电源适配器来提供正确的电力供应。因此,设计个优秀的电源适配器方案变得极为重要。今天要给大家介绍的是基于思睿达主推的CR6891A65W适配器方案,能效方面,
    的头像 发表于 09-29 10:21 441次阅读
    高性价比65W <b class='flag-5'>适配器</b>

    适配器EMC测试要求

    适配器的EMC测试要求是确保其在工作中不会产生超标电磁干扰(EMI),同时具备定的抗干扰能力(EMS)。适配器出口欧美、东南亚、日韩等主流市场时,EMC测试是强制性,并需通过相应的认证(如CE
    的头像 发表于 07-31 17:28 989次阅读
    <b class='flag-5'>适配器</b>EMC测试要求

    Texas Instruments HSEC180ADAPEVM SOM适配器板数据手册

    Texas Instruments HSEC180ADAPEVM适配器板是一款180引脚高速边缘卡 (HSEC) 适配器用于TI C2000模块化系统 (SOM) 平台,向后兼容基于
    的头像 发表于 07-25 14:34 438次阅读
    Texas Instruments HSEC180ADAPEVM SOM<b class='flag-5'>适配器</b>板数据手册

    CYPD3177是否有连接NonPD适配器源时通知电量不足的功能

    CYPD3177是否有连接NonPD适配器源时通知电量不足的功能? 例如,当连接到具有 9V2A 请求的 NonPD 适配器(源连接器为 A 型等)时,将通知电量不足。 对于 PD 兼容适配器
    发表于 05-22 08:24

    MITEQ适配器-N型

    MITEQ适配器-N型 MITEQ适配器中的N型(M/F)至SMA(M/F,DC至18 GHz)是一款高性能、高可靠性的射频适配器,适用于
    发表于 03-12 09:44

    电源适配器做什么的

    )的作用包括: 1.电流调节 :设备通常需要特定的电流(单位是安培A)。适配器会根据设备的要求,提供合适的电流强度。 2.电压转换 :家庭用电般是220V或110V的交流电,而很多电子设备(如笔记本电脑
    发表于 02-12 11:46

    适配器的电压与功率选择

    适配器通常包含个变压器和个整流器,变压器用于降低电压,而整流器则将交流电转换为直流电。此外,适配器还可能包含稳压电路和滤波电路,以确保
    的头像 发表于 02-06 17:14 2502次阅读

    蓝牙适配器连接技巧

    常重要的。市面上主要有以下几种类型的蓝牙适配器: USB蓝牙适配器 :这是最常见的类型,通过USB接口连接到电脑或其他设备。 内置蓝牙适配器
    的头像 发表于 02-06 17:05 2650次阅读

    适配器与转接头的区别

    (Adapter) 适配器种电子设备,用于个接口转换为另个接口,以便连接不同的设备。适配器
    的头像 发表于 02-06 17:00 1932次阅读

    电源适配器怎么使用?

    价格优势,超低空载和待机能量损耗。符合CEC标准,超安全设计,电源适配器符合各国安规认证。高效率的电路设计,性能稳定,低温升。   如果没有电源适配器的话,旦电压不稳,我们的电脑,笔
    发表于 01-18 11:04

    电源适配器和开关电源之间的区别

    随着电力电子技术的发展和创新,使得电源产品市场发展十分的迅速,技术也在不断地创新,这成本反转点日益向低输出电力端移动,这为电源适配器和开关电源产品提供了广阔的发展空间。开关电源和电源适配器
    发表于 01-16 10:57

    适配器电源IC U231X集合高效率、安全性、小体积多重优势

    因素。深圳银联宝科技凭借对适配器应用技术的深入理解,陆续研发推出适用于适配器应用的各类IC,今天推荐适配器电源ICU231X!适配器电源IC
    的头像 发表于 01-09 16:19 1064次阅读
    <b class='flag-5'>适配器</b>电源IC U231X集合高效率、安全性、小体积多重优势

    光纤跳线是否带适配器

    光纤跳线本身并不直接包含适配器,但光纤跳线的两端通常会装有光纤连接器,用于与光纤端口或适配器对接。光纤适配器种使不同尺寸或不同类型的光纤
    的头像 发表于 12-23 10:02 762次阅读