반응형

NodeMCU 펌웨어에는 많은 모듈들이 포함되어 있다. 하지만 사용하지 않을 모듈을 포함하는 것은 용량상으로나 기능적으로 낭비가 아닐 수 없다. 이럴 경우 사용을 원하는 모듈만 포함시켜서 펌웨어를 생성할 수 있는 사이트가 있어서 소개한다. 바로 NodeMCU Build 라는 사이트 이다.  NodeMCU 모듈에 대한 설명은 NodeMCU Documentation 사이트인https://nodemcu.readthedocs.io/en/dev/ 사이트에서 볼 수 있다.




NodeMCU Custom Build 사이트 

https://nodemcu-build.com



https://nodemcu-build.com 사이트로 이동하면... 


이메일로 빌드된 펌웨어 링크를 보내주므로 이메일을 적어준다. 확인을 위해서 두 번 적어준다.


master 와 dev 중에 빌드 브랜치를 고를 수 있다. 특이사항이 없다면 master를 선택해 준다.


여기가 중요하다. 포함하기를 원하는 모듈을 고를 수 있다. 필요한 모듈을 모두 체크해 준다. 가장 기본적인 모듈은 미리 체크가 되어 있으므로 웬만하면 포함하도록 하자


SSL 지원기능을 사용하는지? 디버그 모드를 ON 할 것인지 선택한다.


모든 사항을 입력했으면 맨 아래의 Start your build 를 클릭한다.


위의 화면이 나오면 펌웨어의 빌드가 시작된 것이다. 이제 메일이 오기를 기다리면 된다. 경우에 따라 다르겠지만 나 같은 경우는 메일이 오는데 10분 정도 걸린 것 같다. 네이버 메일 등을 이용할 경우 스팸메일함에 들어가 있을 확율이 높으므로 스팸메일함도 확인을 해 보자


위와 같이 빌드 시작되었다는 메일과 약 2분 후 빌드가 완료 되었다는 메일이 도착했다.


빌드완료 메일을 클릭하면 위와 같이 빌드가 완료된 펌웨어를 다운로드 받을 수 있는 링크를 보내준다. float, integer 버전 중 원하는 것을 다운로드 받아서 ESP8266 하드웨어에 펌웨어를 올리면 된다.


다운로드 받은 펌웨어를 하드웨어에 올리는 방법 및 Esplorer 개발환경 설치에 대해서는 아래의 링크를 참고하면 된다.

ESP8266 기반 NodeMCU 개발보드에 개발환경 설치

http://deneb21.tistory.com/399


반응형
반응형

NodeMCU 에서도 서보 모터를 제어할 수 있다. 바로 PWM (Pulse Width Modulation, 펄스 폭 변조) 신호를 이용해서 제어가 가능한데 NodeMCU 에서는 pwm 이라는 모듈을 기본으로 제공하고 있기 때문에 이를 이용해서 서보를 제어할 수 있다. 응용한다면 인터넷으로 열고 닫을 수 있는 도어락 같은 것을 만들 수도 있을 것이다. 


PWM 은 간단하게 설명하자면 5V 와 0V 의 신호가 번갈아 반복되는 것인데 이것의 반복되는 사이클을 조절해서 신호를 주는 것이다.


이미지 : https://www.arduino.cc/en/Tutorial/PWM

위의 그래프와 같이 5V 와 0V 가 반복 되는 시간을 변환해서 서보에 신호를 전달하는 것이다.


PWM에 대해서 좀 더 자세한 설명은 아래의 링크를 참고하면 된다.


제어할 모터는 가장 대중적으로 많이 사용되는 SG90 서보 모터를 NodeMCU 펌웨어가 올라간 ESP8266 보드에 연결해서 제어해 보았다.


SG90 서보의 모습이다. 갈색, 빨간색, 노란색의 3가닥의 연결선이 있으며 갈색은 GND, 빨간색은 5V, 노란색은 PWM 신호를 받는 선이다.  


아래와 같이 ESP8266 과 연결하였다. 

 ESP8266

 SG90 (Servo)

 GND

 Brown

 5V

 Red

 D4

 Yellow


내가 연결한 ESP8266 개발 보드인 Wemos D1 mini 보드에는 5V 출력이 있어서 거기에 서보를 연결하면 되지만 3.3V 출력 밖에 없는 보드도 있다. 테스트 삼아 3.3V 에 연결해 보았는데 별 차이 없이 동작하긴 했지만 4.8V 이상에서 동작하는 SG90의 특성 상 5V에 연결해 주는 것이 좋다. 이럴 경우 외부전원(5V)을 서보에 연결해주고 외부전원의 마이너스를 ESP8266의 GND와 서보의 GND에 같이 연결해 주어서 전원을 보강해 주는 것이 좋다.


■ 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
local pin4 = 4
 
-- set pin index 1 as pwm output, frequency is 50Hz, 
print("0")
pwm.setup(pin4, 501024*0.075)
 
-- Position 0
-- 20ms cycle, High duration is 20ms * 7.5= 1.5ms
print("1")
pwm.setduty(pin4, 1024*0.075)
pwm.start(pin4)
tmr.delay(5000000)
pwm.stop(pin4)
 
-- Posigion 90
-- 20ms cycle, High duration is 20ms * 10= 2.0ms
print("2")
pwm.setduty(pin4, 1024*0.1)
pwm.start(pin4)
tmr.delay(5000000)
pwm.stop(pin4)
 
-- Posigion -90
-- 20ms cycle, High duration is 20ms * 5= 1.0ms
print("3")
pwm.setduty(pin4, 1024*0.05)
pwm.start(pin4)
tmr.delay(5000000)
pwm.stop(pin4)
 
-- Position 0
-- 20ms cycle, High duration is 20ms * 7.5= 1.5ms
print("4")
pwm.setduty(pin4, 1024*0.075)
pwm.start(pin4)
tmr.delay(5000000)
pwm.stop(pin4)
 
cs


소스는 NodeMCU 의 pwm 모듈을 이용해서 동작한다. high 상태의 duration 을 이용해서 서보를 제어한다. 아래의 SG90 pdf 문서를 보면 pwm 신호를 어떻게 주면 서보의 움직이는 각도를 조절할 수 있는지 알 수 있을 것이다.

SG90Servo.pdf



NodeMCU PWM 모듈에 대해서는 아래의 링크를 참고하면 된다.


https://nodemcu.readthedocs.io/en/dev/en/modules/pwm/




반응형
반응형

아두이노나 ESP8266 관련 프로그래밍을 하다가 보면 가끔 현재 시간 정보가 필요한 경우가 있다. 이럴 경우 쉽게 사용할 수 있는 방법은 예전에 소개한 바 있는 RTC 모듈(Real Time Clock)이라는 장치를 이용하는 것이다. 하지만 장치가 인터넷에 연결되어 있다면 RTC가 필요 없다. 간단하게 현재의 시각을 알 수 있는 방법이 따로 있기 때문이다. 바로 웹서버에 요청(Request)해서 응답(Response)이 오는 HTTP 헤더 정보에 바로 Date, Time 정보가 있는 것이다. 이 정보를 파싱해서 자신의 코드에 삽입해서 이용하면 된다. 


 

그럼 HTTP 헤더란? 


우리가 사용하는 인터넷은 HTTP (Hyper Text Transfer Protocol) 라는 규약(프로토콜)을 이용해서 서버와 브라우저간에 통신을 하게 되고 정보를 교환하게 되는데 이 때 서버에서 브라우저 쪽으로 덧붙여서 보내주는 정보라고 보면 된다. 이 정보 안에는 Date/Time 정보가 있어서 이 것을 이용하면 현재의 시간을 구할 수 있는 것이다. 실제로 구글 크롬에서 F12 버튼을 누르면 HTTP 헤더 정보를 볼 수 있다.


Chrome 에서 F12 를 눌러서 개발자 도구에서 HTTP 헤더를 보는 모습


ESP8266 을 이용해서 서버에 빈(Empty) 요청을 날리면 위와 같이 웹서버에서 Date 라는 Name 으로 날짜, 시간 정보를 준다. 기준은 그리니치 표준시 기준인 GMT 기준으로 제공하기 때문에 우리나라 시간으로 변환을 원한다면 GMT+9시간을 해야한다.


■ 소스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- retrieve the current time from Google
 
function queryTime()
  conn=net.createConnection(net.TCP, 0
 
  conn:on("connection",function(conn, payload)
    conn:send("HEAD / HTTP/1.1\r\n".. 
               "Host: google.com\r\n"..
               "Accept: */*\r\n"..
               "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)"..
               "\r\n\r\n"
                end)
            
  conn:on("receive", function(conn, payload)
    print('Retrieved in '..((tmr.now()-t)/1000)..' milliseconds.')
    print('Google says it is '..string.sub(payload,string.find(payload,"Date: ")
           +6,string.find(payload,"Date: ")+35))
    conn:close()
    end
  t = tmr.now()    
  conn:connect(80,'google.com')
end
 
tmr.alarm(010 * 10001, function() queryTime() end )
 
print("Queries every 10 sec the time from Google server")
print("Stop this by tmr.stop(0)")
cs


소스는 간단하다. google.com 으로 요청을 날리고 응답받은 HTTP 헤더 정보인 payload 에서 Date 부분을 추출해서 표시해주는 소스이다. 여기서는 google 에 요청했지만 다른 웹서버 URL 을 사용해도 상관이 없다.

 

 

실행결과는 위와 같다. 10초 마다 google 서버의 시간을 받아와서 print 해 주고 있다.


이 정보는 HTTP 헤더 정보인 payload 변수에 담겨져 있는 내용인데 payload 정보도 print 해 보았다. 위와 같이 payload 의 마지막 부분에 Date 가 있는 것을 알 수 있다.


소스에 GMT+9 를 하고 적절한 디스플레이를 연결하면 정확한 시간을 보여줄 수 있는 인터넷 시계도 만들 수 있을 것 같다.

반응형
반응형

'NodeMCU Lua 사용해보기 #12 - 인터넷을 통한 릴레이 제어 #1' 글에서는 어떻게 인터넷을 통해서 릴레이(Relay)를 제어할 수 있는지 알아보았다. 그런데 사용을 하다보면 원격지에서 어떤 릴레이가 현재 ON 상태이고 OFF 상태인지 알 수 있는 방법이 없다. 만약 릴레이에 선풍기를 연결해 두었으면 현재 꺼진 상태인지 켜진 상태인지 알 수가 없는 것이다. 그래서 이번에는 NodeMCU 의 gpio 모듈을 이용해서 현재 릴레이의 상태를 알 수 있도록 소스를 수정해서 개선해 보았다. 이전 글에서 모든 연결과 조건은 동일하며 internet_relay.lua 의 소스만 수정하면 된다.


■ NodeMCU gpio Module Documentation

https://nodemcu.readthedocs.io/en/dev/en/modules/gpio/


위의 NodeMCU Documentation 사이트에 들어가면 gpio 모듈에 대한 설명이 나온다. 이 중에서 gpio.read() 를 이용해서 현재 릴레이의 상태를 알 수 있다.


위의 사이트에 들어가면 나오는 gpio.read() 의 사용설명이다. gpio.read(핀번호) 로 현재 해당 gpio 단자의 상태를 알 수 있다. 0 이면 Low, 1 이면 High 의 상태인 것이다. 릴레이에서는 High가 OFF, Low 가 ON 상태 이므로 릴레이 제어에 사용하는 4개의 gpio 핀의 상태를 읽어서 HTML 에서 출력해 주도록 internet_relay.lua 소스를 수정하면 될 것이다. 


■ 소스

인터넷 연결을 위한 credentials.lua 와 init.lua 의 소스는 이전 1편의 글과 동일하다.  internet_relay.lua 소스만 수정이 되었다. 그래도 모든 소스를 다시 올려 본다.


credentials.lua

1
2
3
4
-- WiFi Connect information
SSID = "WiFi Name(SSID)"
PASSWORD = "WiFi Password"
 
cs


init.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- http://deneb21.tistory.com/
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("WiFi Connected...")
        file.close("init.lua")
        -- the actual application is stored in 'application.lua'
        --dofile("webserver.lua")
        dofile("internet_relay.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
 
cs


internet_relay.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
--http://deneb21.tistory.com/
--Configure relay ouutput pins, pins are floating and relay opto needs ground to be activated. So pins are kept high on startup.
Relay1 = 1
Relay2 = 2
Relay3 = 3
Relay4 = 4
 
gpio.mode(Relay1, gpio.OUTPUT)
gpio.write(Relay1, gpio.HIGH);
gpio.mode(Relay2, gpio.OUTPUT)
gpio.write(Relay2, gpio.HIGH);
gpio.mode(Relay3, gpio.OUTPUT)
gpio.write(Relay3, gpio.HIGH);
gpio.mode(Relay4, gpio.OUTPUT)
gpio.write(Relay4, gpio.HIGH);
 
print("internet relay standby...")
 
--Create server and send html data, process request from html for relay on/off.
srv=net.createServer(net.TCP)
srv:listen(8080,function(conn) --change port number if required. Provides flexibility when controlling through internet.
    conn:on("receive", function(client,request)
        local html_buffer = "";
        local html_buffer1 = "";
        local html_buffer2 = "";
        local gpio1, gpio2, gpio3, gpio4
        
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local _GET = {}
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*"do
                _GET[k] = v
            end
        end
 
        html_buffer = html_buffer.."<html><head><meta http-equiv=\"Content-Language\" content=\"en-us\"><meta http-equiv=\"Content-Type\" content=\"text/html;\">";
        html_buffer = html_buffer.."</head><body><font size=5>Internet Relay1 Control (NodeMCU/Lua, ESP8266)</font></br>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON1\"><button style=\"width:300\">Relay1 ON</button></a><a href=\"?pin=OFF1\"><button style=\"width:300\">Relay1 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON2\"><button style=\"width:300\">Relay2 ON</button></a><a href=\"?pin=OFF2\"><button style=\"width:300\">Relay2 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON3\"><button style=\"width:300\">Relay3 ON</button></a><a href=\"?pin=OFF3\"><button style=\"width:300\">Relay3 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON4\"><button style=\"width:300\">Relay4 ON</button></a><a href=\"?pin=OFF4\"><button style=\"width:300\">Relay4 OFF</button></a><br/>";
    
    
        local _on,_off = "",""
        if(_GET.pin == "ON1")then
              gpio.write(Relay1, gpio.LOW);
        elseif(_GET.pin == "OFF1")then
              gpio.write(Relay1, gpio.HIGH);
        elseif(_GET.pin == "ON2")then
              gpio.write(Relay2, gpio.LOW);
        elseif(_GET.pin == "OFF2")then
              gpio.write(Relay2, gpio.HIGH);
        elseif(_GET.pin == "ON3")then
              gpio.write(Relay3, gpio.LOW);
        elseif(_GET.pin == "OFF3")then
              gpio.write(Relay3, gpio.HIGH);
        elseif(_GET.pin == "ON4")then
              gpio.write(Relay4, gpio.LOW);
        elseif(_GET.pin == "OFF4")then
              gpio.write(Relay4, gpio.HIGH);                            
        end
 
        -- Relay Status Read
        if(gpio.read(1)==0) then gpio1 = "ON" else gpio1 = "OFF" end
        if(gpio.read(2)==0) then gpio2 = "ON" else gpio2 = "OFF" end
        if(gpio.read(3)==0) then gpio3 = "ON" else gpio3 = "OFF" end
        if(gpio.read(4)==0) then gpio4 = "ON" else gpio4 = "OFF" end
 
        -- Relay Status print
        print("gpio1:"..gpio1)
        print("gpio2:"..gpio2)
        print("gpio3:"..gpio3)
        print("gpio4:"..gpio4)
 
        -- Relay Status print html
        html_buffer2 = html_buffer2.."<br/>Relay1 : "..gpio1;
        html_buffer2 = html_buffer2.."<br/>Relay2 : "..gpio2;
        html_buffer2 = html_buffer2.."<br/>Relay3 : "..gpio3;
        html_buffer2 = html_buffer2.."<br/>Relay4 : "..gpio4;
        html_buffer2 = html_buffer2.."</body></html>";
        
        --Buffer is sent in smaller chunks as due to limited memory ESP8266 cannot handle more than 1460 bytes of data.
        client:send(html_buffer);
        client:send(html_buffer1);
        client:send(html_buffer2);        
        client:close();
        collectgarbage();
    end)
end)
 
cs


internet_relay.lua 소스를 보면 65행 에서부터 gpio.read() 모듈을 사용해서 해당 릴레이의 상태값을 얻어온다. 얻어온 값 (0 은 ON, 1 은 OFF) 에 따라 'ON' 또는 'OFF' 문자열을 할당한다. 그리고 html_buffer2 에 릴레이 상태 표시를 위한 HTML 을 만들어 준다. 기존의 html_buffer 와 html_buffer1 에 html_buffer2 를 붙여서 클라이언트(브라우저) 요청 시 HTML 을 출력해 준다.



 

동작 화면을 캡처해 보았다. 릴레이가 동작하는 장면도 같이 찍고 싶었지만 손이 3개면 가능하겠는데 2개라 찍지 못했다. 아무튼 잘 작동한다. 브라우저를 닫았다가 다시 열어도 잘 작동한다.


이것을 조금 더 발전시킨다면 인터넷으로 켜고 끌 수 있는 멀티콘센트도 충분히 만들 수 있을 것 같다. 물론 샤오미를 비롯해서 이미 많은 기업에서 Smart Plug 또는 WiFi Plug 라는 이름으로 이미 나와 있지만 말이다.


Xiaomi Smart Plug




▶추가사항(2016.09.30) : 위의 소스를 작성하면서 참고한 소스와 사이트를 정리해 본다.

http://www.instructables.com/id/WiFi-Internet-Controlled-Relays-using-ESP8266-Quic/

http://robokits.co.in/download/init.zip

init.zip

반응형
반응형

이번에는 NodeMCU, Lua, ESP8266 (Amica Board) 를 가지고 인터넷을 통하여 릴레이(Relay) 를 제어해 보려고 한다. 릴레이에 대해서는 이 블로그에서 많이 다루었지만 인터넷으로 릴레이를 제어하는 것은 처음인 듯 하다. 릴레이를 인터넷을 통하여 제어할 수 있다는 의미는 세계 어디서든 인터넷에만 연결되어 있으면 집안 또는 원격지의 전기, 전자기구 들을 제어할 수 있다는 말과 같다. 활용하기에 따라 요즘 IoT 광고에 나오는 기능들을 충분히 DIY로 구현해 볼 수 있다고 생각한다.


릴레이는 예전에 테스트 해 보았던 4채널 릴레이 모듈을 이용했다. 4개의 릴레이가 붙어 있어서 4개의 전원을 ON/OFF 할 수 있다. VCC, GND 와 제어를 위한 IN1 ~ IN4 단자가 달려 있다.


ESP8266 보드는 이제껏 계속 사용해 왔던 위와 같은 Amica 라는 이름의 ESP8266 개발보드를 이용했다. 펌웨어는 'NodeMCU_float_0.9.6-dev_20150704' 버전을 이용했다. 


그런데 문제가 발생했다. 위의 개발보드의 단자를 보면 3.3V 출력 밖에 없다. 하지만 릴레이 모듈은 5V 에서 동작한다. 외부전원을 사용해 볼까? 생각하다가 그냥 보드의 3.3V 에 연결해서 테스트해 보기로 했다. 연결해보니 정상적으로 동작하긴 한다. 그러나 5V 로 동작할 때 보다 뭔가 릴레이의 접점이 붙는 소리가 힘이 없다. 테스트용으로는 상관이 없겠지만 신뢰성 있는 장치를 만들 경우에는 릴레이에 정격의 전압을 반드시 사용해야 할 듯 하다.


 ESP8266

 Relay (4 Channel)

 3.3V

 VCC

 GND

 GND

 D1

 IN1

 D2

 IN2

 D3

 IN3

 D4

 IN4


연결은 위의 표와 같이 해 주었다.


■ 소스

internet_relay.lua 소스는 http://www.robokits.co.in 의 소스를 참고하여 수정하였다. 원래는 2채널용 소스였고 잡다한 HTML 태그가 달려 있었는데 정리해 주고, 인터넷 연결 부분의 소스를 분리해 주었다.


credentials.lua

1
2
3
-- WiFi Connect information
SSID = "와이파이 이름"
PASSWORD = "와이파이 패스워드"
cs


init.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("WiFi Connected...")
        file.close("init.lua")
        -- the actual application is stored in 'application.lua'
        --dofile("webserver.lua")
        dofile("internet_relay.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
 
cs


internet_relay.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
--Configure relay ouutput pins, pins are floating and relay opto needs ground to be activated. So pins are kept high on startup.
Relay1 = 1
Relay2 = 2
Relay3 = 3
Relay4 = 4
 
gpio.mode(Relay1, gpio.OUTPUT)
gpio.write(Relay1, gpio.HIGH);
gpio.mode(Relay2, gpio.OUTPUT)
gpio.write(Relay2, gpio.HIGH);
gpio.mode(Relay3, gpio.OUTPUT)
gpio.write(Relay3, gpio.HIGH);
gpio.mode(Relay4, gpio.OUTPUT)
gpio.write(Relay4, gpio.HIGH);
 
--Create server and send html data, process request from html for relay on/off.
srv=net.createServer(net.TCP)
srv:listen(8080,function(conn) --change port number if required. Provides flexibility when controlling through internet.
    conn:on("receive", function(client,request)
        local html_buffer = "";
        local html_buffer1 = "";
        
        
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
        end
        local _GET = {}
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(%w+)=(%w+)&*"do
                _GET[k] = v
            end
        end
 
        html_buffer = html_buffer.."<html><head><meta http-equiv=\"Content-Language\" content=\"en-us\"><meta http-equiv=\"Content-Type\" content=\"text/html;\">";
        html_buffer = html_buffer.."</head><body><font size=5>Internet Relay Control (NodeMCU/Lua, ESP8266)</font></br>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON1\"><button style=\"width:300\">Relay1 ON</button></a><a href=\"?pin=OFF1\"><button style=\"width:300\">Relay1 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON2\"><button style=\"width:300\">Relay2 ON</button></a><a href=\"?pin=OFF2\"><button style=\"width:300\">Relay2 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON3\"><button style=\"width:300\">Relay3 ON</button></a><a href=\"?pin=OFF3\"><button style=\"width:300\">Relay3 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."<a href=\"?pin=ON4\"><button style=\"width:300\">Relay4 ON</button></a><a href=\"?pin=OFF4\"><button style=\"width:300\">Relay4 OFF</button></a><br/>";
        html_buffer1 = html_buffer1.."</body></html>";
    
    
        local _on,_off = "",""
        if(_GET.pin == "ON1")then
              gpio.write(Relay1, gpio.LOW);
        elseif(_GET.pin == "OFF1")then
              gpio.write(Relay1, gpio.HIGH);
        elseif(_GET.pin == "ON2")then
              gpio.write(Relay2, gpio.LOW);
        elseif(_GET.pin == "OFF2")then
              gpio.write(Relay2, gpio.HIGH);
        elseif(_GET.pin == "ON3")then
              gpio.write(Relay3, gpio.LOW);
        elseif(_GET.pin == "OFF3")then
              gpio.write(Relay3, gpio.HIGH);
        elseif(_GET.pin == "ON4")then
              gpio.write(Relay4, gpio.LOW);
        elseif(_GET.pin == "OFF4")then
              gpio.write(Relay4, gpio.HIGH);                            
        end
        --Buffer is sent in smaller chunks as due to limited memory ESP8266 cannot handle more than 1460 bytes of data.
        client:send(html_buffer);
        client:send(html_buffer1);
        client:close();
        collectgarbage();
    end)
end)
 
cs


internet_relay.lua 소스를 보면 ESP8266 이 웹서버로 동작한다. 8080 포트로 클라이언트의 요청을 기다리고 있다가 클라이언트(브라우저)의 요청이 있을 경우 html_buffer 의 내용을 브라우저로 보내준다. HTML 의 내용에는 각 릴레이에 해당되는 버튼에 링크태그를 걸어서 버튼 클릭 시 pin 이라는 name 으로 릴레이의 ON/OFF value 를 보내준다. 이 값을 가지고 if 문을 이용하여 각각의 릴레이를 ON/OFF 하도록 제어하는 것이다.




위의 소스를 보드에 업로드 하고 브라우저에서 ESP8266에 할당된 IP + 설정한 포트번호를 치고 들어가면 위와 같이 버튼 8개가 나열된다. 각 버튼 클릭 시 릴레이 1 ~ 4 가 제대로 제어가 됨을 확인 하였다.



물론 위와 같이 공유기의 내부IP를 이용한 접속은 말 그대로 내부IP(사설IP)이기 때문에 집에서 밖에 콘트롤 할 수 없으며 별 의미가 없다.  이럴 경우는 공유기의 DDNS, 포트포워딩 설정을 이용하면 외부에서도 접근이 가능하다. 이에 대해서는 예전 글 "외부에서 NodeMCU 웹서버 접속하기" 를 참고하면 된다.



▶추가사항 (2016.07.29) : http://deneb21.tistory.com/427 에 조금 더 업그레이드 된 소스를 올려 놓았다. (릴레이 현재상태를 알 수 있도록 함.)

반응형
반응형

NodeMCU Lua 사용해보기 지난 10편에서는 ThingSpeak 에 ESP8266 보드를 이용해서 DHT11 의 데이터를 업로드 해 보았다.  이번에는 비슷한 서비스인 dweet.io 라는 IoT 클라우드 서비스를 이용해 보려고 한다. ThingSpeak 는 회원가입이 필요 했는데 dweet 은 회원가입이 필요 없고 Things 의 이름을 Key 로 사용한다. 고유한 이름으로 Thing 의 이름을 지정해주고 자신의 IoT 데이터를 업로드 하면 되는 것이다.


dweet.io 사이트에서 어떠한 오퍼레이션 없이 유니크한 Thing Name 을 가지고 dweet 으로 데이터를 보내면 dweet.io 에서 데이터를 받아서 저장하기 때문에 바로 데이터 업로드를 위한 하드웨어 및 소스를 준비하면 된다.  ESP8266 보드인 Amica 에 DHT11 온습도 센서를 아래와 같이 연결을 하였다.


 ESP8266 (Amica Board)

 DHT11

 D5

 Signal

 3.3V

 VCC (+)

 GND

 GND


■ 소스


credentials.lua

1
2
3
4
-- WiFi Connect information
SSID = "Your WiFi SSID"
PASSWORD = "Your WiFi Password"
 
cs


init.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("WiFi Connected...")
        file.close("init.lua")
        -- the actual application is stored in 'application.lua'
        --dofile("webserver.lua")
        dofile("dht11_dweet.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
 
cs


dht11_dweet.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
DHT_PIN = 5 -- defined by DHT shield (D5)
HOST    = "dweet.io"
THING_NAME   = "Your Thing Name"
 
function read_DHT()
  status,temp,humi,temp_decimial,humi_decimial = dht.read(DHT_PIN)
  if( status == dht.OK ) then
    print("DHT Temperature = "..temp.." grdC  ".."Humidity = "..humi.." %")
  elseif( status == dht.ERROR_CHECKSUM ) then
    print"DHT Checksum error." );
  elseif( status == dht.ERROR_TIMEOUT ) then
    print"DHT Time out." );
  end
end
 
function dweet()
  read_DHT()
  conn=net.createConnection(net.TCP,0
  conn:on("receive", function(conn, pl) print("response: ",pl) end)
  conn:on("connection", function(conn, payload) 
          print("connected"
          conn:send("POST /dweet/for/"..THING_NAME.."?"
          .. "temp=" .. temp 
          .. "&humi=" .. humi 
          .. " HTTP/1.1\r\n"
          .. "Host: " .. HOST .. "\r\n"
          .. "Connection: close\r\n"
          .. "Accept: */*\r\n\r\n"end)
  conn:on("disconnection", function(conn, payload)
          print("disconnected"end)
  conn:connect(80, HOST)
end
 
dweet()
 
-- dweets every 60 sec.
tmr.alarm(010 * 10001, function() dweet() end )
 
print("Dweets every 60 sec DHT11 data to dweet.io")
print("Stop this by tmr.stop(0)")
cs


credentials.lua 와 init.lua 에서 ESP8266 보드를 와이파이에 연결시키고 dht11_dweet.lua 에서 dweet.io 로 DHT11의 온습도 데이터를 업로드 한다. 위의 3가지 lua 파일을 ESP8266 보드에 업로드 하고 실행하면 되는 것이다. dweet.io 사이트에서는 아무것도 설정해 주지 않아도 된다. 다만 위의 소스에서 THING_NAME 의 값은 유니트한 값이어야 한다.


ESPlorer 에서 위와 같이 데이터를 업로드하고 실행하면 dweet.io 에서 데이터가 잘 전송되었다는 리턴값을 보내 준다.


소스를 수정 후 업데이트 할 경우에는 위에 사용된 타이머 0번을 Stop 시키고 업로드 해야 한다. tmr.stop(0) 명령어를 이용해서 타이머를 멈추고 업로드 하면 된다.



이제 dweet.io 사이트에 들어가 본다.


■ dweet.io

https://dweet.io/ 

 

dweet.io 사이트에서 상단의 Play 를 클릭하면 아래와 같이 API 설정 목록이 뜬다.


Play 메뉴에서 여러가지 API 에 대한 설명을 볼 수 있고 자신의 Thing 에 대한 설정을 할 수 있다. 둘러보면 모두 이해할 수 있는 내용이다. 이 API 들을 이용해서 데이터를 끌어와 관련 웹이나 스마트폰 앱 또는 또 다른 Thing 을 만들 수 있을 것이다.


위의 소스를 이용해서 데이터를 업로드한 dweet 의 THING NAME 은 'deneb_nodemcu_dht11_01' 이다. http://dweet.io/follow/deneb_nodemcu_dht11_01 (이 URL 은 언제든지 내가 ESP8266의 전원을 끊으면 동작하지 않을 수 있음) 를 클릭해서 들어가보면 데이터가 잘 업로드 되고 있는 것을 알 수 있다.



위의 화면에서 'Create a Custom Dashboard' 를 클릭하면 freeboard.io 사이트로 이동을 하는데 Things의 데이터를 비주얼하게 표현해 주는 사이트이다. 


사이트에 가입하면 위와 같이 게이지 같은 위젯도 추가가 가능하다. 


dweet.io 를 사용해본 소감은 ThingSpeak 보다 간단해서인지 왠지 적응이 잘 안된다. 너무 오픈되어 있어서 그런가? 좀 혼란스럽다. 아직까지는 ThingSpeak 가 더 마음에 든다. 앞으로 dweet 에 대해 새로운 사항을 알게되면 이 포스팅에 내용을 추가할 생각이다.

반응형
반응형

예전에 IoT 클라우드 서비스인 ThingSpeak.com 에 대해서 알아보고 실제로 ESP8266 모듈인 ESP-01과 아두이노를 이용해서 DHT22 의 온도, 습도 데이터를 ThingSpeak 에 올려본 적이 있습니다. 하지만 AT Command 기반 이었고 ESP-01 은 아두이노에서 읽은 센서 데이터를 받아서 인터넷에 올려주는 역할만을 했습니다. 이번에는 NodeMCU 를 이용해서 DHT11 센서의 온도와 습도 데이터를 ThingSpeak 에 올려보도록 하겠습니다. 지난 글에서 구현 했던 DHT11 센서의 데이터를 읽어서 온도, 습도를 알려주는 웹서버는 인터넷을 통해서 들어오는 요청에 대해서 응답을 줬었지만 ThingSpeak 연동은 센서 데이터를 ESP8266을 통해서 보내는 것이므로 반대의 개념이 되겠습니다. ThingSpeak 서비스에 대해서는 예전에 자세하게 다룬 적이 있어서 링크로 대신 합니다. 



ThingSpeak 서비스 개념도 입니다. 센서로 부터 데이터를 받은 ESP8266 보드가 데이터를 ThingSpeak 서버에 업로드하고 그 데이터를 스마트폰, PC, 아두이노, 또 다른 ESP8266 등 n개의 장치로 보내서 활용이 가능 합니다. 물론 받은 데이터로 또 다른 장치를 제어할 수도 있습니다. 활용하기 나름이죠.


ESP8266 보드는 여전히 ESP-12E 기반의 Amica 보드를 이용 합니다. 센서는 DHT11 온도 습도 센서를 이용합니다. 센서와 ESP8266 개발보드와의 연결은 아래의 이전 글 을 참고해서 연결하면 됩니다. 똑같습니다. 다시 말하자면 센서의 전원은 Amica 보드의 3.3V 에 연결하고 Signal 은 D5에 연결했습니다.


이제 ESPlorer를 열고 ESP8266 Amica 보드를 연결하고 코딩을 합니다. credentials.lua 와 init.lua 는 NodeMCU 웹서버 만들기 글에서 사용한 것과 동일 합니다. 대신 dht11_thingspeak.lua 를 init.lua 에서 call 해 줍니다.


■ 소스 #1 (credentials.lua)

1
2
3
4
-- WiFi Connect information
SSID = "your wifi name"
PASSWORD = "your wifi password"
 
cs



■ 소스 #2 (init.lua)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("WiFi Connected...")
        file.close("init.lua")
        dofile("dht11_thingspeak.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
 
cs


■ 소스 #3 (dht11_thingspeak.lua)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
pin = 5 -- dht11 signal pin
temp = 0
humi = 0
writekey = "your thinkspeak channel write api key"
 
tmr.alarm(1,15000,1,function()readDHT()sendData(temp,humi)end)
 
--read DHT11 temp, humi data function
function readDHT()
    status, temp, humi = dht.read(pin)
    if status == dht.OK then
        temp = math.floor(temp)
        humi = math.floor(humi)
    elseif status == dht.ERROR_CHECKSUM then
        print"DHT Checksum error." )
    elseif status == dht.ERROR_TIMEOUT then
        print"DHT timed out." )
    end
    dht = nil
end
 
--send data to thingspeak
function sendData(temp,humi)
    -- conection to thingspeak.com
    print("Sending data to thingspeak.com")
    conn=net.createConnection(net.TCP, 0
    conn:on("receive", function(conn, payload) print(payload) end)
    
    -- api.thingspeak.com 184.106.153.149
    conn:connect(80,'184.106.153.149'
    conn:send("GET /update?key="..writekey.."&field1="..temp.."&field2="..humi.." HTTP/1.1\r\n"
    conn:send("Host: api.thingspeak.com\r\n"
    conn:send("Accept: */*\r\n"
    conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
    conn:send("\r\n")
    conn:on("sent",function(conn)
    print("Closing connection")
    conn:close()
    end)
    conn:on("disconnection", function(conn)
    print("Got disconnection...")
  end)
end
 
cs


인터넷을 통해서 thingspeak에 dht11 의 온도, 습도 데이터를 업로드 하는 소스 입니다. 4번째 줄 writekey 부분에 자신의 thingspeak 채널의 Write API Key 를 입력해야 합니다.


물론 thingspeak 채널에는 온도, 습도를 받을 수 있는 2개의 field 가 등록되어 있어야 합니다. 위의 링크의 thingspeak 글을 참고하면 쉽게 만들 수 있습니다.



소스를 모두 업로드 하고 장치를 Soft Reset 하면 위와 같이 데이터를 ThinsSpeak 에 업로드 하기 시작 합니다.


ThingSpeak.com 에 접속해서 데이터를 업로드 하고 있는 채널에 들어가면 위와 같이 우리집 온도와 습도가 그래프로 표시 됩니다. 물론 스마트폰 웹브라우저로도 볼 수 있으며 데이터를 csv, json, xml 형식으로 다운로드 받을 수도 있습니다. 



위의 링크를 참조하면 자신의 스마트폰에 위젯앱을 추가하여 데이터를 실시간으로 모니터링 할 수 있으며 입계값을 설정하여 경고가 울릴 수 있게 할 수도 있습니다. 예를 들어 온도가 30도가 넘으면 경고 알람을 울리게 설정할수도 있는 것이죠.


스마트폰에서 ThingSpeak 위젯앱 'IoT ThingSpeak Monitor Widget' 을 설치하고 설정한 모습 입니다.

반응형
반응형

지난 글들에서 NodeMCU Lua 를 이용해서 간단한 웹서버를 만들어 보았고 공유기 설정을 통하여 NodeMCU ESP8266 웹서버를 외부에서도 접속이 가능하도록 만들어 보았습니다. 하지만 브라우저로 웹서버에 접속해도 Hello NodeMCU 라는 글자만 출력되었었죠. 아무런 정보도 표시되지 않는다면 IoT 로서의 의미가 없습니다. 이번에는 온습도 센서인 DHT11 을 ESP8266 개발보드인 Amica 에 연결해서 웹서버에 접속하면 온도와 습도가 표시되도록 해 보겠습니다. 어디든 인터넷만 연결이 되면 스마트폰, PC 등에서 현재 집의 온도와 습도를 알 수 있는 것이죠.


제가 가지고 있는 DHT11 센서 입니다. 저항이 달려 있는 모듈형태로 되어 있어서 보드와 연결 시 따로 저항을 연결하지 않아도 됩니다. 모듈형태가 아니라 위의 파란부분의 핀 4개짜리 센서만 가지고 있다면 5K 정도의 저항을 Signal 과 VCC 사이에 달아 주어야 합니다. DHT11 에 대한 자세한 사용법은 [여기] 를 참고 하시면 됩니다.


그리고 Amica  ESP8266 개발 보드 입니다. DHT11 이 3V~5.5V를 지원하므로 전원은 3.3V 핀을 이용하면 됩니다. 연결은 아래의 표를 참조해서 연결하면 됩니다.


 DHT 11

 ESP8266 (Amica)

 Signal

 D5

 VCC

 3.3V

 GND

 GND


연결이 되었으면 이제 소스를 코딩하면 됩니다. 소스는 이전 글에서 해 보았던 웹서버 만들기의 credentials.lua, init.lua, webserver.lua 를 변형해서 사용할 것 입니다.


■ credentials.lua

와이파이 연결정보를 가지고 있는 파일 입니다.


1
2
3
4
-- WiFi Connect information
SSID = "와이파이이름"
PASSWORD = "와이파이패스워드"
 
cs



■ init.lua

와이파이에 연결해 주는 기능을 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("WiFi Connected...")
        file.close("init.lua")
        -- the actual application is stored in 'application.lua'
        dofile("webserver.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
 
cs




■ webserver.lua

웹서버를 실행하고 DHT11 센서의 값을 읽어서 웹에서 요청이 들어오면 준비된 HTML (온도 및 습도값 포함) 을 전송하는 기능을 합니다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
pin = 5 -- dht11 signal pin
srv = net.createServer(net.TCP)
srv:listen(8080, function(conn)
 
    status, temp, humi, temp_dec, humi_dec = dht.read(pin)
    if status == dht.OK then
        temp_1 = math.floor(temp)
        humi_1 = math.floor(humi)
    elseif status == dht.ERROR_CHECKSUM then
        print"DHT Checksum error." )
    elseif status == dht.ERROR_TIMEOUT then
        print"DHT timed out." )
    end
    tmr.delay(1000000)
    conn:on("receive", function(sck, payload)
        print(payload)
        sck:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>My House Temperature & Humidity<br/></h1>" .. "<br/><h1>Temperature = " .. temp .. "C</hr>" .. "<br/><h1>Humidity = " .. humi .. "%</hr>")
    end)
    conn:on("sent", function(sck) sck:close() end)
end)
print("webserver ready...")
cs


위의 소스를 보면 이전 글에서 작성 했던 웹서버 코드를 기반으로 DHT11 값을 추가해서 HTML 을 리턴 할 수 있도록 수정해 주었습니다.


DHT11 의 경우 초기의 NodeMCU 같은 경우는 별도의 라이브러리를 사용해야 코드가 단순화 되었었는데 지금은 위와 같이 간단하게 읽어오는 것이 가능 합니다. 아마도 펌웨어 자체에 라이브러리가 포함이 된 듯 합니다.



위의 3개의 소스를 ESPlorer 를 통해서 ESP8266 개발보드에 'Save to ESP' 해서 업로드 해 줍니다. init.lua 는 맨 마지막에 업로드 해 주는 것이 좋습니다.


소스를 모두 업로드 하고 Reset 을 눌러서 Soft Reset 을 한 번 해 줍니다. 시리얼 창에 'webserver ready...' 라는 메시지가 나오면 준비가 완료된 것 입니다.


이제 브라우저를 열고 저의 공유기에서 ESP8266 웹서버에 할당된 IP 인 192.168.0.18 로 접속해서 온도와 습도가 잘 나오는지 확인해 봅니다. 포트는 8080 을 이용했으므로 다음과 같이 브라우저의 주소창에 입력하면 됩니다. http://192.168.0.18:8080/



이번에는 외부에서 스마트폰 LTE 연결로 확인을 해 보겠습니다. 물론 이것을 가능하게 하려면 [여기] 를 참고 하셔서 공유기의 DDNS, 포트 포워드 를 설정해서 외부에서도 ESP8266 웹서버에 접속 가능하도록 만들어 주어야 합니다.


위와 같이 스마트폰으로 외부에서도 DDNS에서 만들어준 URL을 입력하면 DHT11 센서가 측정한 값을 실시간으로 볼 수 있습니다. 이를 응용하면 가스누출, 조명 밝기, 침입자 탐지 등도 원격지에서 모니터링 할 수도 있을 것 같습니다.



▶ 추가사항 (2016.07.08) : 위의 webserver.lua 소스가 작동에는 지장이 없으나 좀 지저분하여 소스를 수정하고 주석도 좀 추가해 보았습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
pin = 5 -- dht11 signal pin
temp = 0 -- initialize temperature
humi = 0 -- initialize humidity
port = 8080 -- web port
 
srv = net.createServer(net.TCP)
srv:listen(port, function(conn)
    ReadDHT()   -- dht read function call
    tmr.delay(1000000)
    conn:on("receive", function(sck, payload)
        print(payload)
        --// response html
        sck:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>My House Temperature & Humidity<br/></h1>" .. "<br/><h1>Temperature = " .. temp .. "C</hr>" .. "<br/><h1>Humidity = " .. humi .. "%</hr>")
    end)
    -- response
    conn:on("sent", function(sck) sck:close() end)
end)
print("webserver listening..."
 
 
function ReadDHT()
    status, temp, humi = dht.read(pin)
    if status == dht.OK then
        temp = math.floor(temp)
        humi = math.floor(humi)
    elseif status == dht.ERROR_CHECKSUM then
        print"DHT Checksum error." )
    elseif status == dht.ERROR_TIMEOUT then
        print"DHT timed out." )
    end
    dht = nil   --release dht module
end
 
cs


반응형
반응형

지난 NodeMCU 관련 글 7편 에서 ESP8266 보드(Amica Board)에 간단한 웹서버를 만들어 보았습니다. 하지만 공유기의 내부 IP 를 통해서만 접속이 가능 했습니다. IoT 의 개념이 외부에서도 집안의 장치에 마음대로 접근해서 컨트롤 하는 것이 목표이기 때문에 외부에서 접속이 안된다면 별 의미가 없습니다. 공유기의 DDNS 서비스와 포트포워딩 기능을 이용하여 지난번 구현 하였던 웹서버를 외부에서도 접속할 수 있도록 해 보겠습니다. 사실 이 글은 NodeMCU 글이라기 보다는 공유기 설정 관련 글이지만 어차피 NodeMCU 시리즈를 엮는데 필요할 것 같아서 8편 글로 올립니다.


이 글에서 사용한 공유기는 ipTime 유무선 공유기 입니다. 하지만 다른 회사의 공유기를 사용하고 있는 분들이라도 DDNS나 포트포워딩의 개념은 같으므로 적용하는데 별 어려움은 없을 것 입니다.



■ DDNS 서비스란?

먼저 DDNS는 Dynamic DNS 의 약자 입니다. 동적 DNS 라고 하는데 먼저 DNS의 개념을 알아야 합니다.  DNS는 도메인 네임을 IP로 바꿔주어서 인터넷에 연결할 수 있도록 합니다.  모든 인터넷 서버는 IP를 가지고 있으니까요. 우리가 www.naver.com 이라는 도메임을 주소창에 치면 DNS 서버가 이것을 받아서 해당되는 IP를 가지고 있는 서버로 연결해 주는 것이죠. 그런데 Naver 같은 회사는 고정 IP 를 서버에 사용 합니다. 그래서 IP가 변할 일이 없습니다. 반면 가정의 인터넷은 IP가 변합니다.(물론 고정 IP서비스도 있긴 함) 동적 IP를 할당하는 것이죠. IP는 한정된 자원이기 때문에 하나의 IP를 여러사람이 돌아가면서 쓰도록 해 놓은 것 입니다. 고로 기존의 DNS 서비스에는 등록이 불가능 합니다. 이럴 경우 DDNS 라는 서비스를 사용하게 됩니다. 


ipTime 같은 경우는 iptime.org 라는 DDNS 서비스를 자사의 공유기 사용자들에게 무료로 사용하도록 해 주고 있습니다. 서비스에 가입을 하면 공유기가 공인IP를 모니터링 하게 되고 IP가 변경될 경우 이 공인 IP를 DDNS 서비스에 등록해서 계속 갱신하도록 해 줍니다. 고로 xxxxxx.iptime.org 라는 자신만의 도메인으로 가정의 웹서버에 접속 할 수 있도록 해 주는 원리 입니다.


하지만 ipTime 같은 경우는 자체의 DDNS 서비스를 구현하고 공유기 구매자들에게 무료로 제공하고 있지만 그렇지 않은 경우도 많습니다. 그러므로 DDNS 기능을 사용하기 위해서는 공유기 구입 전 공유기가 DDNS 서비스를 지원하는지 알아봐야 합니다. 만약 DDNS 서비스가 지원되지 않는다면 자신의 공인 IP를 알아내서 연결하는 방법을 쓸 수 있습니다. 자신의 공인 IP를 알아내는 방법은 [여기] 를 클릭하면 알 수 있습니다.

 


■ 포트포워딩 이란?

포트포워딩이랑 공유기에서 DDNS 등을 통해 외부에서 요청이 들어올 경우 설정해 놓은 웹서버로 연결해주는 기능 입니다. 예를 들어 xxxxxx.iptime.org:8080 이라고 외부에서 브라우저에 주소를 쳐서 연결을 요청하는 경우 먼저 DDNS 서비스가 이를 공인 IP로 변경해 줍니다. xxxxxx.iptime.org:8080 -> 218.237.234.156:8080 이런 식으로 변경이 됩니다. 그러면 218.237.234.156 IP를 쓰고 있는 공유기를 찾아서 요청 정보를 공유기가 받습니다. 공유기에서는 포트포워딩 목록을 보고 내부 IP 인 192.168.0.18:8080 을 사용하는 NodeMCU 웹서버로 요청을 보내 줍니다. 그럼 NodeMCU 에서는 준비된 응답(HTML)을 보내주게되는 것입니다.


이제 공유기를 실제로 설정해 보겠습니다.


ipTime 공유기의 관리자에 들어 갑니다. 접속 IP 는 192.168.0.1 입니다. 관리화면으로 이동 합니다.


ipTime 공유기의 DDNS 설정 입니다. 고급설정 -> 특수기능 하위에 있습니다. 저의 경우 이미 만들어 놓은 DDNS 도메인이 있어서 저렇게 나옵니다. 추가 버튼을 눌러서 서비스에 가입을 해 주면 됩니다. 접속 도메인에 사용할 자신만의 호스트이름과 이메일, 비밀번호 등을 설정하면 쉽게 추가할 수 있습니다.


 DDNS설정이 끝났으면 포트포워딩을 설정 합니다. 고급설정 -> NAT/라우터관리 하위에 있습니다. 아랫 부분에 새로운 포트포워딩 규칙을 적는 곳이 있습니다. 적절한 이름을 적어주고 프로토콜은 http, tcp 를 선택합니다. 포트는 저 같은 경우는 8080을 할당해 주었습니다. 이렇게 하게되면 지난 NodeMCU 7편에서 설정했던 webserver.lua 의 소스의 포트 설정 부분을 80 에서 8080으로 바꾸어서 다시 업로드 해 주어야 합니다. 그리고 NodeMCU 에 할당된 내부 IP를 적어 줍니다. 모든 것을 이상없이 적었으면 '적용' 버튼을 누르면 됩니다. 


새 포트포워드 규칙이 생성되었습니다. 맨위 오른쪽의 저장 버튼을 눌러서 전체 설정을 한 번 더 저장해 줍니다.


이제 테스트를 하면 됩니다. 테스트 전 [NodeMCU Lua 사용해보기 #7 - 간단한 웹서버 만들어보기] 에서 만들었던 NodeMCU 는 전원이 꼭 들어가 있어야 합니다. 그리고 위에서 말 했지만 다시 말하자면 webserver.lua 의 포트를 아래와 같이 수정해서 다시 업로드 해 주어야 합니다.


1
2
3
4
5
6
7
8
9
-- a simple HTTP server
srv = net.createServer(net.TCP)
srv:listen(8080, function(conn) -- 서비스 포트 수정
    conn:on("receive", function(sck, payload)
        print(payload)
        sck:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1> Hello, NodeMCU.</h1>")
    end)
    conn:on("sent", function(sck) sck:close() end)
end)
cs


3번째 줄의 포트번호 설정이 80 -> 8080 으로 변경 되었습니다. 나머지는 같습니다.


이제 외부에서 NodeMCU 웹서버가 제대로 응답을 해 주는지 확인을 해 봐야 합니다. 직접 확인을 하기 위해 근처의 PC방이나 친구집에 가서 테스트 할 수도 있겠지만 제일 쉬운 방법은 스마트폰의 와이파이를 끄고 LTE 나 3G로 연결해서 스마트폰의 브라우저로 확인해 보는 것입니다.


저의 스마트폰 브라우저에서 DDNS에서 설정한 호스트명으로 연결한 모습 입니다. (저의 호스트명은 지웠습니다. 개인적으로 사용하고 있는 DDNS 서비스라서요.) 외부에서도 연결이 잘 됩니다. 이제 나만의 NodeMCU 웹서버는 인터넷 연결만 가능하면 미국이건 중국이건 아프리카건 어디에서든 연결이 가능한 서버가 된 것입니다.

반응형
반응형

이번에는 NodeMCU Lua 를 사용해서 간단한 웹서버를 만들어보고 브라우저로 웹서버로 접속해서 응답을 얻어보겠습니다. 웹서버를 만들기 위해서는 'NodeMCU Lua 사용해보기 #5 - 인터넷에 연결해보기' 를 먼저 공부해야 합니다. 인터넷에 연결이 되어 있어야 웹서버가 동작 하니까요. 일단 간단하게 브라우저에서 ESP8266 장치로 요청을 보내면 장치가 준비된 HTML 을 브라우저로 응답을 보내주는 형식 입니다.


NodeMCU 펌웨어가 설치된 ESP8266 장치를 PC에 연결 하고 ESPlorer 를 실행 합니다. Open 을 눌러서 PC와 통신 가능 상태로 만들어 줍니다.


웹서버 기능은 총 3개의 Lua 파일로 만들었습니다. 와이파이 연결 정보를 담고 있는 credentials.lua, 인터넷 연결을 해 주는 init.lua, 그리고 웹서버의 역할을 해 주는 webserver.lua 의 3개 파일로 구현 할 수 있습니다.


■ credentials.lua


1
2
3
4
-- WiFi Connect information
SSID = "와이파이 이름"
PASSWORD = "와이파이 패스워드"
 
cs


위와 같이 와이파이 연결 정보를 SSID, PASSWORD 변수에 담아 두는 소스 입니다.


■ init.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("Running")
        file.close("init.lua")
        -- the actual application is stored in 'application.lua'
        dofile("webserver.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
 
cs


init.lua 파일은 ESP8266 이 부팅 시 가장 먼저 실행하는 파일 입니다. 이 파일에 인터넷 연결 소스를 작성 합니다. 와이파이 연결에 credentials.lua 의 내용을 dofile("credentials.lua")  부분을 통해서 참조하게 되고 와이파이에 연결 합니다. 와이파이 연결 후 startup() function을 call 하고 startup() 은 실행 후 dofile("webserver.lua") 을 통해서 webserver.lua 파일을 실행하게 됩니다. 


■ webserver.lua

1
2
3
4
5
6
7
8
9
10
-- a simple HTTP server
srv = net.createServer(net.TCP)
srv:listen(80, function(conn)
    conn:on("receive", function(sck, payload)
        print(payload)
        sck:send("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1> Hello, NodeMCU.</h1>")
    end)
    conn:on("sent", function(sck) sck:close() end)
end)
 
cs


웹서버로 브라우저의 요청이 오면 가지고 있던 HTML 을 응답으로 내어주는 가장 간단한 형태의 웹서버 구현 입니다. 


HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1> Hello, NodeMCU.</h1>


위의 HTML 코드를 브라우저로 보내 줍니다. 그리고 브라우저에서는 웹서버에서 응답받은 내용을 브라우저에 표시해 주겠죠. 그리고 위의 소스를 보면 srv:listen(80, function(conn)  부분이 있습니다. 


여기에서 80은 웹서버의 서비스 포트 입니다. 80은 기본 웹서비스 포트로서 브라우저 URL 입력창에 포트 번호를 붙이지 않아도 됩니다. 만약 포트를 80이 아니라 8080 같은 포트로 설정하면 URL 마지막에 포트 번호를 표기 해야 합니다. 예를 들면 http://192.168.0.18:8080 이런 식으로 주소를 적어야 합니다. 혹시나 가정용 인터넷을 이용할 경우에는 80포트를 인터넷 회사에서 사용하지 못하도록 막아 놓는 경우도 있기 때문에 8080, 8088... 등 다른 포트를 이용해서 외부에서 연결을 설정 하기도 합니다. 



위와 같이 3개의 소스 파일을 ESPlorer 에서 작성하고 Save to ESP 버튼을 눌러서 ESP8266 보드에 업로드 해 줍니다. 업로드 순서는 init.lua 파일을 가장 나중에 업로드 해 주시면 됩니다. 왜냐하면 업로드 후 자동으로 실행이 되는데 나머지 2개의 파일을 찾지 못하면 에러를 내기 때문에 그렇습니다. 업로드 후 Reset 버튼을 눌러서 Soft Reset 해 봅니다. 보드가 다시 시작 하면서 init.lua 를 자동으로 실행하게 되고 위와 같이 192.168.0.18 이라는 IP를 잡고 웹서버가 실행이 됩니다. 고로 웹서버의 IP 가 접속주소가 됩니다.


브라우저를 하나 열고 제대로 ESP8266에서 작동 중인 웹서버가 제대로 응답을 주는지 확인해 봅니다.


PC의 브라우저를 열고 웹서버 주소인 192.168.0.18 로 연결해 보았습니다. 응답을 잘 주고 있습니다.


PC뿐 안니라 스마트폰의 브라우저 에서도 웹서버 연결이 잘 됩니다.


이상으로 NodeMCU Lua를 이용해서 ESP8266 보드에서 간단한 웹서버를 구현해 보았습니다.  간단하지만 센서값을 인터넷을 통해 보여주거나 반대로 외부에서 ESP8266에 연결된 장치 들을 콘트롤 할 수 있는 기초가 마련된 것 입니다.




▶ 추가사항 (2016.07.25) : http://orasman.tistory.com/358 여기에 위의 소스의 개선점을 트랙백으로 올려 주셨네요. 서버가 닫히지 않았을 경우 닫아주는 소스가 추가 되었습니다.

반응형
반응형

지난 글에서 NodeMCU 를 이용해서 ESP8266을 인터넷에 연결해 보았습니다. 그런데 ESPlorer 라는 다소 생소한 이름의 개발툴에 대해서는 그다지 자세하게 알아보지 못했네요. 이번 글에서는 ESPlorer 에 대해서 알아 보겠습니다. ESPlorer 는 러시아 개발자가 만든 소프트웨어 입니다. 그래서 홈페이지에 들어가보면 ESPlorer 메뉴는 영어로 나오지만 다른 메뉴는 러시아어로 나옵니다. 아무튼 이런 프로그램이 없었다면 Putty 같은 터미널 프로그램으로 한 줄 한 줄 정성스럽게(?) 코딩을 했을텐데 매우 편리하게 개발을 할 수가 있습니다. ESPlorer는 JAVA 언어로 만들어져 있습니다. 그래서 어떤 OS 가 됐든지 JAVA SDK 만 설치되어 있다면 하나의 소스로 변경 없이 실행이 가능 합니다.


처음 실행했을 때의 화면 입니다. ESPlorer 는 크게 두 부분으로 구분할 수 있는데 왼쪽은 소스 편집 업로드 등을 할 수 있는 창이고 오른쪽은 시리얼 통신 내용을 보여주는 시리얼 창 입니다. 왼쪽의 소스창 부터 보겠습니다.

  • 빨간색 부분은 소스편집기의 부가 기능 입니다. open, save, copy, paste 등의 일반적인 편집 메뉴와 다르지 않습니다.

  • 파란색 영역은 실제 소스편집이 이루어지는 창 입니다. New 라고 탭이 하나 열려 있는데 여러개의 파일을 열어서 탭으로 이동하면서 소스편집이 가능 합니다.

  • 녹색 영역은 소스 작성 후 ESP8266 에 Send, Save, Upload 기능을 하는 버튼들이 모여 있습니다. 기능에 따라서 여러가지 버튼이 존재 합니다.


이제 오른쪽 시리얼창을 보겠습니다.


  • 노란색 부분은 장치에 연결을 위한 버튼들이 있습니다. 기본적으로 PC에 ESP8266을 연결하고 Open 버튼을 누르면 연결이 됩니다. 

  • 노란색 부분 아래는 실제 시리얼 통신 내용을 보여주는 창 입니다. 

  • 갈색 부분은 Snippet 기능입니다. 자주 사용하는 명령어나 소스를 Snippet 에 저장해 놓고 단추만 누르면 매크로 처럼 자동으로 실행이 되는 기능 입니다. 이 기능은 아래쪽에서 좀 더 자세히 알아보겠습니다.

  • 핑크색 부분은 Heap 메모리, Chip Info 등의 ESP8266 장치의 각종 정보를 보는 기능과 Soft Reset 버튼이 위치하고 있습니다. 그리고 핑크색 아래에 희미하게 창이 또 있는데 여기는 자주 사용하는 명령어 들을 모아놓아서 사용하기 쉽게 만들어 놓은 기능 입니다. 예를 들어 여기에서 file.remove("") 를 선택하면 파일명만 적어서 Send 버튼을 누르면 실행이 되는 기능 입니다.

  • 그리고 제일 오른쪽에 3개의 버튼이 있습니다. Format, FS info, Reload 가 있는데 Format 은 말 그대로 장치에 탑재된 프로그램을 싹 다 지우는 역할을 합니다. FS info 는 장치의 프로그래밍 가능 공간에 대한 정보 입니다. 총용량, 사용된 용량, 남은 용량으로 표시 합니다. Reload 는 FS info 의 상세정보 입니다. 프로그래밍 가능 공간에 대한 정보뿐 아니라 탑재된 프로그램 파일들에 대한 정보도 보여 줍니다.


왼쪽 소스창의 Command 탭 입니다. NodeMCU 에서 자주 사용하는 명령어들이 모여 있습니다. 장치를 Restart 하거나 칩이나 Heap 메모리 정보를 봅니다. List Files 는 장치에 업로드된 파일들을 표시해 줍니다. 위에서 알아보았던 Reload 버튼과 같은 기능 입니다. tmr.stop 은 지금 실행되고 있는 timer 모듈의 실행을 멈춰 줍니다. 오른쪽에서 해당 timer 의 ID 를 선택하고 tmr.stop 버튼을 누르면 해당 timer 가 정지 됩니다. timer 모듈에 의해서 무한루프를 돌고 있을 때 사용하면 됩니다. 그리고 아래쪽으로 WiFi 연결을 쉽게 해 주는 기능이 있습니다.


이번에는 Snippets 탭에 들어가 봅니다. 총 16개의 Snippet 을 설정할 수 있습니다. 빨간 영역의 Edit Snippet 버튼을 누르고 Snippet 편집창에 자주 사용하는 코드를 넣어 주고 Save 버튼을 눌러서 저장해 줍니다. 그리고 오른쪽 시리얼 창의 노란색 영역의 Snippet0 ~ Snippet15 까지의 버튼이 있는데 저장한 Snippet 버튼을 눌러주면 입력한 소스를 실행해 주는 기능 입니다. 일종의 매크로 기능이라고 보시면 됩니다.


Snippet0 에 WiFi AP 리스트를 보여주는 소스를 저장하고 시리얼 창의 Snippet0 버튼을 클릭해서 실행한 모습 입니다. 시리얼 창에 WiFi 리스트가 쫙 뜹니다.


Settings 탭 입니다. ESPlorer 의 환경설정을 위한 기능들 입니다. NodeMCU 와 MicroPython 중 사용하고자 하는 펌웨어를 고를 수 있고 통신을 위한 설정들... 그리고 코딩을 하고 소스 저장 시 자동으로 ESP8266에도 Save 되도록 ESPlorer 실행 시 Default 로 잡혀 있는데 'AutoSave file to ESP after save to disk' 옵션을 Uncheck 해 주면 소스를 저장해도 자동으로 장치에 업로드 되지 않습니다. 따로 Save to ESP 버튼을 클릭해야만 소스가 장치에 업로드 됩니다. 


ESPlorer 는 AT Command 기반의 개발도 지원을 합니다. AT-based 탭에 들어가면 각종 AT Command 를 쉽게 사용할 수 있도록 많은 버튼들이 마련되어 있습니다.


끝으로 무료 소프트웨어 이나 마음에 들면 러시아 개발자에게 Donation 할 수 있습니다. 시리얼 창의 Donate 버튼을 누르면 paypal 로 이동해서 기부할 수도 있네요. ^^

반응형
반응형

이제 드디어 NodeMCU 개발 보드인 ESP8266(ESP-12E) 기반의 아미카(Amica) 를 인터넷에 연결해 보겠습니다. '드디어' 라는 말을 쓴 이유는 ESP8266 보드는 IoT(Internet of Things) 구현을 위한 보드인데 인터넷에 연결이 되지 않으면 아무런 의미가 없기 때문에 인터넷 연결을 시작으로 본격적인 개발을 할 수 있다는 의미에서 사용해 보았습니다.  이 글에서는 인터넷 Wi-Fi 에 보드를 연결해보고 통신이 되는지 확인해 보도록 하겠습니다. 시작하기 전에 예전에 올렸던 Amica 보드의 모습을 다시 보도록 하겠습니다.


보드는 위와 같이 생겼습니다. ESP8266 이라고 쓴 부분이 와이파이를 통해서 인터넷에 연결하고 각종 제어를 담당하는 핵심 부품인 MCU 부분 입니다. ESP8266 이라는 칩 입니다. 그리고 칩은 Wi-Fi 안테나와 연결이 되어서 무선 인터넷에 연결할 수 있도록 해 줍니다. 예전에 했던 말이지만 개발환경만 갖춘다면 꼭 위와 같은 보드가 아니더라도 ESP8266 칩을 사용한 어떠한 보드 모듈이라도 인터넷에 연결 할 수 있습니다. 다만 저의 경우는 ESP-01과 USB UART 로 NodeMCU 펌웨어와 ESPlorer  를 이용해서 개발을 시도해 봤지만 너무 불안정해서 이 보드를 사용할 뿐 입니다.


이번에는 저의 맥북을 사용해서 ESPlorer 를 통해서 보드에 연결을 해 보았습니다. 맥에서도 개발환경을 갖추기 위해서는 윈도우와 다를 바가 없습니다. Mac에  Mac OS X 용  CP2102 드라이버를 설치하고 ESPlorer 실행, 연결해서 Open 후 사용하면 됩니다.  다만 ESPlorer Open 시 윈도우에서는 COM1, COM2 등으로 포트를 지정했는데 맥에서는 '/dev/cu.SLAB_USBtoUART' 로 시리얼 통신 장치를 지정해 주면 됩니다.


자, 이제 준비는 끝났습니다. NodeMCU를 통해서 ESP8266을 인터넷에 연결해 봅시다.


■ credentials.lua 파일 생성

연결하려는 와이파이의 연결 정보를 담고 있는 파일 입니다. 그냥 코드에 적어 주어도 되지만 이런 정보는 파일을 분리해 주는 것이 좋습니다.


1
2
3
-- WiFi Connect information
SSID = "와이파이 이름"
PASSWORD = "와이파이 패스워드"
cs


ESPlorer 에서 File -> New 를 선택해서 새 파일을 생성해서 credentials.lua 라고 저장해 주면 됩니다. 물론 SSID (와이파이 이름), Password 는 자신이 연결하려는 와이파이 연결 정보를 입력해야 합니다. 이름은 꼭 credentials 가 아니어도 됩니다. 다만 파일을 로드 할 때는 그 이름을 사용해야 하겠죠. 위의 코드는 연결하려는 와이파이의 SSID, Password 를 설정하는 코드 입니다.



위와 같이 디스크에 저장 시 보드에 자동으로 업로드가 됩니다.



■ init.lua 파일 생성

init.lua 파일은 예전에 설명했던 바와 같이 NodeMCU가 처음으로 부팅될 때 기본으로 실행되는 파일 입니다. 이 파일에 인터넷 연결을 설정해 두면 보드에 전원이 공급될 시 자동으로 인터넷에 연결이 되는 것 입니다. 그러므로 인터넷 연결이 필수인 NodeMCU 에서는 init.lua 에 인터넷 연결 정보를 담아 놓으면 개발 시 편리하겠죠. 그 이외 보드 부팅 시 기본적인 Loading 이 필요한 사항을 담아 놓기도 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
 
function startup()
    if file.open("init.lua"== nil then
        print("init.lua deleted or renamed")
    else
        print("Running")
        file.close("init.lua")
        -- the actual application is stored in 'application.lua'
        -- dofile("application.lua")
    end
end
 
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
wifi.sta.connect()
tmr.alarm(110001, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
    else
        tmr.stop(1)
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 3 seconds to abort")
        print("Waiting...")
        tmr.alarm(030000, startup)
    end
end)
cs


init.lua 도 credentials.lua 와 마찬가지로 새파일을 만들고 위의 코드를 써서 저장을 해 줍니다. 맨 첫줄에 보면 credentials.lua 파일을 loading 하고 있습니다. 그리고 와이파이 연결 시까지 timer 모듈을 통해서 반복해서 연결이 시도되고 연결이 완료되면 startup function 을 call 합니다. 그리고 init.lua 를 닫아주고 프로그램이 실행될 실제 코드가 있는 application.lua (주석처리 되어 있음) 를 열어주게 됩니다. 인터넷 연결을 이용해서 실행될 실질적인 코드는 application.lua 에 위치하게 되는 것 입니다. 


위와 같이 credentials.lua 에 설정한 와이파이 연결 정보로 192.168.0.18 의 IP가 할당이 되고 인터넷에 연결이 되었습니다. 인터넷 연결이 되었으니 이 상태에서 본격적인 다음의 코드를 작업하면 되는 것 입니다. 이제 Amica 보드(ESP8266)에 전원이 들어오면 맨 먼저 위에서 설정한 인터넷에 연결을 시도할 것 입니다.


만약 잘 안된다면 credentials.lua 의 정보를 한 번 더 확인하고 두 파일을 모두 'Save to ESP' 버튼을 눌러서 개발보드(ESP8266)에 업로드 해 줍니다.



네트워크에 잘 연결이 되었는지 확인해 보기 위해서 위의 IP 로 ping 을 해 보았습니다.


통신이 잘 됩니다.


이상으로 ESP8266을 NodeMCU를 사용해서 인터넷에 연결해 보았습니다. 이제 이 작은 모듈이 인터넷이라는 거대한 네트워크에 연결이 되었으니 이를 무궁무진하게 활용하는 일만 남았네요. 상상력이 필요 합니다.


※ 참고 사이트 : https://nodemcu.readthedocs.io/en/dev/

반응형
반응형

NodeMCU 에서는 활용하기 쉽도록 미리 정의된 기능들의 모음이 있는데 이를 모듈(Modules) 라고 부릅니다. 여러가지 복잡한 기능들을 모듈화해서 간단한 명령으로 복잡한 프로그래밍 없이 동작하도록 만드는 것입니다. 예를 들어 NodeMCU 관련 이전 글에서의 소스를 봐도 많은 모듈이 사용되었습니다. 예전에 사용했던 소스를 다시 보면서 어떤 모듈이 사용되었는지 알아보겠습니다.


NodeMCU Logo



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- Pin definition 
local pin = 7            --  GPIO13
local status = gpio.LOW
local duration = 1000    -- 1 second duration for timer
 
-- Initialising pin
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, status)
 
-- Create an interval
tmr.alarm(0, duration, tmr.ALARM_AUTO, function ()
    if status == gpio.LOW then
        status = gpio.HIGH
    else
        status = gpio.LOW
    end
 
    gpio.write(pin, status)
end)
 
cs


"NodeMCU Lua 사용해보기 #2 - GPIO 사용 (LED Blink)" 글의 말미에 적었던 추가사항에 있던 소스 입니다. 모듈들은 gpio 모듈, tmr 모듈이 있습니다. 각각에 대해서 알아보겠습니다. gpio.mode() 는 말 그대로 gpio 핀의 상태를 설정 합니다. gpio.write() 는 디지털 출력핀에 해당 값을 적용 합니다. tmr.alarm() 은 여러가지 기능이 있는데 위의 경우는 while 문 처럼 해당 function 을 반복하는 기능을 합니다. 조금 더 자세히 알아보겠습니다.


■ 소스에 쓰인 Modules


1. gpio.mode() : gpio 핀의 초기화, 핀의 IN/OUT 을 지정하고 내부 pull-up 사용여부를 지정 합니다.

  • 문법

gpio.mode(pin, mode [, pullup])

  • 파라미터 

pin : pin to configure, IO index

mode : one of gpio.OUTPUT, gpio.OPENDRAIN, gpio.INPUT, or gpio.INT (interrupt mode)

pullup : gpio.PULLUP enables the weak pull-up resistor; default is gpio.FLOAT

  • gpio.mode() 의 문법과 파라미터 정의는 위와 같습니다. 고로 소스에 있는 gpio.mode(pin, gpio.OUTPUT) 의 의미는 해당 핀(7번 핀)을 OUTPUT (출력) 으로 지정하는 것 입니다. 


2. gpio.write() : 디지털 GPIO 핀에 값을 지정한다.

  • 문법

gpio.write(pin, level)

  • 파라미터 

pin : pin to write, IO index

level : gpio.HIGH or gpio.LOW

  • 소스에 있는 gpio.write(pin, status) 의 의미는 해당 핀(7번 핀)에 대해 if 문의 판단으로 status 변수에 값을 저장하고 HIGH 또는 LOW 로 지정하는 것 입니다.


3. tmr.alarm() : Timer 모듈의 하나로써 원하는 시간을 지정해 놓고 시간이 지나면 function() 을 실행 합니다. 

  • 문법

tmr.alarm(id, interval_ms, mode, function())

  • 파라미터 

id : timer id (0-6)

interval_ms : timer interval in milliseconds. Maximum value is 6870947 (1:54:30.947).

mode : timer mode:

tmr.ALARM_SINGLE a one-shot alarm (and no need to call tmr.unregister())

tmr.ALARM_SEMI manually repeating alarm (call tmr.start() to restart)

tmr.ALARM_AUTO automatically repeating alarm

  • 소스에 있는 tmr.alarm(0, duration, tmr.ALARM_AUTO, function () .....  의 의미는 소스에서 해당 타이머의 ID 는 0번으로 지정했고 duration (소스에서는 1초 ms 단위) 의 시간이 흐른 후 function() 을 실행하라는 의미 입니다. mode 지정으로 tmr.ALARM_AUTO 을 설정해서 타이머가 계속 반복 됩니다. 타이머가 한 번만 실행되게 하려면 mode 의 파라미터를 tmr.ALARM_SINGLE 로 지정 하면 됩니다.


위에서 알아본대로 NodeMCU 를 효율적으로 사용하기 위해서는 여러가지 모듈들을 잘 다룰 수 있어야 합니다. 모듈들에 대한 기능 정의는 아래의 사이트에 영문이지만 상세하게 설명되어 있습니다. 마음 같아서는 하나 하나 번역해서 본 블로그에서 소개하고 싶으나 분량이 꽤 되므로 그 때 그 때 필요한 모듈을 찾아보면서 사용하는 것이 효율적인 것 같습니다. 게다가 해당 모듈을 사용한 샘플코드도 제공하고 있으니 하나 씩 실행해 보면서 체험 하는 것이 제일 좋은 학습 방법 같습니다.


■ NodeMCU Documentation

https://nodemcu.readthedocs.io/en/dev/


사실 위의 문서는 우리가 NodeMCU 의 펌웨어를 설치하기 위해서 다운로드 받았던 펌웨어 Zip 파일에도 들어 있습니다.


■ NodeMCU 펌웨어 다운로드

https://github.com/nodemcu/nodemcu-firmware


위와 같이 펌웨어 다운로드 사이트에서 펌웨어 다운로드 후 docs 폴더에 들어가면 md(Mark Down) 파일로 모듈에 대한 문서들이 들어 있습니다. 위에서 설명 했던 gpio 에 관한 문서 gpio.md 도 있네요.


앞으로 NodeMCU 학습을 하거나 개발을 할 때 사이트를 띄우거나 문서를 보면서 각각의 모듈에 대해서 참고하면서 코딩하면 되겠습니다.

반응형
반응형

NodeMCU Lua 사용해보기 #2 글에서는 ESP8266 개발보드인 Amica 에 LED 를 달아서 깜빡여 보았습니다. 이번에는 온도센서인 LM35 를 달아서 LED 와는 반대로 센서값을 ESP8266 (Amica Board) 에서 입력받아 보겠습니다.  OUTPUT 을 해 봤으니 INPUT 도 알아봐야겠죠? 나중에 보드를 인터넷에 연결하는 방법을 익히게 된다면 센서값을 인터넷을 통해서 볼 수 있게 될 것입니다. 그것이 이 보드의 제일 중요한 역할이니까요. 이미 아두이노와 ESP8266 (ESP-01) 을 이용해서 AT Command 기반으로 ThingSpeak 연동까지 해 봤지만 이젠 ESP8266 과 NodeMCU Lua 기반으로 인터넷에 접속이 되는 것입니다. 본격적인 사물 인터넷의 시작이라고 할 수 있겠습니다. 아무튼 그렇게 되기 위해서는 기초가 중요 합니다.


https://arduino-info.wikispaces.com/LM35

LM35 온도센서 입니다. 작동 전압은 2.7V ~ 5.5V 입니다. 고로 Amica 보드의 3,3V 에 연결하면 되겠습니다. 


ESP8266 Amica Board Pin Definition - http://artofcircuits.com



■ 연결


 LM35

 ESP8266 (Amica Board)

 VCC

 3.3V

 Signal

 A0

 GND

 GND


LM35와 Amica의 연결 입니다. 전원은 보드의 3.3V 를 이용하고 Signal 은 보드의 Analog In 단자인 A0 에 연결 합니다.





■ 소스 및 결과


1
2
3
4
5
6
  while 1 do
    r = adc.read(0)
    c = r * 285 / 1024
    print("temperature = " .. c)
    tmr.delay(1000000)   -- wait 1,000,000 us = 1 second
  end
cs


소스는 매우 간단 합니다. 변수 선언도 필요가 없네요. LED Blink 소스처럼 while 을 이용해서 1초 마다 반복되도록 했습니다. A0 에서 센서의 값을 받아서 값을 섭씨 온도로 바꿔주고 Print 해주면 됩니다. 어떻게 보면 아두이노의 C언어 코드보다 더욱 간단합니다. 


= adc.read(0) 에서 A0 (Analog in) 의 온도값을 읽습니다. adc 는 Analog to Digital Converter 를 뜻 합니다. 그 아래 줄은 LM35로 부터 받은 값을 섭씨온도로 고쳐주는 부분 입니다.


그리고 여기서 처음 보는 문법이 나오는데 print("temperature = " .. c)  부분 입니다. .. 가 문자열을 연결해 주고 있습니다. 매우 편합니다.


작성 후 Send to ESP 를 클릭해서 보드에서 실행을 시켜 봅니다.


위와 같이 LM35 의 온도값을 읽어서 시리얼 창에 1초 간격으로 잘 나타내 줍니다.   



하기 전에는 막막했는데 이제 뭔가 감이 오는 것 같습니다. GPIO I/O 를 해 봤으니 다음 부터는 Wi-Fi 연결을 통해서 본격적으로 무언가 해 볼까 합니다.

반응형
반응형

이전 글에서는 ESPlorer 를 이용해서 간단한 코드를 작성하고 업로드하고 실행해 보았습니다. 이번에는 ESP8266 개발보드인 Amica 의 GPIO 단자를 제어해 보겠습니다. GPIO 단자에 LED를 연결해서 제어해 보는 것 입니다. 아두이노의 Blink 예제와 비슷한 것입니다. 다만 다른 점이라면 하드웨어가 다르고 C 언어를 사용하는 아두이노와 다르게 Lua 언어를 사용한다는 점 입니다. Amica 보드의 입출력 단자는 ESP-12E 기반으로 모든 단자를 이용할 수 있도록 되어 있습니다.


ESP8266 Amica Board Pin Definition - http://artofcircuits.com

핀의 배치는 위와 같습니다. 13개의 GPIO 단자가 있습니다. 여기에 LED를 연결하고 제어해 보겠습니다.


■ 연결 & 준비

Amica 보드의 D1 에 LED의 + 를 연결하고 GND에 - 를 연결했습니다. 보드는 PC에 연결하고 ESPlorer 를 실행 하고 Open 버튼을 눌러서 보드와 통신을 연결해 줍니다.


ESPlorer 가 실행된 모습 입니다. Open 을 눌러 줍니다.


ESP8266 과 연결이 되었습니다.


코딩 준비 끝.


■ 소스


1
2
3
4
5
6
7
8
while 1 do
  gpio.write(1, gpio.HIGH)
  print("LED ON")
  tmr.delay(1000000)   -- wait 1,000,000 us = 1 second
  gpio.write(1, gpio.LOW)
  print("LED OFF")
  tmr.delay(1000000)   -- wait 1,000,000 us = 1 second
end
cs


소스창에 위와 같이 입력하고 'Send to ESP' 를 클릭해서 보드에서 실행해 봅니다. 여기서 알고 넘어가야 할 것이 Send to ESP 는 임시로 보드에 올려서 코드를 테스트 해 보는 것입니다. 보드를 USB 에서 뺏다가 다시 실행하는 경우 프로그램이 날아갑니다. 하지만 ESPlorer 의 Reset 버튼을 눌러서 Soft Reset 하는 경우는 프로그램이 날아가지 않습니다. 전원을 빼거나 보드의 리셋 버튼을 눌러서 Hard Reset 하는 경우만 프로그램이 날아갑니다. 


반면 Save to ESP 는 전원을 제거하거나 Hard Reset 하는 경우도 프로그램이 사라지지 않습니다. 보드에 저장이 되는 것이죠. 이 경우 수정하려면 ESPlorer 에서 프로그램을 재작성해서 Save to ESP 해서 덮어 쓰거나 file.remove("파일명") 해서 삭제 후 재 업로드 하는 방법이 있습니다. 가끔 아무리 리셋을 해도 예전에 Save to ESP 했던 프로그램이 사라지지 않고 ESPlorer에서 인식도 되지 않는 경우가 있는데 이럴 경우 다소 무식한 방법이지만 고민하지 말고 펌웨어를 다시 올려서 보드를 완전 초기화 시켜 버리면 됩니다.


소스는 간단합니다. 문법은 lua 를 사용하기 때문에 아두이노의 C언어와는 다릅니다. while 문에 의해서 계속 반복이 되는 코드 입니다. 아두이노의 loop() 같이 무한반복이 되겠죠. gpio.write(1, gpio.HIGH) 는 D1 에 HIGH 신호를 보냅니다. LED가 켜지는 것이죠. 타이머 같은 경우는 아두이노의 경우 밀리세컨드 단위로 조절을 했는데 여기서는 나노세컨드 단위 입니다. 0 이 세 개 더 붙습니다. 고로 tmr.delay(1000000) 하면 1초 동안 동작을 delay 합니다. print 는 시리얼 창에 출력을 해 줍니다.


실행 결과를 보겠습니다.



이상으로 ESP8266 보드인 Amica 에 LED 를 달아서 GPIO 를 통해서 제어해 보았습니다.



▶추가내용(2016.07.04) : 위의 기능과 같은 소스를 while 문이 아니라 NodeMCU 의 Timer 모듈(Modules)을 통해서 구현할 수도 있습니다. 사실 이 방법이 훨씬 좋은 방법 입니다. 위의 소스는 무한루프가 돌게 되어 있어 프로그램 수정이 불가능할 수도 있습니다. 타이머 같은 경우도 무한루프이긴 하지만 tmr.stop(타이머ID) 명령으로 무한루프를 멈출 수 있거든요.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- Pin definition 
local pin = 7            --  GPIO13
local status = gpio.LOW
local duration = 1000    -- 1 second duration for timer
 
-- Initialising pin
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, status)
 
-- Create an interval
tmr.alarm(0, duration, tmr.ALARM_AUTO, function ()
    if status == gpio.LOW then
        status = gpio.HIGH
    else
        status = gpio.LOW
    end
 
    gpio.write(pin, status)
end)
cs


위의 소스에서 tmr.alarm() 부분이 NodeMCU 의 Timer 모듈 입니다. 파라미터를 통해서 동작하는데 첫 번째부터 Timer ID, 반복 간격 (Milli Second 단위), Timer Mode, 그 다음 실행할 Function 으로 구성되어 있습니다. 더욱 자세한 모듈에 대한 설명은 [여기] 를 클릭하시면 볼 수 있습니다.

반응형
반응형

이전 글 에서 ESP8266 개발보드인 Amica에 NodeMCU 펌웨어를 설치해보고 개발툴인 ESPlorer 연결까지 해 보았습니다. 이번에는 처음으로 보드에 프로그램을 올려보려고 합니다. 저도 인터넷 뒤져서 습득한 내용이니 틀린 내용을 전달할 가능성도 있습니다. 혹시 이 글을 보다가 틀린 것을 발견하면 댓글 부탁 드립니다. 이 글의 내용을 실습해 보려면 우선 [이전 글] 을 참고해서 개발환경이 세팅되어 있어야 합니다. 개발보드는 당연히 있어야 하구요. 하드웨어는 ESP8266 보드라면 Amica 가 아니어도 어떤 보드라도 상관은 없습니다. 다만 저의 경험상 ESP-01 + USB UART 에서는 너무 불안정한 모습을 보여주어서 개발용으로는 추천하지는 않습니다. 그럼에도 불구하고 혹시 ESP-01 로 시도해 보려는 분들은 [여기] 를 참고해서 개발환경을 갖추어 주면 됩니다.


NodeMCU 펌웨어를 올린 개발보드를 PC에 연결하고 ESPlorer 를 실행한 후 Open 을 누르면 보드와 연동이 되었었습니다. 그런데 Reset 을 누르게 되면 시리얼 창에 다음과 같은 메시지가 나옵니다.


NodeMCU 0.9.6 build 20150704  powered by Lua 5.1.4


Communication with MCU...

Got answer! AutoDetect firmware...

Communication with MCU established.

Can't autodetect firmware, because proper answer not received (may be unknown firmware). 

Please, reset module or continue.

lua: cannot open init.lua


리셋 할 때마다 Can't autodetect firmware, because proper answer not received (may be unknown firmware). Please, reset module or continue. 라는 이상한 메시지가 계속 나오는데 무시합니다. 어쨋건 작동은 다 되니까요. (구글링을 조금 해 봤는데 없애는 방법을 찾지 못 했습니다. 다들 그냥 쓰더군요. 혹시 방법을 아는 분은 댓글 부탁 드립니다.)


위의 메시지 맨 마지막줄에 보면 init.lua 를 열 수가 없다고 나옵니다. 보드가 리셋 되고 부팅될 때 처음 찾는 파일이 init.lua 같습니다. 그래서 init.lua 파일을 만들어서 업로드를 해 보았습니다.


■ init.lua 로 Hello World 찍어 보기


1. ESPlorer 에서 File -> New 를 선택해서 새 파일을 하나 열어 줍니다.

2. 소스 입력창에 print("hello world") 라고 코드를 작성합니다. lua 의 주석은 '--' 로 시작 합니다.


3. File -> Save to disk 를 선택해서 ESPlorer 가 설치된 폴더의 하위인 _lua 폴더에 init.lua 라는 이름으로 작성된 코드를 저장해 줍니다. 그런데 사실 Save 만 해도 파일도 저장이 되고 보드에 업로드까지 자동으로 됩니다. 굳이 Save to ESP 버튼을 눌러서 업로드를 할 필요는 없습니다. 


4. 파일을 저장하니 소스가 보드에 자동으로 업로드 되었지만 그래도 기능도 알아볼 겸 소스창 하단에 Save to ESP 버튼을 클릭해서 Amica 보드에 저장을 해 봅니다. 


위와 같이 시리얼 창에 표시가 되면서 프로그램이 보드로 업로드가 됩니다. 여기서 알 수 있는 것은 file.remove() 는 보드에 업로드된 파일을 제거하는 명령어이고 file.open() 은 업로드할 프로그램을 오픈 하는 것이고 file.close() 는 파일을 닫고 dofile() 은 업로드된 파일을 실행하는 명령이라는 것임을 알 수 있습니다. 실제로 소스창에 dofile("init.lua") 라고 작성하고 하단의 Send to ESP 버튼을 클릭하면 보드의 init.lua 코드가 실행이 됩니다. Send to ESP 는 ESP8266 에 명령을 하는 기능 입니다.

위와 같이 실행이 됩니다. 앞으로 ESP8266에 명령을 내릴 때에는 위와 같은 방법으로 하면 됩니다. 조금 더 편한 방법으로 명령을 내리고 싶다면 아래와 같이 하면 됩니다.


시리얼 창 아랫 부분에 보면 위와 같이 드랍 다운 메뉴가 있습니다. 눌러보면 위와 같이 기본적인 명령어들을 모아 놓았습니다. dofile("") 을 클릭하고 쌍따옴표 안에 파일명을 적고 Send 버튼을 눌러도 명령어가 실행이 됩니다.



5. 이제 보드에 init.lua 가 저장이 되었습니다. 보드는 처음 부팅 시 이 파일을 무조건 실행하게 될 것 입니다. Reset 버튼을 눌러서 Reset 을 해 봅니다.


Reset 시 보드가 부팅이 되면 맨 먼저 init.lua 를 찾아서 실행 되면서 'Hello World' 라는 문자열이 시리얼 창을 통해서 출력이 되는 것을 확인 할 수 있습니다.


6. init.lua 파일의 수정, 삭제

init.lua 파일의 변경은 코드를 새로 작성하고 'Save to ESP' 버튼을 누르면 덮어쓰게 됩니다. 만약에 init.lua 또는 다른 파일을 삭제하고 싶다면 file.remove("파일명")  명령을 'Send to ESP' 하면 됩니다.


file.remove("init.lua") 를 'Send to ESP' 하고 Reset 한 결과 입니다. init.lua 파일을 open 할 수 없다는 메시지가 나옵니다.



이상,... 처음으로 ESP8266 보드인 Amica 보드에 NodeMCU Lua 와 ESPlorer 를 이용해서 코드도 올려보고 명령어를 통해서 제어도 해 보았습니다. 앞으로 초보의 입장에서 하나 하나 NodeMCU Lua 에 대해서 알아보도록 하겠습니다.



▶추가사항 (2016.07.04) : NodeMCU 는 Lua 를 기반으로 하고 있지만 정확히 말하자면 eLua 라는 언어를 기반으로 한다고 합니다. Embeded 에 Lua 를 붙여서 eLua 라고 합니다. Lua 문법을 따르지만 Embeded 시스템에 특화된 언어라고 합니다. eLua 에 대한 정보는 다음의 URL을 참고해 주세요.



Embedded power, driven by Lua : http://www.eluaproject.net/

반응형
반응형

지난 글 에서 ESP8266 모듈의 일종인 ESP-01 에 NodeMCU 기반의 개발을 위해 개발환경을 설치해 보았습니다. 그러나 안타깝게도 마지막 추가 내용에 썼듯이 ESPlorer 개발툴에서 장치가 자꾸 다운되거나 통신포트가 끊기는 매우 불안정한 모습을 보여 주었습니다. 그래서 ESP-01은 AT Command 기반의 개발에만 사용할 예정이고 새로운 보드를 영입 했습니다. 시리얼 통신칩(CP2102)과 레귤레이터, ESP8266 등이 하나의 보드에 합쳐져 있는 Open Source IoT Platform 보드 입니다. 보드에 이름도 있는데 Amica 라는 이쁜 이름의 보드 입니다.  가격은 알리 직구로 5000원 정도 합니다. 앞으로 이 보드를 가지고 사물 인터넷 연습을 해 볼 생각 입니다.


보드의 구조는 위와 같습니다. PC에 연결해서 개발하라고 나온 보드이니 ESPlorer 에서도 잘 인식하겠죠?


뒷면 입니다. 모든 ESP8266의 I/O가 가능한 핀들이 있습니다. 작은 글씨로 간단한 사용법이 적혀 있습니다. 



1. Install CP2102 Driver

2. Use 9600 Baud Rate

3. Connect Wi-Fi and Enjoy

VIN +5V Recommended +10V Max


라고 뒷면에 적혀 있습니다. 시리얼 통신을 위한 칩인 CP2102 드라이버를 설치해서 PC에서 포트를 잡고 9600 Baud rate 를 사용해서 통신하고 와이파이에 연결해서 즐겨라 라고 되어 있네요.


AMS1117 레귤레이터가 있으므로 VIN 의 전압은 5V~10V 입력까지 허용이 됩니다. 다만 5V 를 권장한다고 되어 있네요.


ESP8266 Amica Board Pin Definition - http://artofcircuits.com

보드의 Pin 정의 입니다. ESP-12E 의 모든 기능을 사용할 수 있습니다.



1. CP2102 USB UART 드라이버 설치

https://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx#windows 에 들어가면 CP2102 드라이버를 다운 받을 수 있습니다. Windows 뿐만 아니라 거의 모든 OS의 드라이버를 받을 수 있습니다. 다운로드 받아서 설치를 해 줍니다.

CP2102 Drivers All OS.zip



2. NodeMCU 펌웨어 설치

왠지 이 보드는 펌웨어 설치가 필요 없어 보였으나 CP2102 드라이버 설치 후 그냥 ESPlorer 에서 Open 해 보았는데 연결이 되지 않더군요. 그래서 펌웨어를 설치해 주었습니다. R2 버전 부터는 펌웨어가 설치되어 판매 된다는데 이건 R1 인가? 모르겠습니다. 펌웨어 설치는 ESP-01 과 같습니다. Flasher 프로그램을 실행해서 펌웨어 Binary 파일을 열고 Flash 버튼을 누르면 됩니다.


https://github.com/nodemcu/nodemcu-flasher 에서 Flasher 프로그램을 다운로드 받습니다.

nodemcu-flasher-master.zip

 

https://github.com/nodemcu/nodemcu-firmware/releases 에서 최신의 Bin 을 받습니다. Bin 은 Integer 타입을 받아 줍니다. 

nodemcu_integer_0.9.6-dev_20150704.bin


Flasher 프로그램을 실행하고 아래와 같이 Bin 파일을 지정하고 Flash 버튼을 누르면 끝 입니다.

Config 탭에서 톱니바퀴 모양을 클릭하고 Bin 파일(NodeMCU 펌웨어)을 지정해 줍니다.


Flash 버튼을 누르면 펌웨어가 업로드 됩니다.


NodeMCU 펌웨어 업로드를 무사히 마쳤으면 장치를 한 번 PC에서 뺏다가 껴야 합니다. 그리고 개발툴인 ESPlorer 를 실행 합니다.


http://esp8266.ru/esplorer/#download ESPlorer 다운로드 주소 입니다. ESPlorer는 java 기반이기 때문에 Java 가 설치 되어 있어야 실행이 됩니다. 안 되어있다면 https://java.com/ko/download/ 여기에서 설치하면 됩니다.

ESPlorer.zip


ESPlorer는 그냥 압축을 풀고 ESPlorer.jar 파일을 실행하면 열립니다. 


ESPlorer 를 실행하면 정상적으로 위의 과정이 진행되었다면 위와 같이 통신포트가 자동으로 잡히고 Open 을 클릭하면 Amica 와 연결이 됩니다. 그리고 Reset 버튼을 눌렀더니 위와 같이 제가 설치한 펌웨어의 버전인 0.9.6 이 나옵니다. 오른쪽 창은 시리얼 통신 내용을 보내주는 창이고 왼쪽 창이 Lua 코딩을 위한 창 입니다.


드디어 안정적인 IoT 개발환경이 꾸며졌습니다. 이제 공부하는 일만 남았네요. 그런데 국내 인터넷에는 Lua 에 대한 정보가 너무 없습니다. 책도 거의 없구요. 참 힘이 들지만 남들이 별로 가지 않았던 길이기에 재미 있는 작업이 될 것 같습니다.



※ 추가내용 (2018.09.05) : http://deneb21.tistory.com/591 에 아두이노 IDE에 개발환경 만드는 방법을 올렸다.

반응형
반응형

저가의 IoT 솔루션으로 각광받고 있는 Espressif 사의 와이파이 모듈인 ESP8266 에는 32비트 MCU가 달려 있습니다. 그래서 아두이노 없이 모듈 단독으로 프로그램을 업로드하여 용도에 맞게 사용이 가능합다. 아두이노의 8Bit 보다 성능이 좋은 MCU가 달려 있는 셈입니다. ESP8266을 단독으로 사용하는 방법에는 여러가지 방법이 있지만 NodeMCU 라는 IoT 플랫폼을 이용하는 방법이 각광을 받고 있습니다. NodeMCU는 Lua 라는 스크립트 언어를 사용합니다. 이번에는 ESP8266 을 위한 NodeMCU 개발환경을 만들어 보겠습니다. 개발환경을 구성하는 방법은 크게 2단계 입니다. NodeMCU 펌웨어 설치, NodeMCU Lua 개발환경 설치 입니다.


연결

PC와의 통신을 위해 FTDI FT232RL 칩을 사용한 USB UART 모듈과 ESP8266 을 연결하고 PC 의 USB 단자에 연결했습니다. ESP8266(ESP-01) 모듈에 대한 자세한 사항은 [이전 포스팅] 을 참조 하면 됩니다.


ESP8266 PINOUT 단자

ESP8266 (ESP-01) 모듈 입니다. 핀 배열은 위와 같습니다.


FTDI사의 FT232RL 칩을 사용한 USB UART 모듈 입니다. 이것 말고 CH340 칩을 이용한 좀 더 저렴한 모듈을 이용해서 설치를 해 보려고 했으나 펌웨어 까지는 정상적으로 설치가 되는 것 같은데 개발툴인 Esplorer 에서 인식하지 못하는 문제가 있었습니다. 약간 비싸지만 이 모듈을 사용해서 개발을 진행하는 것이 안정적일 것 같습니다. 이 모듈의 출력전압은 전압선택 점퍼를 통해서 결정 됩니다. ESP8266 은 3.3V 에서 동작하기 때문에 3.3V 쪽으로 점퍼를 끼워주어야 됩니다.


■ FTDI FT232RL USB UART 모듈 드라이버 설치

http://deneb21.tistory.com/393

 

USB UART

ESP8266 (ESP-01)

VCC (3.3V)

VCC

VCC (3.3V)

CH_PD

GND

GND 

GND

GPIO0 (펌웨어 설치에만 사용)

TXD

RX

RXD

TX








위와 같이 USB UART 와 ESP-01 을 연결하면 됩니다. 여기서 주의할 사항이 있는데 펌웨어 업데이트 시에만 GPIO0 단자가 연결되고 Esplorer 등으로 개발할 경우에는 GPIO0 단자를 빼야 한다는 것입니다. 


그림으로 그려보면 위와 같이 됩니다. 펌웨어 업데이트 시에는 위와 같이 연결하고 개발 시에는 GPIO0 연결을 끊어주면 되는 것입니다.




1. ESP8266에 NodeMCU 펌웨어 설치하기

NodeMCU 펌웨어 설치를 위해서는 펌웨어와 펌웨어를 ESP8266에 올릴 수 있는 Flasher 프로그램이 필요 합니다. 두 가지 소프트웨어를 다운로드 받습니다.


■ 펌웨어 : https://github.com/nodemcu/nodemcu-firmware/releases 에서 nodemcu_integer_0.9.6-dev_20150704.bin 를 다운로드 받았습니다.

nodemcu_integer_0.9.6-dev_20150704.bin



■ 펌웨어 Flasher : https://github.com/nodemcu/nodemcu-flasher 에서 Download Zip 을 클릭해서 다운로드 받았습니다.

nodemcu-flasher-master.zip




NodeMCU 펌웨어 설치를 위한 준비는 끝났습니다.


이제 펌웨어를 설치해야 합니다. ESP-01 이 연결괸 USB UART를 PC에 연결 합니다.


다운로드 받은 NodeMCU Flasher 의 압축을 풀면 Win32, Win64 폴더가 나오는데 자신의 윈도우 OS 버전에 맞는 파일을 실행하면 됩니다. 저는 64비트 버전의 윈도우라 Win64 안에 있는 ESP8266Flasher.exe 를 실행했습니다.


우선 USB To TTL 이 연결된 PC의 COM 포트를 알아야 합니다. 장치관리자에서 확인 COM6 포트로 연결됨


ESP8266Flasher.exe 를 실행했습니다. COM6 포트로 연결 되었습니다. 자동으로 포트가 잡히지만 맞는지 확인해 봅니다.


Config 탭을 눌러서 위에서 다운로드 받은 펌웨어 파일을 선택해 줍니다. 톱니바퀴 모양을 누르면 펌웨어 선택창이 뜹니다.


Operation 탭으로 돌아와서 Flash 버튼을 클릭 합니다. ESP8266에 펌웨어가 설치 됩니다. 


잠시 후 펌웨어 설치가 완료 됩니다.




2. NodeMCU 개발환경(Esplorer) 설치하기

NodeMCU 개발도구는 Esplorer 입니다. Java 로 작성되어 있기 때문에 실행을 위해서는 Java 가 설치되어 있어야 합니다. 설치되어 있지 않다면 아래의 링크를 클릭해서 설치해 주세요. 그리고 잊지 말아야 할 것이 펌웨어 설치 시 의 연결에서 USB UART 모듈과 연결된 GPIO0 의 연결을 끊어주어야 개발툴과 통신이 됩니다.


■ Esplorer 다운로드 : http://esp8266.ru/esplorer/#download 사이트에서 다운로드 받을 수 있습니다. 

ESPlorer.zip


■ Java 다운로드 : https://java.com/ko/download/


Esplorer 의 실행은 ESPlorer.bat 를 실행하면 됩니다. 아무런 반응이 없으면 Java 가 설치되지 않은 것이

므로 위의 Java 설치 링크를 클릭해서 설치해 줍니다.


ESP8266 은 펌웨어 업데이트 후 USB 단자에서 뽑아서 GPIO0 연결을 제거하고 다시 PC에 연결 합니다. 그리고 Esplorer 를 실행 합니다. Esplorer.jar 를 실행해도 상관은 없습니다.


Esplorer 에서 Open 을 클릭 합니다. ESP8266 과 연결하는 단계 입니다.


포트가 연결되고 MCU 와 연결을 시도 합니다. NodeMCU 펌웨어가 발견 되었다고 나옵니다. Esplorer와 ESP8266 모듈이 연결된 것입니다.


아래 Heap, Chip Info, Chip ID 등을 눌러보니 정보를 제대로 가지고 옵니다. 이제 왼쪽 프로그램 소스 입력창에 프로그램을 작성하고 ESP8266 으로 보내면 되는 것입니다.


이상으로 ESP8266(ESP-01)에 NodeMCU 펌웨어를 설치하고 개발환경을 구성해 보았습니다. 이제 어떻게 개발하는지 공부하는 일만 남았군요. NodeMCU 개발에 대해서는 저도 자세한 것은 모르는데 앞으로 익혀가면서 포스팅할 예정 입니다.



※ 추가내용(2016.06.30) : 위와 같이 개발환경을 설치하고 Lua 에 대해서 알아 보던 중 이상한 현상이 발생 하네요. ESplorer 에서 Lua 로 와이파이 연결을 테스트 하던 중 PC에서 장치의 인식이 끊기면서 (장치 관리자에서 사라짐) 통신이 되지 않는 사태가 발생 합니다. 저의 생각으로는 ESP8266 이 전류를 많이 잡아 먹어서 발생하는 문제 같기도 하고 그렇습니다. 그런데 이게 참 열 받는게 어떤 때는 또 잘 되기도 합니다. 장치의 인식이 끊기면 모듈에서 엄청난 열이 발생 합니다. 열을 식히고 다시 연결하면 잘 되기도 합니다. 아무래도 ESP-01 모듈은 아두이노와 연결해서 AT Command 기반의 프로그래밍을 하는게 맞는 것 같고 ESplorer 개발은 전용 개발보드를 이용하는게 좋을 것 같습니다. 


사실 전용보드를 구입했거든요. ^^



※ 추가내용 (2018.09.05) : http://deneb21.tistory.com/591 에 아두이노 IDE에 개발환경 만드는 방법을 올렸다.

반응형

+ Recent posts