[아두이노] Calibration의 의미

IOT/아두이노|2019. 4. 29. 09:00

[아두이노] Calibration의 의미



오늘은 Calibration의 대해서 알아보고자 합니다. 우리가 Sensor를 사용하면 처음에 Sensor의 입력값에 대한 초기 보정이 필요하다고 이야기 한 적이 있을 꺼에요. 대표적으로 마이크사운드감지센서가 떠오르는군요. 이 Sensor의 초기 값은 처음 찍어보기 전까지는 알 수 없습니다. 그러면 코딩을 할 때 초기 Sensor의 값을 찍어봐야 알 수 있고 그 찍힌 값을 기준으로 코딩을 해야 합니다. 참 번거로운 코딩이 되겠죠. 그리고 같은 Sensor라도 초기값이 제각각 입니다. 대개 아날로그 신호를 출력하는 Sensor은 가변저항이 붙어 있어서 초기 값이 약간씩 차이를 보이고 이 가변저항을 돌리면 초기값이 변경 되기 때문에 미리 코딩을 해놓으면 초기 Sensor값이 다르기 때문에 원치 않는 동작을 수행 할 수 도 있겠죠. 이런 문제를 해결하기 위해서 Calibration라는 의미의 교정 작업을 코딩으로 표현할 수 있습니다. 이제부터서 Calibration에 대해서 자세히 살펴보도록 하겠습니다.

1. Calibration이란,


교정의 의미로 아두이노가 처음 전원이 공급되면 사용 할 부품에 대한 값에 대한 교정을 수행하기 위한 코딩입니다. 우리가 그래픽카드를 사면 젤 먼저 그래픽드라이버를 설치하고 모니터의 해상도를 설정 하잖아요. 여기서, 모니터의 해상도를 설정하는 작업을 교정작업이라고 생각하면 될 듯 싶네요. 실제 모니터의 해상도 작업이 아니라 의미적으로 그런 느낌의 작업을 처음에 수행하는 것을 Calibration이라고 의미적으로 이해하시면 될 듯 싶네요.

아두이노에서 Calibration의 작업은 Sensor의 초기값이나 초기 측정된 값에 대한 범위 지정을 설정하는데 주로 이용합니다. 즉, 초기 Sensor의 값을 기준점을 잡거나 기준 범위를 설정할 때 수행 합니다.

예를들어,


조도센서가 있다면 현실 환경에서는 측정되는 환경의 조건에 따라 그 값이 일정범위로 유지 되잖아요. 그러면 구지 전체 범위의 0~1023의 값의 기준으로 동작제어를 할 필요가 없습니다. 현재 환경에서 조도센서가 필요한 영역에 맞게 동작제어를 하면 효율적인 제어를 할 수 있겠죠. 그러면, 측정되는 조도센서값에서 동작 제어 값의 범위를 교정작업을 통해 최소~최대값을 잡아놓으면 그 값의 범위에 맞게 수행되기 때문에 정교하게 제어를 할 수 있게 됩니다.


또한, 마이크사운드감지센어의 경우에서도 가변저항기의 초기 값이 제각각이니깐 초기 값을 일정시간 동안 측정하고 측정된 값으로 교정하면 교정된 값이 기준이 되고 그 기준을 통해 마이크사운드감지센서의 소리가 입력에 대해 맞춰서 동작을 제어할 수 있게 됩니다.

예)

 int soundSensor =analogRead(A0);
    if(soundSensor>100) 작업명령1;
      else if(SoundSensor>50) 작업명령2;
        else 작업명령3;

이런 코드가 있다면 soundSensor 초기값이 만약 51이면 위 코딩에서는 else문을 절대 수행 할 수 없습니다. soundSensor 초기 값이 39면 else문을 수행 할 수 있지만 뭔가 너무 낮은 값에서 시작하기 때문에 조건식 100, 50의 비교가 옳바른지를 판단하기 애매합니다. 정확한 의미 전달의 작업명령을 하기 위해서는 어떻게 해야해야 할가요. 즉 초기의 soundSensor의 값을 기준으로 비교하는 값을 교정해야면 soundSensor의 값에 맞게 동작하겠죠.

SoundSensor의 초기 측정을 5초동안 수행해서 얻어진 평균값을 기준으로 해서

s = 기준값- 5초동안 측정한 평균값;

에서,

   if(soundSensor>100-s) 작업명령1;
      else if(soundSensor>50-s) 작업명령2;
        else 작업명령3;

이렇게 하면 대충 SoundSensor의 초기값에 맞게 작업명령을 수행하겠죠. 이렇게 교정하는 과정을 Calibration이라고 생각하시면 됩니다. 약간 의미의 느낌이 보정에 가까워져 버렸네요. 아두이노가 어떤 명령을 수행하기 위한 범위를 미리 잡아놓고 작업을 교정으로 생각하시면 될 듯 싶네요.

이제 본격적으로 실험을 해보도록 하겠습니다.

2. 회로도 구성


  • 준비물 : - 조도 센서 1개, 저항 10K옴 1개, 아두이노우노, 뻥판
  • 내용 : 아날로그핀에 조도센서의 입력 받을 수 있게 연결 한다.


저는 A0핀에 조도센서의 입력을 받도록 연결 했습니다.

3. 코딩


  • 내용 : 조도센서에서 일정시간동안 측정하고자 하는 최소~최대값을 범위를 측정한다.

함수

  • analogRead(아날로그핀) : 0~1023의 아날로그 신호를 읽음
  • millis() : 현재 타이머 시간값 반환
  • map(입력값, 입력최소값, 입력최대값, 출력최소값, 출력최대값) : 입력값이 입력 최소~최대값의 어느 위치이고 그 위치에 매칭되는 출력 최소~최대값 사이의 값을 반환한다.
  • constrain(입력값, 최소값, 최대값) : 입력값이 최소값보다 적을 경우 최소값에 수렴하고 입력값이 최대값보다 클 경우 최대값에 수렴한다.
    예로 constrain(3, 0, 10)이면 3이 반환, constrain(-3, 0, 10)이면 0이 반환, constrain(15, 0, 10)이면 10이 반환

Serial 통신

- Serial.begin(9600) : 시리얼통신 시작
- mySerial.print(값) : 값을 시리얼모니터로 출력하지만 커서는 현재 라인에 계속 유지.
- mySerial.println값) : 값을 시리얼 모니터로 출력하지만 커서는 새로운 라인으로 이동. 


const int sensorPin = A0;
int sensorValue = 0;      
int sensorMin = 1023;     
int sensorMax = 0;       

void setup() {
  Serial.begin(9600);
  
  while (millis() < 5000) {
    sensorValue = analogRead(sensorPin);

    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
 
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }
  }  
}

void loop() {
  
  sensorValue = analogRead(sensorPin);   
  sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);  
  sensorValue = constrain(sensorValue, 0, 255);

  Serial.print(sensorMin);
  Serial.print(" ");
  Serial.print(sensorMax);
  Serial.print(" ");
  Serial.println(sensorValue);  
}

제 블로그에도 소개한 적이 있는데 다시 소개하게 되었네요. loop문에서 사용 될 sensorMin과 sensorMax의 값을 교정작업을 setup() 함수에서 수행이 됩니다. Calibration의 동작은 setup()함수의 while()문이니깐 어떻게 교정되는지 잘 살펴 볼까요.

int sensorMin = 1023;     
int sensorMax = 0;      
  while (millis() < 5000) {
    sensorValue = analogRead(sensorPin);

    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
 
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }
  }  

위 코딩은 최소값을 1023으로 하고 최대값 0으로 초기값으로 while()문에 들어갑니다. 이때 while()함수의 조건식은 millis() 함수의 값이 5초보다 작을 때까지 참이 되는 문장입니다. 여기서, millis()은 시간함수로 아두이노에 전원이 공급되는 순간부터 0부터 시작하여 타이머가 돕니다. 시간값을 1000당 1초라고 생각하시면 됩니다. 처음 전류가 공급되니 0부터 시작해서 5000이 될 때 5초가 되게 됩니다. 즉, 5초동안 무한 루프를 돌게 됩니다.

if(조도센서값 >최대값){
  최대값=초도센서값;
}
if(조도센서값 <최소값){
  최소값=조도센서값;
}

조도센서값이 최대값보다 크면 그 값을 최대값으로 바꾸고 조도센서값이 최소값보다 작으면 그 값을 최소값으로 5초동안 반복 명령을 수행한다고 생각하시면 됩니다. 5초동안 측정된 최소~최대값을 실제 측정하는 입력범위 최소~최대값을 교정하게 됩니다.

void loop() {  
  sensorValue = analogRead(sensorPin);   
  sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);  
  sensorValue = constrain(sensorValue, 0, 255);
}

조도센서값을 읽고

map(조도센서값, 교정최소값, 교정최대값, 0, 255)

이렇게 교정된 값을 기준으로 조도센서값이 처리되어 나오게 되는 것이죠. 다음 라인은 만약에 교정된 최소~최대값의 범위를 벗어나는 값이 입력되었다면 예외처리가 필요합니다. constrain()함수로 값을 벗어나지 못하게 합니다.
map()함수에서는 교정값에 대해서 0~255가 매칭되어 출력되지만 벗어나게 되면 마이너스값이나 255이상의 값으로 나오게 됩니다. 그럴 경우에 대해서 다음과 같은 명령라인을 코딩하게 됩니다.

constrain(sensorValue, 0, 255);

마이너스 값을 가지게 되면 0에 수렴되게 하고 255이상의 값을 가지게 되면 255에 수렴되게 하는 일종의 값의 범위에 락을 걸어놓은 느낌이라고 생각하시면 될 듯 싶네요.

이제 코딩에 대해서 설명했으니깐 정확하게 교정된 값이 출력되는지 살펴 볼까요.

4. 결과



조도센서의 측정된 값이 교정최소값 54와 교정 최대값 951사이에서 map()수행 후 241로 반환되어 나왔네요.

가령, 아래와 같은 예외 상황이 발생한다면


조도센서값이 951을 넘어갈 경우 최대값을 넘어가기 때문에 map()함수는 255 이상의 값을 반환됩니다. 하지만 constrain()함수로 255에 수렴 되게 해서 결과가 255로 나왔네요.

마무리


아두이노공식 홈페이지에 튜토리얼에 나온 예제입니다. 너무 괜찮은 소스라 그대로 인용하게 되었네요. Calibration의 의미를 잘 이해하시고 아두이노에서 사용하셨으면 합니다. 사용하는 이유는 사용하는 Sensor의 초기값을 교정함으로써 보다 정교하게 컨트롤 하기 위함이니깐 좀 더 정교하게 동작을 제어하고 싶다면 꼭 Calibration의 의미를 꼭 이해를 하셨으면 합니다. 그리고 위 코딩과 같은 것이 교정의 하나의 방법이지 절대적 교정이 아닌 점을 기억 하세요. 이런 느낌의 교정하는게 Calibration 라고 생각하시면 됩니다.

여러분들도 한번 조이스틱의 초기 중심값에 대해 교정작업을 이 원리를 곰곰히 생각한 뒤 에 적용해 보셨으면 합니다. 그러면 따로 초기에 코딩으로 측정하고 측정된 값을 다시 수작업으로 코딩하지 말고 교정작업으로 한번에 처리해서 어느 조이스틱과 연결해도 해당 조이스틱에 맞게 컨트롤 될 수 있게 만들어 보세요.

이 외에도 생각하는 Sensor가 있다면 그 Sensor에 Calibration를 적용한다면 어떻게 코딩할까 하고 상상의 나래를 펼쳐 보세요.

댓글()