아두이노 NodeMCU를 사용하는 다양한 WiFI 통신 예제를 이미 접해보았지만 웬지 만족도가 거의 바닥일 것이다. Thingspeak 예제가 잘된다 하더라도 기껐 15초 간격 이상으로만 측정한 아날로그 데이터를 전송할 수 있다.
더 나아가 아두이노 NodeMCU에 의한 Thingspeak의 MQTT방식 조차도 그다지 만족스럽지 못하며 별 차이가 없다고 느껴질 것이다.
아두이노 NodeMCU 또는 아두이노 와이파이 모듈을 Web으로 삼고 자신의 스미트 폰을 아두이노의 LED나 스위치 또는 릴레이를 제어할 수 있는 가능성은 이미 웹서버 예제에서 학습하였다.
그렇다면 보다 높은 전송 속도로 아두이노 NodeMCU에서 생성한 데이터를 보다 빠르게 생생하게 자신의 스마트 폰에서 비쥬얼하게 볼 수 있는 방법은 없는 것일까?
이 번 블로그에서는 구글차트 기법을 아두이노 NodeMCU 웹서버 기법과 결합하는 프로그래밍 사례를 제시하기로 한다. 구글 차트 기법은 HTML과 Java Script가 혼합되어 있는 프로그램임을 감안한다. 그렇다고 각자가 Java Script 전문가일 필요는 없다.
이 블로그의 프로그램을 성공시키면 수많은 구글 그래프를 아두이노 NodeMCU를 웹서버로 사용하여 각자의 스마트 폰에 연동하여 그래프를 올려 볼 수 있게 된다.
일단 웹서버 프로그램 예제에서 가장 단순한 버튼 형의 인터액티브 프로그램을 맛보았으므로 그 사이에 구글 차트에 의한 그래프 프로그램을 삽입하여 비쥬얼하게 자신의 스마트 폰에서 볼 수 있도록 예제를 구성해 보도록 한다.
필요한 준비물은 앞서의 예제에서 사용했던 가변저항이 하나 설치된 아두이노 NodeMCU를 그대로 사용하면 된다.
Step 1: 다음 주소의 구글 차트 홈으로 들어간다.
https://google-developers.appspot.com/chart/interactive/docs/gallery
Step 2: 빨간 박스를 클릭하면 수많은 종류의 정형화된 그래프 종류를 나열한 메뉴를 볼 수 있다.
그 중에 빨간 박스 친 차트에 관심을 가지기로 한다. 필자는 이것이 아두이노 NodeMCU 웹서버와 구글 차트를 연동시키기 쉬우면서 좋은 예제로 판단하였다.
Step 3: 그 다음 다음의 Point 그래프 주소로 들어가자.
Step 4: Overview 메뉴 탭 밑으로 좀 이동하면 Advanced Usage의 빨간 박스 친Points를 찾을 수 있을 것이다. 아울러 오른 쪽 그래픽 화면에서 드래그하면 좌측의 점 그래프 예제를 쉽게 찾을 수 있을 것이다.
그래프 하단에 HTML 프로그램이 일부 보이는데 바로 이 프로그램을 데모버전에 이용하도록 하자. 번역판 구글이 아닌 원본 구글의 프로그램은 버그가 거의 없어 신뢰할만하다.
이 프로그램을 굳이 확인해보자고 한다면 NotePad++과 같은 무료 웹프로그램을 활용하면 좋다.
하지만 꼭 그럴 필요조차도 없음을 지적한다.
내용을 분석해 보면 8개의 좌표 데이터를 사용함을 알 수 잇다. 첫 번째가 (1,3)에서 시작하여 마지막이 (8,3)으로 끝남을 알 수 있다. 그러면 이 프로그램을 Data Refresh가 가능했던 웹서버 예제에 추가하는 방법을 터득하면 일단 쉽게 스마트 폰에서 그래프를 확인해 볼 수 있다.
이 프로그램을 옮김에 극히 주의할 점은 두 가지 따옴표 사용에 주의해야 한다.
이 구글 차트 프로그램 문장 전체의 각 줄별로 client.print(“ 와 )”;로 싸주어야 한다. 약간의 타이핑 노력은 필요하리라 본다. 단 주의 할 점은 구글 차트 프로그램 문장 중에 따옴표 “ 와 ”를 사용하고 있다면 client.print(“ 와 ”);에서 추가된 따옴표와 구분하지 못하여 아두이노 편집기가 컴파일 문법 에러를 발 할 것이다. 그래서 구글 차트 프로그램에서 사용된 따옴표를 하나 짜리 따옴표 ‘ 또는 ’로 반드시 수정해야 한다. 이 점 만 주의하면 아무런 문제없이 당신의 스마트 폰 인터넷 주소 창에서 스마트 폰 핫스팟 ip 주소를 타이핑 하고 이동키를 누르면 잠시 후 원하는 그래프 모양을 관찰할 수 있을 것이다.
그래도 이 과정을 쉽게 확인할 수 있도록 확인된 프로그램을 다음에 실어 두기로 한다.
단 이프로에서 Data Refresh 버튼을 누르더라도 동일한 점 그래프가 그려짐에 유의하자.
스마트폰 데이터 네트워크와 핫스팟을 켠 후 프로그램을 컴파일해서 업로딩하면 시리얼 모니터를 통해 공유기 핫스팟의 ip 주소를 볼 수 있다.
웹서버 예제에서와 마찬가지로 스마트 폰 인터넷 주소 창에 ip 주소를 입력한 후에 엔터(이동) 키를 누르면 스마트 폰 화면에서 유려하게 인터폴레이션 된 곡선을 볼 수 있다.
하단의 Data Refresh 키를 누르면 이 동일한 곡선이 다시 출력된다.
각자 Good Luck!
곧 아래의 프로그램을 조금 수정하여 아주 느린 속도의 실시간 아날로그 데이터를 센싱하여 하여 그래프를 그려주는 프로그램을 뒤이어 올리도록 할 예정이다. 혹 블로그에 글 올리는 중에 프로그램 줄이 긴 경우 두 줄로 나누어지는 경우가 있는데 이는 각자가 찾아서 한 줄로 만들어야 함.
//Webserver_NodeMCU_googlechart_01
#include <ESP8266WiFi.h>
const char* ssid = "AndroidHotspot1234"; //자신의 ID를 정확히 타이핑 하도록.
const char* password = "00000000"; //자신의 스마트 폰 비번을 확인하고 입력할 것.
// 비번 없을 경우는 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 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;
}
// 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(" <head>");
client.println("<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>"); //줄이 길어 넘어갔으면 //아두이노 편집기에서 한 줄로 합치도록
client.println("<script type='text/javascript'>");
client.println("google.charts.load('current', {packages:['corechart']});");
client.println("google.charts.setOnLoadCallback(drawChart);");
client.println("function drawChart() {");
client.println("var data = google.visualization.arrayToDataTable");
client.println("([['X', 'Y'],");
client.println("[2, 2.5],");
client.println("[3, 3],");
client.println("[4, 4],");
client.println("[5, 4],");
client.println("[6, 3],");
client.println("[7, 2.5],");
client.println("[8, 3]");
client.println("]);");
client.println("var options = {");
client.println("legend: 'none',");
client.println("hAxis: { minValue: 0, maxValue: 10 },");
client.println("curveType: 'function',");
client.println("pointSize: 20,");
client.println("};");
client.println("var chart = new
google.visualization.LineChart(document.getElementById('chart_div'));");//줄이 길어
//넘어갔으면 아두이노 편집기에서 한 줄로 합치도록
client.println("chart.draw(data, options);");
client.println("}");
client.println("</script>");
client.println("</head>");
client.println("<body>");
client.println("<div id='chart_div' style='width: 900px; height: 500px;'></div>");
client.println(" </body>");
client.println("<br><br>");
client.println("<a href=\"/on\"\"><button>Data Refresh </button></a><br />");
client.println("</html>");
delay(1);
Serial.println("Client disonnected");
Serial.println("");
}