본문 바로가기
임베디드/Arduino

키입력인터럽트 + LED + buzzer

by sj0020 2020. 9. 2.

1button pushed : led red on + buzzer buzz once

2button pushed : led yellow on + buzzer buzz twice

3button pushed : led green on + buzzer buzz 3times

/*
* 키입력 인터럽트 Update 2019.08.30 by hack4ork
* 풀다운 폴링
*/
#define BUTTON_PIN1 2

const int buttonPin1 = 2; // 인터럽트 0
const int buttonPin2 = 3; // 인터럽트 1
const int buttonPin3 = 4;
volatile char flag=0;
volatile long preTime = 0;
volatile long curTime = 0;
const int deBounce = 200;
int buttonState; 

int LED_R = 11;
int LED_Y = 9;
int LED_G = 10;
#define BUZZER 6
const int beepFrequency = 900; //900Hz
const int beepDuration = 500; //0.5sec
volatile int checkBtn;

void setup()
{
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(buttonPin1), buttonInterrupt1, FALLING);
  attachInterrupt(digitalPinToInterrupt(buttonPin2), buttonlnterrupt2, FALLING);

  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(LED_Y, OUTPUT);
  pinMode(LED_G, OUTPUT);
  digitalWrite(LED_R, LOW);
  digitalWrite(LED_Y, LOW);
  digitalWrite(LED_G, LOW);
  digitalWrite(BUZZER, LOW);
  pinMode(BUZZER, OUTPUT);
}

void loop() {
   
  // put your main code here, to run repeatedly:
  int reading = digitalRead(buttonPin3); // 폴링 방식 //클럭주파수 때문에 쫙 떨어지면서 뜬다.
 

  // if the button state has changed:
  if (reading != buttonState) { // buttonState의 값은 전역변수 0 => reading이 1일 때,
    buttonState = reading; // buttonState 값을 0으로 바꿔라

    // only toggle the LED if the new button state is HIGH
    if (buttonState == 1) { // if 버퍼 -> 시간차 조정
      Serial.println("1번 누름");
      flag=1;
      checkBtn = 1;
      digitalWrite(LED_R, HIGH);
      digitalWrite(LED_Y, LOW);
      digitalWrite(LED_G, LOW);
    }
  }

  if(flag)
  {
    if (checkBtn == 1) {     
      digitalWrite(BUZZER, HIGH);
      delay(500);
      digitalWrite(BUZZER, LOW);
    }
    else if (checkBtn == 2) {
      digitalWrite(BUZZER, HIGH);
      delay(500);
      digitalWrite(BUZZER, LOW);
      delay(500);
      digitalWrite(BUZZER, HIGH);
      delay(500);
      digitalWrite(BUZZER, LOW);
    }
    else if (checkBtn == 3) {
     digitalWrite(BUZZER, HIGH);
     delay(500);
     digitalWrite(BUZZER, LOW);
     delay(500);
     digitalWrite(BUZZER, HIGH);
     delay(500);
     digitalWrite(BUZZER, LOW);
     delay(500);
     digitalWrite(BUZZER, HIGH);
     delay(500);
     digitalWrite(BUZZER, LOW);
    }
    flag=0;
  }
}

void buttonInterrupt1() {
  checkBtn = 2;
  curTime = millis();
  if(curTime - preTime >= deBounce) {
    uint8_t oldSREG = SREG;
    cli();
    flag=1;
    Serial.println("2번버튼 누름");
    digitalWrite(LED_R, LOW);
    digitalWrite(LED_Y, HIGH);
    digitalWrite(LED_G, LOW);
    preTime = curTime;
    SREG = oldSREG;
  }
}

void buttonlnterrupt2() {
  checkBtn = 3;
  curTime = millis();
  if(curTime - preTime >= deBounce) {
    uint8_t oldSREG = SREG;
    cli();
    flag=1;
    Serial.println("3번버튼 누름");
    digitalWrite(LED_R, LOW);
    digitalWrite(LED_Y, LOW);
    digitalWrite(LED_G, HIGH);
    preTime = curTime;
    SREG = oldSREG;
  }
}

* 외부입력 인터럽트는 반드시 아두이노 2,3번 포트 에서만!! 동작한다.

* flag 넣어주지 않으면 루프에서 계속 돌기 때문에 buzzer 계속 울림 ..

* LED on 들은 인터럽트 핸들러에 넣어줘도 문제없음 . 하지만 buzzer는 인터럽트 핸들러 외부에 넣어줘야됨. 인터럽트 핸들러에 delay는 가급적 안넣어주는게 좋아서. 왜냐면 인터럽트를 빨리 처리하고 나와야 되므로