아두이노프로세싱 프로그래밍

온습도계를 가진 아날로그시계

coding art 2011. 12. 30. 14:03
728x90


아날로그 시계속에 보다 작은 초시계와 온도계가 설치되었다면 습도계 설치는 관련된 속성들에 대해 약간의 손질로만으로 충분하다.

이와 같은 시계 속의 작은 시계에 온도계를 추가해 보기로 하자. 온도 측정은 아두이노 NodeMCU 무선 와이 보드에 설치된 DHT11 온습도 센서를 D5 핀에 설치하여 사용하기로 한다. 아울러 마두이노 NodeMCU 보드의 빌트인 LED D4 즉 GPIO 2번을 on OFF 하는 기능은 그대로 살려 두기로 한다.

 HTNL+SVG+Java Script 로 이루어진 웹서버 프로그램이 클라이언트와 연결이 되면 아날로그 시계로서의 기능은 웹브라우저의 자바스크립트가 담당하며 반면에 온도 측정은 여전히 아두이노 NodeMCU 보드에 설치된 DHT11이 담당하므로 웹서버 연결을 유지할 필요가 있다. 아울러 온도 데이터 업데이트 필요 시 버튼 키를 사용할 필요가 있다. 비록 LED on OFF를 위한 버튼 키이긴 하지만 한 번씩 request가 가면 온습도 데이터를 한번 씩 갱신해주는 효과가 있다.

이미 아두이노 NodeMCU 보드에서 DHT11 센서에 의한 IOT 코딩을 성공적으로 완료한 경험이 있으므로 온습도 측정 및 LED on OFF 제어 부분에 해당하는 코드 내용은 아날로그 시계 프로그램에 그대로 이식할 필요가 있다.

여기서 주목해야 할 점은 자바스크립트 언어에 의해 작동하는 시계 기능과 별도로 아두이노 NodeMCU 보드에 설치되어 있는 온습도 센서가 측정한 물리량을 함께 표현해야 한다는 점이다. 특히 온도 값은 아날로그 시계의 초침 운동에 비해 대단히 느리며 거의 시침 수준으로 움직이는 특성을 보인다.

아울러 온도계 또한 시계에서처럼 하나의 바늘로 표현되고 있으므로 코딩 또한 자바스크립트 기반의 시계 프로그램을 효율적으로 이용해 보도록 한다.


청색 박스 친 부분이 아두이노 NodeMCU 보드에서 측정한 온도 temp 값과 습도 humi 값을 Java Script 코드에 삽입하는 방법이다.
 나머지 아날로그 시계 Java Script 코드 부분은 원형 그대로 유지된다. 마지막 줄의 tempangle 은 온도가 섭씨 1° 변할 때에 온도계 바늘 침이 9도씩 회전시키도록 한다. 따라서 온도계 전체로는 0°∼40° 범위를 가지게 된다. 비슷한 방법으로 습도계 회전각 humiangle 은 상대 습도가 1% 씩 변할 때에 온도계 바늘 침이 4.5 도씩 회전시키도록 한다. 따라서 습도계 전체로는 0∼80% 범위를 가지게 된다. DHT11 규격을 보면 상대습도 80%까지 측정이 가능한 것으로 되어 있음을 참고하였다.






온도계 바늘 침이 temphand로 정의 되었듯이 습도의 경우도 humihand 로 정의하고   setAttribute() 명령 실행에 의해 바늘을 회전 시킨다.

습도계도 온도계와 마찬가지로 각종 속성 및 문자를 정의하고 circle 명령을 실행한다.


원형 습도계를 시계 중심의 오른 쪽에 작도 후 360도 전체 범위를 상대 습도 80%로 잡고 4개의 눈금과 숫자를 기입한다.





Webserver_html_svg_analog_clock_smalllclock_therm_humi_01


#include <ESP8266WiFi.h>
 #include <DHT11.h>
 
 const char* ssid = "android1234";//자신의 무선와이파이 공유기 id로 수정
 const char* password = "dddddddddd";//자신의 무선와이파이 공유기 비빌번호로 수정

 int ledPin = 2; //
 int pin = D5; //온습도센서
 
 WiFiServer server(80);
 DHT11 dht11(pin);
 
 void setup() {
   Serial.begin(115200);
   delay(10);

   pinMode(ledPin, OUTPUT);
   digitalWrite(ledPin, HIGH);

   // Set WiFi to station mode and disconnect from an AP if it was previously connected
   WiFi.mode(WIFI_STA);
   WiFi.disconnect();
   delay(100);

   Serial.println("Setup done");

   // Connect to WiFi network
   Serial.println();
   Serial.println();
   Serial.print("Connecting to ");
   Serial.println(ssid);

   WiFi.begin(ssid, password);

   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
   }
   Serial.println("");
   Serial.println("WiFi connected");

   // Start the server
   server.begin();
   Serial.println("Server started");

   // Print the IP address
   Serial.print("Use this URL to connect: ");
   Serial.print("http://");
   Serial.print(WiFi.localIP());
   Serial.println("/");

 }

 void loop() {
   // Check if a client has connected
   WiFiClient client = server.available();
   if (!client) {
     return;
   }

   // Wait until the client sends some data
   Serial.println("new client");
   while(!client.available()){
     delay(1);
   }

   // Temperature & Humidity Sensing
   int err;
   float temp, humi;
   if((err=dht11.read(humi, temp))==0) //온도, 습도 읽어오기 및 에러 체크
   {
     Serial.print("temperature:");
     Serial.print(temp);
     Serial.print(" humidity:");
     Serial.print(humi);
     Serial.println();
   }
   else                                //에러 처리 과정
   {
     Serial.println();
     Serial.print("Error No :");
     Serial.print(err);
     Serial.println();   
   }
   delay(2000);                        //2초마다 측정


   // Read the first line of the request
   String request = client.readStringUntil('\r');
   Serial.println(request);
   client.flush();

   // Match the request

   int value = LOW;
   if (request.indexOf("/LED=ON") != -1)  {
     digitalWrite(ledPin, LOW);
     value = HIGH;
   }
   if (request.indexOf("/LED=OFF") != -1)  {
     digitalWrite(ledPin, HIGH);
     value = LOW;
   }
 // Set ledPin according to the request


   // Return the response
   client.println("HTTP/1.1 200 OK");
   client.println("Content-Type: text/html");
   client.println(""); //  do not forget this one
   client.println("<!DOCTYPE HTML>");
   client.println("<html>");
   client.println("<body>");
   client.println("<p>");
   client.print("Led pin is now: ");

   if(value == HIGH) {
     client.print(on");
     client.println("<br><br>");
     client.print(" Temperature = ");
     client.print(temp);
     client.print(" Humidity = ");
     client.print(humi);
   } else {
     client.print("OFF");
   }
   client.println("<br><br>");
   client.println("<a href=\"/LED=ON\"\" ><button>Turn on </button></a>");
   client.println("<a href=\"/LED=OFF\"\" ><button>Turn Off </button></a>");

   client.println("</p>");
   client.println("</body>");
  
        client.println("<head>");
        client.println("<title>Analog Clock</title>");
        client.println("<script>");
        client.println("function updateTime() { // Update the SVG clock");
        client.print("var temperature =");
        Serial.println(temp);
        client.print(temp);
        client.println(";");
        client.print("var humidity =");
        Serial.println(humi);
        client.print(humi);
        client.println(";");
        client.println("var now = new Date();");
        client.println("var sec = now.getSeconds();");
        client.println("var min = now.getMinutes();");
        client.println("var hour = (now.getHours() % 12) + min/60;");
        client.println("var secangle = sec*6;");
        client.println("var minangle = min*6;");
        client.println("var hourangle = hour*30;");
        client.println("var tempangle = temperature*9;");
        client.println("var humiangle = humidity*4.5;");
        // Get SVG elements for the hands of the clock
        client.println("var sechand = document.getElementById('secondhand');");
        client.println("var minhand = document.getElementById('minutehand');");
        client.println("var hourhand = document.getElementById('hourhand');");
        client.println("var temphand = document.getElementById('temphand');");
        client.println("var humihand = document.getElementById('humihand');");
        // Set an SVG attribute on them to move them around the clock face
        client.println("sechand.setAttribute('transform', 'rotate(' + secangle + ',50,32)');");
        client.println("minhand.setAttribute('transform', 'rotate(' + minangle + ',50,50)');");
        client.println("hourhand.setAttribute('transform', 'rotate(' + hourangle + ',50,50)');");
        client.println("temphand.setAttribute('transform', 'rotate(' + tempangle + ',32,50)');");
        client.println("humihand.setAttribute('transform', 'rotate(' + humiangle + ',68,50)');");
        client.println("setTimeout(updateTime, 1000);");
      client.println("}");
      client.println("</script>");
      client.println("<style>");
      /* These CSS styles all apply to the SVG elements defined below */
      client.println("#clock {");
        /* styles for everything in the clock */
      client.println("stroke: black;");
        /* black lines */
      client.println("stroke-linecap: round;");
        /* with rounded ends */
      client.println("fill: #eef;");
        /* on a light blue gray background */
      client.println("}");
      client.println("#face { stroke-width: 3px;}");
      client.println("#smallface { stroke:green; stroke-width: 1px;}");
      /* clock face outline */
      client.println("#ticks { stroke-width: 2; }");
      client.println("#smallticks { stroke:green; stroke-width: 1; }");
      /* lines that mark each hour */
      client.println("#hourhand {stroke-width: 5px;}");
      /* wide hour hand */
      client.println("#minutehand {stroke:deepskyblue; stroke-width: 3px;} /* narrow minute hand */");
      client.println("#secondhand {stroke:red; stroke-width: 1px;}");
      client.println("#numbers {");
        /* how to draw the numbers */
       client.println("font-family: sans-serif; font-size: 7pt; font-weight: bold;");
       client.println("text-anchor: middle; stroke: none; fill: blue;");
      client.println("}");
//온도계
      client.println("#thermometer { stroke: black; stroke-linecap: round; fill: #eef; } ");
      client.println("#thermometerface { stroke:purple stroke-width: 1px;}");
      client.println("#thermometerticks_thick { stroke:red; stroke-width: 1px; }");
      client.println("#temphand {stroke:blue; stroke-width: 1px;}");
      client.println("#smallnumbers { font-family: sans-serif; font-size: 2pt; font-weight: bold; ");
      client.println("text-anchor: middle; stroke: none; fill: red; }");
//습도계
      client.println("#hygrothermal { stroke: red; stroke-linecap: round; fill: #eef; } ");
      client.println("#hygrothermalface { stroke:brown stroke-width: 1px;}");
      client.println("#hygrothermalticks_thick { stroke:pink; stroke-width: 1px; }");
      client.println("#humihand {stroke:green; stroke-width: 1px;}");
      client.println("#extranumbers { font-family: sans-serif; font-size: 2pt; font-weight: bold; ");
      client.println("text-anchor: middle; stroke: none; fill: black; }");
       
      client.println("</style>");
      client.println("</head>");
      client.println("<body onload='updateTime()'>");
      client.println("<!-- viewBox is coordinate system, width and height are on-screen size -->");
      client.println("<svg id='clock' viewBox='0 0 100 100' width='500' height='500'>");

      client.println("<circle id='face' cx='50' cy='50' r='45'/> <!-- the clock face -->");
      client.println("<circle id='smallface' cx='50' cy='32' r='10'/>");
      client.println("<circle id='thermometerface' cx='32' cy='50' r='10'/>");
      client.println("<circle id='hygrothermalface' cx='68' cy='50' r='10'/>");
   //continue
      client.println("<g id='ticks'>");
      client.println("<!-- 12 hour tick marks -->");
      client.println("<line x1='50' y1='5.000' x2='50.00' y2='10.00'/>");
      client.println("<line x1='72.50' y1='11.03' x2='70.00' y2='15.36'/>");
      client.println("<line x1='88.97' y1='27.50' x2='84.64' y2='30.00'/>");
      client.println("<line x1='95.00' y1='50.00' x2='90.00' y2='50.00'/>");
      client.println("<line x1='88.97' y1='72.50' x2='84.64' y2='70.00'/>");
      client.println("<line x1='72.50' y1='88.97' x2='70.00' y2='84.64'/>");
      client.println("<line x1='50.00' y1='95.00' x2='50.00' y2='90.00'/>");
      client.println("<line x1='27.50' y1='88.97' x2='30.00' y2='84.64'/>");
      client.println("<line x1='11.03' y1='72.50' x2='15.36' y2='70.00'/>");
      client.println("<line x1='5.000' y1='50.00' x2='10.00' y2='50.00'/>");
      client.println("<line x1='11.03' y1='27.50' x2='15.36' y2='30.00'/>");
      client.println("<line x1='27.50' y1='11.03' x2='30.00' y2='15.36'/>");
      client.println("</g>");

      client.println("<g id='smallticks'>");
      client.println("<!-- 160second tick marks -->");
      client.println("<line x1='50' y1='24' x2='50.00' y2='22'/>");
      client.println("<line x1='58' y1='32' x2='60' y2='32'/>");
      client.println("<line x1='50' y1='40' x2='50' y2='42'/>");
      client.println("<line x1='42' y1='32' x2='40' y2='32'/>");
      client.println("</g>");

      client.println("<g id='numbers'>");
      client.println("<!-- Number the cardinal directions-->");
      client.println("<text x='50' y='16'>12</text><text x='87' y='53'>3</text>");
      client.println("<text x='50' y='90'>6</text><text x='13' y='53'>9</text>");       
      client.println("</g>");
     
      client.println("<!-- Draw hands pointing straight up. We rotate them in the code. -->");
      client.println("<g id='hands'> <!-- Add shadows to the hands -->");
      client.println("<line id='hourhand' x1='50' y1='50' x2='50' y2='24'/>");
      client.println("<line id='minutehand' x1='50' y1='50' x2='50' y2='20'/>");
      client.println("<line id='secondhand' x1='50' y1='32' x2='50' y2='24'/>");
      client.println("<line id='temphand' x1='32' y1='50' x2='32' y2='42'/>");
      client.println("<line id='humihand' x1='68' y1='50' x2='68' y2='42'/>");
      client.println("</g>");

      client.println("<g id='thermometerticks_thick'>");
      client.println(" <!-- 30 degree tick marks --> ");
      client.println("<line x1='32' y1='42' x2='32' y2='40'/>");
      client.println(" <line x1='40' y1='50' x2='42' y2='50'/>");
      client.println("<line x1='32' y1='58' x2='32' y2='60'/>");
      client.println("<line x1='24' y1='50' x2='22' y2='50'/>");
      client.println(" </g>");

      client.println("<g id='hygrothermalticks_thick'>");
      client.println(" <!-- 30 degree tick marks --> ");
      client.println("<line x1='68' y1='42' x2='68' y2='40'/>");
      client.println(" <line x1='60' y1='50' x2='58' y2='50'/>");
      client.println("<line x1='68' y1='58' x2='68' y2='60'/>");
      client.println("<line x1='76' y1='50' x2='78' y2='50'/>");
      client.println(" </g>");
    
      client.println("<g id='smallnumbers'>");
      client.println("<!-- Temperature & Number the cardinal directions-->");
      client.println("<text x='32' y='47'>Temp:C</text>");
      client.println("<text x='32' y='38'>0</text><text x='45' y='51'>10</text>");
      client.println("<text x='32' y='65'>20</text><text x='19' y='51'>30</text>");
      client.println("</g>");

      client.println("<g id='extranumbers'>");
      client.println("<!-- Humidity & Number the cardinal directions-->");
      client.println("<text x='68' y='46'>Humid:%</text>");
      client.println("<text x='68' y='38'>0</text><text x='55' y='51'>60</text>");
      client.println("<text x='68' y='65'>40</text><text x='81' y='51'>20</text>");
      client.println("</g>");
      
      client.println("</svg>");
      client.println("</body>");
      client.println("</html>");
   delay(1);
   Serial.println("Client disonnected");
   Serial.println("");

 }//프로그램 끝