ESP8266 NodeMCU 와이파이에 의한 PC와의 인터페이스도 흥미롭지만 시리얼 통신에 의한 Processing 프로그램과의 인터페이스 또한 매력적이다. 비록 무선은 아닐지라도 프로그래밍이 대단히 간편하여 배워두면 쉽게 유익한 시스템을 만들어 낼 수 있다.
특히 실험실에서 아두이노에 센서를 설치해 사용한다면 너무나 쉽게 그 데이터를 PC로 읽어 와 저장하거나 심지어 비쥬얼하게 실시간 그래픽 처리를 할 수 있다.
아두이노에 가변저항을 선택하여 5V 및 GND , 그리고 가운데 전압이 나오는 배선은 아날로그 핀 A0에 배선하자. 가변저항의 값이 1KΩ 이거나 10KΩ이든 그다지 상관이 없다.
다음은 아두이노의 프로그램이다. setup()에서 Serial.begin()을 보통 9600으로 설정하자.
loop()에서 읽어들이는 아날로그 전압데이터는 정수형으로 0∼1023까지 분포한다. 따라서 4로 나누어서 0∼255로 값을 조절한다. 0∼255 로 표현된 정수 값은 8비트 데이터 즉 1 바이트 데이터로 처리할 수 있다. 아두이노에서 시리얼 인터페이스를 통해 Processing 코드에 Serialwrite() 명령을 사용하여 쉽게 데이터를 전송할 수 있다.
한가지 주의해야 할 점은 아두이노가 시리얼 통신으로 데이터를 PC로 보낼 때에 PC에서는 반드시 Processing 코드만이 시리얼 포트를 쓰도록 유의하기 바란다. 멀티태스킹 하는 것은 좋으나 Processing 코드 실행 중에는 절대 다른 프로그램이 시리얼 COM 포트 사용을 금하도록 하자.
다음은 아두이노 코드이다.
//Analog data sending to Processing
int ledPin = 3;
void setup() {
Serial.begin(9600);
}
void loop() {
int analogValue = analogRead(A0)/4; // read the sensor value
analogWrite(ledPin,analogValue);
Serial.write(analogValue); // send a byte binary value serially
}//프로그램 끝
프로세싱 프로그램 구성해 보자. 도입부에서 시리얼 통신 인터페이스를 지원하기 위한 라이브러리에 해당하는 import processing.serial.* 실행이 필수적이다. 아울러 시리얼 통신 인터페이스를 myPort로 명명해둔다.
import processing.serial.*;
Serial myPort;
실시간 그래픽 작업을 준비하기 위해서 다음과 같이 실수형태로 원점을 정의한다.
// Graphic setting
float xPos = 0; // horizontal position of the graph
float yPos = 0; // vertical position of the graph
setup()에서 그래픽 화면 크기를 800X260으로 정한다. 높이 260은 256 보다 조금 큰 편이다.
배경 색은 거의 검정색으로 선택한다.
장치관리자처럼 가용한 시리얼 포트를 조사해서 출력한다. 특히 아래의 장치 관리자 포트와 비교해 보면 현재 아두이노의 USB-2-Serial 커넥터가 “COM5“에 연결 인식되고 있음을 알 수 있다.
따라서 다음과 같이 코딩해서 사용해도 무방하며
port = new Serial(this, "COM5", 9600);
아니면 Serial.list()[2] 즉 콘솔 창 출력 결과의 3번째 COM 포트를 의미하는 아래의 명령도 좋다.
port = new Serial(this, Serial.list()[2], 9600);
초보자라면 이 부분에 주의를 기울이기 바란다.
void setup() {
size(800, 260);
background(#081640);
println("Available serial ports:");
println(Serial.list());
//port = new Serial(this, "COM17", 9600);
myPort = new Serial(this, Serial.list()[2], 9600);
}
아두이노에서 보내는 데이터를 받아들이기 위해서 프로세싱 프로그램은 반드시 serialEvent() 방식의 루틴을 사용한다. 현재 데이터를 받아들이는 작업뿐이므로 아두이노는 무조건 시리얼 통신에 Serial.write() 해주면 프로세싱이 serialEvent 루틴에 의해 알아서 데이터를 읽어 들이는 방식이다.
void serialEvent (Serial myPort) {
// get the byte:
int inByte = myPort.read();
println(inByte);
yPos = height - inByte;
}
아두이노로부터 전송된 전압 데이터를 inByte에 저장하여 그래픽 스크린에 적합하도록 연산 후 yPos에 저장한다.
실시간 그래픽을 위한 draw()에서는 읽어 들인 데이터에 맞춰 스크린 아랫 바닥 선에서 yPos 까지 높이에 해당하는 수직선을 긋는다. 속도가 충분히 빠른 편이다. 스크린 오른쪽 한계에 도착하면 전체를 배경색으로 초기화 하고 다시 그래픽을 시작한다.
동영상을 통해 가변저항을 돌려 발생된 전압을 PC의 Processing 코드에서 수신하여 그래프 출력을 관찰해 보자.
//Processing_receiving_data_from Arduino_01
import processing.serial.*;
Serial myPort;
// Graphic setting
float xPos = 0; // horizontal position of the graph
float yPos = 0; // vertical position of the graph
void setup() {
size(800, 260);
background(#081640);
println("Available serial ports:");
println(Serial.list());
//port = new Serial(this, "COM5", 115200);
myPort = new Serial(this, Serial.list()[2], 9600);
}
void serialEvent (Serial myPort) {
// get the byte:
int inByte = myPort.read();
println(inByte);
yPos = height - inByte;
}
void draw() {
// draw the line in a pretty color:
stroke(#A8D9A7);
line(xPos, height, xPos, yPos);
// at the edge of the screen, go back to the beginning:
if (xPos >= width) {
xPos = 0;
// clear the screen by resetting the background:
background(#081640);
} else {
// increment the horizontal position for the next reading:
xPos++;
}
}//End of Processing program