본문 바로가기
Arduino&RasberryPi/Arduino Uno

12. Arduino - 택트 스위치와 풀업 저항

by Rosmary 2019. 11. 5.
728x90
반응형

Arduino Uno 스타터킷에는 택트 스위치라고 불리는 부품이 들어있다. 이 택트 스위치는 쉽게 설명하자면, 초등학교 과학 시간에 진행했던 전기 실험의 스위치와 유사한 물건이라고 생각하면 된다. 모양은 일반적으로 볼 수 있는 버튼처럼 생겼으며, 누를 때 마다 똑딱거리는 소리가 난다. (세부 모양은 조금씩 다르며, 일부 제품은 간단한 조립을 진행해야하는 경우도 있다)

 

 

1. 택트 스위치의 내부 구성

 

브래드보드나 회로 위에서 택트 스위치를 사용하기 위해서는, 택트 스위치의 내부 구조에 대해 알고 있어야 한다. 다행히도, 택트 스위치는 내부 구조가 복잡한 부품은 아니다.

 

이 스위치는 회로와 연결되는 단자가 4개 존재한다. 정사각형 4개의 변 중, 2개의 변에 각각 2개의 단자가 부착되어 있는데, 서로 다른 변에 붙어있는 단자는 스위치의 동작 없이도 서로 전기가 통하도록 내부 회로가 구성되어 있다.

 

 

스위치를 누르게 되면, 좌측과 우측의 회로가 서로 연결되어 전기가 흐르게 되는 구조를 가지고 있다. 따라서, 스위치를 누르면 작동하는 회로를 만들기 위해서는, 전원 공급부와 연결되는 단자가 GND와 연결되는 단자와 스위치 내의 같은 회로에 연결되면 안된다. 만약, 같은 회로로 연결한다면 스위치를 사용하는 의미가 없어진다. 아래의 그림을 참조하자.

 

< 스위치를 사용하기 위해서 우측과 같이 회로를 구성해야 한다 >

 

 

2.  풀업 저항과 INPUT_PULLUP 인자의 사용.

 

스위치를 사용하면서 알아야 할 개념 중에 풀업 저항이라는 개념이 있다. 풀업 저항은, 스위치가 설치된 회로에 전류가 흐르는지/흐르지 않는지를 확실하게 표시해주는 개념 중 하나라고 보면 된다. Arduino에서 이 풀업 저항을 사용하기 위해서는 pinMode() 함수의 두 번쨰 인자에 INPUT_PULLUP이라는 값을 입력해 주어야한다.

 

지금까지, pinMode() 함수를 사용하면서, 두 번째 인자로 사용할 수 있는 값이 INPUT/OUTPUT 만 있다고 설명을 했다. 하지만, 택트 스위치가 부착된 회로에서 전기 흐름을 판단하기 위해, INPUT과 OUTPUT을 동시에 사용해야 할 필요가 있는데, 이 때 사용할 수 있는 인자가 INPUT_PULLUP이라는 값이다.

 

========================

pinMode( # Pin, INPUT_PULLUP);

========================

 

pinMode() 함수에 이 값이 인자로 들어가면, 해당 핀은 회로로 5V의 전압을 공급함과 동시에, 회로 내의 잉여 전압을 측정할 수 있는 기능을 가지게 된다.

 

 

만약, 스위치가 열려있는 상태라면, 5V의 공급 전압이 고스란히 회로에 머무르게 되며, 이에 따른 8번 핀의 INPUT 값은 1이 나오게 된다(digital 핀이므로, digitalRead() 함수로 값을 읽는다). 반대로, 스위치가 닫히게 되면, 공급 전압이 모두 GND로 빠져나가기 때문에, 회로에 남는 잉여 전압이 없어, 8번 핀의 INPUT 값이 0으로 표시되게 된다.

 

그렇다면, pinMode() 함수를 2 개 만들어, INPUT과 OUTPUT을 작성하면 해결될 문제가 아니냐고 반문하는 분들이 있을 것이다(필자도 그랬다). 하지만, pinMode() 함수를 2개 만드는 방식에서 파생되는 문제 때문에 해당 방식을 사용할 수 없다. 

 

스위치가 떨어진 상태의 회로를 보자. 8번 핀에서 들어온 5V 전압이 회로를 흐르다가, 스위치에 막혀 더이상 흐르지 못한다. 이상적인 상황을 가정한다면(전선의 저항이 0일 경우), 8번 핀에서 측정한 회로값은 변함없이 1로 측정이 되어야한다. 하지만, 실제 회로에서는 전선에서도 저항이 약간이나마 존재하며, 이로 인해 회로 내의 잉여 저항값이 5V 보다는 조금 더 작게 존재하게 된다. 8번 핀에서는 회로의 전압을 측정한 뒤, 이를 digital 신호로 바꾸게 되는데, 5V에 해당하는 digitalRead() 값인 1023보다 작은 값이 측정되게 되면, 이를 1로 표시해야할지, 아니면 0으로 표시해야할지 알 수 없게 되어버린다. 이러한 상황이 지속적으로 발생하면, Arduino에 오류가 발생할 수도 있다고 하며, 이를 방지하기 위해 INPUT_PULLUP이라는 인자를 사용하는 것이다.

 

INPUT_PULLUP은, 핀에서 읽어들이는 값을 true / false로 나누는 것이라고 보면 된다. 풀업 저항의 경우, 0이 아닌 digitalRead() 값을 모두 1로 표시하도록, digitalRead() 값이 0인 경우 0으로 표시하도록 만들어주는 코드라고 보면 된다. 따라서, Arduino도 실제 측정 전압값에 의해 혼선을 빚지 않고 일정한 digital 값을 반환할 수 있게 되는 것이다.

 

 

3. 회로의 구성 및 실습.

 

 

(1) 스위치를 누를 때 LED가 점등되는 회로

 

회로의 구성은 아래와 같다. 택트 스위치의 한 쪽에는 8번 핀과 연결하였고, 다른 한 쪽은 LED와 GND 핀을 연결하였다.

 

< 저항을 또 깜빡하고 회로에 집어넣지 않았다... 부품 안태워먹었기에 망정이지... >

 

 

회로를 동작시키는 코드는 아래와 같다

 

int sourcePin = 8;

void setup() {
  Serial.begin(9600);
  pinMode(sourcePin, INPUT_PULLUP);
}

void loop()

{
  Serial.print("Voltage On / Off : ");
  Serial.println(digitalRead(sourcePin));    
}

 

8번 핀은 INPUT과 OUTPUT의 기능을 동시에 수행하고 있기 때문에, 버튼을 누르면 LED가 점등되는 것을 확인할 수 있음은 물론, Serial Monitor에서 회로 내의 전압 값을 지속적으로 측정할 수 있게 된다. Serial Monitor의 내용을 확인해보면, 버튼이 눌릴 경우 0이, 그렇지 않을 경우 1이 출력되는 것을 확인할 수 있다.

 

 

 

 

(2) 스위치를 누르면, LED가 On/Off 되는 회로

 

이제, 조금 더 업그레이드 된 형태의 코드를 작성해보려고 한다. 지금까지의 회로는 버튼을 누르고 있어야만, 불이 들어오는 형태였다. 하지만 필자는, 버튼이 한 번 눌리면 불이 켜진 상태로 지속되고, 다시 한 번 더 누르면 불이 꺼진 상태로 지속되도록 만들고자 한다. 앞서 포스팅한 가변 저항에서 이분화된 회로를 사용하듯이 회로를 구성하면 된다. 필자는 9번 핀을 통해 추가로 LED로 전원을 공급하며, GND는 Bus strip (-)를 이용해 두 회로의 출구를 공유하려고 한다.

 

 

코드는 아래와 같다.

 

int sourcePin = 8;
int ledPin = 9;
boolean switch_status = false;

void setup() {
  // put your setup code here, to run once:
  
  pinMode(sourcePin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  
}

void loop() {
  // put your main code here, to run repeatedly:

  while(switch_status == false)   
  {
    if(digitalRead(sourcePin) == 0)
    {
      delay(300);
      digitalWrite(ledPin, HIGH);
      switch_status = true;
    }
  }
  while(switch_status == true)
  {
    if(digitalRead(sourcePin) == 0)
    {
      delay(300);
      digitalWrite(ledPin, LOW);
      switch_status = false;
    }    
  }
  
}

 

Arduino에 해당 코드를 밀어넣고 작동시켜보면, 아래와 같이 의도한 대로 잘 동작함을 확인할 수 있다.

 

 

 

 

FIN.

반응형

댓글