아두이노 스위치

2021. 8. 2. 10:41아두이노

지금까지 우리는 디지털 핀을  pinMode(pin번호, OUTPUT),   출력으로만 사용해봤다. 

OUTPUT이 있으면 INPUT도 있다. 디지털 핀을 입력으로 사용하는 대표적인 예가 스위치다.

스위치를 사용해 LED를 제어해보자.

 

아두이노에서 OUTPUT,INPUT의 의미

OUTPUT : 아두이노로부터 전격전압을 받음. 스케치 코드에 따라 5V(상태1) or 0V(상태0)를 단자로 전달

              데이터가       아두이노 ->  단자

 

INPUT :  단자가 아두이노한테 전격전압을 줌.

           데이터가             단자 - > 아두이노

 

회로상에서 사용자가 스위치의 버튼을 누르고 떼는  행위 등을 통해

INPUT핀에 5V(1)이 전달되면 HIGH,   0V(0)이 전달되면 LOW가 된다.  

이를 소스코드에서 digitalRead(INPUT핀번호)로  읽을 수 있다.

 

ex ) : if (digitalRead(5)==HIGH){} 

         

 

스위치 종류 

   

4핀스위치,2핀 스위치가 있다.  

2핀스위치에서 보듯이  A type은 누르고 있을 때 연결된다. B type은 반대로 떼고 있을 때 연결된다.

4핀 스위치는 2핀스위치 2개를 합친 것.

 

 

 

4핀 스위치 사용

 

 

내부적으로 버튼을 누르지않아도 (1,3),   (2,4)는 서로 연결되어있다. 

따라서 항상 1,4  2,3이  연결되도록 하기 위해선 대각선으로 연결하도록 하자.

 

 

 

 

 

플로팅

 

출처 : https://k-bro.tistory.com/72

'입력' 부분이 아두이노 입력핀이라 생각해보자.

위의 경우에 HIGH가 입력되고 아래경우에는 LOW가 입력이 될 것처럼 보인다.

하지만 스위치를 눌렀을때는  정상적으로 HIGH가 입력되지만

스위치를 뗏을 때는 흐르던 전류가 갈곳을 잃어 주변 자기장에 영향을 끼쳐 곧바로 LOW가 되지 않는다.

이를 값이 0이되지않고 붕 떠있다고 해서  floating현상이라고 합니다.

이를 해결하기 위해 저항을 연결해  전류의 흐름을 통제하는 방법인 

풀업 또는 풀다운 저항을 이용합니다.

 

풀업,풀다운은 내부, 외부이 있습니다.

내부는  pinMode(pin번호, INPUT_PULLUP)와 같이 소스코드에서 PULLUP,PULLDOWN 선언만  해주면 돼서 간단합니다.
외부는  외부에 저항을 연결해 더 복잡하지만 안정적입니다.

 

외부풀업, 풀다운에 대해 알아봅시다.

 

 

풀업 : 스위치를 기준으로 입력전압쪽에 저항 연결

 

풀업 스위치 열렸을 때                          

4번 핀의 전위는 5V이기때문에 HIGH(1)

 

 

풀업 스위치 닫혔을 때

 

4번 핀의 전위는 0V  (GND) 이기때문에 LOW(1)

풀다운 :스위치를 기준으로 GND 쪽에 저항 연결

 

풀다운 스위치 열렸을 때      

4번 핀의 전위는 0V  (GND) 이기때문에 LOW(1)

 

풀다운 스위치 닫혔을 때  

4번 핀의 전위는 5V이기때문에 HIGH(1)

 

 

우리는 풀다운으로 실습해보자.

 

 

 

 

실습1. 외부 풀다운 방식으로  Switch를 누르고있으면 점등, 떼면은 소등이 되도록 해보자.

더보기
const int led=13;
const int btn=5;
void setup() {
  pinMode(13,OUTPUT);
  pinMode(btn,INPUT);

}

void loop() {
  if(digitalRead(btn)==LOW){
    digitalWrite(led,LOW);
  }else{
    digitalWrite(led,HIGH);
  }

}

 

 

 

실습2.  외부 풀다운 방식으로 Switch를 한번 누를 때마다 led상태가 변화하도록 해보자.

더보기
int btn=5;    
int red=13;

boolean btnCurrent=LOW;       //현재 버튼 상태

void setup() {
  pinMode(red,OUTPUT);
  pinMode(btn,INPUT) ;
}

void loop() {
  //현재버튼 읽음
  btnCurrent=digitalRead(btn);
  if( btnCurrent==HIGH){   // 버튼 누름
    if(digitalRead(red)==LOW){  //현재 꺼져있으면
      digitalWrite(red,HIGH);  //킨다
    }else{ 
      digitalWrite(red,LOW);  //끈다
    }
  }
  
}

 

실습2의 경우 누를 때마다 바뀌긴 하는데 조금 이상하게 바뀐다면 매우 정상입니다.

한번 누를때마다 여러변 반짝이는 듯한 현상은 바로 채터링때문입니다.

 

 

 

채터링

스위치를  한번 누를 때 디지털신호가 한번에 ON이 되는게 아니라 저 Bounce구간을 거쳐 ON이 된다.

이 Bounce 구간때문에 채터링이 발생.  이를 해결하는 것을 Debouncing이라고 한다.

Debouncing에는 HW방식, SW방식으로 해결할 수 있지만 HW방식으로 해결하기 위해서는 캐패시터가 필요.

결국 SW방식으로 해결해야 한다.

 

 

SW방식 디바운싱

1.이전 버튼 상태와 현재 버튼 상태를 저장(초기상태는 모두 LOW)

2. 현재 버튼상태를 읽음 ( 현재버튼상태= digitalRead(스위치핀번호);)

3. 현재 버튼 상태가 이전 버튼상태와 다른 경우 5ms 대기

4. 5ms 후 버튼 상태를 다시 읽어 현재 버튼 상태로 저장

5. 이전 버튼 삳태가 LOW이고 현재 버튼 상태가 HIGH 인 경우 버튼 입력 발생

6. 현재 버튼 상태를 이전 버튼 상태로 대입

7. 2번부터 반복 

 

 

 

실습 2_2 .  실습2의 debouncing을 적용해 채터링 현상 제거해서 

               한번 누를 때마다 스위치 상태가 제대로 변화하도록 해보자.

더보기
int btn=5;    // switch를 누르면 HIGH, 안누르면 LOW
int red=13;
boolean lastBtn=LOW;      //전 버튼 상태
boolean currentBtn=LOW;   //현재버튼 상태
#define DEBOUNCING_DELAY 5 //const int debouncingDelay=5;  



void setup() {
  // put your setup code here, to run once:
  pinMode(red,OUTPUT);
  pinMode(btn,INPUT);
}

//현재버튼과 전 버튼 비교
//같으면 암것도 안함,  다르면 5ms 기다림
//기다리고 버튼상태를 현재버튼으로 저장,    현재버튼이 HIGH, 전버튼이 LOW이면 버튼 입력 발생 , 현재버튼상태를 이전버튼으로 변경 
boolean buttonInputChattering(){
   boolean current=digitalRead(btn);
   if(current!=lastBtn){                 //현재읽은에 전상황이랑 다르면..... 
    delay(DEBOUNCING_DELAY);
    current=digitalRead(btn); //5ms 뒤 다시 읽음
   }
   return current;        //다시 읽은 입력상태 return 
}


void loop() {
  currentBtn=buttonInputChattering();     //현재 btn은 5ms 후의 읽은 값이 현재 버튼 상태
  if(currentBtn==HIGH && lastBtn==LOW){  // 전버튼은 low, 현재버튼 HIGH ==> 버튼 누른것으로 간주 
        if(digitalRead(red)==HIGH ){
          digitalWrite(red,LOW);
        }else if(digitalRead(red)==LOW ){
          digitalWrite(red,HIGH);
        }
  }     
  lastBtn=currentBtn;                                
}

 

 

 

문제1. 스위치 누를 때마다 3개의 led가 순차적으로 켜지도록. ( 한 번에 한개씩만 켜지게)

더보기
int btn=5;    
int red=13;
int green=12;
int blue=11;

boolean lastBtn=LOW;      
boolean currentBtn=LOW;   
#define DEBOUNCING_DELAY 5 



void setup() {
  // put your setup code here, to run once:
  pinMode(red,OUTPUT);
  pinMode(green,OUTPUT);
  pinMode(blue,OUTPUT);
  pinMode(btn,INPUT);
}


boolean buttonInputChattering(){
   boolean current=digitalRead(btn);
   if(current!=lastBtn){                 //현재읽은게 전상황이랑 다르면..... 
    delay(DEBOUNCING_DELAY);
    current=digitalRead(btn); //5ms 뒤 다시 읽음
   }
   return current;        //다시 읽은 입력상태 return 
}
void onlyOneLedOn(int led){
  if(led==red){
    digitalWrite(red,HIGH);
    digitalWrite(green,LOW);
    digitalWrite(blue,LOW);
  }else if(led==green){
     digitalWrite(red,LOW);
    digitalWrite(green,HIGH);
    digitalWrite(blue,LOW);
  }else if(led==blue){
     digitalWrite(red,LOW);
    digitalWrite(green,LOW);
    digitalWrite(blue,HIGH);
  }else if(led==0){
      digitalWrite(red,LOW);
    digitalWrite(green,LOW);
    digitalWrite(blue,LOW);
  }
}


int count=0;
void loop() {
  currentBtn=buttonInputChattering();     //현재 btn은 5ms 후의 읽은 값이 현재 버튼 상태
  if(currentBtn==HIGH && lastBtn==LOW){  // 전버튼은 low, 현재버튼 HIGH ==> 버튼 누른것으로 간주
      count++;
      switch (count%4){
        case 1 : onlyOneLedOn(red);break;
        case 2 : onlyOneLedOn(green);break;
        case 3 : onlyOneLedOn(blue);break;
        default :onlyOneLedOn(0);break;
      }
  }     
  lastBtn=currentBtn;                                
}