아두이노 코딩-83: WeMos 조도센서 저항값 변동 Processing 클라이언트 실시간 그래프 처리

codingart(66)
Published in
#kr
Words
865
Reading
4 min
Listen
Play
8y

noname01.png조도센서에 의해 주위 환경의 밝기를 측정해 LED를 ON OFF 하는 아두이노 프로젝트에서 지속적으로 변동되는 조도 센서 저항 값을 WeMos 보드에서 웹서버 방식으로 와이파이에 의해 클라이언트에 송신해 보자.

noname02.png

조도센서 배선 자체는 아두이노 우노와 WeMos 간에 특별한 차이는 없다. 하지만 WeMos 보드에서의 코딩은 ESP8266WiFi.h 라이브러리를 사용하는 웹서버 코딩 틀을 사용하도록 한다. 조도 센서와 함께 직렬로 설치된 1KΩ옴저항을 사용하여 1KΩ옴저항에 가해진 전압을 측정한 후 실측한 저항값(986Ω)을 사용하여 회로에 흐르는 전류를 계산할 수 있다. 아울러 조도센서 + 1KΩ옴저항 전체에 가해지는 전압이 WeMos 보드의 Vcc 전압 5V 이므로 1KΩ옴저항에 가해진 전압을 빼면 조도센서에 가해지는 전압이 얻어진다. 조도센서와 1KΩ옴저항에 흐르는 전류는 동일 므로 앞서 계산된 전류를 사용하여 조도센서의 저항 값 환산이 가능하다.
조도센서 저항값을 1000으로 나누면 KΩ 단위로 값이 얻어지는데 LED 가 ON OFF 되는 임계 값이 실측해 보면 약 6KΩ 이 된다. 그런데 이 값을 Processing 클라이언트에 전송해서

noname03.png

그래프를 작성하면 값이 너무 작으므로 10배하면 60 정도 크기의 숫자가 되므로 Processing 그래픽 화면에서 디스플레이 하기가 용이해진다.
Processing 클라이어트로부터 HTTP request “GET / HTTP/1.0” 이 입력 버퍼에 수신되면조도센서 저항 값 cdsRk를 준비하여 C 명령 dtostrf()를 사용하여 ASCII 문자열로 변환한다. 예를 들어 47.1이면 저항값은 부호가 항상 플러스이므로 필요없고 소숫점 포함 폭이 4가된다. 소숫점 이하 자릿수는 1로두면 되며 현재 더블이 아닌 싱글 버퍼 즉 4개 buf[4]로 처리하면 충분하다. 이 기법은 ThingSpeak 이나 앱 인벤터에 와이파이로 전송할 때도 동일하게 적용된다.

Processing 헤더 영ㅇ역에서 processing.net 라이브러리를 호출하고 Client c에 의해 클라스를 c로 간단히 선언하다.
setup()에서 그래픽 화면 크기는 size(600,400)으로 충분히 크게 잡는다. 그래프의 가로축과 세로축을 긋고 라벨 문자들을 출력한다. 이어서 setup() 후반부에 WeMos 보드의 가상ip를 대상으로 일단 HTTP request를 넣도록 한다.

draw()에서 c.available()체크에 의해 Processing 클라이언트 입력 버퍼에 데이터가 입력되었는지 확인한다. 입력버퍼에 데이터가 수신되었으면 c.readString() 에 의해 데이터를 읽어 콘솔 창에 출력하자. 이어서 그래픽 화면에 아두이노로부터의 입력 데이터를 사용하여 실시간 그래프를 작도한 후 다시 HTTP request “GET / HTTP/1.0”를 실행한다. Processing 코드르 실행해보면 request에 의해 한번 가상ip에 접속이 되었다가 일정 시간 후 다시 끓어지므로 draw()루프를 돌때마다 접속할 필요가 있다. 접속후 1초 정도의 시간이면 충분하다.

PC상에서 Processing 코드를 사용하여 마우스 위치를 센싱 후 데이터를 아두이노에 전송할 경우 4초 이상이 걸리지만 반대로 아두이노가 전송해 주는 상황에서 수신을 할 경우 충분히 빠른 속도를 보여준다.

다음 동영상에서 초점이 잘 맞을대 관찰해 보면 아두이노 시리얼 모니터와 Processing 실시간 그래프를 볼 수 있다. 그래프가 튀는 곳은 조도센서를 손으로 가렸을 때이다.

//HTTPclient_weMos_Cds_01
int xPos = 1; // horizontal position of the graph

String xLabel = "Time";
String yLabel = "CDs Resistance";
String Heading = "Real Time Data";
PFont font;

//Variables to draw a continuous line.
int lastxPos=1;
int lastheight=0;

import processing.net.*;
Client c;
String data;

void setup() {

size(600, 400);
background(255);
fill(200);

stroke(127,34,255); //stroke color
strokeWeight(4); //stroke wider
Axis_center();
stroke(127,34,0); //stroke color
strokeWeight(1);
Axis_ON_OFF();
font = createFont("Arial",12);
textAlign(CENTER);
textFont(font);
Labels();

c = new Client(this, "192.168.0.11", 80);
c.write("GET / HTTP/1.0\r\n");
delay(50);
}

void draw() {

if (c.available() > 0) { // If there's incoming data from the client...
data = c.readString(); // ...then grab it and print it
println(data);// c.clear();
}

if (data != null) {
// data = trim(data); // trim off whitespaces.
float inByte = float(data); // convert to a number.
inByte = map(inByte, 0, 300, 0, height); //map to the screen height.

//Drawing a line from Last inByte to the new one.
stroke(127,34,255);     //stroke color
strokeWeight(2);        //stroke wider
line(lastxPos, lastheight, xPos, height - inByte); 
lastxPos= xPos;
lastheight= int(height-inByte);

// at the edge of the window, go back to the beginning:
if (xPos >= width) {
  xPos = 0;
  lastxPos= 0;
  background(0);  //Clear the screen.
} 
else {
  // increment the horizontal position:
  xPos = xPos + 5;
}

}

c = new Client(this, "192.168.0.11", 80);
c.write("GET / HTTP/1.0\r\n");
delay(1000);

}

void Axis_center() {
// center line plot
stroke(0);
line(0,200,600,200);
}
void Axis_ON_OFF() {
// center line plot
stroke(255,0,0);
line(0,320,600,320);
}

void Labels(){

textFont(font,18);
fill(180);
rotate(radians(-90));
text(yLabel,-200,20);
textFont(font,16);

textFont(font,18);
rotate(radians(90));
text(xLabel,300,380);
textFont(font,24);
fill(250);
text(Heading,300,50);

}//Processing End

//Webserver_WeMos_Processing_Cds_switch_01
#include "ESP8266WiFi.h"

const char* ssid = "android1234";//무선 공유기 id로 수정
const char* password = "dddddddddd";//무선 공유기 비빌번호

String s;
String strVolt;

int measurePin = 0; //Connect variable resistor to A0 pin
float arduVolt = 4.9; //아두이노 전압 실측치
float r = 986; //1K옴 실측치
int ledPin = D2;

WiFiServer server(80);

void setup() {
Serial.begin(9600);
delay(10);

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

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.println(WiFi.localIP());
}

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 req = client.readStringUntil('\r');
Serial.println(req);
client.flush();

// Match the request

int val;
if (req.indexOf("GET / HTTP/1.0") != -1) {
val = 1;
int analogV = analogRead(A0);//0-1023
float V = arduVolt*analogV/(1023.0);//1K옴 저항 전압 환산
float i = V/r;//1K옴 저항 전류 계산, 암페어
float cdsV = arduVolt-V;//조도센서 전압 계산
float cdsR = cdsV/i;//조도센서 저항 계산
float cdsRk=cdsR/100.0; //10배 K옴으로 환산
Serial.println(cdsRk,1);//시리얼 모니터 출력
if( cdsR>6000) { // 6K옴 이하면 ON
digitalWrite(ledPin,HIGH);//어두우면 ON
}
else {
digitalWrite(ledPin, LOW);//밝으면 OFF
}

char buf[4];
strVolt = dtostrf(cdsRk, 4, 1, buf);
}
else {
Serial.println("invalid request");
client.stop();
return;
}
client.flush();
// Prepare the response
s = "";
s += strVolt;
s +="\n\r";
// Serial.print(s);
client.print(s);
delay(50);

Serial.println("Client disonnected");

}//끝