You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP8266 NodeMCU中Lua旋转编码器回调的Upvalue为nil问题

问题分析与解决

你的核心误区在于对Lua闭包(Upvalue)的作用范围理解错误:只有当函数定义在包含目标局部变量的作用域内时,才能捕获该变量作为Upvalue。

代码问题拆解

你当前的turn函数是在setupRotary外部定义的局部函数,它和setupRotary参数里的sv没有任何闭包关联。当rot模块触发回调调用turn时,Lua会在turn的作用域里找sv——找不到局部变量就会去全局表中查找,而你并没有定义全局的sv,自然会出现nil错误。

修正方案

方案1:将turn定义在setupRotary内部

让turn直接处于sv的作用域内,自然捕获该变量作为Upvalue:

local setupRotary = function(sv)
    local ch, a, b, sw = sv.rotary_ch, sv.rotary_a, sv.rotary_b, sv.rotary_sw
    print(ch, a, b, sw)
    rot.init(ch, a, b, 1, sw)
    sv.last = 0

    -- 将turn定义在setupRotary内部,直接捕获当前的sv
    local turn = function(type, pos, when)
        print(type, pos, when, sv.value)
        if type == rotary.TURN then
            local move = sv.last - pos
            sv.last = pos
            sv.x = sv.value + move
            local tm
            if tm == nil then
                tm = tmr.create()
                tm:register(500, tmr.ALARM_SINGLE, function()
                    setTo(sv)
                end)
            end
            tm:start()                  
        end
    end

    rot.on(ch, rot.TURN, turn)
end

方案2:用工厂函数生成绑定sv的回调

如果需要复用turn的逻辑,可以通过工厂函数返回闭包,显式绑定目标sv:

-- 工厂函数:传入sv,返回绑定了该sv的回调函数
local createTurnHandler = function(sv)
    return function(type, pos, when)
        print(type, pos, when, sv.value)
        if type == rotary.TURN then
            local move = sv.last - pos
            sv.last = pos
            sv.x = sv.value + move
            local tm
            if tm == nil then
                tm = tmr.create()
                tm:register(500, tmr.ALARM_SINGLE, function()
                    setTo(sv)
                end)
            end
            tm:start()                  
        end
    end
end

local setupRotary = function(sv)
    local ch, a, b, sw = sv.rotary_ch, sv.rotary_a, sv.rotary_b, sv.rotary_sw
    print(ch, a, b, sw)
    rot.init(ch, a, b, 1, sw)
    sv.last = 0
    -- 生成绑定当前sv的回调
    local turn = createTurnHandler(sv)
    rot.on(ch, rot.TURN, turn)
end

关键知识点回顾

  • Upvalue是内部函数对外部函数局部变量的引用,必须满足"函数嵌套定义"的结构才能形成闭包。
  • 若函数不在目标变量的作用域内定义,Lua会优先查找局部变量,找不到则去全局表中查找,不会自动关联其他作用域的变量。

内容的提问来源于stack exchange,提问作者fanThomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 23:48:27