ESP8266 NodeMCU Lua

From ElectroDragon
Jump to: navigation, search

Relevant Topics

Doc page

Git page

Hardware page

Firmware build

Examples and Demo

  • using IDE esplorer can easily manage and program the ESP8266 board
  • Here we only try and make sure the code can be compiled well, ds18b20 is not connected.
  • Use "upload" to upload code is better for avoiding errors

Using esplorer.png

DS18B20 Read Temperature (simplified codes)

  • ds18b20.lua shorten code, this will be used as a lua module
--
-- DS18B20 one wire module for NODEMCU 
-- LICENCE: http://opensource.org/licenses/MIT 
-- Vowstar <vowstar@nodemcu.com> 
-- Dramatic simplification: Peter Scargill 
--
 
-- Set module name as parameter of require 
local modname = ...
local M = {} 
_G[modname] = M 
 
--
-- Local used modules 
--
-- Table module 
local table = table 
-- String module 
local string = string 
-- One wire module 
local ow = ow 
-- Timer module 
local tmr = tmr 
-- Limited to local environment 
setfenv(1,M) 
----
-- Implementation – you don’t get any shorter than this 
----
 
function readNumber(pin) 
        ow.setup(pin) 
        ow.reset(pin) 
        ow.write(pin, 0xCC, 1) 
        ow.write(pin, 0xBE, 1) 
        data = nil 
        data = "" 
        for i = 1, 2 do 
            data = data .. string.char(ow.read(pin)) 
        end 
        t = (data:byte(1) + data:byte(2) * 256) / 16 
        if (t>100) then 
        t=t-4096 
        end 
        ow.reset(pin) 
        ow.write(pin,0xcc,1) 
        ow.write(pin, 0x44,1)   
        return t           
end
 
-- Return module table 
return M
  • Main code file readDS.lua, will use module ds18b20
t=require("ds18b20") 
print("the temperature is  "..t.readNumber(4)) 
t = nil 
ds18b20 = nil 
package.loaded["ds18b20"]=nil
  • Init.lua entry, setup wifi and dofile readDS.lua
print(wifi.sta.getip())
wifi.setmode(wifi.STATION)
wifi.sta.config("apname","password")
print(wifi.sta.getip())
dofile('readDS.lua')

HTTP Client

  • simple HTTP client
-- A simple http client
conn=net.createConnection(net.TCP, false) 
conn:on("receive", function(conn, pl) print(pl) end)
conn:connect(80,"121.41.33.127")
conn:send("GET / HTTP/1.1\r\nHost: www.nodemcu.com\r\n"
    .."Connection: keep-alive\r\nAccept: */*\r\n\r\n")

More simple HTTP client

-- a simple http server
srv=net.createServer(net.TCP) 
srv:listen(80,function(conn) 
    conn:on("receive",function(conn,payload) 
    print(payload) 
    conn:send("<h1> Hello, NodeMcu.</h1>")
    end) 
end)

PWM operation

function led(r,g,b) 
    pwm.setduty(1,r) 
    pwm.setduty(2,g) 
    pwm.setduty(3,b) 
end
pwm.setup(1,500,512) 
pwm.setup(2,500,512) 
pwm.setup(3,500,512)
pwm.start(1) 
pwm.start(2) 
pwm.start(3)
led(512,0,0) -- red
led(0,0,512) -- blue

Blink LED

lighton=0
tmr.alarm(0,1000,1,function()
if lighton==0 then 
    lighton=1 
    led(512,512,512) 
    -- 512/1024, 50% duty cycle
else 
    lighton=0 
    led(0,0,0) 
end 
end)

repeat using timer

tmr.alarm(1,5000,1,function() print("alarm 1") end)
tmr.alarm(0,1000,1,function() print("alarm 0") end)
tmr.alarm(2,2000,1,function() print("alarm 2") end)
-- after sometime
tmr.stop(0)

Telnet server

-- a simple telnet server
s=net.createServer(net.TCP,180) 
s:listen(2323,function(c) 
    function s_output(str) 
      if(c~=nil) 
        then c:send(str) 
      end 
    end 
    node.output(s_output, 0)   
    -- re-direct output to function s_ouput.
    c:on("receive",function(c,l) 
      node.input(l)           
      --like pcall(loadstring(l)), support multiple separate lines
    end) 
    c:on("disconnection",function(c) 
      node.output(nil)        
      --unregist redirect output function, output goes to serial
    end) 
    print("Welcome to NodeMcu world.")
end)

Read ds18b20

-- read temperature with DS18B20
t=require("ds18b20")
t.setup(9)
addrs=t.addrs()
-- Total DS18B20 numbers, assume it is 2
print(table.getn(addrs))
-- The first DS18B20
print(t.read(addrs[1],t.C))
print(t.read(addrs[1],t.F))
print(t.read(addrs[1],t.K))
-- The second DS18B20
print(t.read(addrs[2],t.C))
print(t.read(addrs[2],t.F))
print(t.read(addrs[2],t.K))
-- Just read
print(t.read())
-- Just read as centigrade
print(t.read(nil,t.C))
-- Don't forget to release it after use
t = nil
ds18b20 = nil
package.loaded["ds18b20"]=nil


  • List the code files inside of the board
Lua run2.jpg
--list.lua
l = file.list();
    for k,v in pairs(l) do
      print("name:"..k..", size:"..v)
    end

--init.lua will be excuted file.open("init.lua","w") file.writeline(print("Hello World!")) file.close() node.restart() -- this will restart the module.

Basic Init for wifi setup

  • Connect wifi
print(wifi.sta.getip())
--nil
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
print(wifi.sta.getip())
--192.168.18.110
  • default init lua, connect to wifi, retrieve IP and then dofile
Lua run1.jpg
  • init file
--init.lua
print("set up wifi mode")
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","PassWord")
 --here SSID and PassWord should be modified according your wireless router
wifi.sta.connect()
tmr.alarm(1, 1000, 1, function() 
    if wifi.sta.getip()== nil then 
    	print("IP unavaiable, Waiting...") 
    else 
    	tmr.stop(1)
    	print("Config done, IP is "..wifi.sta.getip())
    	--dofile("yourfile.lua")
    end 
 end)

GPIO control

pin = 1
 
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, gpio.HIGH)
 
gpio.mode(pin, gpio.INPUT)
print(gpio.read(pin))
  • Blink LED or relay
pin = 6
lighton=0
 
gpio.mode(pin,gpio.OUTPUT)
 
tmr.alarm(1, 1000, 1, function()
    if lighton==0 then
        lighton=1
        gpio.write(pin,gpio.HIGH)
    else
      lighton=0
      gpio.write(pin,gpio.LOW)
    end
  end)

File operation

  • Read config from config.tx
  --MQTT, server, user, password, port
  file.open("config.txt", "r")
  MQTTs = file.readline()
  print("server:"..MQTTs)
  --MQTTs = "m11.cloudmqtt.com"
  MQTTu = file.readline()
  MQTTp = file.readline()
  MQTTpo = file.readline()
  file.close()
  print("server:"..MQTTs)
  • the config should represent:
m = net.createConnection(net.TCP, 0)
print("user:"..MQTTu)
m = mqtt.Client(MQTTu, 120, MQTTu, MQTTp)
m:connect(MQTTs, MQTTpo, 0, function(conn) 
        print("connected") 
        m:subscribe("/android/",0, function(conn)
           print("subscribed") 
        end)
     end)

Smartconfig

wifi.setmode(wifi.STATION)
 
wifi.startsmart(0,
  function(ssid, password)
  print(string.format(“Success. SSID:%s ; PASSWORD:%s”, ssid, password))
  end
)


MQTT

  • Client ID can be anything you like, for example Nodemcu_ID1234
  • Topic and message is a pair, each topic can have its own message, only the client who subscribe to this topic can receive the message
  • You can find the MQTT SPY demo test tool here.
  • See how it works below

Demo Code

  • Note to change client_id, username, password, hostname and port below
-- initiate the mqtt client and set keepalive timer to 120sec
mqtt = mqtt.Client("client_id", 120, "username", "password")
 
mqtt:on("connect", function(con) print ("connected") end)
mqtt:on("offline", function(con) print ("offline") end)
 
-- on receive message
mqtt:on("message", function(conn, topic, data)
  print(topic .. ":" )
  if data ~= nil then
    print(data)
  end
end)
 
mqtt:connect("hostname", port, 0, function(conn) 
  print("connected")
  -- subscribe topic with qos = 0
  mqtt:subscribe("my_topic",0, function(conn) 
    -- publish a message with data = my_message, QoS = 0, retain = 0
    mqtt:publish("my_topic","my_message",0,0, function(conn) 
      print("sent") 
    end)
  end)
end)

Custom firmware

Online custom-build, or Docker Build

  • Could run from https://nodemcu-build.com/
  • Docker build
  • Install docker, git clone or download nodemcu firmware from github to your user directory for example c:\users\electrodragon\
git clone https://github.com/nodemcu/nodemcu-firmware.git
  • run command to generate bin firmware file, in windows folder c:/user/hechao/nodemcu-firmware/ can not be changed, for example:
docker run --rm -it -v //c/Users/electrodragon/nodemcu-firmware:/opt/nodemcu-firmware marcelstoer/nodemcu-build
  • run either integer or float only INTEGER or FLOAT
docker run -e "INTEGER_ONLY=1" --rm -it -v //c/Users/electrodragon/nodemcu-firmware:/opt/nodemcu-firmware marcelstoer/nodemcu-build
docker run -e "FLOAT_ONLY=1" --rm -it -v //c/Users/hechao/nodemcu-firmware:/opt/nodemcu-firmware marcelstoer/nodemcu-build

Build Details

Enable/disable Modules - user_modules.h

Edit app/include/user_modules.h and comment-out the #define statement for modules you don't need. Example:

...
#define LUA_USE_MODULES_MQTT
// #define LUA_USE_MODULES_COAP
// #define LUA_USE_MODULES_U8G
...

board related configuration - user_config.h

Enable smart config: in file /app/include/user_config.h

//#define WIFI_SMART_ENABLE

version related properties - user_version.h

#define NODE_VERSION    "NodeMCU 1.5.4.1 - custom build by electrodragon.com"
#ifndef BUILD_DATE  
#define BUILD_DATE        "2016-09-23"

Flashing details

  • Need to flash nodemcu firmware and your code bin firmware now together into target device
  • calculate your nodemcu firmware size for the code bin firmware address first, for example:
  1. use the nodemcu firmware, size on disk as below:

Nodemcu size on disc.png

  1. so the bits size is: 408KB + 4KB =412 KB, 412 KB*1024 = 421888, change from dec to hex by using "calculator" you get 67000
  2. so for the two firmware, the upload address should be:
0x00000 for nodemcu firmware bin
and 0x67000 for your code firmware bin
  1. Finally use esp download tool, combine bin function to combine the two bin files

Spiffy combine.png


Custom Lua to Bin file by Using SPIFFY

  • The following methods has too many bugs, main file spiffs also obsoleted, better do not use
  • Reference: spiffimg and spiffy use spiffs as core file

Setup

/home/esp8266/Share/nodemcu-firmware-master/spiffy
  • in spiffy folder, create build and run make, a few files will be generated into build folder
  • create files folder, files to store lua file like init.lua print ("Hello")
  • run spiffy to build the rom, before this, you may need delete file "spiff_rom.bin" first, this is the generated bin file
./build/spiffy
  • Open file spiff_rom.bin by ultraedit can see the original codes
  • If the file large than 16K should edit main.c to change this:
4*4*1024 = 16K, can change to 8*4*1024 = 32K


Obselete

Module and library

  • U8G - display 128x64 OLED, example lua in nodemcu folder "nodemcu-firmware/lua_examples/u8glib/u8g_graphics_test.lua"
  • DHT22 - example avaialble