아두이노기반 압력센서 개발 [2]
지난시간에 제작했던 압력센서를 이용해 아두이노와 프로세싱에서 값을 읽어보겠습니다.
자 먼저 아두이노기반 압력센서 개발 [1] 에서 만들었던 수정된 예제파일을 이용해 값을 볼 수도 있지만, 저희만의 프로그램을 짜보도록 합시다.
먼저 아두이노에서 코드를 더 수정해서 센서값만 받아와보도록 할까요?
/************************************************************************/
#include <Wire.h>
#include "Adafruit_MPR121.h"
// You can have up to 4 on one i2c bus but one is enough for testing!
Adafruit_MPR121 cap = Adafruit_MPR121();
void setup() {
while (!Serial); // needed to keep leonardo/micro from starting too fast!
Serial.begin(9600);
if (!cap.begin(0x5A)) {
Serial.println("MPR121 not found, check wiring?");
while (1);
}
}
void loop() {
for (uint8_t i=0; i<12; i++) {
Serial.print(cap.filteredData(i)); Serial.print(" ");
}
Serial.println();
// put a delay so it isn't overwhelming
delay(100);
}
/************************************************************************/
이 코드를 입력하고나면 시리얼 모니터에서는 아래와 같이 데이터들이 쭉 나열되서 확인이 될겁니다.
그럼 끝 아닌가요??
네 데이터만 받아보는거는 이렇게만 하면 끝입니다. 다만 값을 0 - 1023까지 값이 아닌 실제 압력이나 무게로 변환하기 위해서는 보정(Calibration) 작업이 필요합니다.
보정방법은 단순히 측정 무게의 추를 올려서 무게를 측정하는 방법으로 진행했습니다.
무게와 센서값을 엑셀에 잘 정리하면 하나의 그래프를 그릴수 있습니다.
저는 Matlab을 이용하여 그래프를 나타내고, fit() 함수를 사용하여 센서값과 최대한 근사된 다항함수를 이용하여 보정을 했습니다.
%%%%% Matlab Code %%%%%%%%
data = [0, 470;
5.4, 433;
10.8, 420;
16.2, 380;
21.6, 357;
27.0, 342;
32.4, 330;
37.8, 315;
43.2, 295;
100.0, 203;
200.0, 150;
300.0, 137;
400.0, 128;
500.0, 130;
1000.0, 72;
1500.0, 53;
2000.0, 63;
2500.0, 45;
3000.0, 33;];
force = data(:,1);
voltage = data(:,2)/1023*5;
figure();plot(force, voltage);
set(gca,'xscale','log');
hold on;
filtY=fit(force,voltage,'exp2');
plot(filtY, force, voltage);
hold off;
%%%%%%%%%%%%%%%%%%%%%%%
실제로 피팅하면 아래와 같은 보정 그래프를 볼 수 있고, 이를 통해 압력을 알 수 있습니다.
그럼 보정하는 다항식을 아두이노에 넣을건가?
실시간으로 아두이노 모니터를 통해 보신다면 그게 좋지만, 혹시나 프로세싱이나 안드로이드 등 다른 프로그램을 통해 압력값을 본다면, 아두이노에서는 그냥 0 - 1023의 데이터를 보내고, 프로세싱, 안드로이드에서 보정을 해주는 것이 효율적이다!
그럼 프로세싱으로는 어떻게 값을 읽어올까?
먼저 아두이노에서 값을 던질때,
387 396 410 419 421 422 419 422 412 399 388 379
387 396 410 419 421 422 419 422 412 399 388 379
387 396 410 419 421 422 419 422 412 399 388 379
이런 식으로 데이터가 나올텐데, 만약
#387 396 410 419 421 422 419 422 412 399 388 379!
#387 396 410 419 421 422 419 422 412 399 388 379!
#387 396 410 419 421 422 419 422 412 399 388 379!
위와 같이 나온다면, 어디서부터 어디까지가 한번에 읽어들인 데이터인지 알 수 있다.
그럼 프로세싱에서도 위와같이 컴퓨터가 #이라는 데이터를 받아들인 순간부터 !를 읽어들일때 까지를 하나의 데이터로 인식하게끔 만들면 된다.
/*****************************************************/
// 시리얼 통신을 위한패키지 호출
import processing.serial.*;
// 시리얼 통신 및 콘솔 아우풋을 위한 설정
Serial myPort;
PrintWriter output;
int lf = 40;
String inString;
float[] intensity = new float[8];
void setup() {
size(288, 276);
String portName = Serial.list()[2];
// 위 함수에서 컴퓨터와 연결된 아두이노의 포트넘버를 확인하고 거기에 맞는 숫자를 입력해야한다. (여기선 2번째라 '2'가 들어갔다)
// println(Serial.list());
myPort = new Serial(this, portName, 9600);
myPort.clear();
myPort.bufferUntil(lf);
}
void draw() {
background(0);
}
void serialEvent(Serial p) {
inString = (myPort.readString());
try {
String[] dataStrings = split(inString, ' ');
if ('s' == dataStrings[0].charAt(0)) {
// dataStrings.length = number of array elements seperated by '#'.
for (int i = 1; i < dataStrings.length; i++) {
intensity[i-1] = Integer.parseInt(dataStrings[i].substring(0, 3));
output.print(intensity[i-1] + " ");
}
output.println();
}
}
catch (Exception e) {
println("Caught Exception");
exit();
}
}
// ESC키가 눌렸을 때 프로그램 종료
void keyPressed() {
if (key == 27) { // 27 means ESC key
exit(); // Stops the program
}
}
/*****************************************************/
아마 사용하실 때 수정하셔야 할 부분은 serialEvent 함수 중에서 33 ~ 38번 줄만 수정하면 원하는 데이터 형태를 바로 정수로 변환하여 모니터링 할 수 있을거다.
만약 아두이노와 프로세싱간에 연동이 잘 된다면 아두이노의 시리얼 모니터에서 보는것과 같은 데이터가 프로세싱의 콘솔창에 나타날 것이다.
그 후 센서의 보정을 원한다면 프로세싱에서 작업을 해주면 된다 :)
사실 뒷부분은 예전에 센서를 제작한 터라 구체적인 설명이 부족합니다ㅠㅠ
혹시나 프로젝트를 진행하시다가 궁금하거나 어려운점이 있으시면 댓글에 남겨주세요ㅎㅎ
Have a good time with Arduino :)