기존에 작성했던 상기 포스트가 완료되었고, 기숙사 생활을 청산(?) 한 뒤 자취를 시작하게 되었다.
스탠드, 인체감지 센서, 온습도 센서, 조도 센서, 스탠드, 선풍기, 에어컨, TV 들은 이제 샤오미로 대체했고
19.02.16 - 빌트인 보일러를 외부에서 끄고 켜는 것에 도전해보게 되었다. 애인도 없이 외로이 홀로 살다보니 퇴근해서 얼음장 같은 집에 들어가면 안그래도 외로운데 더 춥고 더 외롭다...
자 우리의 친구 아두이노 웹서버와 함께 미리미리 펄펄 끓는 따뜻한 겨울을 보내보도록 하자.
코딩 작업 |
1. 전원버튼/실내/ 외출/ 목욕/ 예약 모드 중 실내버튼을 1회 누르면 실내기능, 2회면 예약, 3회면 외출 기능이 된다.
2. 목욕버튼은 어떤 모드에서 한방에 목욕기능으로 전환된다.
3. (핵심) 목욕 기능 구동 중 원하는 모드로 전환하려면 목욕 기능 구동 직전 모드가 실내인지 외출인지 예약인지에 따라서 버튼을 누르는 횟수가 달라진다
아래는 위 내용을 토대로 작성한 코드이다. 대부분의 예전 웹서버 코드가 재활용되었다.
#include <Arduino.h> #include <SPI.h> #include <Ethernet.h> #define in 1 //스탠드 릴레이에 신호를 보낼 핀설정 #define reserv 2 //출입문 릴레이에 신호 보낼 핀임 #define out 3 #define bath 3 byte mac[] = { 0x5E, 0x3D, 0x54, 0xF5, 0xE1, 0xD3 } ; //mac address IPAddress ip(192, 168, 0, 240) ; EthernetServer server(9090) ; String readString; int val; int Sval; int Prestatus; void setup() { // start the Ethernet connection and the server: Ethernet.begin(mac, ip); server.begin(); Serial.begin(115200); pinMode(2, OUTPUT); // relay2,3,4,5 를 output으로 설정한다. pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); digitalWrite(2, HIGH); digitalWrite(3, HIGH); digitalWrite(4, HIGH); digitalWrite(5, HIGH); // 이걸 안넣었더니 보일러 컨트롤러가 시작부터 그냥 먹통됨 val = 1; } void loop() { EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { // This is all where we start up the server and strings. char c = client.read(); if (readString.length() < 100) { readString += c; } if (c == '\n') { Serial.println(readString); client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html; charset=UTF-8"); client.println(""); client.println("<hmtl>"); client.println("<head>"); client.println("<meta charset=utf-8>"); client.println("<meta name=viewport content=width=device-width, initial-scale=1>"); client.println("</head>"); client.println("<title>"); client.println("예진이의 보일러 오토메이션 Page"); client.println("</title>"); client.println("<body bgcolor=black>"); client.println("<font color=white>"); client.println("<meta http-equiv=\"refresh\" content=\"4\">"); client.println("<center>"); client.println("<p>"); client.println("<FORM>"); client.println("</br>"); client.println("</br>"); client.println("</br>"); client.println("<INPUT type=button value=실내 onClick=window.location='/?in'>"); client.println("<INPUT type=button value=예약 onClick=window.location='/?reserv'>"); client.println("<INPUT type=button value=외출 onClick=window.location='/?out'>"); client.println("<INPUT type=button value=목욕 onClick=window.location='/?bath'>"); client.println("<INPUT type=button value=초기화 onClick=window.location='/?reset'>"); client.print("<table border=1 width=200>"); client.print("<tr>"); client.print("<td align=center>"); client.print("<font color=white size=3>"); client.print("<b>"); client.print("현재 보일러 상태"); client.print("</b>"); client.print("</td>"); client.print("</tr>"); client.print("<tr>"); client.print("<td align=center>"); client.print("<font color=white size=3>"); if (val == 1) { client.print("<font color=magenta size=3>"); client.print("실내"); } if (val == 2) { client.print("<font color=white size=3>"); client.print("예약"); } if (val == 3) { client.print("<font color=white size=3>"); client.print("외출"); } if (val == 4) { client.print("<font color=yellow size=3>"); client.print("목욕"); } client.print("</td>"); client.print("</tr>"); client.print("</table>"); client.println("</br>"); client.print("</FORM>"); client.print("</center>"); client.print("</font>"); client.print("</body>"); client.print("</html>"); delay(1); if (readString.indexOf("?in") > 0) { if (val == 1){ // val이 현 1로 실내 상태일 경우에는 아무것도 안함 val = 1; Prestatus = 1; } if (val == 2) { //예약이면 실내 2회 digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); delay(250); digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); val=1; //실내 Prestatus = 1; //결과 : 실내 } if (val == 3) { //외출이면 실내한번 더 누름 digitalWrite(2, LOW); delay(250); digitalWrite(2, HIGH); val=1; //실내 Prestatus = 1; } if (val == 4) { //전 상태가 목욕일 땐 직전 상태가 실내인지 외출인지 확인하고 가야함 if (Prestatus == 3){ // 전상태가 외출+목욕 이었으면 실내로 바꾸기 위해서 실내 버튼 2번 후 digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); delay(250); digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); val=1; //외출 Prestatus = 1; Sval = 1; } if (Prestatus == 1){ if(Sval == 0){ digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); val=1; //외출 Prestatus = 1; } } } if(val == 1){ server.send(200, "text/plain", "1"); else { server.send(200, "text/plain", "0"); } } Sval = 0; readString = ""; } else { if (readString.indexOf("?reserv") > 0) { digitalWrite(5, LOW); // 목욕 delay(250); digitalWrite(5, HIGH); delay(250); digitalWrite(4, LOW); // 전원 delay(250); digitalWrite(4, HIGH); delay(250); digitalWrite(4, LOW); // 전원 delay(250); digitalWrite(4, HIGH); delay(250); digitalWrite(2, LOW); // 예약 delay(250); digitalWrite(2, HIGH); val=2; //예약 readString = ""; Sval = 0; //세미밸류 초기화 } else { if (readString.indexOf("?out") > 0) { if (val == 1) { //현재상태 실내면 실내 추가로 2회 digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); delay(250); digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); val = 3; //외출 Sval = 1; //세미밸류도 외출로 지정 Prestatus = 3; } if (val == 2) { //예약이면 실내 1회 digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); val = 3; //외출 Prestatus = 3; } if (val == 3) { //현재 상태도 외출이면 아무것도 안함 val = 3; Prestatus = 3; } if (val == 4) { //현재 목욕상태인데 외출로 바꾸고싶으면 일단 현재상태가 실내인지 외출인지 확인해야함. if(Prestatus == 1){ //실내였을경우 3번눌러서 외출로 변경 - 이거 0216-1에서도 3회로 수정해야함 //실내 3회 digitalWrite(2, LOW); // 실내1 delay(250); digitalWrite(2, HIGH); delay(250); digitalWrite(2, LOW); // 실내2 delay(250); digitalWrite(2, HIGH); delay(250); digitalWrite(2, LOW); // 실내3 delay(250); digitalWrite(2, HIGH); val = 3; Prestatus = 3; Sval = 1; } if(Prestatus == 3){ //외출이었을경우 실내 1번눌러서 바로 그냥 외출로 변경 //실내 1회 if (Sval == 0){ digitalWrite(2, LOW); // 실내 delay(250); digitalWrite(2, HIGH); val = 3; Prestatus = 3; } } } readString = ""; Sval = 0; //세미밸류 초기화 } else { if (readString.indexOf("?bath") > 0) { if (val == 4) { //이미 목욕이면 아무것도 안함 val = 4; } if (val == 1) { //실내이면 목욕으로 변경 하지만 Prestatus를 1로 남김 digitalWrite(5, LOW); // 목욕 delay(250); digitalWrite(5, HIGH); val = 4; // 목욕 Prestatus = 1; } if (val == 2) { //예약이면 목욕으로 변경 digitalWrite(5, LOW); // 목욕 delay(250); digitalWrite(5, HIGH); val = 4; // 목욕 } if (val == 3) { //외출상태면 목욕으로 변경 하지만 Prestatus를 3으로 남김 digitalWrite(5, LOW); // 목욕 delay(250); digitalWrite(5, HIGH); val = 4; // 목욕 Prestatus = 3; } Sval = 0; readString = ""; } else { if (readString.indexOf("?reset") > 0) { val = 1; // 상태 값 실내로(디버깅용) Prestatus = 1; Sval = 0; //세미밸류 초기화 readString = ""; } } // 넷째 reset else 닫음 } //셋째 bath else 닫음 } //둘째 out else 닫음 } //첫 reserv 닫음 readString = ""; client.stop(); } delay(5); } } } }
각 버튼을 누를 때마다 현재의 모드를 상태값으로 계속 가지고 가는 방법으로 코드를 짰다.
이 집은 귀뚜라미 보일러 모델명 CTR-5700 으로 무선 또는 IOT를 지원하지 않는 제품이다.
버튼식으로 되어있으니 필시 뚜껑을 벗겨보면 스위치가 있을 터.. 2개 단자를 잠깐 접촉시켜주는 것이 스위치의 역할일테니 웹서버를 가동하고 웹서버에 명령을 주면 릴레이가 각 스위치에 있는 2개의 단자를 잠깐 잠깐씩 접촉 시켜주는 역할을 하도록 하면 되겠다.
아두이노 메가 + 적층형 이더넷 쉴드 + 4개짜리 릴레이를 결선해서 코딩 할 준비를 마쳤다. |
요렇게 생긴 녀석으로 귀뚜라미 보일러 모델 CTR-5700 이다 |
껍데기를 분리해서 보니 3개의 귀여운 스위치가 보인다. |
기판 뒷면 모습. 이쪽 면에 납뗌으로 릴레이들을 결선 할 예정 |
날이 갈수록 납뗌 기술이 레벨업하고 있다. 생각보다 쉽게 납뗌을 했다. 사용한 선은 납뗌이 용이하도록 선 노출부에 미리 납이 발라져 있는 제품으로 알리에서 구매했다. |
생각보다 선이 짧아서..ㅋㅋ 선과 선을 추가로 납뗌을 했다.. 아.. 허접하다. 작업 후 전기테잎으로 깔끔하게 마무리 해주었다. |
이런식으로 남는 박스에 넣어서 보일러 컨트롤러가 비스듬하게 시야 방향으로 보이도록 설치 하려고 한다. (이 포스트에서 저는 임시로 종이박스를 사용했으나 화재의 위험이 있을 수 있으니 따라하지마시고 불연소성 소재를 사용하시길 당부드립니다.) |
보일러가 또 선이 짧아 각도가 안나오는 관계로 추가 연장선도 납뗌질을 하고야 말았다. |
릴레이 결선 전 모습 |
보일러 끄고 켜기 애플워치로 제어 : 아이폰용 앱(Launcher) + 단축어(shortcut) 기능을 활용 동영상
목욕 끄고 켜기 애플워치로 제어 : 아이폰용 앱(Launcher) + 단축어(shortcut) 기능을 활용 동영상
비로소 따뜻한 겨울이 되었다. 흐뭇
대단!!
답글삭제