代码错误。 Lua 在 NodeMCU 上

Error in code. Lua on NodeMCU

我有一个电动卷帘项目。 我正在关注这个指导:https://www.instructables.com/id/Motorized-WiFi-IKEA-Roller-Blind/ .

我正在使用 instructable 中的代码,但我怀疑这些代码之一有问题:

config.lua

-- file : config.lua
local module = {}
module.SSID = {}
module.SSID["ssid"] = "password"

-- example for local MQTT
--module.MQHOST = "ohab.local"
--module.MQPORT = 1883
--module.MQID = node.chipid()
--module.MQUSR = ""
--module.MQPW = ""

-- example for cloud MQTT
module.MQHOST = "192.***.*.*"
module.MQPORT = 1883
module.MQID = node.chipid()
module.MQUSR = "username"
module.MQPW = "password"
module.MQTLS = 1 -- 0 = unsecured, 1 = TLS/SSL
module.ENDPOINT = "/house/masterbedroom/rollerblind/"
module.ID = "0"

--module.SUB = "set"
module.SUB = {[module.ENDPOINT .. module.ID .. "/set"]=0,[module.ENDPOINT .. "all"]=0}
module.POST = module.ENDPOINT .. module.ID .. "/status"
return module

wifi_setup

-- file: setup.lua
local module = {}
local function wifi_wait_ip()
    if wifi.sta.getip()== nil then
        print("IP unavailable, Waiting...")
    else
        tmr.stop(1)
        gpio.write(pin_led,1) --off
        print("\n================== ==================")
        print("ESP8266 mode is: " .. wifi.getmode())
        print("MAC address is: " .. wifi.ap.getmac())
        print("IP is "..wifi.sta.getip())
        print("====================================")
        mq.start()
    end
end

local function wifi_start(list_aps)
    if list_aps then
        gpio.write(pin_led,0) --on
        for key,value in pairs(list_aps) do
            if config.SSID and config.SSID[key] then
                wifi.setmode(wifi.STATION);
                wifi.sta.config(key,config.SSID[key])
                wifi.sta.connect()
                print("Connecting to " .. key .. " ...")
                --config.SSID = nil  -- can save memory
                tmr.alarm(1, 2500, 1, wifi_wait_ip)
            end
        end
    else
        print("Error getting AP list")
    end
end

function module.start()
  print("Configuring Wifi ...")
  wifi.setmode(wifi.STATION);
  wifi.sta.getap(wifi_start)
end
return module

可悲的是,我无法超越第 4 步。在我尝试将代码下载到 ESP8266 后,我只收到此错误:

PANIC: unprotected error in call to Lua API (wifi_setup.lua:25: bad argument #1 to 'config' (config table not found!))

我只改变了指导员告诉我改变的东西,我试图自己寻找错误但我找不到任何......这是我第一次使用 Lua,所以这个对我来说是全新的。

希望这里有人能提供一些帮助。坚持了好几天...

这部分问题已解决。查看解决方案的评论


可悲的是,当一个问题解决了,新的问题又出现了...

芯片现在已成功连接到 wifi 和 mqtt 服务,但是当我尝试通过输入命令 'step_move(1000,FWD,2)' 来干 运行 时,没有任何反应。电机应该旋转...

此外,当我按下按钮时,我收到如下新的恐慌错误:

PANIC: unprotected error in call to Lua API (button.lua:23: attempt to perform arithmetic on upvalue '?' (a nil value))

button.lua

--file button4.lua

do
  -- use pin 1 as the input pulse width counter
  local pin=5
  local debounce = 150 --ms
  local longpress = 2000 --ms
  local pulse1, pulse2, du, now, trig = 1, 0, 0, tmr.now, gpio.trig
  local prev_int_time, int_time, up_time = 0
  local cal_steps = 100000
  local cal_steps_dn = 0
  local cal_steps_up = 0
  local cal_state = 0 -- 0 = not calibration, 1 = calibrating down, 2 = calibrating up
  state = 0 -- state: 0 = up, 1 = transition, 2 = down
  gpio.mode(pin,gpio.INT)

  local function pin4cb(level)
    int_time = now() / 1000
    if ((int_time - prev_int_time) > debounce) then
      if (level == 0) then
        up_time = int_time
      else
        if((int_time - up_time) > longpress) then
          print("calibrating")
          cal_state = 1
          --cur_step = 100000
          step_move(cal_steps,FWD,2)
        else -- short press
          print("short", cal_state)
          if (cal_state == 2) then -- calibrated up (done)
            print("calibration done")
            state = 0 -- up
            cur_step = 0
            tot_steps = cal_steps - step_stepsleft
            print("cal_steps: " .. cal_steps)
            print("step_stepsleft: " .. step_stepsleft)
            print("tot_steps: " .. tot_steps)
            step_stop()
            pins_disable()
            cal_state = 0
            if file.open("cfg_tot_steps.lua", "w+") then
              file.write("tot_steps=" .. tot_steps .. '\n')
              file.close()
            end
          elseif (cal_state == 1) then -- calibrated dn (switch direction)
            print("calibration low point")
             print(cal_steps - step_stepsleft) 
            step_stop()
            step_move(cal_steps,REV,2)
            cal_state = 2
          elseif (cal_state == 0) then
            if (state == 0 and step_stepsleft == 0) then -- i am up, go dowm
              rollerblind.down()
--              state = 2
            elseif (state == 1) then -- i am moving, do nothing
              -- do nothing
            elseif (state == 2 and step_stepsleft == 0) then -- i am down, go up
              rollerblind.up()
--              state = 0
            end
         end
       end
      end
      --print (level)
      prev_int_time = int_time
    end
  end
      gpio.trig(pin, "both", pin4cb)
 end

这是 stepper.lua 的代码:

    -- stepper.lua
-- code from: http://www.esp8266.com/viewtopic.php?f=19&t=2326
-- simple stepper driver for controlling a stepper motor with a
-- l293d driver
-- nodemcu pins:  0  5  6  7
stepper_pins = {1,3,2,4} -- (A-)blue, (A+)pink, (B-)yellow, (B+)orange
--stepper_pins = {1,2,3,4}
-- half or full stepping
step_states4 = {
 {1,0,0,1},
 {1,1,0,0},
 {0,1,1,0},
 {0,0,1,1}
}
step_states8 = {
 {1,0,0,0},
 {1,1,0,0},
 {0,1,0,0},
 {0,1,1,0},
 {0,0,1,0},
 {0,0,1,1},
 {0,0,0,1},
 {1,0,0,1},
}
step_states = step_states4 -- choose stepping mode
step_numstates = 4 -- change to match number of rows in step_states
step_delay = 10 -- choose speed
step_state = 0 -- updated by step_take-function
step_direction = 1 -- choose step direction -1, 1
step_stepsleft = 0 -- number of steps to move, will de decremented
step_timerid = 4 -- which timer to use for the steps
status_timerid = 2 -- timer id for posing of status messages
-- setup pins
function pins_enable()
  for i = 1, 4, 1 do
    gpio.mode(stepper_pins[i],gpio.OUTPUT)
  end
end

function pins_disable()
--  for i = 1, 4, 1 do -- no power, all pins
  for i = 2, 4, 1 do -- no power, all pins except one (to keep it in place)
    gpio.mode(stepper_pins[i],gpio.INPUT)
  end
end
-- turn off all pins to let motor rest
function step_stopstate() 
  for i = 1, 4, 1 do
    gpio.write(stepper_pins[i], 0)
  end
end

-- make stepper take one step
function step_take()
  -- jump to the next state in the direction, wrap
  step_state = step_state + step_direction
  cur_step = cur_step + step_direction * FWD
      if step_state > step_numstates then
    step_state = 1;
  elseif step_state < 1 then
    step_state = step_numstates
  end
  -- write the current state to the pins
  pins_enable()
  for i = 1, 4, 1 do
    gpio.write(stepper_pins[i], step_states[step_state][i])
  end
  -- might take another step after step_delay
  step_stepsleft = step_stepsleft-1
  if step_stepsleft > 0 then
--  if cur_step > 0 and cur_step < tot_steps and step_stepsleft > 0 then
    tmr.alarm(step_timerid, 10, 0, step_take )
    --tmr.alarm(step_timerid, 10, 0, step_take )
  else
    step_stopstate()
    step_stop()
    pins_disable()
    mq.post_status()
    if file.open("cfg_cur_step.lua", "w+") then
      file.write("cur_step=" .. cur_step .. '\n')
      file.close()
    end
  end
end

-- public method to start moving number of 'int steps' in 'int direction'    
function step_move(steps, direction, delay)
  tmr.stop(step_timerid)
  step_stepsleft = steps
  step_direction = direction
  step_delay = delay
  step_take()
end

function step_go_to(step, delay)
  if step >= cur_step then
    steps = step - cur_step
    step_move(steps, FWD, delay)
  end
  if step <= cur_step then
    steps = cur_step - step
    step_move(steps, REV, delay)
  end
end

function percent_go_to(percent, delay)
  if(percent >= 0 and percent <= 100) then
    step_stop()
    tmr.register(status_timerid, 1000, tmr.ALARM_AUTO, function () mq.post_status() end)
    tmr.start(status_timerid)
    step = percent * tot_steps / 100
    step_go_to(step, delay)
  end
end

-- public method to cancel moving
function step_stop()
  tmr.stop(step_timerid)
  tmr.stop(status_timerid)
  step_stepsleft = 0
  step_stopstate()
end

我们来一一解析错误信息:

unprotected error in call to Lua API (wifi_setup.lua:25: bad argument #1 to 'config' (config table not found!))

未受保护的错误意味着您进行了正常的函数调用,而不是受保护的调用(又名 pcall),后者是您预计会发生错误并希望提供处理这些错误的方法的函数调用.由于您没有执行受保护的调用,Lua 不知道如何处理错误并立即终止(这不是一件坏事)。

wifi_setup.lua:25 告诉您发生错误的文件和行。

bad argument #1 to 'config' 表示问题是由于传递给名为 config.

的函数的第一个参数引起的

config table not found!是该函数的实现者提供的错误信息。

所以总而言之,函数调用 wifi.sta.config(key,config.SSID[key]) 存在问题,因为它期望将 table 作为第一个参数,而您提供了不同的东西(即带有 BSSID 的字符串)。确实检查 NodeMCU docs 表明您需要将 table 传递给此函数:

wifi.sta.config()

Sets the WiFi station configuration. [...]

Syntax

wifi.sta.config(station_config)

Parameters

station_config table containing configuration data for station

table 的预期布局也在该页面上有详细记录。

ComicSansMS 提供了一个很好的答案,其本质是你需要替换

wifi.sta.config(key,config.SSID[key])

wifi.sta.config{ssid=key,pwd=config.SSID[key]}

因此,一个独立的例子可能是这样的:

--wifi.setmode(wifi.NULLMODE)

config = {}
config.SSID = {}
config.SSID["ssid"] = "password"

function wifi_wait_ip()
  if wifi.sta.getip() == nil then
    print("IP unavailable, Waiting...")
  else
    tmr.stop(1)
    print("\n====================================")
    print("ESP8266 mode is: " .. wifi.getmode())
    print("MAC address is: " .. wifi.ap.getmac())
    print("IP is " .. wifi.sta.getip())
    print("====================================")
  end
end

function wifi_start(list_aps)
  if list_aps then
    for key, value in pairs(list_aps) do
      if config.SSID and config.SSID[key] then
        wifi.setmode(wifi.STATION);
        wifi.sta.config{ssid=key, pwd=config.SSID[key]}
        -- wifi.sta.connect() not needed as config() uses auto-connect=true by default
        print("Connecting to " .. key .. " ...")
        tmr.alarm(1, 2500, 1, wifi_wait_ip)
      end
    end
  else
    print("Error getting AP list")
  end
end

function start()
  print("Configuring Wifi ...")
  wifi.setmode(wifi.STATION)
  wifi.sta.getap(wifi_start)
end

start()