이번에는 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(1, 1000, 1, 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(0, 3000, 0, 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 에 조금 더 업그레이드 된 소스를 올려 놓았다. (릴레이 현재상태를 알 수 있도록 함.)
'ESP8266' 카테고리의 다른 글
NodeMCU Lua 사용해보기 #14 - 인터넷에서 현재시간 가져오기 (2) | 2016.07.29 |
---|---|
NodeMCU Lua 사용해보기 #13 - 인터넷을 통한 릴레이 제어 #2 (18) | 2016.07.26 |
NodeMCU Lua 사용해보기 #11 - dweet.io 온습도 데이터 업로드 (0) | 2016.07.19 |
MQTT 개념과 Mosquitto 설치 및 사용 (0) | 2016.07.12 |
ESP8266 보드 비교 및 선택기준 (0) | 2016.07.10 |