Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Agus Kurniawan
Depok, July 2015
1. Preparing Development Environment
1.1 NodeMCU
NodeMCU is an open source IoT platform. It uses the Lua scripting language. NodeMCU
was created shortly after the ESP8266 came out. Further information, you can read it
on http://nodemcu.com/index_en.html . The following is a form of NodeMCU v2.
You can buy this product on your local electronic store. The following is the list of
Arduino store you can buy
SeeedStudio, http://www.seeedstudio.com/
Amazon, http://www.amazon.com
eBay, http://www.ebay.com
Banggood, http://www.banggood.com/
DX, http://www.dx.com/
1.2 Electronics Components
We need electronic components to build our testing, for instance, Resistor, LED, sensor
devices and etc. I recommend you can buy electronic component kit. We can use
electronics kit from Arduino to be developed on NodeMCU. The following is a list of
electronics kit which can be used in our case.
1.2.2 Fritzing
Store website: http://shop.fritzing.org/ .
You can buy Fritzing Starter Kit with Arduino UNO or Fritzing Starter Kit with Arduino
Mega.
1.2.3 Cooking-Hacks: Arduino Starter Kit
Store website: http://www.cooking-hacks.com/index.php/shop/arduino/starter-
kits/arduino-starter-kit.html
1.2.4 Arduino Sidekick Basic kit v2
Store website: http://www.seeedstudio.com/depot/Sidekick-Basic-Kit-for-Arduino-V2-p-
1858.html
You also can find this kit on this online store.
http://www.exp-tech.de/seeed-studio-sidekick-basic-kit-for-arduino-v2
1.2.5 Grove - Starter Kit for Arduino
Another option, you can buy this kit on Seeedstudio,
http://www.seeedstudio.com/depot/Grove-Starter-Kit-for-Arduino-p-1855.html .
If you are working on Windows platform, open Device Manager, you should see
NodeMCU board detected on Ports (COM & LPT).
However, if you get a problem about NodeMCU hardware driver, you update that driver.
You also can install a driver from Silicon Labs because NodeMCU v2 uses this chip,
from https://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx .
Please download it based on your platform.
For instance, you download the driver for mac. Just follow instructions.
After installed, you verify it. For instance, on my OS X it has detected. Type this
command.
ls /dev/cu*
In this case, we must flash the latest NodeMCU firmware. I will explain it on the next
section.
2.3 Flashing The Latest NodeMCU Firmware
In this section, we try to flash the latest NodeMCU firmware. You can get the latest
NodeMCU firmware on https://github.com/nodemcu/nodemcu-firmware . Download *.bin
file.
In this scenario, I try to flash NodeMCU firmware on Windows, OSX and Linux.
To test, you can use serial/UART tool and connect to NodeMCU board. Set NodeMCU
serial port and set baudrate 9600.
Then, connect to the board. If success, you should see NodeMCU shell.
Try to write a simple script print(Hello NodeMCU) so you will get a response.
After running, wine directory has created. Navigate to dosdevices folder and create a
symlink to your NodeMCU tty device. For instance, on OS X my NodeMCU has detected
on /dev/tty.SLAB_USBtoUART so I map it to com1 .
$ cd ~/.wine/dosdevices
$ ln -s /dev/tty.SLAB_USBtoUART com1
After installed, you can see a list of ESP8266 Modules target on Arduino IDE.
Now you can write the program for NodeMCU.
2.5.1 Wiring
Connect LED on NodeMCU D1. Other LED pin is be connected to NodeMCU GND.
Now you connect NodeMCU board to Computer via USB cable.
2.5.2 Writing Program Using Serial/UART Tool
The first demo is to blink a LED. Type this script per lin on Serial/UART tool.
-- hello.lua
pin = 1
gpio.mode(pin,gpio.OUTPUT)
gpio.write(pin,gpio.HIGH)
print(gpio.read(pin))
gpio.write(pin,gpio.LOW)
This script will turn on a LED on D1 and then turn off it.
If you should see lighting LED after executed gpio.write(pin, gpio.HIGH).
You should see a blinking LED. If you want to stop, you can press RST button on
NodeMCU board.
Remove sudo if youre working on Windows platform. Just run Command Prompt with
Administrator level.
Now you can download this tool using wget or download it directly on Github website.
$ wget https://raw.githubusercontent.com/4refr0nt/luatool/master/luatool/luato
$ wget https://raw.githubusercontent.com/4refr0nt/luatool/master/luatool/init.
$ wget https://raw.githubusercontent.com/4refr0nt/luatool/master/luatool/main.
If your installed Python is python, then change code on the top of script, from this script.
#!/usr/bin/env python2
For testing, I use blinking led from section 2.5.2. Save that script into a file, called
blinking_led.lua.
Type this command to upload to NodeMCU board.
$ ./luatool.py --port /dev/cu.SLAB_USBtoUART --src blinking_led.lua --dest bli
Change port parameter based on your attached NodeMCU board, for instance, COM5,
/dev/ttyAM0.
If done, this file will be available on NodeMCU.
To execute this file, connect to NodeMCU via serial tool and type this command.
> dofile("blinking_led.lua")
If you want to upload and execute Lua script file, you can add dofile parameter on your
command.
Type this command.
$ ./luatool.py --port /dev/cu.SLAB_USBtoUART --src blinking_led.lua --dest bli
This command will upload Lua file and then execute it.
If you modified codes and upload the file again, you must press RST to make sure
NodeMCU doesnt keep your file.
Sometimes you want your program run after NodeMCU restarts, you can write Lua file
with named main.lua. This file will be executed by NodeMCU. Warning!! if your main.lua
is error, you will get problem on NodeMCU.
3. Lua Programming Language
This chapter explains the basic of Lua programming language. If you already know about
Lua programming, you can skip this chapter.
3.1 Preparing Development Environment
To work with Lua development, we must install Lua compiler and its runtime. You can
download it on http://www.lua.org based your platform. For OS X user, you can install it
via brew.
$ brew install lua
After installed, you can execute Lua and run some Lua syntax.
$ lua
> print("Hello Lua")
> a = 5 + 8
> print(a)
If you want to quit from Lua shell, you can press CTRL+D keys.
3.2 Common Rule
You can write Lua script without ending ; at the end of syntax. Here is the syntax rule:
syntax_code1
syntax_code2
syntax_code3
3.3 Variables
In this section, we explore how to define a variable and assign its value.
Once declared, these variables can be used to store any type data.
3.3.3 Demo
For illustration for declaring variables using Lua, create a file, called basic.lua.
Write the following script for basic.lua.
-- this a simple script for Lua
-- declare variables
local city
local m, n
-- assignment
city = "Berlin"
m = 2
n = 5
print(city)
print(m)
print(n)
print(a)
print(str)
print(p)
print(q)
a = 3
b = 2.4
c = a + b
d = a - b
e = a / b
f = a * b
print(c)
print(d)
print(e)
print(f)
a = 2.5
b = 1.6
c = math.pow(a,2)
d = math.sin(a)
e = math.cos(b)
f = math.sqrt(a * b)
g = math.pi
print(c)
print(d)
print(e)
print(f)
print(g)
increment a = a + 1
decrement. a = a - 1
a = 4
print(a)
-- increment
a = a + 1
print(a)
-- decrement
a = a - 3
print(a)
a = 3
b = 10
print(a < b)
print(a > b)
print(a <= b)
print(a >= b)
print(a == b)
print(a ~= b)
Sample code:
-- logical operators
a = 3
b = 4
Save this script into a file, called logical.lua. Build and run it.
A sample output of the program can be seen in Figure below.
3.10 Decision - if..then
Syntax model for if..then can be formulated as below:
if conditional then
-- do something
else
-- do something
end
a = 3
if a>1 then
print("a>1")
b = 3
print(b)
else
print("a<1")
b = 10
print(b)
end
end
Save this code into a file, called whiledemo.lua. Build and run it.
A sample output of the program can be seen in Figure below.
3.13 Iteration - repeat
Lua also provides repeat syntax to do looping. For a sample demo, type these scripts.
n = 5
repeat
print(n)
n = n + 1
until n > 12
print(cities)
print("length:",#cities)
print(cities[3])
print("length numbers:",#numbers)
print(numbers[5])
function add(a,b)
return a + b
end
print("---function demo---")
foo()
c = add(10, 5)
print(c)
function compute(a, b, c)
return a + b - c
end
Then, we call simplemodule.lua on our code. Create a file, called loadmodule.lua and
write these scripts.
require("simplemodule")
print("--load module--")
res = add(10, 4)
print(res)
c = compute(5, 6, 8)
print(c)
In this chapter Im going to explain how to work with GPIO on NodeMCU and write a
program.
4.1 Getting Started
In general, GPIO can be used to control digital I/O on NodeMCU. We can use gpio.read()
to read GPIO value and gpio.write() to write HIGH/LOW to GPIO pins. Firstly, we define
our GPIO mode using gpio.mode(). It can be either GPIO output or GPIO input. A list of
NodeMCU API can be read on this site, https://github.com/nodemcu/nodemcu-
firmware/wiki/nodemcu_api_en .
In this chapter, we build a program to illustrate how NodeMCU GPIO work. We need a
LED and a pushbutton.
Lets start!.
4.2 Wiring
Connect LED to D1 on Arduino and pushbutton to D2. The following is a sample of
wiring.
4.3 Writing a Program
To create a program, we just create a new Lua file, called gpiodemo.lua. Then, write these
scripts.
led = 1
pushbutton = 2
gpio.mode(led,gpio.OUTPUT)
gpio.mode(pushbutton,gpio.INPUT)
while 1 do
state = gpio.read(pushbutton)
if state==0 then
gpio.write(led,gpio.LOW)
else
gpio.write(led,gpio.HIGH)
end
print(state)
tmr.delay(1000000)
end
You also see the program output if you connect to NodeMCU board via Serial app.
5. PWM and Analog Input
In this chapter, we try to access NodeMCU Analog I/O using Lua program. There are two
scenarios for our cases:
Lets start.
5.2 Demo Analog Output (PWM) : RGB LED
In this scenario we build a Lua program to control RGB LED color using NodeMCU
Analog output (PWM). RGB LED has 4 pins that you can see it on Figure below.
Note:
Pin 1: Red
Pin 2: Common pin
Pin 3: Green
Pin 4: Blue
5.2.1 Wiring
For our testing, we configure the following PWM pins.
function set_rgb(r, g, b)
print(r,g,b)
pwm.setup(red, 100, r)
pwm.setup(green, 100, g)
pwm.setup(blue, 100, b)
pwm.start(red)
pwm.start(green)
pwm.start(blue)
end
function stop_all_pwm()
pwm.stop(red)
pwm.stop(green)
pwm.stop(blue)
end
while 1 do
print("red")
set_rgb(0, 1023, 1023)
tmr.delay(1000000)
stop_all_pwm()
print("green")
set_rgb(1023, 0, 1023)
tmr.delay(1000000)
print("blue")
set_rgb(1023, 1023, 0)
tmr.delay(1000000)
print("yellow")
set_rgb(0, 0, 1023)
tmr.delay(1000000)
print("purple")
set_rgb(700, 1023, 700)
tmr.delay(1000000)
print("aqua")
set_rgb(1023, 0, 0)
tmr.delay(1000000)
end
This program will generate six colors: red, green, blue, yellow, purple, and aqua.
Save this file.
5.2.3 Testing
Upload and run the program. You should see several color on RGB LED.
The following is a sample demo on RGB LED.
If you connect to NodeMCU board via Serial app, you should get program output, shown
in Figure below.
5.3 Demo Analog Input: Working with Potentiometer
In this section, we learn how to read analog input on NodeMCU board. For illustration, I
use Potentiometer as analog input source. Our scenario is to read analog value from
Potentiometer. Then, display it on Lua shell.
NodeMCU v2 only has one ADC on A0. If you want to work with many analog input, you
must expand it using ICs based ADC. In this section, we are working on NodeMCU ADC
on A0.
Lets start!.
5.3.1 Wiring
To understand Potentiometer, you see its scheme in Figure below.
You can connect VCC to NodeMCU board on 3V3 pin (VCC +3.3V). Vout to NodeMCU
board Analog input A0. In addition, GND to NodeMCU board GND. The following is
hardware implementation. I use slide potentiometer.
5.3.2 Writing Program
Firstly, create a file, called adcdemo.lua. To read analog input, we can use adc.read()
function. Ok, Lets write these scripts.
print("ADC demo")
while 1 do
print("reading")
val = adc.read(0)
print("Analog: ",val)
tmr.delay(1000000)
end
5.3.3 Testing
Upload and run this program. If success, you can see analog value on Serial app.
6. Working with I2C
In this chapter we learn how to work with I2C on NodeMCU board using Lua script.
6.1 Getting Started
The I2C (Inter-Integrated Circuit) bus was designed by Philips in the early 80s to allow
easy communication between components which reside on the same circuit board. TWI
stands for Two Wire Interface and for most marts this bus is identical to IC. The name
TWI was introduced by Atmel and other companies to avoid conflicts with trademark
issues related to IC.
I2C bus consists of two wires, SDA (Serial Data Line) and SCL (Serial Clock Line).
NodeMCU v2 has I2C/TWI on SD0 (SDA), SD1 (SDA), SD2 (SDA), SD3 (SDA) and
CLK (SCL).
For testing, I used PCF8591 AD/DA Converter module with sensor and actuator devices.
You can find it on the following online store:
Amazon, http://www.amazon.com/PCF8591-Converter-Module-Digital-
Conversion/dp/B00BXX4UWC/
eBay, http://www.ebay.com
Dealextreme, http://www.dx.com/p/pcf8591-ad-da-analog-to-digital-digital-to-
analog-converter-module-w-dupont-cable-deep-blue-336384
Aliexpress, http://www.aliexpress.com/
In addition, you can find this device on your local electronics store/online store.
This module has mini form model too, for instance, you can find it on Amazon,
http://www.amazon.com/WaveShare-PCF8591T-Converter-Evaluation-
Development/dp/B00KM6X2OI/ .
This module use PCF8591 IC and you can read the datasheet on the following URLs.
http://www.electrodragon.com/w/images/e/ed/PCF8591.pdf
http://www.nxp.com/documents/data_sheet/PCF8591.pdf
I usually use this module to test I2C but NodeMCU v2 firmware doesnt support with I2C
address 0x90. Basically you can modify firmware code and then built it.
In this chapter, we build a program to access sensor via I2C using Lua script and use
Arduino as I2C slave. We can use any pin on NodeMCU GPIO for I2C using I2c library
from NodeMCU firmware.
6.2 Writing Program
We use Arduino Uno as I2C source. You can connect Arduino Uno to NodeMCU board
directly.
The following is our wiring lab:
void sendData(){
byte data = randomDigit();
data = data + 30;
Wire.write(data);
Serial.println(data);
}
void setup() {
pinMode(led, OUTPUT);
Serial.begin(9600);
Wire.begin(SLAVE_ADDRESS);
TWBR = 152; // 50 kHz speed
Wire.onRequest(sendData);
}
void loop() {
delay(500);
}
Save this code. Compile and upload this program to Arduino board.
Now you can start to write a Lua program for NodeMCU. Create a file, called i2cdemo.lua
and write these scripts.
id=0
sda=1
scl=2
ARDUINO_I2C = 0x15
i2c.setup(id,sda,scl,i2c.SLOW)
function read_data(id,dev_addr)
i2c.start(id)
i2c.address(id, dev_addr,i2c.RECEIVER)
c = i2c.read(id,1)
c = i2c.read(id,1)
i2c.stop(id)
return c
end
print("I2C demo")
while 1 do
val = read_data(id, ARDUINO_I2C)
print("RCV: ",string.byte(val))
tmr.delay(1000000)
end
You also can see the Arduino output using Serial Monitor.
7. UART
In this chapter, I use Arduino board as UART source. We read incoming message from
UART.
Lets start!.
7.2 Wiring
In this scenario, I use Arduino Uno which is connected to NodeMCU board. The
following is our wiring.
void setup()
{
Serial.begin(9600);
mySerial.begin(9600);
}
void loop()
{
if (mySerial.available() > 0) {
Serial.write(mySerial.read());
}
}
Save this program. Then, upload it to Arduino board. Before uploading, please make sure
Arduino UART (digital 0, 1, 10, and 11 pins) doesnt connect to any board.
The next step is to write a program for NodeMCU board. Create a file, called
uartdemo.lua. Write these scripts.
uart.setup(0, 9600, 8, 0, 1, 0)
val = 65
-- looping
while 1 do
uart.write(0,string.char(val),"\r\n")
val = val + 1
if val>90 then
val = 65
end
tmr.delay(1000000)
end
In this chapter Im going to explain how to work with SPI on NodeMCU board.
8.1 Getting Started
The Serial Peripheral Interface (SPI) is a communication bus that is used to interface one
or more slave peripheral integrated circuits (ICs) to a single master SPI device; usually a
microcontroller or microprocessor of some sort.
SPI in NodeMCU board can be defined on the following pins:
MOSI
MISO
SCK
You can see these pins on S NodeMCU board, shown in Figure below.
We can only use one SPI on NodeMCU board with SPI master mode. If were working on
SPI, we cant access UART on the board. In this chapter, I use Arduino board as SPI slave.
Lets start!.
8.2 Wiring
To work both SPI and UART/USB, we dont connect MISO pin. For testing, I use Arduino
board. Do wiring as follows.
NodeMCU MOSI (SD1) pin is connected to Arduino MOSI (Digital 11) pin
NodeMCU SCLK (CLK) pin is connected to Arduino SCK (Digital 13) pin
NodeMCU GND pin is connected to Arduino GND pin
NodeMCU CS (CMD) pin is connected to Arduino SS (Digital 10) pin
char buf;
volatile byte pos;
volatile boolean isAvailable;
void setup() {
Serial.begin (9600); // for debugging
// SPI slave mode
SPCR |= bit (SPE);
SPCR |= _BV(SPIE);
isAvailable = false;
pos = 0;
pinMode(MISO, OUTPUT);
SPI.attachInterrupt();
}
ISR (SPI_STC_vect)
{
byte c = SPDR;
if(c>64 && c<91){
buf = c;
isAvailable = true;
}
}
void loop() {
if(isAvailable){
Serial.println (buf);
isAvailable = false;
}
}
This program does wait incoming data from SPI master and then display the received data
to Arduino Serial so we can see it on Serial Monitor.
Save this program as Arduino_spi. Build and upload the program to Arduino board.
The next step is to write a program for NodeMCU. Create a file, called spidemo.lua, and
write these scripts.
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
val = 65
while 1 do
spi.send(1,string.char(val))
print(string.char(val))
val = val + 1
if val>90 then
val = 65
end
tmr.delay(1000000)
end
If you connect to NodeMCU board via Serial tool, you should see the program output too.
9. Working with OLED Display
Lets start!.
9.2 Wiring
The following is our wiring:
function box_frame(a)
disp:drawStr(0, 0, "drawBox")
disp:drawBox(5, 10, 20, 10)
disp:drawBox(10+a, 15, 30, 7)
disp:drawStr(0, 30, "drawFrame")
disp:drawFrame(5, 10+30, 20, 10)
disp:drawFrame(10+a, 15+30, 30, 7)
end
function disc_circle(a)
disp:drawStr(0, 0, "drawDisc")
disp:drawDisc(10, 18, 9)
disp:drawDisc(24+a, 16, 7)
disp:drawStr(0, 30, "drawCircle")
disp:drawCircle(10, 18+30, 9)
disp:drawCircle(24+a, 16+30, 7)
end
function r_frame(a)
disp:drawStr(0, 0, "drawRFrame/Box")
disp:drawRFrame(5, 10, 40, 30, a+1)
disp:drawRBox(50, 10, 25, 40, a+1)
end
function stringtest(a)
disp:drawStr(30+a, 31, " 0")
disp:drawStr90(30, 31+a, " 90")
disp:drawStr180(30-a, 31, " 180")
disp:drawStr270(30, 31-a, " 270")
end
function line(a)
disp:drawStr(0, 0, "drawLine")
disp:drawLine(7+a, 10, 40, 55)
disp:drawLine(7+a*2, 10, 60, 55)
disp:drawLine(7+a*3, 10, 80, 55)
disp:drawLine(7+a*4, 10, 100, 55)
end
function triangle(a)
local offset = a
disp:drawStr(0, 0, "drawTriangle")
disp:drawTriangle(14,7, 45,30, 10,40)
disp:drawTriangle(14+offset,7-offset, 45+offset,30-offset, 57+offset,
disp:drawTriangle(57+offset*2,10, 45+offset*2,30, 86+offset*2,53)
disp:drawTriangle(10+offset,40+offset, 45+offset,30+offset, 86+offset,
end
function ascii_1()
local x, y, s
disp:drawStr(0, 0, "ASCII page 1")
for y = 0, 5, 1 do
for x = 0, 15, 1 do
s = y*16 + x + 32
disp:drawStr(x*7, y*10+10, string.char(s))
end
end
end
function extra_page(a)
disp:drawStr(0, 12, "setScale2x2")
disp:setScale2x2()
disp:drawStr(0, 6+a, "setScale2x2")
disp:undoScale()
end
prepare()
if (component == 0) then
box_frame(bit.band(draw_state, 7))
elseif (component == 1) then
disc_circle(bit.band(draw_state, 7))
elseif (component == 2) then
r_frame(bit.band(draw_state, 7))
elseif (component == 3) then
stringtest(bit.band(draw_state, 7))
elseif (component == 4) then
line(bit.band(draw_state, 7))
elseif (component == 5) then
triangle(bit.band(draw_state, 7))
elseif (component == 6) then
ascii_1()
elseif (component == 7) then
extra_page(bit.band(draw_state, 7))
end
end
function graphics_test(delay)
print("--- Starting Graphics Test ---")
init_i2c_display()
graphics_test(50000)
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
print("connecting")
wifi.sta.connect()
ip = wifi.sta.getip()
print("IP: ",ip)
Change SSID and password values. Save this code into a file called network.lua.
Upload this program. Then, run it via Serial program so you can see NodeMCUs IP
Address.
10.2 Building a Simple Web Server
The second demo is to build a simple web server. Write this code.
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
print("connecting")
wifi.sta.connect()
ip = wifi.sta.getip()
print("IP: ",ip)
srv = net.createServer(net.TCP)
srv:listen(80, function(conn)
conn:on("receive",function(conn,payload)
print(payload)
conn:send("HTTP/1.1 200/OK\r\nServer: NodeMCU\r\nContent-Type: text/html
conn:send("<html><head><title>NodeMCU</title></head><body><p>Hello, NodeMc
end)
conn:on("sent",function(conn) conn:close() end)
end)
Change SSID and password values. Save this code into a file called webserver.lua.
Upload this program. Then, run it via Serial program so you can see NodeMCUs IP
Address.
Open a browser and navigate to IP address of NodeMCU.