Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Контроллер вакуумно-люминесцентного дисплея (VFD) на Arduino — DIY набор

Компоненты и материалы

Arduino UNO (или любая 8-битная Arduino)×1
VFD-дисплей×1
CD4094 (DIP, сдвиговый регистр)×2
CD4017 (DIP, десятичный счётчик)×2
BC557 (PNP-транзистор, или 2N3906, 2SA733 и др.)×17
BC547 (NPN-транзистор, или 2N3904, 2SC945 и др.)×2
PC817 (оптопара)×1
1N4007 (высоковольтный диод)×4
Электролитические конденсаторы (значения по схеме)×4
Конденсатор 470 нФ×1
Монтажная плата (perfboard)×1
Резисторы 1/4 Вт (значения по схеме)×24
Перемычки Dupont×1
Провода (тонкие, для обратной стороны платы и подключения дисплея)×1

Инструменты

О проекте

Зачем это нужно?

VFD-дисплеи сегодня не в тренде, но они крутые: стеклянные колбы, накатанные нити накала, по сути — вакуумные лампы. Они дают яркий, иногда цветной свет, требующий тёмного фильтра. Обычно для управления нужен специализированный драйвер (I2C/SPI). Если у вас есть «голый» дисплей без драйвера, подключить его непросто — драйверы обычно в SMD. Эта схема даёт универсальный интерфейс для Arduino, способный управлять практически любым VFD, включая винтажные «ламповые» индикаторы. Матричные дисплеи с тысячами сегментов — не лучшая идея, хотя схему можно расширить.

Плюсы и минусы

Плюсы:

Минусы:

Принцип работы

VFD работает в мультиплексном режиме (матрица X×Y). Нагревается катод (нить накала), на сетку (X) и анод (Y) подаётся положительное напряжение — загорается один сегмент. Для отображения изображения сканируют сетки последовательно, устанавливая конфигурацию анодов для каждой. Достаточная скорость создаёт эффект одновременного свечения (POV — Persistence Of Vision).

Схема использует два CD4094 (управление анодами, хранят состояние выходов) и два CD4017 (последовательное переключение сеток). После загрузки конфигурации в CD4094 сигнал строба защёлкивает данные и тактирует CD4017 — автоматическая секвенция.

Ключевые транзисторы BC557 поднимают напряжение на анодах выше 5 В Arduino. Сетки управляются CD4017 напрямую. Оптопара PC817 позволяет запитать CD4017 от напряжения выше 5 В и гальванически разделить цепи — это сильно упрощает схему.

Arduino orchestreрует процесс: хранит конфигурацию сегментов и по прерыванию таймера (~1000 раз/сек) загружает CD4094. Для 10 сеток частота обновления ~100 Гц. Данные хранятся в массиве segments[] — можно менять в любом месте кода, прерывание само выведет изменения.

Источники питания

Советы и примечания

Код

Arduino-скетч с рабочим прерыванием

/* Versatile VFD Display Hardware Interface Arduino Program
   Copyright (C) 2019 Genny A. Carogna
   GNU GPL v3 */
   
// Используются Timer1 и SPI «под капотом» — они заняты.
// Дисплей сканируется непрерывно (100 Гц), нагрузка на CPU ~3%.
// Работает на любой 8-битной Arduino, 3.3 В — возможно, снизьте SCK.

#define ledLed 13
#define strobePin 4
#define strobeHold 10  // мкс, удержание строба для оптопары

// Пример конфигураций для разных дисплеев (оставьте нужную)
#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[grid] — биты сегментов (LSB = сегмент 0)
// Автоматически выбирает тип: uint8_t / uint16_t / uint32_t
#if anodeAmount > 16
volatile uint32_t segments[gridAmount] = {0};
#elif anodeAmount > 8
volatile uint16_t segments[gridAmount] = {0};
#else
volatile uint8_t segments[gridAmount] = {0};
#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);
  *portModeRegister(digitalPinToPort(ledLed))       |= digitalPinToBitMask(ledLed);
  *portOutputRegister(digitalPinToPort(ledLed))     &= ~digitalPinToBitMask(ledLed);
  
  delay(800); // ждём сброс CD4017 при включении питания
  
  cli(); // запрет прерываний для настройки
  
  // Timer1: прерывание grids×100 раз в сек = 100 Гц обновление
  TCCR1A = 0; TCCR1B = 0; TCNT1 = 0;
  OCR1A = 160000 / gridAmount;
  TCCR1B |= (1 << WGM12) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);
  
  // SPI: мастер, 1 МГц (SPR0). Для 0.5 МГц раскомментируйте SPSR строку.
  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
  // SPSR = (1 << SPI2X); // двойная скорость (если раскомментировать и убрать SPR0)
  
  sei(); // прерывания разрешены
  // Дополнительный setup() код — сюда
}

void loop() {
  show(); // демо-режим, можно удалить
}

// Прерывание Timer1 — каждая смена сетки
ISR(TIMER1_COMPA_vect) {
  static uint8_t turn = 1; // текущая сетка (1-based в оригинале)
  
  // Передача битов анодов (младшие байты первыми), инвертированных (из-за PNP)
  #if anodeAmount > 24
  SPDR = ~uint8_t(segments[turn] >> 24); while(!(SPSR & (1< 16
  SPDR = ~uint8_t(segments[turn] >> 16); while(!(SPSR & (1< 8
  SPDR = ~uint8_t(segments[turn] >> 8);  while(!(SPSR & (1<2) pos++;
  uint16_t mask = 0xFF80;
  uint8_t nums[] = {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] |= nums[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; break;
  }
}
void marantzPrintNum(uint8_t val, uint8_t pos) {
  if(pos>5) return; pos+=2;
  uint16_t mask = 0xFF80;
  uint8_t nums[] = {B00111111,B00000110,B01011011,B01001111,B01100110,B01101101,B01111101,B00100111,B01111111,B01101111,B00000000};
  segments[pos] &= mask; segments[pos] |= nums[val];
}

Схема

На схеме не нарисованы все 17 транзисторов BC557 — они одинаково подключены к выходам CD4094. Перемычка на CD4017 (красная линия) сбрасывает счётчики после последней сетки: соедините её с выводом после последней используемой сетки (для 10 сеток — 11-й вывод).

Подключения Arduino выделены красным. USB питание для Arduino, но для остальных источников настоятельно рекомендуется классический трансформатор (не импульсный, заземлённый). Все источники — DC, кроме возможно филамента. Диодный мост и 1000 мкФ на случай отдельного трансформатора филамента (обычно ~3 В, 150 мА, подойдёт 5 В AC). «Балласт» — мощностной потенциометр ~100 Ом или резистор/диоды для снижения напряжения.

BC557 подтягивают аноды к анодному напряжению, 100 кОм опускают при выключении. CD4017 запитаны от напряжения сеток, доп. транзисторы не нужны. «Гетто»-сброс CD4017 (~0.1 с) — ждите перед запуском кода. Каскад CD4017 без логических элементов: NPN-транзистор + оптопара эмулируют AND — достаточно быстро.

Обратите внимание на разные земли — изучите схему внимательно.

Производственный процесс

  1. Интерактивная кукла «Игра в кальмара» на Arduino UNO: DIY-проект
  2. Профессиональное руководство по анимации битмапов на TFT-экране ILI9341 2.4" с Visuino
  3. Веб-управляемая DMX-система освещения: Arduino Mega как мастер-контроллер
  4. Создание классической игры Pong на Arduino UNO с OLED-дисплеем: пошаговый урок
  5. DIY USB-геймпад на Arduino: собственный высокопроизводительный контроллер
  6. Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
  7. Монитор температуры и реальные часы на Arduino Due с TFT-дисплеем 3.2"
  8. Интерактивный HMI-проект на Nextion с Arduino Mega и датчиками
  9. Сборка вольтметра на Arduino с дисплеем Nokia 5110 — Пошаговое руководство
  10. Вывод данных BME280 (температура, влажность, давление) на сенсорный экран Nextion