산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트

부품 및 소모품

부품 수량 비고
아두이노 우노 (Arduino UNO) 1 또는 8비트 아두이노 보드
VFD 디스플레이 1 메인 디스플레이
CD4094 2 DIP 타입 집적회로
CD4017 2 DIP 타입 집적회로
BC557 17 또는 동등 트랜지스터 (2N3906, 2SA733 등) 또는 고전압 PNP 타입
BC547 2 또는 동등 트랜지스터 (2N3904, 2SC945 등)
PC817 1 대부분의 스위칭 파워서플라이에 사용되는 옵토커플러
1N4007 – 고전압, 고전류 정격 다이오드 4
전해 커패시터 4 회로도 참조 (값 및 전압)
470nF 커패시터 1 타입 무관
퍼프보드 (만능 기판) 1 페이퍼 보드, 프로토보드 등 선호하는 조립 방식
1/4W 저항 24 회로도 참조 (값)
듀퐁 점퍼 와이어 1 또는 선호하는 커넥터 및 포스트
와이어 1 회로 후면 배선용 및 디스플레이 연결용 얇은 와이어, 커넥터 사용 비권장 (핀 간격 가변적, 직접 납땜이 편리)

필요 도구 및 장비

프로젝트 소개

용도는?

VFD 디스플레이는 몇 가지 분명한 이유로 더 이상 트렌드가 아닙니다. 유리로 만들어졌고("우와, 멋지다!"), 백열 필라멘트를 가지고 있으며("진짜?"), 기본적으로 진공관입니다("흥미롭다!"). 매우 밝은 빛을 내며, 때로는 컬러로 빛나 어두운 플라스틱 커버가 필요합니다("우와, 다시 멋지다!").

보통 VFD를 구동하려면 전용 칩이 필요합니다. 대부분의 모듈/기기에는 이 칩이 탑재되어 있어 I2C나 SPI로 독립적으로 제어할 수 있습니다(훨씬 편리). 하지만 디스플레이만 있고 구동 칩이 없는 경우 "연결 후 바로 사용"하기는 쉽지 않습니다. 이상적으로는 해당 칩을 구매하는 것인데(주로 SMD 타입), 이 회로는 아두이노용으로 꽤 괜찮은 인터페이스를 제공하며 대다수 VFD를 구동할 수 있습니다. 빈티지 "튜브" 타입 대형 VFD도 가능하지만, 세그먼트가 많은 매트릭스 디스플레이는 확장이 필요하여 추천하지 않습니다(수천 개 세그먼트... 글쎄요).

장단점

장점

단점

동작 원리

VFD는 일반적으로 멀티플렉스 방식으로 동작합니다. 2D 매트릭스처럼 X, Y 축이 있고, 필라멘트(캐소드, 앞에 보이는 얇은 와이어)를 가열하고 그 필라멘트에 그라운드를 연결합니다. 그리드(제어 그리드, X축의 한 점)에 양전압을, 세그먼트 핀(애노드, Y축의 한 점)에도 양전압을 가하면 하나의 세그먼트가 점등합니다. 원하는 세그먼트와 조합을 점등시키고 배선을 최소화하기 위해, 멀티플렉싱은 한 번에 하나의 그리드를 선택하고 동시에 해당 그리드 아래의 세그먼트들이 점등되도록 애노드를 구성합니다. 잠시 후 다음 그리드를 선택하고 애노드를 다시 구성합니다. 이 연속 스캔을 충분히 빠르게 반복하면 잔상 효과(POV, Persistence Of Vision)로 모든 그리드가 동시에 구동되는 것처럼 보입니다.

이 회로는 같은 계열의 두 가지 IC를 사용합니다. 두 개의 CD4094가 애노드를, 두 개의 CD4017이 그리드를 구동합니다. CD4094는 출력에 하이/로우 구성을 저장할 수 있어 애노드 측에 적합하고, CD4017은 10개의 시퀀싱 출력을 가진 고전적인 칩으로 그리드에 적합합니다. CD4094가 순간 애노드 구성으로 로드되면 "OK" 신호(스트로브)가 이 설정을 적용하고 동시에 CD4017을 한 스텝 진행시켜 자동 시퀀싱을 가능하게 합니다.

전원부는 기본적으로 BC557 트랜지스터(또는 동등품)만으로 구성되어 애노드 측에서 아두이노의 5V보다 넓은 전압 스윙을 허용합니다. VFD는 5V보다 높은 전압을 필요로 하기 때문입니다. 그리드는 CD4017이 직접 구동하며, PC817 옵토커플러를 통해 5V 이상의 전압을 CD4017 주변에 사용하고 CD4094와 다른 전압 레벨을 사용할 수 있어 회로가 크게 단순화됩니다.

아두이노가 모든 오케스트레이션을 담당합니다. 모든 세그먼트 구성을 저장하고 그리드 전환마다 회로에 애노드 설정을 다시 로드해야 합니다. 이는 사용자 액션 외에도 꽤 영리한 코드가 필요함을 의미합니다. 작성한 코드는 타이머 기반 인터럽트를 설정하여 4094 칩을 매 스텝마다 리로드합니다. 초당 약 1000회, 10개 그리드 기준 100Hz 리프레시 레이트를 제공하며 이는 충분합니다. 세그먼트 구성을 저장하는 데이터 배열이 있으며, 특별한 절차나 후속 조치 없이 코드에서 수정할 수 있고 인터럽트 루틴이 알아서 데이터를 업로드합니다.

전원 공급

그리드 전압 (CD4017 칩): 5Vdc~18Vdc, 최소 50mA, 정전압 불필요. 보통 12V면 충분하며, 높여도 밝기 향상은 크지 않습니다(진공관인 경우 그리드에 큰 전압 불필요).

애노드 전압: 0V부터 트랜지스터 내압(BC557 기준 50Vdc)까지. 보통 디스플레이가 양호하면 20~30Vdc로 충분하며 비정전압도 괜찮습니다. 정상 설정 시 50mA 이상이면 넉넉합니다.

디지털 전원: 5Vdc 또는 3.3Vdc(해당 아두이노/MCU용), 약 100mA 소모. CD4094가 느려지면 코드에서 SPI 클럭을 낮추거나 첫 번째 4094의 "Q'S" 출력을 사용해 통신 안정성을 높일 수 있습니다.

필라멘트 전원: 최소 5V 200~300mA. 이미 DC 소스가 있다면 브리지 정류기와 1000uF 커패시터 생략 가능하지만, 아두이노용 디지털 전원과 절대 공유 불가입니다. 일반적인 소형 기기 디스플레이의 필라멘트는 약 3V, 150mA로 동작합니다.

아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트
아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트
아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트
아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트
아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트

팁 및 주의사항

코드

작동 루틴 포함 아두이노 코드 (아두이노)

/* Versatile VFD Display Hardware Interface Arduino Program Copyright (C) 2019 Genny A. Carogna
이 프로그램은 자유 소프트웨어입니다: GNU General Public License v3 또는 이후 버전의 조건에 따라 재배포 및 수정 가능.
이 프로그램은 유용하게 사용되기를 바라지만, 어떠한 보증도 없이 제공됩니다. 상업성 또는 특정 목적 적합성에 대한 묵시적 보증도 포함되지 않음.
GNU General Public License 사본을 함께 받았어야 합니다. 받지 못한 경우  참조. */

/* 이 코드는 아두이노 리소스를 "막후에서" 사용합니다. 타이머1과 SPI 모듈 모두 사용 중이므로,
 * SPI, SPI 핀, 타이머1 기반 기능 사용 시 큰 문제가 발생할 수 있습니다.
 * 제안 회로에는 온보드 메모리가 없어 세그먼트 설정을 아두이노 세그먼트 배열에서 매 그리드마다 초당 100회 연속 "스캔"해야 함.
 * 이는 소위 "오버헤드" CPU 작업으로, 일반 마이크로컨트롤러 사용 수준이며 약 3% CPU 점유율 예상.
 * 일반 아두이노 SPI 도구 사용 가능하지만 심층 분석 필요.
 * 이 코드는 모든 8비트 아두이노에서 작동, 3.3V도 괜찮을 수 있음(SCK 주파수 낮추기 권장, CD4094가 같은 전원으로 구동되어 "언더볼트" 가능). */

#define ledLed 13 // LED 핀
#define strobePin 4 // "스트로브" 라인 전용 아두이노 핀
#define strobeHold 10 // 마이크로초 - 옵토커플러 스위칭 홀딩 시간

// 내 디스플레이용 데이터(비디오 카세트 레코더, 오디오파일 CD 플레이어, 컴팩트 스테레오)... 무시하고 삭제 후 "gridAmount", "anodeAmount"만 정의
#define JVC
#define mitsubishiGrids 10
#define mitsubishiAnodes 9
#define marantzGrids 9
#define marantzAnodes 14
#define JVCGrids 11
#define JVCAnodes 19

#if defined mitsubishi
#define gridAmount mitsubishiGrids
#define anodeAmount mitsubishiAnodes
#elif defined marantz
#define gridAmount marantzGrids
#define anodeAmount marantzAnodes
#elif defined JVC
#define gridAmount JVCGrids
#define anodeAmount JVCAnodes
#endif

// segments[x] 배열: 세그먼트 비트 저장
// segments[0] = 그리드 0, 최하위 비트 = 해당 그리드의 세그먼트 0
// 이 배열은 어디서든 접근/수정 가능, 효과 즉시 디스플레이 반영, 비트 변경 전까지 유지
// 그리드당 8개 초과 세그먼드 디스플레이는 16/32비트 컨테이너 필요, #define으로 자동 관리
#if anodeAmount > 16
volatile uint32_t segments[gridAmount] = {0}; // 그리드당 16개 초과 (32비트 필요)
#elif anodeAmount > 8
volatile uint16_t segments[gridAmount] = {0}; // 그리드당 8개 초과 (16비트, 이중 전송)
#else
volatile uint8_t segments[gridAmount] = {0};  // 그리드당 8개 이하 (8비트)
#endif

void setup(){
  // SPI 핀 및 일부 기능 핀을 빠르고 직접적으로 출력으로 설정
  *portModeRegister(digitalPinToPort(PIN_SPI_SS)) |= digitalPinToBitMask(PIN_SPI_SS);
  *portModeRegister(digitalPinToPort(PIN_SPI_MOSI)) |= digitalPinToBitMask(PIN_SPI_MOSI);
  *portModeRegister(digitalPinToPort(PIN_SPI_SCK)) |= digitalPinToBitMask(PIN_SPI_SCK);
  *portModeRegister(digitalPinToPort(strobePin)) |= digitalPinToBitMask(strobePin);
  *portOutputRegister(digitalPinToPort(strobePin)) &= ~digitalPinToBitMask(strobePin); // LOW
  *portModeRegister(digitalPinToPort(ledLed)) |= digitalPinToBitMask(ledLed);
  *portOutputRegister(digitalPinToPort(ledLed)) &= ~digitalPinToBitMask(ledLed); // LOW
  delay(800); // CD4017 리셋 완료 대기 (4017 전원 투자 후 코드 실행 필요, 일괄 전원 투자 시 자동화)

  cli(); // 인터럽트 비활성화하여 설정 중 간섭 방지

  // 타이머1 설정: "그리드 수 × 100" 회/초 인터럽트 발생 → 100Hz 전체 리프레시
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 160000 / gridAmount;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);

  // SPI 설정: 아두이노 SPI 도구 사용 불가 (인터럽트 의존적, 인터럽트 내부에서 통신 필요)
  // SPR0을 SPR1로 변경하고 마지막 줄 주석 해제하면 SPI 클럭 절반 속도
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); // 1MHz 기본 SCK 속도
  // SPSR = (1 << SPI2X); // 주석 해제하고 위 수정으로 절반 클럭 속도

  sei(); // 인터럽트 재활성화
  // 추가 setup() 코드는 여기부터 작성 권장
}

// loop(): 원하는 작업 수행 가능, 딜레이, 폴링 등.
// 하지만 인터럽트 비활성화나 마이크로컨트롤러 완전 정지는 디스플레이를 한 그리드에 고정시킴.
// 전압이 최대일 경우 세그먼트 소손 위험!!
void loop() {
  show(); // 일종의 스크린세이버, 삭제 가능
}

// 인터럽트 서비스 루틴: 그리드 스캔 전환마다 발생, 초당 100회
ISR(TIMER1_COMPA_vect){
  /* 주의: "turn"을 1부터 시작해야 정상 동작하는 이유 불명(아두이노 후 전원 투자 시 그리드 플립 가능).
   * 시작 시 계속 올바른 그리드를 놓치면 이 값 조정 필요. 주의! */
  static uint8_t turn = 1; // 다음 인터럽트에서 어느 그리드인지 기억하는 불변 변수

  #if anodeAmount > 24
  SPDR = ~uint8_t(segments[turn] >> 24); // CD4094에 반전 비트 필요 (트랜지스터 구성 때문)
  while (!(SPSR & (1 << SPIF))) ; // 전송 완료 대기
  #endif

  #if anodeAmount > 16
  SPDR = ~uint8_t(segments[turn] >> 16);
  while (!(SPSR & (1 << SPIF))) ;
  #endif

  #if anodeAmount > 8
  SPDR = ~uint8_t(segments[turn] >> 8);
  while (!(SPSR & (1 << SPIF))) ;
  #endif

  SPDR = ~uint8_t(segments[turn]);
  while (!(SPSR & (1 << SPIF))) ; // 전송 완료 대기... yyyYYYAAAAWWWWNNNnnn...........

  // 스트로빙(드디어!!) 이 또한 CD4017의 그리드 전환
  *portOutputRegister(digitalPinToPort(strobePin)) |= digitalPinToBitMask(strobePin); // 빠른 핀 드라이브 ON
  delayMicroseconds(strobeHold);
  *portOutputRegister(digitalPinToPort(strobePin)) &= ~digitalPinToBitMask(strobePin); // 빠른 핀 드라이브 OFF

  // 그리드 순번 갱신
  turn++;
  if (turn == gridAmount) turn = 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////여기부터는 내 디스플레이 및 비주얼 게임 관련 스케치, 여기부터 삭제 가능/////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// 데모용, 원하는 만큼 삭제
void show() {
  // 숫자 플립
  #ifdef mitsubishi
  for (uint8_t i = 0; i < 9; i ++)
    for (uint8_t j = 0; j < 11; j ++) {
      delay(200);
      mitsubishiPrintNum(j, i);
    }
  for (uint8_t i = 0; i < 9; i ++)
    for (uint8_t j = 0; j < 11; j ++) {
      delay(20);
      mitsubishiPrintNum(j, i);
    }
  #elif defined marantz
  for (uint8_t i = 0; i < 6; i ++)
    for (uint8_t j = 0; j < 11; j ++) {
      delay(200);
      marantzPrintNum(j, i);
    }
  for (uint8_t i = 0; i < 6; i ++)
    for (uint8_t j = 0; j < 11; j ++) {
      delay(20);
      marantzPrintNum(j, i);
    }
  #elif defined JVC
  /* for (uint8_t i = 0; i < 9; i ++)
    for (uint8_t j = 0; j < 11; j ++) {
      delay(200);
      JVCPrintNum(j, i);
    }
  for (uint8_t i = 0; i < 9; i ++)
    for (uint8_t j = 0; j < 11; j ++) {
      delay(20);
      JVCPrintNum(j, i);
    }*/
  #endif
  delay(500);

  // 세그먼트 플립
  for (uint8_t i = 0; i < gridAmount; i ++)
    for (uint8_t j = 0; j < anodeAmount + 1; j ++) {
      delay(100);
      segments[i] = (uint32_t(1) << j);
    }
  delay(500);

  // 전체 디스플레이 깜빡임
  for (uint8_t i = 0; i < 5; i ++) {
    delay(200);
    for (uint8_t j = 0; j < gridAmount; j ++) {
      segments[j] = 0xFFFFFFFF;
    }
    delay(200);
    for (uint8_t j = 0; j < gridAmount; j ++) {
      segments[j] = 0;
    }
  }
  delay(500);
}

// 간편 7세그먼트 숫자 표시 (미쓰비시)
void mitsubishiPrintNum(uint8_t val, uint8_t pos) {
  if (pos > 2) pos ++;
  uint16_t mask = 0xFF80;
  uint8_t numbers[] = {B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00100111, B01111111, B01101111, B00000000};
  switch (pos) {
    case 0: case 1: case 4: case 5: case 6: case 7: case 8:
      segments[pos] &= mask;
      segments[pos] |= numbers[val];
      break;
    case 2:
      if (val == 1) segments[1] |= (1 << 8);
      else segments[1] &= ~(uint16_t(1) << 8);
      break;
    case 9:
      segments[9] &= 0xFFF0;
      if (val == 1) segments[9] |= 3;
      else if (val == 2) segments[9] |= B1101;
  }
}

// 간편 7세그먼트 숫자 표시 (마란츠)
void marantzPrintNum(uint8_t val, uint8_t pos) {
  if (pos > 5) return;
  pos ++;
  pos ++;
  uint16_t mask = 0xFF80;
  uint8_t numbers[] = {B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00100111, B01111111, B01101111, B00000000};
  segments[pos] &= mask;
  segments[pos] |= numbers[val];
}

// 간편 7세그먼트 숫자 표시 (JVC)
void JVCPrintNum(uint8_t val, uint8_t pos) {
  // 추후 구현 (관심 없으실 듯)
}

회로도

모든 BC557 트랜지스터를 그리지는 않았습니다. CD4094 모든 출력에 동일하게 연결되기 때문입니다.

점퍼 셀렉터(빨간 선 상단)가 4017 칩에 있습니다. 그리드 스캔 완료 시 두 4017을 리셋하도록 설정해야 합니다. 플라잉 점퍼를 마지막 그리드 다음 출력 핀에 연결(또는 납땜)하세요. 디스플레이가 10개 그리드면 11번째 출력에 점퍼 연결.

아두이노 연결은 빨간색으로 표시. USB 전원 사용 가능하지만, 나머지 전원에는 기존 구형 트랜스포머 사용 강력 권장(이미 PC 같은 접지된 전원 사용 중인 경우). 이 전원들은 모두 DC여야 하며 필라멘트 전원만 예외적으로 AC 가능. 필라멘트용 별도 트랜스포머 저전압 2차 코일 필요 시 다이오드 추가. 필라멘트 전원은 보통 3V 150mA 수준, 5V AC 트랜스포머면 충분. "밸러스트"는 100옴 권선 포텐셔미터나 고정 저항, 또는 1N4007 다이오드 여러 개로 전압 강하.

BC557 트랜지스터가 애노드를 애노드 전압까지 풀업하고 100k옴 저항이 세그먼트 오프 시 전압 강하 유도, CD4094는 평소 5V 유지.

CD4017은 그리드 전원으로 구동되며 추가 트랜지스터 불필요. 4017용 "게토" 리셋 회로는 약 0.1초 지속, 코드 실행 전 안정화 대기 필요.
CD4017 캐스케이드 "정석" 회로는 추가 로직 게이트 칩 필요. 대신 NPN 트랜지스터와 옵토커플러로 AND 게이트 재현. 클로징은 충분히 빠르고, 릴리즈는 느리지만 상관없음(4017 클럭 입력이 슈미트 트리거, 요구 속도 "무서운" 수준 아님).

칩 및 부품별 다양한 그라운드 존재. 잘 살펴보세요.

아두이노 기반 진공 형광 디스플레이(VFD) 컨트롤러 키트

제조공정

  1. 아두이노 우노로 만드는 오징어 게임 테마 인터랙티브 인형 – DIY 프로젝트
  2. ILI9341 2.4인치 TFT 터치스크린 실드에서 비트맵 애니메이션 구현하기 (Visuino 활용)
  3. 웹 제어 DMX 조명 시스템 - 아두이노 마스터 컨트롤러
  4. 아두이노 우노와 OLED 디스플레이로 클래식 퐁(Pong) 게임 만들기: 단계별 튜토리얼
  5. DIY 아두이노 USB 게임 컨트롤러 - 나만의 고성능 게임패드 만들기
  6. Unopad: 아두이노 우노로 만드는 에이블턴 라이브용 MIDI 컨트롤러
  7. 아두이노 듀(Due) + 3.2″ TFT로 만드는 실시간 시계 & 온도 모니터
  8. 아두이노 메가와 센서를 활용한 인터랙티브 넥시온 HMI 프로젝트
  9. 아두이노와 노키아 5110 LCD로 만드는 DIY 전압계 - 단계별 가이드
  10. BME280 온도·습도·기압을 넥시온 터치스크린에 표시하기