코딩교육-아두이노

아두이노 디지털 핀 (7-세그먼트 게소드 제어 - 시리얼 통신) - Arduino Digtal Pin - Seven-Segment Cathode Control

carrotweb 2022. 1. 23. 18:22
728x90
반응형

Interrupt(인터럽트) - 시리얼 통신 입력

1. 이전 소스에 시리얼 통신을 테스트하기 위해 setup()함수에서 Serial.begin()함수를 설정하고 serialEvent()함수를 추가하여 컴파일하고 업로드합니다.

void setup() {
  for (int pinIndex = 0; pinIndex < pinCount; pinIndex++) {
    pinMode(ledPins[pinIndex], OUTPUT);
  }
  Serial.begin(9600);
  while (!Serial) {
  }
  Serial.println("Serial Port Connected.");
}

void serialEvent() {
  int readByte = Serial.read();
  Serial.println(readByte);
}

 

2. 시리얼 모니터를 실행시킨 후 "1234567890"을 입력하고 전송시킵니다.

응답 결과를 보면 10초마다(실제로는 10초 이상씩 걸립니다.) serialEvent()함수가 한 번씩 호출되는 것을 확인할 수 있습니다.

그 이유는 loop()함수에서 for문의 반복 횟수가 많거나 처리할 내용 복잡하여 연산 시간이 오해 걸리거나 for문안에 delay()함수가 포함되어 있으면 시리얼 통신으로 입력이 들어와도 바로 serialEvent()함수가 호출되지 않고 for문이 종료된 후 한 번만 호출됩니다.

그래서 loop()함수에는 for문대신 전역 변수와 delay()함수만 사용하여 for문처리 처리되게 수정합니다.

1. 전역에 반복 인덱스 변수를 선언합니다.

// 반복 인덱스
byte loopIndex = 0;

 

2. loop()함수에서 반복 인덱스를 증가시켜 7-세그먼트에서 숫자(0부터 9까지)를 표시하게 하고 1초를 대기하게 합니다.

void loop() {
  if (loopIndex > 9) {
    loopIndex = 0;
  }
  segmentDigitWrite(loopIndex);
  delay(1000);
  loopIndex++;
}

 

3. 컴파일하고 업로드합니다. 그리고 시리얼 모니터를 실행시킨 후 "1234567890"을 입력하고 전송시킵니다.

응답 결과를 보면 1초마다 serialEvent()함수가 한 번씩 호출되는 것을 확인할 수 있습니다.

for문이 사용하지 않기 때문에 serialEvent()함수가 호출되는 시간이 짧아졌습니다.

향후에 delay()함수를 사용하지 않고 millis()함수로 처리하는 방법에 대해 알아보겠습니다.

이제부터 serialEvent()함수를 사용하여 숫자 카운트를 실행시키거나 중지시키거나 지정된 숫자부터 다시 시작되게 해보겠습니다.

디지털 핀 출력 제어 - 7-Segment LED 숫자 카운트 제어

1. 전역에 반복 여부 변수와 반복 상태 변수를 선언합니다.

// 반복 여부
boolean loopDigit = true;
// 반복 상태
byte loopState = 's';

 

숫자 2차원 배열에 8개 LED(a, b, c, d, e, f, g, dp)에 디지털 신호를 주는 배열을 추가합니다.

// 숫자 0~9
byte segmentDigit[12][8] = {
  {1, 1, 1, 0, 1, 0, 1, 1}, // 0
  {0, 1, 1, 0, 0, 0, 0, 0}, // 1
  {1, 1, 0, 0, 0, 1, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 0, 1}, // 3
  {0, 1, 1, 0, 1, 1, 0, 0}, // 4
  {1, 0, 1, 0, 1, 1, 0, 1}, // 5
  {1, 0, 1, 0, 1, 1, 1, 1}, // 6
  {1, 1, 1, 0, 0, 0, 0, 0}, // 7
  {1, 1, 1, 0, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 0, 1}, // 9
  {0, 0, 0, 1, 0, 0, 0, 0}, // dot
  {0, 0, 0, 0, 0, 0, 0, 0} // clear
};

 

2. loop()함수에서 반복 여부 변수를 이용하여 조건으로 true이면 처리하고 false이면 처리하지 않게 합니다.

void loop() {
  if (loopDigit) {
    if (loopIndex > 9) {
      loopIndex = 0;
    }
    segmentDigitWrite(loopIndex);
    Serial.println(loopIndex);
    delay(1000);
    loopIndex++;
  }
}

 

3. 7-세그먼트에 숫자를 Blink(블링크 - 깜박거리다) 처리하게 함수를 선언합니다.

1초 동안 0.1초마다 7-세그먼트에 숫자를 표시하고 지워서 깜빡거리게 합니다.

void segmentDigitBlink(byte digit) {
  for (byte index = 0; index < 5; index++) {
    segmentDigitWrite(digit);
    delay(100);
    segmentDigitWrite(11);
    delay(100);
    segmentDigitWrite(digit);
  }
}

 

4. serialEvent()함수가 시리얼 버퍼로부터 읽은 바이트를 switch case문으로 처리합니다.

switch case 문은 if 문과 비슷하지만 여러 조건들을 처리할 수 있습니다. if문에 else if문을 여러 개 사용하는 것과 같습니다.

switch의 변수와 case의 비교 값을 맞으면 처리됩니다. case는 break가 나올 때까지 처리합니다. default는 case에 맞는 조건이 것이 없으면 처리됩니다. default는 생략할 수 있습니다.

switch(변수) {
  case 비교1 값:
    처리할 코드
    break;

  ...

  case 비교n 값:
    처리할 코드
    break;
  default:
    처리할 코드
    break;
}

 

 

아두이노 IDE에서는 시리얼 통신을 통한 디지털 핀 제어를 switch case 문으로 처리하는 방법을 예제로 제공하고 있습니다.

다음은 아두이노 IDE에서 제공하는 switch case문의 예제 소스입니다.

메뉴 : 파일 > 예제 > 05. Control > switchCase2

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  // initialize the LED pins:
  for (int thisPin = 2; thisPin < 7; thisPin++) {
    pinMode(thisPin, OUTPUT);
  }
}

void loop() {
  // read the sensor:
  if (Serial.available() > 0) {
    int inByte = Serial.read();
    // do something different depending on the character received.
    // The switch statement expects single number values for each case; in this
    // example, though, you're using single quotes to tell the controller to get
    // the ASCII value for the character. For example 'a' = 97, 'b' = 98,
    // and so forth:

    switch (inByte) {
      case 'a':
        digitalWrite(2, HIGH);
        break;
      case 'b':
        digitalWrite(3, HIGH);
        break;
      case 'c':
        digitalWrite(4, HIGH);
        break;
      case 'd':
        digitalWrite(5, HIGH);
        break;
      case 'e':
        digitalWrite(6, HIGH);
        break;
      default:
        // turn all the LEDs off:
        for (int thisPin = 2; thisPin < 7; thisPin++) {
          digitalWrite(thisPin, LOW);
        }
    }
  }
}

 

's'가 입력되면 시작, 'p'가 입력되면 중지, 'r'이 입력되면 재시작, 'e'가 입력되면 종료 처리하게 합니다.

조건문 처리에 대한 내용은 주석문으로 참고하세요.

그리고 숫자 0부터 9까지 입력되면 7-세그먼트에 숫자를 표시하고 Blink(블링크 - 깜박거리다) 처리합니다.

void serialEvent() {
  int readByte = Serial.read();
  switch (readByte) {
    case 's':
      if (loopState == 'e') { // 반복 상태가 end일때 처리
        loopIndex = 0; // 숫자를 0으로 변경
        loopState = 's';
        loopDigit = true;
        Serial.println("start");
      }
      break;
    case 'p':
      if (loopState == 's') { // 반복 상태가 start일때 처리
        loopDigit = false;
        loopState = 'p';
        Serial.println(loopIndex);
        Serial.println("pause");
        segmentDigitWrite(loopIndex); // pause 될때 숫자
      }
      break;
    case 'r':
      if (loopState == 'p') { // 반복 상태가 pause일때 처리
        loopDigit = true;
        loopState = 's';
        Serial.println("restart");
      }
      break;
    case 'e':
      if (loopState == 's' || loopState == 'p') { // 반복 상태가 start 또는 pause일때 처리
        loopDigit = false;
        loopState = 'e';
        Serial.println("end");
        segmentDigitWrite(11); // 7-세그먼트의 표시를 지움
      }
      break;
    default:
      if (loopState == 'p') { // 반복 상태가 pause일때 처리
        if (readByte >= '0' && readByte <= '9') { // 숫자 0부터 9까지만 처리
          // ASCII코드
          // 0: 48, 1: 49, 2: 50, 3: 51, 4: 52, 5: 53, 6: 54, 7: 55, 8: 56, 9: 57
          loopIndex = readByte - 48; // 0의 ASCII코드는 값인 48로 빼면 숫자 값이 됨
          segmentDigitBlink(loopIndex); // 변경된 숫자를 깜빡 거림
          Serial.println(loopIndex);
        }
      }
      break;
  }
}

도트 표시는 숫자가 아니라 재시작할 수 없어서 제어 처리에서는 제외하였습니다.

5. 컴파일하고 업로드합니다. 잠시 후 7-세그먼트의 LED에 불이 들어오면서 숫자 0부터 순차적으로 숫자가 표시됩니다. 시리얼 모니터에서 8자일 때 'p'을 전송하여 중지시키고 다시 'r'를 전송하여 재시작시킵니다. 그리고 2자일 때 'p'을 전송하여 중지시키고 '4'를 전송하여 깜빡거리면서 숫자 '4'가 표시됩니다. 다시 '7'를 전송하여 깜빡거리면서 숫자 '7'이 표시됩니다. 마지막으로 'e'를 전송하여 반복 처리와 숫자를 지웁니다.

 

다음 시리얼 모니터에 전송된 내용입니다.

728x90
반응형