레이블이 아두이노 실습인 게시물을 표시합니다. 모든 게시물 표시
레이블이 아두이노 실습인 게시물을 표시합니다. 모든 게시물 표시

2017년 5월 18일 목요일

아두이노 실습] QDSP6064 Bubble Display (4 digit FND)

QDSP6064는 일명 Bubble display라고도 불리는데 4개의 FND가 하나의 패키지에 들어 있는 Common-Cathode 타입의 디스플레이이다.



크기는 크지 않아도 숫자 부분이 뽈록 튀어나와 렌즈 역할을 해 주기 때문에 숫자는 꽤 크게 보인다.


핀 배치는 위의 그림과 같고 Common-Cathode 타입이기 때문에 active high 구동을 하면 된다.


동작을 확인하기 위해 아두이노에는 위의 그림처럼 연결 해 주었다. 그리고 표시되는 카운트를 up/down 하기 위해 두개의 스위치를 추가했다. 우노의 경우 0,1번 핀은 시리얼 포트가 사용하고 있기 때문에 스위치를 추가할 핀이 모자르다. 그래서 아날로그 입력 A0, A1을 디지털 핀으로 사용하였다.


회로도 그림대로 브레드보드에 연결하고 스케치를 실행한 상태이다. 초기 카운트 값이 0이라 QDSP6064에 0000이 표시되고 있다.


동작 동영상은 위와 같다.

위에 사용한 스케치 코드는 다음과 같다.

#define UP A0
#define DN A1

const byte gDgtFont[] = {0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x72,0x7f,0x7b};
int gCnt = 0;

void setup() {
  int i;

  for (i=0;i<7;i++) pinMode(i+2, OUTPUT);
  for (i=0;i<4;i++) pinMode(i+9, OUTPUT);
  pinMode(UP,INPUT_PULLUP);
  pinMode(DN,INPUT_PULLUP);
  Serial.begin(115200);
}

void loop() {
  dispVal(gCnt);
  checkUpSw();
  checkDnSw();
}

void checkUpSw()
{
  static unsigned long last;
  static boolean prev = HIGH;
  unsigned long now = millis();
  boolean curr;

  if ((now-last)>10) {
    curr = digitalRead(UP);
    if ((HIGH==prev) && (LOW==curr)) {
      gCnt = (gCnt+1)%10000;
    }
    prev = curr;
    last = now;
  }
}

void checkDnSw()
{
  static unsigned long last;
  static boolean prev = HIGH;
  boolean curr;
  unsigned long now = millis();

  if ((now-last)>10) {
    curr = digitalRead(DN);
    if ((HIGH==prev) && (LOW==curr)) {
      gCnt = gCnt-1;
      if (-1 == gCnt) gCnt = 9999;
    }
    prev = curr;
    last = now;
  }
}

void dispVal(int val)
{
  static byte pos = 0;
  static unsigned long last = 0;

  if ((millis()-last)>2) {
    switch(pos) {
      case 0: dispDgt((val/1000),0); break;
      case 1: dispDgt((val/100)%10,1); break;
      case 2: dispDgt((val/10)%10,2); break;
      case 3: dispDgt((val%10),3); break;
    }
    pos = (pos+1) & 3;
    last = millis();
  }
}

void dispDgt(byte dgt, byte pos)
{
  int i;

  for (i=0;i<4;i++) digitalWrite(i+9, HIGH);
  for (i=0;i<7;i++) digitalWrite(i+2, (gDgtFont[dgt]&(1<<(6-i))));
  digitalWrite(pos+9, LOW);
}







2017년 5월 9일 화요일

아두이노 실습] 푸쉬버튼 long press, short press 판단하기

아두이노에서 푸쉬버튼 스위치의 long press와 short press를 구분하기 위해서는 스위치가 눌린 시간을 기록해 놓은 다음 눌린 스위치가 떨어질 때 스위치가 눌려있던 기간을 계산해 특정 시간보다 짧으면 short press, 길면 long press로 판단 해 주면 된다.



이번 실험을 위해 연결한 회로이다. 13번 핀에 시스템이 동작하는지 확인하기 위한  heartbeat LED를 연결 해 주고 4번 핀에 푸쉬버튼 스위치를 연결해 주었다. 4번 핀의 pinMode로 INPUT_PULLUP을 사용할 것이기 때문에 추가로 저항을 연결할 필요는 없다.

#define SW 4
#define RELEASED 0
#define SHORT_PRESS 1
#define LONG_PRESS  2
#define SW_THRESHOLD  500

#define HB_LED 13

void setup() {
  pinMode(HB_LED, OUTPUT);
  pinMode(SW, INPUT_PULLUP);
  Serial.begin(115200);
}

void loop() {
  static boolean hbLedStat = LOW;
  static unsigned long last;
  int swState = readSw();
 
  if (SHORT_PRESS == swState) {
    Serial.println("SWITCH SHORT PRESSED");
  } else if (LONG_PRESS == swState) {
    Serial.println("SWITCH LONG PRESSED");
  }
  if ((millis()-last) >= 500) {
    digitalWrite(HB_LED, hbLedStat);
    hbLedStat = !hbLedStat;
    last = millis();
  }
}

int readSw()
{
  static boolean prev = HIGH;
  static unsigned long last, pressed;
  boolean curr;

  if ((millis()-last) >= 10) {
    curr = digitalRead(SW);
    if ((HIGH==prev)&&(LOW==curr)) {
      pressed = millis();
      prev = LOW;
    } else if ((LOW==prev)&&(HIGH==curr)) {
      prev = HIGH;
      if ((millis()-pressed) > SW_THRESHOLD) {
        return LONG_PRESS;
      } else {
        return SHORT_PRESS;
      }
    }
    last = millis();
  }
  return RELEASED;
}


코드는 위와 같다. 프로그램이 실행되면 heartbeat LED는 1초 간격으로 계속 깜빡이고 스위치를 눌렀다 떼면 누르고 있던 시간 길이에 따라 short press, long press를 판정해 시리얼 포트로 결과를 출력해 준다.



아두이노 실습] Push button 스위치로 FND 카운트 증가/감소

2개의 push button으로 FND의 숫자 카운트를 up/down 시키는 실습

회로도...여기서는 Common Anode 타입의 FND를 사용


 브레드보드 연결도



4번핀에 연결된 스위치로 숫자 카운트를 up, 5번핀에 연결된 스위치로 숫자 카운트를 down하는 스케치

#define FND_A 13
#define FND_B 12
#define FND_C 11
#define FND_D 10
#define FND_E 9
#define FND_F 8
#define FND_G 7
#define FND_DP 6

#define UP  4
#define DN  5

#define dW digitalWrite
#define ON LOW
#define OFF HIGH

int gCnt = 0;

void setup() {
  for (int i=6;i<14;i++) pinMode(i, OUTPUT);
  pinMode(UP, INPUT_PULLUP);
  pinMode(DN, INPUT_PULLUP); 
}

void loop() {
  readUpSw();  // UP 스위치 처리
  readDnSw();  // DOWN 스위치 처리
  dispFnd(gCnt);
}

void dispFnd(int val)
{
  static int prevVal = -1;

  if (prevVal != val) {   // FND에 표시할 값이 바뀐 경우에만 표시를 변경
    switch (val) {
      case 0:
        dW(FND_A, ON); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, ON); dW(FND_E, ON); dW(FND_F, ON); dW(FND_G, OFF);
        break;
      case 1:
        dW(FND_A, OFF); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, OFF); dW(FND_E, OFF); dW(FND_F, OFF); dW(FND_G, OFF);
        break;
      case 2:
        dW(FND_A, ON); dW(FND_B, ON); dW(FND_C, OFF); dW(FND_D, ON); dW(FND_E, ON); dW(FND_F, OFF); dW(FND_G, ON);
        break;
      case 3:
        dW(FND_A, ON); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, ON); dW(FND_E, OFF); dW(FND_F, OFF); dW(FND_G, ON);
        break;
      case 4:
        dW(FND_A, OFF); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, OFF); dW(FND_E, OFF); dW(FND_F, ON); dW(FND_G, ON);
        break;
      case 5:
        dW(FND_A, ON); dW(FND_B, OFF); dW(FND_C, ON); dW(FND_D, ON); dW(FND_E, OFF); dW(FND_F, ON); dW(FND_G, ON);
        break;
      case 6:
        dW(FND_A, ON); dW(FND_B, OFF); dW(FND_C, ON); dW(FND_D, ON); dW(FND_E, ON); dW(FND_F, ON); dW(FND_G, ON);
        break;
      case 7:
        dW(FND_A, ON); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, OFF); dW(FND_E, OFF); dW(FND_F, ON); dW(FND_G, OFF);
        break;
      case 8:
        dW(FND_A, ON); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, ON); dW(FND_E, ON); dW(FND_F, ON); dW(FND_G, ON);
        break;
      case 9:
        dW(FND_A, ON); dW(FND_B, ON); dW(FND_C, ON); dW(FND_D, ON); dW(FND_E, OFF); dW(FND_F, ON); dW(FND_G, ON);
        break;
    }
    prevVal = val;
  }
}

boolean readUpSw()
{
  static boolean prev = HIGH;
  static unsigned long last;
  boolean curr;

  if ((millis()-last)>10) {
    curr = digitalRead(UP);
    if ((HIGH==prev)&&(LOW==curr)) {   // UP SW가 눌린 시점
      gCnt = (gCnt+1)%10;
    }
    prev = curr;
    last = millis();
  }
}

boolean readDnSw()
{
  static boolean prev = HIGH;
  static unsigned long last;
  boolean curr;

  if ((millis()-last)>10) {
    curr = digitalRead(DN);
    if ((HIGH==prev)&&(LOW==curr)) {  // DOWN SW가 눌린 시점

      gCnt = gCnt-1;
      if (-1 == gCnt) gCnt = 9;
    }
    prev = curr;
    last = millis();
  }
}