사물인터넷(IoT)2016. 7. 7. 15:32

지난 글들에서 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


반응형
Posted by 대네브 (deneb)

댓글을 달아 주세요

  1. a

    웹페이지를 새로고침 할때마다 7번째줄 srv:listen(port, function(conn) 이부분부터 실행하는것을 확인했는데요

    사용자가 웹페이지를 새로고침하는 등의 직접적인 간섭이 없어도 실시간으로 계속 갱신하는 방법은 없을까요?

    즉, 제가지금 하는 과정이 외부 MCU에서 어떠한 값을 연속으로 4번 보내고 그것을 esp8266의 핀에서 읽어와야 하는데
    지금 할수있는 방법은 1번째보내고 웹페이지 새로고침해서 esp8266에서 읽어오고,
    2번째보내고 또 웹페이지 새로고침해서 esp8266에서 읽어오고.. 이렇게 4번을 각각 MCU에서 보낼때마다 새로고침을 해야합니다..

    외부 MCU에서 보낸 값을 웹페이지 새로고침 없이 자동으로 읽어와서 변수에 저장시키고 싶은데요
    어떻게 구현을해야할까요?..

    음..좀더 쉽게 말하면 esp8266이 무한루프를 돌면서 계속 실시간으로 외부에서 오는 데이타의 입력을 대기하고있는겁니당..

    2017.02.24 14:05 [ ADDR : EDIT/ DEL : REPLY ]
  2. 9577

    똑같이 dht.read(5) 으로 했는데 lolin nodemcu사용 중입니다. D5에 꼽았는데 시리얼 값이 계속 -2가 뜨네요... 왜그럴까요..

    2017.11.24 16:05 [ ADDR : EDIT/ DEL : REPLY ]
    • 글쎄요. 일단 같은 esp8266 기반이기 때문에 lolin 이건 amica 건 상관은 없습니다. 펌웨어는 잘 올라간것 맞나요? 아무튼 글만봐선 잘 모르겠네요. 다시 한 번 점검해 보시길... 또는 nodemcu 가 아닌 아두이노IDE를 통해서도 개발이 가능하니 그쪽도 알아보시면 좋을 겁니다. nodemcu가 사용하는 lua가 좀 생소한 면이 많아서...

      2017.11.25 20:00 신고 [ ADDR : EDIT/ DEL ]