资讯详情

Luat 功能开发教程(十七) 长连接超低功耗方案

目录

  • 简介
    • 什么是超低功耗?
    • 能降低多少功耗?
    • 什么时候用
    • 支持哪个版本?
  • 实现方法
    • 主要命令
  • 示例
    • 实现原理
    • 两种心跳包
    • 现代
  • 常见问题
  • 相关资料以及购买链接

简介

什么是超低功耗

超低功耗相对于低功耗。考虑到模块的大部分应用场景:系统休眠后,仍需每隔一段时间收发一次数据,报告设备状态。因此,传统的低功耗数据只具有一定的参考意义,在实际业务场景中无法达到此值。超低功耗是对每隔一段时间收发数据场景的具体优化,以降低产品的整体功耗。

特别说明:服务器发送的数据不会丢失,无论是进入低功耗还是超低功耗。

能降低多少功耗?

合宙Cat1 AT在实网下测量的标准固件功耗数据如下: image.png 注:表中电流相关单位ma】 LUAT 功耗调试是参考 AT标准固件的结果。

从最后两行的对比结果来看,心跳包保存场景的功耗在超低功耗模式下降低了一半以上。

注:实际测量数据将受到网络信号的影响,是否已注册,外围是否连接到设备因素。如果差异很大,建议先断开外围设备,进入飞行模式比较数据。

什么时候用

超低功耗可用于大多数数数字传输业务场景。这些场景有一个共同的特点:当需要传输数据时,使用网络传输数据。传输完成后,设备进入心跳包保存状态。超低功耗是优化心跳保存功耗,降低整体功耗。典型的产品场景包括:云喇叭、监控摄像头、共享设备、远程控制等。

支持哪个版本?

实现方法

主要命令

首先,打开低功耗休眠模式,使设备在空闲时进入低功耗状态;其次,通过AT命令ATRTIME打开超低功耗模式。 LUAT 开机注册上网后操作 以下两句话 (句子没有顺序,一般成对使用) ril.request(“AT WAKETIM=2”) ril.request("ATRTIME=2")

AT WAKETIM=< s >

参数 定义 取值 说明取值
s 在IDL在休眠状态下等待多久? 0~100 单位:秒,0表示关闭。

在 IDLE 状态下(无 AT,没有短信,没有通话 AP_WAKEUP_MODULE 在高的情况下) 等待多久才能入睡?

AT*RTIME=< n >

参数 定义 取值 说明取值
n 在数传模式下等待多久? 0~20 单位:秒,0表示关闭。

正常情况下,值越短,功耗越低。建议设置为2。如果实际使用环境信号较差,数据收发往往会出现重传延迟,则需要增加此值。

示例

实现原理

首先, 数据通信模块功耗很高(80-120mA区间), 不做数据传输,只保持一个SOCKET 连接本身不是很耗电,只有连接是连接的,才能保证及时收到服务器发出的指令。 如果SOCKET连接10分钟以上(有些地区在5分钟内不稳定。)没有数据传输,该连接将被网络回收,导致连接断开;为了避免这种情况,心跳包需要保持在线连接。

两种心跳包

它在应用层中看不到数据交互:参考 https://doc.openluat.com/wiki/21?wiki_page_id=2256 中的 socketcore.sock_setopt() 因为这种方法用得少,所以在LUAT LIB 没有包装,知道有这个方法就好了。

A 固定周期保存 无论当前连接是否有数据传输,间隔时间到了,心跳包都会发送到服务器;目的是 保活 同步。 这种场景可能用于对心跳包周期有严格要求的业务。 B. 网络通信TIMEOUT 保活 如果当前链接上有任何数据收发,下一次心跳将在指定时间后发出,目的是保存 省电。这种场景应用广泛,目前LUAT 的示例TCP、MQTT 这样设计默认。 上面 AB 根据服务器的心跳要求设计两种选项,各有用

实现代码

在实现TCP 在长连接之前,需要解释几个参数:

  1. 服务器IP以及准备工作
bool flag_conned=false --服务器是否已连接 local tip,  tport  = "106.13.6.X", "6640" --向TCP服务端发送普通数据或心跳数据 function send_tcp_request(pdata)     sys.publish("T_SOCKET_SEND_DATA",pdata) end 
  1. 参与测试的串口收发代码(不必要,添加到这里进行测试),用户可以通过串口1和服务器之间TCP 做透传
local UART1_ID, recvQueue = 1, {} local uartimeout, recvReady,RECV_MAXCNT = 2000, "UART_RECV_ID",1024  ---这里使用uart1 连接计算机与服务器进行数据交互 local function uart1_write(data)     for i = 1, #data, 1460 do         uart.write(UART1_ID, data:sub(i, i   1460 - 1))     end end ---配置串口参数 uart.setup(UART1_ID, 115200, 8, uart.PAR_NONE, uart.STOP_1) ---串口数据通过注册回调函数收集 uart.on(UART1_ID, "receive", function(uid)     local str_recv = uart.read(uid, RECV_MAXCNT)     log.info("uart recv <---------", str_recv)     send_tcp_request( str_recv)     uart1_write("OK\r\n") end) 
  1. TCP 工作线程
sys.taskInit(function()     local r, s, p     local result,  unProcData=false,""     while true do         local count = 0         flag_conned=false         while not socket.isReady() do--等联网             cunt = count + 1
            log.info("check net",count)
            sys.wait(1000)
            if count > 60 then  --如果太长时间连不上,则进入飞行模式重连(属小概率事件)
                net.switchFly(true)
                sys.wait(5000)
                net.switchFly(false)
                count = 0
            end
        end
        log.info("+++++++++++++++ socket ready+++++++++++++++")
        -- 找到网络后发出下面两个指令,优化休眠。
       ril.request("AT+WAKETIM=1\r\n")
        sys.timerStart(function() 
              ril.request("AT*RTIME=2\r\n")
        end,1000)
        local c = socket.tcp()
        if c:connect(tip, tport) then
            flag_conned=true
            ---每次重新连接TCP服务器都要做一次登录操作
            while true do
                local r, s, p = c:recv(120000, "T_SOCKET_SEND_DATA")
                if r then
                    if  s and  #s >0 then
                        --假定用户用串口1 和TCP 进行透传,则把从服务器收到的内容转发到串口1
                        uart1_write(s)
                    end
                elseif s == "T_SOCKET_SEND_DATA" then
                   log.info("socket send----->", p)
                   if not c:send(p,10) then break end
                elseif s == "timeout" then
                    --注意#B,如果是网络通信TIMEOUT 保活,这里可以发送保活数据包
                    --send_tcp_request("heartdata")
                else
                    log.info("loop exit r,s,p",r,s,p)
                    break
                end
            end
        end
        flag_conned=false
        r,s,p = nil,nil,nil
        c:close()
        link.shut()
    end
end)
  1. 如果是固定周期保活的,则TCP 工作线程中的 timout (–注意#B)就不需要发送心跳了,而是开一个循环定时器,如下 120秒上报一次心跳:
sys.timerLoopStart(function() 
    if flag_conned then
        send_tcp_request("heartdata")
    end
end, 12000)

常见问题

1,在进行CTA/GCF等测试认证的时候需要关闭该功能。 2,如果心跳包比较频繁,比如10秒一次,那就不建议开启这个功能,极端情况下可能会导致设备断网。 3,如果数传是基于UDP这种非可靠传输,打开这个功能后,丢包概率会变大。

4 LUAT 的底包在应用层不做任何休眠调度时,默认是启用休眠的。休眠会让部分外设停止工作,比如彩屏的SPI ,CAT1的串口2 和串口3 等,如果要对外设进行控制,建议主动唤醒模块 pm.wake(“flagxxx”), 当需要进入休眠了,就调用 pm.sleep(“flagxxx”), 应用逻辑上,要这两个操作是成对的。 5.关于休眠的测量,建议使用高精度的电流测试仪器,测试条件定义为连上服务器后首次电流数字持续跌落 到几个毫安的时候开始, 测量时间越长平均功耗越准确,总测量时长最少要超过半小时。

相关资料以及购买链接

SOCKETAPI说明 源代码 : JLF_TEST.lua

相关开发板购买链接

Air724UG开发板 Air724 开发板使用说明

标签: sub连接器78p

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台