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

HTML SVG 그래픽 언어로 프로그램한 Arduino NodeMCU Scope에 의해 아날로그 파형 및디지털 듀티 신호 real time 측정

coding art 2017. 2. 15. 17:46
728x90




아두이노 우노의 클럭 주파수 16MHz 에 비해 CPU 클럭 주파수가 무려 80MHz인 아두이노 NodeMCU의 엄청난 연산 응력을 활용하여 스마트 폰에서 만족할 만한 속도로 real time 파형을 볼 수 있는 Arduino NodeMCU Scope 프로그램을 작성하기로 한다.
     




실시간 파형 관측을 위한 아날로그 신호는 A0 핀에 가변 저항을 연결하여  부드럽게 파형이 움직이는 모습을 관찰할 수 있다.

좌측의 아날로그 파형 은 손으로 가변저항을 여유 있게 돌려 얻은 전압 파형이다.









 이 디지털 파형은 LED_Blink 실험 장치에서 1초 및 0.1초로 ON OFF  시킬 때 발생된 LED 양단의 전압을 캐치한 스코프 파형이다.
0.1초의 경우 듀티 파형이 조밀한 편이다. 


그래픽 프로그램에서 선 굵기를 아주 가늘게 조절하게되면 보다 세밀한 파형 관찰이 가능할 것이다.




아래에서는 HTML SVG의 그래픽 기능 중심으로 하는 프로그램의 구조 및 내용을 살펴보기로 한다. 단 여기서는 LED_Blink 프로그램에 의해 발생된 디지털 듀티 파형 관찰을 위한 프로그램 중심으로 설명하기로 한다.
     
setup()과 loop()프로그램에서 WiFi 연결과 관련된 부분은 전혀 변동이 없으므로 생략하고 HTML 과 SVG 프로그램 중심으로 설명하기로 한다.
     
아래의 프로그램은 HTML 도입부문이며 태그 <html>과 대응하는 </html>는 거의 프로그램 끝부분에 위치한다.
     
   // 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>");
     
일단 스마트 폰이 가상 ip를 주소창에 입력하여 엔터 키를 눌러 웹의 Request에 의해 연결되면 웹브라우저의 배경 색이 노란색으로 바뀌고 태그 <head>에서 시작하여 Arduino NodeMCU Webserver Scope 라는 텍스트 출력 후 태그 </head>로 끝맺는다.
 //배경 색 문자 색 사이즈 HTML CSS 설정   
   client.println("<head>"); 
   client.println("<style>");
   client.println("body {");
   client.println("background-color: yellow;");
   client.println("}");
   client.println("p {");
   client.println("color:red;");
   client.println("font-size:250%;");
   client.println("}");
    client.println("</style>");  
       client.println("<title>Page Title</title>");
       client.println("<h2> Arduino NodeMCU Webserver Scope</h1>");  
    client.println("</head>"); 
     
계속하여 태그 <body>를 시작하는데 이에 대응하는 태그</body>는 프로그램의 거의 끝 부분에 위치하며 그 중간에 스코프의 그랙을 담당하는 중요한 부분들이 포함된다.
   client.println("<body>");
    ⚫
    ⚫
    ⚫
     
      client.println("<a href=\"/on\"\" class='button'>Data Refresh </button></a>");
   client.println("</body>");           
   client.println("</html>");
   delay(1);
   Serial.println("Client disonnected");
     
태그 <body> 이후 가장 중요한 Scalable Vector Graphics의 태그 <svg... 가 시작된다.
스코프 화면 크기를 높이 200 폭 500으로 정의한다 아울러 CSS처럼 style 파라메터들도 함께 정의 되며 스코프 화면 색, 중앙선 및 윤곽선등이 표현되며 />로 끝난다.
     
     client.println("<svg height='200' width='500'>");
     client.println("<rect height='200' width='500' style='fill:rgb(0,220,230);stroke-width:10;stroke:rgb(0,0,0)' />");
     client.println("<rect height='100' width='500' style='fill:rgb(0,220,230);stroke-width:10;stroke:rgb(0,0,0)' />");
     
아래의 analogRead() 항에서 아두이노 NodeMCU는 3.3V를 1023으로 받아들인다. 위에 정의된 스코프 화면 폭이 200 이므로 analogRead() 항을 5로 나누어 비슷하게 맞춘다.
int y1 = 200-val; 프로글램의 의미는 이미 앞 블로그에서 설명 했으므로 생략한다.
그 다음 i=1에서 500까지 500회에 걸쳐 읽어 들인 데이터를 line 명령을 사용하여 연결 출력한다. 
다음은 (0,0)에서 (200,200)까지 직선을 긋는 HTML SVG 의 line 명령 사례이다. 
이 명령문에서 “와 ”를 모조리 ‘와 ’로 바꾸고 난 후 좌표 데이터에 해당하는 부분을 따로 분리해 좌표 데이터를 변수로 출력한다.
     
<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
     
이 명령문에서 “와 ”를 모조리 ‘와 ’로 바꾸고 난 후 좌표 데이터에 해당하는 부분을 따로 분리해 좌표 데이터를 변수로 출력한다.
     
<line x1=‘0’ y1=‘0’ x2=‘200’ y2=‘200’ style=‘stroke:rgb(255,0,0);stroke-width:2’ />
     
다음과 같이 줄 바꿈하여 프로그램을 쪼갠 후 client(“와 ”);를 앞뒤로 입력한다. 단 숫자 데이터인 0,0,200,200은 프로그램에서 변수 x1,y1,x2,y2에 해당하므로 이들 값을 출력하는 것으로 대체한다.
     
<line x1=‘
0
’ y1=‘
0
’ x2=‘
200
’ y2=‘
200
’ style=‘stroke:rgb(255,0,0);stroke-width:2’ />
     
실제 프로그램 된 아래의 사례를 참조하기 바란다.
  
int val = analogRead(A0)/5;
     int y1 = 200-val;
     for(int i=1;i<500;i++){
     // 아나로그입력 생성(0-1023):1023=3.3V
     int x1 = (i-1);
     int x2 = i;
     int val = analogRead(A0)/5;
     int y2 = 200-val;
     client.println("<line x1='");
     client.println(x1);
     client.println("' y1='");
     client.println(y1);
     client.println("' x2='");  
     client.println(x2);
     client.println("' y2='");
     client.println(y2);
     client.println("'");
     client.println("' style='stroke:rgb(255,0,0);stroke-width:2' />");
     client.println("Sorry, your browser does not support inline SVG.");
     y1 = y2;
     }
     
앞에서 500회까지 샘플링 출력이 끝나면 </svg> 태그로 그래픽 작업을 종료한다. 그 다음에 다시 새호이 그래픽을 하여면 한번 화면을 flush해 주는 작업이 필요하다.
     
     client.println("</svg>");
     client.flush();
     client.println("<br><br>");
   
     
끝으로 CSS 명령을 사용하여  버튼의 배경색 테두리 색 폰트 사이즈 등을 지정한다. 이 부분은 다시 태그 <head>로 시작해서 </head>태그로 끝 맺음 하도록 한다.
     
//버튼 HTML CSS 설정   
    client.println("<head>");
    client.println("<style>");
    client.println(".button {");
//    client.println("background-color: #4CAF50;");
    client.println("background-color: green;");
    client.println("border: none;");
    client.println("color: white;");
    client.println("padding: 15px 32px;");
    client.println("text-align: center;");
    client.println("text-decoration: none;");
    client.println("display: inline-block;");
    client.println("font-size: 20px;");
    client.println("margin: 14px 20px;");
    client.println("cursor: pointer;");
    client.println("}");    
    client.println("</style>");
    client.println("</head>");
  


마지막으로 CS에서 설정된 환경대로 Data Refresh 버튼이 나타나는데 이 버튼을 누르면 스마트 폰에서 flush 작업과 함께 아두이노 NodeMCU 웹서버와 통신하는데 시간이 좀 걸린다.
  
  // client.println("<a href=\"/on\"\"><button>Data Refresh </button></a><br />");
      client.println("<a href=\"/on\"\" class='button'>Data Refresh </button></a>");
   client.println("</body>");           
   client.println("</html>");
   delay(1);
   Serial.println("Client disonnected");
     
아래에 실행이 성공할 수 있도록 프로그램 전문을 수록하니 참조하기 바란다. 물론 자신의 스마트폰 핫스팟ID와 비밀번호를 입력을 잊지 말기 바라며, 참고로 상당히 긴 명령 줄들이 있는지 혹시 끓어지는지 여부를 한번 살펴보기 바란다.
     
Webserver_nodemcu_html_svg_realtime_var_resistor_01
     
     
     
 #include <ESP8266WiFi.h>
     
 const char* ssid = "AndroidHotspot1234";//자신의 스마트폰 핫스팟 ID입력
 const char* password = "00000000";//자신의 스마트폰 핫스팟 비밀번호 입력
     
 int ledPin = 2; //
 
 WiFiServer server(80);
     
 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);
   }
     
   // 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>");
   
   //배경 색 문자 색 사이즈 HTML CSS 설정   
   client.println("<head>"); 
   client.println("<style>");
   client.println("body {");
   client.println("background-color: yellow;");
   client.println("}");
   client.println("p {");
   client.println("color:red;");
   client.println("font-size:250%;");
   client.println("}");
    client.println("</style>");  
       client.println("<title>Page Title</title>");
       client.println("<h2> Arduino NodeMCU Webserver Scope</h1>");  
    client.println("</head>"); 
     
 
     client.println("<body>");
     
     client.println("<svg height='200' width='500'>");
     client.println("<rect height='200' width='500' style='fill:rgb(0,220,230);stroke-width:10;stroke:rgb(0,0,0)' />");
     client.println("<rect height='100' width='500' style='fill:rgb(0,220,230);stroke-width:10;stroke:rgb(0,0,0)' />");
     int val = analogRead(A0)/5;
     int y1 = 200-val;
     for(int i=1;i<500;i++){
     // 아나로그입력 생성(0-1023):1023=3.3V
     int x1 = (i-1);
     int x2 = i;
     int val = analogRead(A0)/5;
     int y2 = 200-val;
     client.println("<line x1='");
     client.println(x1);
     client.println("' y1='");
     client.println(y1);
     client.println("' x2='");  
     client.println(x2);
     client.println("' y2='");
     client.println(y2);
     client.println("'");
     client.println("' style='stroke:rgb(255,0,0);stroke-width:2' />");
     client.println("Sorry, your browser does not support inline SVG.");
     y1 = y2;
     }
     client.println("</svg>");
     client.flush();
     client.println("<br><br>");
   
  
//버튼 HTML CSS 설정   
    client.println("<head>");
    client.println("<style>");
    client.println(".button {");
//    client.println("background-color: #4CAF50;");
    client.println("background-color: green;");
    client.println("border: none;");
    client.println("color: white;");
    client.println("padding: 15px 32px;");
    client.println("text-align: center;");
    client.println("text-decoration: none;");
    client.println("display: inline-block;");
    client.println("font-size: 20px;");
    client.println("margin: 14px 20px;");
    client.println("cursor: pointer;");
    client.println("}");    
    client.println("</style>");
    client.println("</head>");
    
  // client.println("<a href=\"/on\"\"><button>Data Refresh </button></a><br />");
      client.println("<a href=\"/on\"\" class='button'>Data Refresh </button></a>");
   client.println("</body>");           
   client.println("</html>");
   delay(1);
   Serial.println("Client disonnected");
   Serial.println("");
     
 }//프로그램 끝