shackspace/nodemcu-firmware-dali

Name: nodemcu-firmware-dali

Owner: stuttgart hackerspace

Description: lua based interactive firmware for mcu like esp8266 with a specific DALI flavour

Created: 2015-12-14 08:04:38.0

Updated: 2018-04-02 12:44:55.0

Pushed: 2016-02-06 22:55:21.0

Homepage: http://shackspace.de/wiki/doku.php?id=project:dali_nodemcu

Size: 87489

Language: C

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

«««< HEAD

NodeMCU 1.4.0

Join the chat at https://gitter.im/nodemcu/nodemcu-firmware Build Status

A lua based firmware for wifi-soc esp8266

Summary

Useful links

| Resource | Location | | ————– | ————– | | Developer Wiki | https://github.com/nodemcu/nodemcu-firmware/wiki | | API docs | NodeMCU api | | Home | nodemcu.com | | BBS | Chinese BBS | | Docs | NodeMCU docs | | Tencent QQ group | 309957875 | | Windows flash tool | nodemcu-flasher | | Linux flash tool | Esptool | | ESPlorer GUI | https://github.com/4refr0nt/ESPlorer | | NodeMCU Studio GUI | https://github.com/nodemcu/nodemcu-studio-csharp |

Programming Examples

Because Lua is a high level language and several modules are built into the firmware, you can very easily program your ESP8266. Here are some examples!

Connect to your AP
ip = wifi.sta.getip()
print(ip)
--nil
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID", "password")
ip = wifi.sta.getip()
print(ip)
--192.168.18.110
Manipulate hardware like an Arduino
pin = 1
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, gpio.HIGH)
print(gpio.read(pin))
Write a network application in Node.js style
-- A simple http client
conn=net.createConnection(net.TCP, 0)
conn:on("receive", function(conn, payload) print(payload) end)
conn:connect(80, "115.239.210.27")
conn:send("GET / HTTP/1.1\r\nHost: www.baidu.com\r\n"
    .. "Connection: keep-alive\r\nAccept: */*\r\n\r\n")
Or a simple HTTP server
-- 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)
  conn:on("sent", function(conn) conn:close() end)
end)
Connect to MQTT broker
nit mqtt client with keepalive timer 120sec
mqtt.Client("clientid", 120, "user", "password")

etup Last Will and Testament (optional)
roker will publish a message with qos = 0, retain = 0, data = "offline"
o topic "/lwt" if client doesn't send keepalive packet
t("/lwt", "offline", 0, 0)

("connect", function(con) print("connected") end)
("offline", function(con) print("offline") end)

n publish message receive event
("message", function(conn, topic, data)
int(topic .. ":")
 data ~= nil then
print(data)
d


:connect(host, port, secure, auto_reconnect, function(client) end)
or secure: m:connect("192.168.11.118", 1880, 1, 0)
or auto-reconnect: m:connect("192.168.11.118", 1880, 0, 1)
nnect("192.168.11.118", 1880, 0, 0, function(conn) print("connected") end)

ubscribe to topic with qos = 0
bscribe("/topic", 0, function(conn) print("subscribe success") end)
r subscribe multiple topics (topic/0, qos = 0; topic/1, qos = 1; topic2, qos = 2)
:subscribe({["topic/0"]=0,["topic/1"]=1,topic2=2}, function(conn) print("subscribe success") end)
ublish a message with data = hello, QoS = 0, retain = 0
blish("/topic", "hello", 0, 0, function(conn) print("sent") end)

ose();  -- if auto-reconnect == 1, it will disable auto-reconnect and then disconnect from host.
ou can call m:connect again
UDP client and server
 udp server
t.createServer(net.UDP)
("receive", function(s, c) print(c) end)
sten(5683)

 udp client
et.createConnection(net.UDP)
n("receive", function(cu, c) print(c) end)
onnect(5683, "192.168.18.101")
end("hello")
Do something shiny with an RGB LED
nction led(r, g, b)
pwm.setduty(1, r)
pwm.setduty(2, g)
pwm.setduty(3, b)
d
m.setup(1, 500, 512)
m.setup(2, 500, 512)
m.setup(3, 500, 512)
m.start(1)
m.start(2)
m.start(3)
d(512, 0, 0) -- red
d(0, 0, 512) -- blue
And blink it
ghton=0
r.alarm(1, 1000, 1, function()
if lighton==0 then
  lighton=1
  led(512, 512, 512)
else
  lighton=0
  led(0, 0, 0)
end
d)
If you want to run something when the system boots
init.lua will be executed
le.open("init.lua", "w")
le.writeline([[print("Hello, do this at the beginning.")]])
le.close()
de.restart()  -- this will restart the module.
Add a simple telnet server to the Lua interpreter
-- 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)           -- works like pcall(loadstring(l)) but support multiples separate lines
   end)
   c:on("disconnection", function(c)
      node.output(nil)        -- un-register the redirect output function, output goes to serial
   end)
   print("Welcome to NodeMCU world.")
end)

Building the firmware

There are several options for building the NodeMCU firmware.

Online firmware custom build

Please try Marcel's NodeMCU custom build cloud service and you can choose only the modules you need, and download the firmware once built.

NodeMCU custom builds can build from all active branches (with the latest fixes).

Docker containerised build

See https://hub.docker.com/r/marcelstoer/nodemcu-build/

This Docker image includes the build toolchain and SDK. You just run the Docker image with your checked-out NodeMCU firmware repository (this one).

You will need to see BUILD OPTIONS below, to configure the firmware before building.

Build it yourself

See BUILD OPTIONS below, to configure the firmware before building.

Minimum requirements:
Build instructions:

Assuming NodeMCU firmware is checked-out to /opt/nodemcu-firmware:

clone --recursive https://github.com/pfalcon/esp-open-sdk.git /opt/esp-open-sdk
opt/esp-open-sdk
 STANDALONE=y
=/opt/esp-open-sdk/xtensa-lx106-elf/bin:$PATH
opt/nodemcu-firmware

BUILD OPTIONS

Disable modules you won't be using, to reduce firmware size on flash and free more RAM. The ESP8266 is quite limited in available RAM, and running out can cause a system panic.

Edit app/include/user_modules.h

Comment-out the #define statement for unused modules. Example:

ef LUA_USE_MODULES
ine LUA_USE_MODULES_NODE
ine LUA_USE_MODULES_FILE
ine LUA_USE_MODULES_GPIO
ine LUA_USE_MODULES_WIFI
ine LUA_USE_MODULES_NET
ine LUA_USE_MODULES_PWM
ine LUA_USE_MODULES_I2C
ine LUA_USE_MODULES_SPI
ine LUA_USE_MODULES_TMR
ine LUA_USE_MODULES_ADC
ine LUA_USE_MODULES_UART
ine LUA_USE_MODULES_OW
ine LUA_USE_MODULES_BIT
ine LUA_USE_MODULES_MQTT
define LUA_USE_MODULES_COAP
define LUA_USE_MODULES_U8G
define LUA_USE_MODULES_WS2801
define LUA_USE_MODULES_WS2812
define LUA_USE_MODULES_CJSON
ine LUA_USE_MODULES_CRYPTO
ine LUA_USE_MODULES_RC
ine LUA_USE_MODULES_DHT
ine LUA_USE_MODULES_RTCMEM
ine LUA_USE_MODULES_RTCTIME
ine LUA_USE_MODULES_RTCFIFO
ine LUA_USE_MODULES_SNTP
define LUA_USE_MODULES_BMP085
ine LUA_USE_MODULES_TSL2561
define LUA_USE_MODULES_HX711

if /* LUA_USE_MODULES */
Tagging your build

Identify your firmware builds by editing app/include/user_version.h

ine NODE_VERSION    "NodeMCU 1.4.0+myname"
def BUILD_DATE
ine BUILD_DATE        "YYYYMMDD"
if
Setting the boot time serial interface rate

The initial baud rate at boot time is 9600 bps, but you can change this by editing app/include/user_config.h and change BIT_RATE_DEFAULT, e.g.:

ine BIT_RATE_DEFAULT BIT_RATE_115200
Debugging

To enable runtime debug messages to serial console, edit app/include/user_config.h

ine DEVELOP_VERSION

DEVELOP_VERSION changes the startup baud rate to 74880.

Flash the firmware

Flash tools for Windows

You can use the nodemcu-flasher to burn the firmware.

Flash tools for Linux

Esptool is a python utility which can read and write the flash in an ESP8266 device. See https://github.com/themadinventor/esptool

Preparing the hardware for firmware upgrade

To enable ESP8266 firmware flashing, the GPIO0 pin must be pulled low before the device is reset. Conversely, for a normal boot, GPIO0 must be pulled high or floating.

If you have a NodeMCU Development Kit then you don't need to do anything, as the USB connection can pull GPIO0 low by asserting DTR, and reset your board by asserting RTS.

If you have an ESP-01 or other device without inbuilt USB, you will need to enable flashing yourself by pulling GPIO0 low or pressing a “flash” switch.

Files to burn to the flash

If you got your firmware from NodeMCU custom builds then you can flash that file directly to address 0x00000.

Otherwise, if you built your own firmware from source code:

Also, in some special circumstances, you may need to flash blank.bin or esp_init_data_default.bin to various addresses on the flash (depending on flash size and type).

If upgrading from spiffs version 0.3.2 to 0.3.3 or later, or after flashing any new firmware (particularly one with a much different size), you may need to run file.format() to re-format your flash filesystem. You will know if you need to do this because your flash files disappeared, or they exist but seem empty, or data cannot be written to new files.

Connecting to your NodeMCU device

NodeMCU serial interface uses 9600 baud at boot time. To increase the speed after booting, issue uart.setup(0,115200,8,0,1,1) (ESPlorer will do this automatically when changing the speed in the dropdown list).

If the device panics and resets at any time, errors will be written to the serial interface at 115200 bps.

User Interface tools

Esplorer

Victor Brutskiy's ESPlorer is written in Java, is open source and runs on most platforms such as Linux, Windows, Mac OS, etc.

Features
NodeMCU Studio

NodeMCU Studio is written in C# and supports Windows. This software is open source and can write lua files to filesystem.

OPTIONAL MODULES

Use DS18B20 module extends your esp8266
-- read temperature with DS18B20
node.compile("ds18b20.lua")   --  run this only once to compile and save to "ds18b20.lc"
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
Operate a display with u8glib

u8glib is a graphics library with support for many different displays. The nodemcu firmware supports a subset of these. Both I2C and SPI:

SPI only:

U8glib v1.18.1

I2C connection

Hook up SDA and SCL to any free GPIOs. Eg. u8g_graphics_test.lua expects SDA=5 (GPIO14) and SCL=6 (GPIO12). They are used to set up nodemcu's I2C driver before accessing the display:

= 5
= 6
setup(0, sda, scl, i2c.SLOW)
SPI connection

The HSPI module is used, so certain pins are fixed:

All other pins can be assigned to any available GPIO:

Also refer to the initialization sequence eg in u8g_graphics_test.lua:

setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
Library usage

The Lua bindings for this library closely follow u8glib's object oriented C++ API. Based on the u8g class, you create an object for your display type.

SSD1306 via I2C:

= 0x3c
 = u8g.ssd1306_128x64_i2c(sla)

SSD1306 via SPI:

= 8 -- GPIO15, pull-down 10k to GND
= 4 -- GPIO2
= 0 -- GPIO16, RES is optional YMMV
 = u8g.ssd1306_128x64_hw_spi(cs, dc, res)

This object provides all of u8glib's methods to control the display. Again, refer to u8g_graphics_test.lua to get an impression how this is achieved with Lua code. Visit the u8glib homepage for technical details.

Displays

I2C and HW SPI based displays with support in u8glib can be enabled. To get access to the respective constructors, add the desired entries to the I2C or SPI display tables in app/include/u8g_config.h:

ine U8G_DISPLAY_TABLE_I2C                   \
U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_i2c) \

ine U8G_DISPLAY_TABLE_SPI                      \
U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_hw_spi) \
U8G_DISPLAY_TABLE_ENTRY(pcd8544_84x48_hw_spi)  \
U8G_DISPLAY_TABLE_ENTRY(pcf8812_96x65_hw_spi)  \

An exhaustive list of available displays can be found in the u8g module wiki entry.

Fonts

u8glib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in app/include/u8g_config.h and recompile. Simply add the desired fonts to the font table:

ine U8G_FONT_TABLE \
U8G_FONT_TABLE_ENTRY(font_6x10)  \
U8G_FONT_TABLE_ENTRY(font_chikita)

They'll be available as u8g.<font_name> in Lua.

Bitmaps

Bitmaps and XBMs are supplied as strings to drawBitmap() and drawXBM(). This off-loads all data handling from the u8g module to generic methods for binary files. See u8g_bitmaps.lua. In contrast to the source code based inclusion of XBMs into u8glib, it's required to provide precompiled binary files. This can be performed online with Online-Utility's Image Converter: Convert from XBM to MONO format and upload the binary result with nodemcu-uploader.py.

Unimplemented functions Operate a display with ucglib

Ucglib is a graphics library with support for color TFT displays.

Ucglib v1.3.3

SPI connection

The HSPI module is used, so certain pins are fixed:

All other pins can be assigned to any available GPIO:

Also refer to the initialization sequence eg in GraphicsTest.lua:

setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
Library usage

The Lua bindings for this library closely follow ucglib's object oriented C++ API. Based on the ucg class, you create an object for your display type.

ILI9341 via SPI:

= 8 -- GPIO15, pull-down 10k to GND
= 4 -- GPIO2
= 0 -- GPIO16, RES is optional YMMV
 = ucg.ili9341_18x240x320_hw_spi(cs, dc, res)

This object provides all of ucglib's methods to control the display. Again, refer to GraphicsTest.lua to get an impression how this is achieved with Lua code. Visit the ucglib homepage for technical details.

Displays

To get access to the display constructors, add the desired entries to the display table in app/include/ucg_config.h:

ine UCG_DISPLAY_TABLE                          \
UCG_DISPLAY_TABLE_ENTRY(ili9341_18x240x320_hw_spi, ucg_dev_ili9341_18x240x320, ucg_ext_ili9341_18) \
UCG_DISPLAY_TABLE_ENTRY(st7735_18x128x160_hw_spi, ucg_dev_st7735_18x128x160, ucg_ext_st7735_18) \
Fonts

ucglib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in app/include/ucg_config.h and recompile. Simply add the desired fonts to the font table:

ine UCG_FONT_TABLE                              \
UCG_FONT_TABLE_ENTRY(font_7x13B_tr)             \
UCG_FONT_TABLE_ENTRY(font_helvB12_hr)           \
UCG_FONT_TABLE_ENTRY(font_helvB18_hr)           \
UCG_FONT_TABLE_ENTRY(font_ncenR12_tr)           \
UCG_FONT_TABLE_ENTRY(font_ncenR14_hr)

They'll be available as ucg.<font_name> in Lua.

Control a WS2812 based light strip
-- set the color of one LED on GPIO2 to red
ws2812.writergb(4, string.char(255, 0, 0))
-- set the color of 10 LEDs on GPIO0 to blue
ws2812.writergb(3, string.char(0, 0, 255):rep(10))
-- first LED green, second LED white
ws2812.writergb(4, string.char(0, 255, 0, 255, 255, 255))
coap client and server
se copper addon for firefox
oap.Server()
isten(5683)

r=1
ar("myvar") -- get coap://192.168.18.103:5683/v1/v/myvar will return the value of myvar: 1

'[1,2,3]'
ar("all", coap.JSON) -- sets content type to json

unction should tack one string, return one string.
tion myfun(payload)
int("myfun called")
spond = "hello"
turn respond

unc("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun

 coap.Client()
et(coap.CON, "coap://192.168.18.100:5683/.well-known/core")
ost(coap.NON, "coap://192.168.18.100:5683/", "Hello")
cjson
ote that when cjson deal with large content, it may fails a memory allocation, and leaks a bit of memory.
o it's better to detect that and schedule a restart.

ranslate Lua value to/from JSON
ext = cjson.encode(value)
alue = cjson.decode(text)
_text = '[ true, { "foo": "bar" } ]'
e = cjson.decode(json_text)
eturns: { true, { foo = "bar" } }
e = { true, { foo = "bar" } }
_text = cjson.encode(value)
eturns: '[true,{"foo":"bar"}]'
Read an HX711 load cell ADC.

Note: currently only chanel A with gain 128 is supported. The HX711 is an inexpensive 24bit ADC with programmable 128x, 64x, and 32x gain.

-- Initialize the hx711 with clk on pin 5 and data on pin 6
hx711.init(5,6)
-- Read ch A with 128 gain.
raw_data = hx711.read(0)
Universal DHT Sensor support

Support DHT11, DHT21, DHT22, DHT33, DHT44, etc. Use all-in-one function to read DHT sensor.

= 5
us,temp,humi,temp_decimial,humi_decimial = dht.readxx(pin)
status == dht.OK ) then
 Integer firmware using this example
int(
string.format(
  "DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
  math.floor(temp),
  temp_decimial,
  math.floor(humi),
  humi_decimial
)

 Float firmware using this example
int("DHT Temperature:"..temp..";".."Humidity:"..humi)
if( status == dht.ERROR_CHECKSUM ) then
int( "DHT Checksum error." );
if( status == dht.ERROR_TIMEOUT ) then
int( "DHT Time out." );

=======

Well hello there!

This repository is meant to provide an example for forking a repository on GitHub.

Creating a fork is producing a personal copy of someone else's project. Forks act as a sort of bridge between the original repository and your personal copy. You can submit Pull Requests to help make other people's projects better by offering your changes up to the original project. Forking is at the core of social coding at GitHub.

After forking this repository, you can make some changes to the project, and submit a Pull Request as practice.

For some more information on how to fork a repository, check out our guide, “Forking Projects””. Thanks! :sparkling_heart:

upstream/master


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.