반응형

예전에 작성했던 글 http://deneb21.tistory.com/222 에서는 전자석의 원리를 이용한 접점식 릴레이를 아두이노에서 제어하는 방법을 알아보았다이번에는 기계식 접점이 없는 반도체식 릴레이인 SSR (Solid State Relay)  아두이노에 연결해서 제어해 보려고 한다. 사실 아두이노에서의 사용방법은 접점식 릴레이와 거의 같다. 기존 릴레이 대비 SSR의 장점으로는 기계적으로 움직이는 부품이 없으므로 수명이 반영구적이다. (접점식 릴레이는 접점이 떨어졌다 붙었다 하면서 발생되는 아크 채터링에 의한 열화로 고장이 생길 수 있다.) 작동 시 소음이 전혀 없다. 전류의 스위칭이 매우 빠르다. 등이 있겠다. 단점으로는 반도체 스위칭 시 발열이 발생할 수 있다는 점이다


위의 그림이 내가 가지고 있는 1채널 SSR 모듈이다. SSR을 사용하기 쉽도록 단자를 달아서 모듈 형태로 만든 것이다. 기존 릴레이 메이커인 일본 Omron 사의 SSR을 이용하고 있다. INPUT 5V DC 이며 LOAD 240VAC 2A 이므로 아두이노의 5V 전원과 디지털 단자로 충분히 제어가 가능하며 우리나라의 가정용 전원인 220VAC 의 제어가 가능하다. 가격은 기존 접점식 릴레이 모듈 대비 3배 정도 비싸다. (1채널 알리익스프레스 기준, 접점식 릴레이 모듈 0.5달러, SSR 모듈 1.5 달러)
 


연결은 위와 같이 된다. 제어 입력부에 3개의 단자가 있는데 CH1 에는 아두이노의 디지털 단자를 DC- DC+ 에는 아두이노의 GND 5V를 연결하면 된다. 스위칭 부분에는 아래와 같은 전원 콘센트를 만들어 사용했다.


220V용 콘센트, 플러그, 전선을 가지고 위와 같은 선을 만들고 SSR의 스위칭 제어부에 연결하였다. 위험한 220V 전원을 사용하므로 매우 주의해서 연결해야 한다.

※ 만약 이 글을 보고 따라하려는 사람이 있다면 220V의 높은 전압을 다루게 되므로 자칫 잘못하면 감전되어 다칠 수 있으므로 주의를 기울여야 하며 사용하려는 릴레이의 허용전압/전류를 꼭 확인하고 사용해야 한다.


SSR 모듈의 뒷면.

 

1
2
3
4
5
6
7
8
9
10
11
12
int relay = 8//릴레이에 5V 신호를 보낼 핀설정
void setup ()
{
  pinMode (relay, OUTPUT); // relay output으로 설정한다.
}
void loop ()
{
  digitalWrite (relay, HIGH); // 릴레이 ON
  delay (10000);              //10 delay
  digitalWrite (relay, LOW); // 릴레이 OFF
  delay (5000);               //5 delay
}
cs


아두이노 우노를 사용하였고 소스는 기존의 릴레이 제어 소스와 동일하다. 위의 소스에서는 제어핀으로 D8을 릴레이의 CH1에 연결하였다10초 동안 전원이 켜지고 (SSR ON) 5초 동안 전원이 꺼지는 것이 반복된다. (SSR OFF)


소스대로 SSR 동작하는 모습이다. 220V 전원에 헤어드라이기를 연결하였다. 우선 기존의 접점식 릴레이와 틀린점이 보인다. 접점이 붙었다 떨어지는 소리인 '딸깍' 하는 소리가 전혀 나지 않는다

조용해야 하는 , 긴 수명을 가진 릴레이가 필요한 곳, 빠른 전류의 단속이 필요한 곳 등에서는 접점식 릴레이 보다는 SSR (Solid State Relay) 를 사용하는 것이 더욱 현명한 선택일 것이다. , 접점식에 비해 비싸므로 가성비도 따져보아야 할 것이다.

반응형
반응형

아두이노나 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 에 조금 더 업그레이드 된 소스를 올려 놓았다. (릴레이 현재상태를 알 수 있도록 함.)

반응형
반응형

4채널 릴레이 모듈을 구입해서 아두이노 나노와 연결해서 테스트 해 보았습니다. 우노가 아니라 나노와 연결해서 릴레이 동작을 위한 전력이 부족할지 우려가 되었는데 결론적으로 나노의 5V 출력과 디지털핀 연결을 통해서도 모든 동작이 가능했습니다. 릴레이에 대해서는 예전의 글인  '[아두이노] 릴레이(Relay)를 이용하여 220V 전원을 제어해보자' 라는 글에서 릴레이의 원리부터 자세히 알아 본 적이 있으므로 참고 하시면 됩니다. 


모듈은 위와 같이 생겼습니다. 4개의 릴레이가 붙어 있고 각각 상태를 나타내는 LED 가 붙어 있습니다. 그리고 제어를 위한 핀 4개와 전원연결 핀 2개, 총 6개의 핀이 있습니다. 사진의 릴레이의 스위칭 가능 전력은 AC250V 10A, DC30V 10A 이므로 AC의 경우 우리나라 가정용 전원인 220V 전원을 컨트롤 가능 합니다. 동작 전원은 5V 를 이용하며 IN1 ~ IN4 에 아두이노의 디지털 핀을 연결해 주면 됩니다.


■ 릴레이 데이터시트

solgle_relay_datasheet.pdf



릴레이의 전원제어부 단자 입니다. 릴레이 1개당 3개의 단자가 제공되며 릴레이에 전원이 공급되지 않을 때 (릴레이 OFF 시) 에는 공통단자(COM)가 사진 상 우측의 단자와 연결이 되고 릴레이에 전원이 공급될 경우는 좌측의 단자와 연결이 됩니다. 곧, 릴레이 ON 시에 전원을 연결할지 OFF 할지는 용도에 따라 결정하면 될 것 입니다.


■ 연결

연결은 아래 표와 같이 했으며 아두이노 우노에서도 연결은 같습니다.

 4 Channel Relay

 Arduino Nano

 GND

 GND

 IN1

 D2

 IN2

 D3

 IN3

 D4

 IN4

 D5

 VCC

 5V




■ 소스

테스트를 위한 소스 이므로 간단 합니다. 각각의 릴레이를 1초 간격으로 ON/OFF 하고 전체 릴레이를 ON/OFF 해 보는 소스 입니다. 참고로 이 모듈의 경우 Digital Wite LOW 시 릴레이에 전원이 공급이 되네요. 뭔가 반대로 된 것 같기도 한데 뭐 상관 없습니다. 적용 시 거꾸로 하면 되니까요.


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
int relay1 = 2//릴레이1 핀설정
int relay2 = 3//릴레이2 핀설정
int relay3 = 4//릴레이3 핀설정
int relay4 = 5//릴레이4 핀설정
 
void setup ()
{
  pinMode (relay1, OUTPUT); // relay1를 output으로 설정한다.
  pinMode (relay2, OUTPUT); // relay2를 output으로 설정한다.
  pinMode (relay3, OUTPUT); // relay3를 output으로 설정한다.
  pinMode (relay4, OUTPUT); // relay4를 output으로 설정한다.
 
  //시작시 릴레이를 OFF 로 설정
  digitalWrite (relay1, HIGH);
  digitalWrite (relay2, HIGH);
  digitalWrite (relay3, HIGH);
  digitalWrite (relay4, HIGH);
}
void loop ()
{
  digitalWrite (relay1, LOW); // 릴레이 ON
  delay (1000);              //1초 delay
  digitalWrite (relay1, HIGH); // 릴레이 OFF
  delay (1000);               //1초 delay
 
  digitalWrite (relay2, LOW); // 릴레이 ON
  delay (1000);              //1초 delay
  digitalWrite (relay2, HIGH); // 릴레이 OFF
  delay (1000);               //1초 delay
 
  digitalWrite (relay3, LOW); // 릴레이 ON
  delay (1000);              //1초 delay
  digitalWrite (relay3, HIGH); // 릴레이 OFF
  delay (1000);               //1초 delay
 
  digitalWrite (relay4, LOW); // 릴레이 ON
  delay (1000);              //1초 delay
  digitalWrite (relay4, HIGH); // 릴레이 OFF
  delay (1000);               //1초 delay
 
  digitalWrite (relay1, LOW); // 릴레이 ON
  digitalWrite (relay2, LOW); // 릴레이 ON
  digitalWrite (relay3, LOW); // 릴레이 ON
  digitalWrite (relay4, LOW); // 릴레이 ON
  delay(1000);
  digitalWrite (relay1, HIGH); // 릴레이 OFF
  digitalWrite (relay2, HIGH); // 릴레이 OFF
  digitalWrite (relay3, HIGH); // 릴레이 OFF
  digitalWrite (relay4, HIGH); // 릴레이 OFF
  delay (1000);               //1초 delay
  digitalWrite (relay1, LOW); // 릴레이 ON
  digitalWrite (relay2, LOW); // 릴레이 ON
  digitalWrite (relay3, LOW); // 릴레이 ON
  digitalWrite (relay4, LOW); // 릴레이 ON
  delay(1000);
  digitalWrite (relay1, HIGH); // 릴레이 OFF
  digitalWrite (relay2, HIGH); // 릴레이 OFF
  digitalWrite (relay3, HIGH); // 릴레이 OFF
  digitalWrite (relay4, HIGH); // 릴레이 OFF
  delay(1000);
}
cs

차례대로 릴레이가 잘 작동하는 모습 입니다.


아래 소스는 릴레이가 얼마나 빨리 전류를 단속할 수 있는지 테스트 해 보았습니다. 50ms 즉, 1/20초 마다 동작하도록 해 보았는데 이것도 잘 되네요. 더 이상은 무리 같아서 더 줄이지는 않았습니다. ^^


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
int relay1 = 2//relay1에 5V 신호를 보낼 핀설정
int relay2 = 3//relay2에 5V 신호를 보낼 핀설정
int relay3 = 4//relay3에 5V 신호를 보낼 핀설정
int relay4 = 5//relay4에 5V 신호를 보낼 핀설정
 
void setup ()
{
  pinMode (relay1, OUTPUT); // relay1를 output으로 설정한다.
  pinMode (relay2, OUTPUT); // relay2를 output으로 설정한다.
  pinMode (relay3, OUTPUT); // relay3를 output으로 설정한다.
  pinMode (relay4, OUTPUT); // relay4를 output으로 설정한다.
 
  digitalWrite (relay1, HIGH);
  digitalWrite (relay2, HIGH);
  digitalWrite (relay3, HIGH);
  digitalWrite (relay4, HIGH);
}
 
void loop ()
{
  digitalWrite (relay1, LOW); // 릴레이 ON
  delay (50);              //50ms delay
  digitalWrite (relay1, HIGH); // 릴레이 OFF
  delay (50);               //50ms delay
 
  digitalWrite (relay2, LOW); // 릴레이 ON
  delay (50);              //50ms delay
  digitalWrite (relay2, HIGH); // 릴레이 OFF
  delay (50);               //50ms delay
 
  digitalWrite (relay3, LOW); // 릴레이 ON
  delay (50);              //50ms delay
  digitalWrite (relay3, HIGH); // 릴레이 OFF
  delay (50);               //50ms delay
 
  digitalWrite (relay4, LOW); // 릴레이 ON
  delay (50);              //50ms delay
  digitalWrite (relay4, HIGH); // 릴레이 OFF
  delay (50);               //50ms delay
}
cs


매우 빠르게 스위칭이 됩니다. 따라라라락~



4채널 릴레이는 IoT 등에서도 유용하게 쓰일 수 있을 것 같습니다. 채널이 많으니 그 만큼 제어가 가능한 장치도 늘어날 것이기 때문 입니다. ESP8266 모듈 등과도 조만간 연결해서 인터넷을 통해 제어해 볼 생각 입니다.

반응형
반응형

초여름 6월인데 벌써 30도가 넘어가는 날이 나오고 습도도 조금씩 높아지고 있습니다. 에어컨처럼 온도를 맞춰 놓으면 자동으로 풍량을 조절하는 선풍기도 있는걸로 알고 있지만 아직 그런 선풍기는 대부분 가지고 있지 않죠. 이번에는 선풍기에 온습도 센서 DHT11을 연결해서 일정온도 이상이 되면 켜지고 온도가 낮아지면 알아서 꺼지는 선풍기를 만들어 보겠습니다. 사실 이걸 만들려고 생각한 이유가 요즘 밤에 잘때 더워서 조그만 USB 선풍기를 켜고 잡니다. 그런데 새벽에 추워져도 선풍기는 계속 돌아가니 끄고는 싶은데 침대에서 나오기는 싫고... 자동으로 꺼졌으면 좋겠는데... 그런 귀차니즘에 만들게 되었습니다. ^^;


좌측부터 DHT11 온습도 센서, 아두이노 나노, 릴레이를 이용할 것입니다. 아두이노 우노를 쓰더라도 코드와 연결은 같습니다.


그리고 지난 릴레이편에서 사용한 위와 같이 생긴 전원코드가 필요 합니다. 220V용 전선, 플러그, 콘센트를 이용해서 만들어 주었습니다. 중간에 릴레이가 들어가서 전원을 끊거나 이어주는 역할을 합니다.


※ 주의: 이 글 에서는 전압과 전류가 높은 위험한 가정용 220V 전원을 다룹니다. 감전되면 위험하므로 만약 따라하실 경우 상당한 주의를 요합니다. 또한 릴레이 규격은 작은 전압 제어용부터 큰 전압용까지 매우 다양하므로 반드시 용도에 맞는 정격용량의 제품을 이용해야 합니다.


그런데, 이 프로젝트에서 사용할 DHT11 은 온도와 습도를 동시에 측정이 가능한 센서 입니다. 온도와 습도를 알 수 있으니 불쾌지수도 구할 수가 있습니다. 따라서 단순하게 온도에 따라 ON/OFF 할 수도 있지만 불쾌지수를 구해서 그 값에 따라서 선풍기가 ON/OFF 되도록 해 보겠습니다. 그럼 사람이 불쾌감을 느끼는 불쾌지수의 기준은 어떻게 될까요?


불쾌지수 기준 - 출처: 기상청 사이트 http://www.kma.go.kr/HELP/basic/help_01_05.jsp


위의 표에 따라서 불쾌감을 느끼기 시작하는 단계인 70 이상이 되면 선풍기가 켜지도록 해 보겠습니다.


■연결


DHT11_RELAY_FAN.fzz


위와 같이 연결하며 DHT11 센서 모듈이 아닌 경우는 위와 같이 VCC 와 Signal 사이에 10KΩ 저항을 풀업용으로 달아주어야 합니다. 저의 경우는 저항이 포함되어 있는 모듈형태의 센서이므로 저항 없이 연결해 주었습니다.


DHT11

아두이노 나노

VCC

3V3

Signal

D2

GND

GND


Relay

아두이노 나노

Signal

D10

VCC

5V

GND

GND


아두이노 우노의 경우도 연결은 같습니다.


위와 같이 연결하고 릴레이 측의 ON 과 C 단자에 위의 전원코드를 연결해 주면 됩니다.


아두이노 나노 사용 시 IDE 는 아래와 같이 설정해 주면 됩니다. 다만 ATmega168 칩을 사용한 나노일 경우에는 ATmega168 을 선택하면 됩니다. 물론 포트도 자신의 컴퓨터에 맞게 설정합니다.



■ 소스1 (불쾌지수로 선풍기 ON/OFF)

온도와 습도로 불쾌지수 구하는 공식은 기상청 홈페이지에서 참조해서 함수로 만들었기 때문에 정확할 것으로 생각 됩니다.

 

불쾌지수 구하는 공식, 출처: 기상청 사이트 kma.go.kr

 

▶ DHT 센서 라이브러리 : 아두이노 IDE 의 Libraries 폴더에 압축풀어서 복사

DHT.zip

 

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
#include "DHT.h"  //DHT 라이브러리
 
#define DHTPIN 2        // SDA 핀의 설정
#define DHTTYPE DHT11   // DHT22 센서종류 설정
int relay = 10;         //릴레이단자
 
DHT dht(DHTPIN, DHTTYPE);
 
void setup() {
  Serial.begin(9600); 
  Serial.println("DHT11 RELAY FAN !!!");
  dht.begin();
  pinMode (relay, OUTPUT); 
}
 
void loop() {
  // 센서의 온도와 습도를 읽어온다.
  float humi = dht.readHumidity();
  float temp = dht.readTemperature();
  // 불쾌지수
  float di = discomfortIndex(temp,humi);
 
  if (isnan(temp) || isnan(humi)) {
    //값 읽기 실패시 시리얼 모니터 출력
    Serial.println("Failed to read from DHT");
  } else {
    //습도, 온도, 불쾌지수 시리얼 모니터 출력
    Serial.print("Humi: "); 
    Serial.print(humi);
    Serial.print(" %\t");
    Serial.print("Temp: "); 
    Serial.print(temp);
    Serial.print(" *C");
    Serial.print(" \t");
    Serial.print("DI: ");
    Serial.println(di);
 
    if(di>=70)
    {
      digitalWrite (relay, HIGH);
    } else {
      digitalWrite (relay, LOW);
    }
  }
  //delay(2000);
}
 
//불쾌지수 구하기 (공식출처: 기상청)
float discomfortIndex(float temp, float humi) {
    return (1.8f*temp)-(0.55*(1-humi/100.0f)*(1.8f*temp-26))+32;
}
 
cs



테스트 동영상 입니다. 온도가 높아지면 불쾌지수도 높아지기 때문에 센서를 손으로 집어서 온도를 높였습니다. 온도가 높아지니 불쾌지수가 70을 넘어갑니다. 그럼 릴레이가 ON 되고 선풍기가 돌아 갑니다. 그 후 센서를 선풍기 바람으로 식혀서 온도를 낮추어주니 선풍기가 꺼집니다.


그리고 아래와 같은 식으로 소스를 수정하면 온도만 모니터링 해서 선풍기가 켜지고 꺼지게 만들수도 있습니다. 마찬가지로 습도값 만으로도 선풍기를 ON/OFF 할 수 있습니다. (사실 처음 생각은 온도만 가지고 선풍기를 ON/OFF 할 생각 이었습니다.) 


■ 소스2 (온도에 따라 선풍기 ON/OFF)


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
#include "DHT.h"  //DHT 라이브러리
 
#define DHTPIN 2        // SDA 핀의 설정
#define DHTTYPE DHT11   // DHT22 센서종류 설정
int relay = 10;         //릴레이단자
 
DHT dht(DHTPIN, DHTTYPE);
 
void setup() {
  Serial.begin(9600); 
  Serial.println("DHT11 RELAY FAN !!!");
  dht.begin();
  pinMode (relay, OUTPUT); 
}
 
void loop() {
  float temp = dht.readTemperature();
 
  if (isnan(temp)) {
    //값 읽기 실패시 시리얼 모니터 출력
    Serial.println("Failed to read from DHT");
  } else {
    Serial.print("Temp: "); 
    Serial.print(temp);
    Serial.println(" *C");
    
    if(temp>=30//30도 이상이면 선풍기 ON
    {
      digitalWrite (relay, HIGH);
    } else {
      digitalWrite (relay, LOW);
    }
  }
  //delay(2000);
}
cs



이상으로 온습도 센서와 릴레이를 가지고 선풍기를 ON/OFF 해 보았습니다. 소스에 사용한 DHT 라이브러리는 DHT22 등 DHT 시리즈 센서에는 공통으로 사용이 가능한 라이브러리 입니다. 따라서 소스의 센서종류 정의 부분만 바꿔주면 다른 센서에서도 사용이 가능한 소스 입니다.

반응형
반응형

릴레이는 자동으로 컨트롤이 가능한 스위치의 일종으로 작은 전압으로 큰 전압을 컨트롤 하기 위한 부품이다. 

 

쉽게 말해 아두이노로 가정용 전기인 220V나 그 이상의 전기를 제어하려고 할 때 쓰이는 부품이다.

아두이노에서 선풍기, 가정용 전등 등을 켜고 끌수 있는 것이다.



릴레이의 원리이다. 위의 그림을 보면 5V 전압으로 릴레이를 동작시켜 가정용 전기에 연결된 오븐을 제어하는 것을 볼 수 있다. 릴레이에 5V 전기가 가해지면(릴레이 규격에 따라 동작 전압이 다름) 릴레이 안의 전자석이 자성을 띄어 스위치를 ON 한다. 5V전기를 끊으면 전자석이 자성을 잃고 스프링에 의해 원복되면서 전류도 끊어지게 된다. 사실 이 글에서 해 보는 것은 이 그림의 손 역할을 아두이노가 대신 하게 되는 것이다.


릴레이 전원연결측 단자. 중간이 공통단자, 좌측단자가 ON, 우측단자가 OFF 시 연결된다.


내가 가지고 있는 릴레이 모듈이다. 릴레이 부품에 아두이노와의 연결을 용이하게 하기 위하여 다이오드, LED 등의 부품이 들어있는 보드가 부착되어 있다. 


릴레이에 쓰여져 있는 부분을 보면 SRD-05VDC-SL-C(모델명) 라고 되어 있는데 릴레이 컨트롤을 위한 전압은 5VDC(5V 직류)인 것을 알 수 있다. 5V는 아두이노에서도 공급가능한 전압이기 때문에 아두이노에서 컨트롤이 가능하다.


그 위에 10A 250VAC, 10A 30VDC 라는 것은 릴레이에서 컨트롤 가능한 최대전압/전류이다.

10A 250VAC 는 10암페어, 250볼트(교류) 이므로 우리나라 가정용 전압인 220VAC(교류)도 컨트롤 가능하다.

10A 30VDC 는 컨트롤 가능한 직류전압이다.


단, 10A를 넘어가는 전열기 같은 것을 컨트롤 하려면 더욱 큰 전류를 컨트롤 가능한 릴레이를 사용하여야 한다.


릴레이(SRD-05VDC-SL-C) 데이터시트:

27115-Songle-Relay-Datasheet.pdf


릴레이모듈 사용 매뉴얼:

27115-Single-Relay-Board-Guide-v1.0.pdf




나는 위와 같이 전원플러그와 연결된 220V용 전선의 중간 부분을 끊어서 릴레이와 연결하였다. 제어가 필요한 가전제품은 멀티탭에 꼽아서 쓸 수 있도록 만들었다. 릴레이가 ON되면 전원의 끊어진 부분이 이어지면서 멀티탭에 전원이 공급될 것이고 멀티탭에 연결된 가전제품이 동작이 될 것이고 반대의 경우 가전제품의 동작이 중단될 것이다. 


※ 만약 이 글을 보고 따라하려는 사람이 있다면 220V의 높은 전압을 다루게 되므로 자칫 잘못하면 감전되어 다칠 수 있으므로 주의를 기울여야 하며 사용하려는 릴레이의 허용전압/전류를 꼭 확인하고 사용해야 한다.



위와 같이 아두이노를 연결해 준다. 아두이노의 역할은 단순히 프로그램에 의해 릴레이에 전원을 공급하거나 끊어주는 것이다. 전원 ON/OFF를 다른 입력센서를 이용하여 하게되면 온도가 올라가면 가동되는 선풍기(온도센서 이용-블로그 참조), 가까이가면 켜지는 전등(초음파센서 이용-블로그 참조) 등을 만들 수 있을 것이다.

위의 그림에서 릴레이의 전원연결은 공통단자인 검정색과 릴레이 ON시 연결되는 빨간색 단자를 연결해 주었다.



##소스##

10초간 릴레이가 ON 되고 5초간 OFF 되는 프로그램

사실 소스는 별거 없다. 어떤 센서를 이용하여 어떤 상황에서 전원을 ON/OFF를 할지가 가장 중요하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
//KY019 5V 릴레이 모듈
 
int relay = 10//릴레이에 5V 신호를 보낼 핀설정
void setup ()
{
  pinMode (relay, OUTPUT); // relay를 output으로 설정한다.
}
void loop ()
{
  digitalWrite (relay, HIGH); // 릴레이 ON
  delay (10000);              //10초 delay
  digitalWrite (relay, LOW); // 릴레이 OFF
  delay (5000);               //5초 delay
}


cs


##결과##

나의 경우엔 헤어드라이어를 아두이노에서 ON/OFF 해 보았다. 

프로그램대로 10초간 전원이 연결되어 켜지고, 5초간 전원이 차단되어 꺼진다.



사실 진짜 해 보고 싶었던 것은 아두이노로 집안의 전체 전등을 컨트롤 해보려고 생각해봤지만

일이 너무 커질것 같은 생각이 들었다. 하나 정도는 가능할.듯 하지만 전체는 불가능에 가까울 듯 하다.

콘크리트 천장을 뜯으면 가능할거 같은데.... ;; 

나중에 돈 많이 벌어서 집을 짓게되면 중앙에서 집안의 전원을 따로 따로 관리 할 수 있는 콘솔 같은걸 만들어 보고 싶다. 거기에 아두이노와 이더넷 쉴드 같은걸 연결하면 외출중에도 PC나 스마트폰으로 집안 전체의 전원을 컨트롤 할 수 있겠지... 아마도 요즘 짓는 고급아파트들을 그렇게 이미 되어 있지 않을까???


반응형

+ Recent posts