Мультиплексирование трех ламп VFD — почему сегменты и синхронизация отображения неверны?
Я использую Arduino Nano, микросхему UNL2803 и три транзистора 2N3904 для управления тремя семисегментными вакуумными люминесцентными лампами (IV-6) в мультиплексной конфигурации. UNL2803 используется для управления сегментами: когда на вывод Arduino подается низкий уровень, 25 В отправляется в соответствующий сегмент. Транзисторы 2N3904 используются для управления каждой из цифр: когда на выводе Arduino высокий уровень, на сетку цифры подается 25 В, тем самым активируя цифру.
Проблема: трубки показывают неправильные сегменты, а дисплеи не активируются с правильным временем. Я проверил соединение каждого сегмента, чтобы убедиться, что оно подключено к правильному сегменту. Замедляя временной интервал между цифрами, я вижу, что вторая и третья цифры (десятки и единицы) отображаются последовательно с правильным интервалом, но первая цифра (сотни) появляется со второй цифрой и остается на в два раза больше интервала времени. Также кажется, что некоторые цифры пытаются отобразить более одного числа (последовательно) при активации.
Код:
// Назначение контактов для сегментов
const int SEG_A = 2;
const int SEG_B = 3;
const int SEG_C = 4;
const int SEG_D = 6;
const int SEG_E = 5;
const int SEG_F = 7;
const int SEG_G = 8;
// Назначение контактов для цифр
const int DIG1 = 9;
const int DIG2 = 10;
const int DIG3 = 11;
int digit = 1;
int dig_number = 0;
unsigned int number = 321;
void setup() {
Serial.begin(9600);
// Установить выводы сегмента в качестве выходов
pinMode(SEG_A, OUTPUT);
pinMode(SEG_B, OUTPUT);
pinMode(SEG_C, OUTPUT);
pinMode(SEG_D, OUTPUT);
pinMode(SEG_E, OUTPUT);
pinMode(SEG_F, OUTPUT);
pinMode(SEG_G, OUTPUT);
// Установить цифровые контакты в качестве выходов
pinMode(DIG1, OUTPUT);
pinMode(DIG2, OUTPUT);
pinMode(DIG3, OUTPUT);
// Отключаем цифры
digitalWrite(DIG1, LOW);
digitalWrite(DIG2, LOW);
digitalWrite(DIG3, LOW);
}
void loop() {
if (digit == 1) {
digitalWrite(DIG1, HIGH);
digitalWrite(DIG2, LOW);
digitalWrite(DIG3, LOW);
dig_number = number / 100;
if (number < 100) { // отключить цифру, если она не используется
dig_number == 99; // запускает 'по умолчанию' в switch/case
display_number(dig_number);
} else {
display_number(dig_number);
}
digit = 2;
Serial.println("The first digit is: ");
Serial.print(dig_number);
delay (250);
}
if (digit == 2) {
digitalWrite(DIG1, LOW);
digitalWrite(DIG2, HIGH);
digitalWrite(DIG3, LOW);
dig_number = (number / 10) % 10;
if (dig_number == 0 && number < 10) { // чтобы отключить цифру, если она не используется
dig_number == 99; // запускает 'по умолчанию' в switch/case
display_number(dig_number);
} else {
display_number(dig_number);
}
digit = 3;
Serial.println("The second digit is: ");
Serial.print(dig_number);
delay (250);
}
if (digit == 3) {
digitalWrite(DIG1, LOW);
digitalWrite(DIG2, LOW);
digitalWrite(DIG3, HIGH);
dig_number = number % 10;
display_number(dig_number);
digit = 1;
Serial.println("The third digit is: ");
Serial.print(dig_number);
delay (250);
}
}
void display_number(int dig_number) {
switch (dig_number) {
case 0:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, HIGH);
break;
case 1:
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, HIGH);
break;
case 2:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, LOW);
break;
case 3:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, LOW);
break;
case 4:
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 5:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 6:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 7:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, HIGH);
break;
case 8:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, LOW);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
case 9:
digitalWrite(SEG_A, LOW);
digitalWrite(SEG_B, LOW);
digitalWrite(SEG_C, LOW);
digitalWrite(SEG_D, LOW);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, LOW);
digitalWrite(SEG_G, LOW);
break;
default:
digitalWrite(SEG_A, HIGH);
digitalWrite(SEG_B, HIGH);
digitalWrite(SEG_C, HIGH);
digitalWrite(SEG_D, HIGH);
digitalWrite(SEG_E, HIGH);
digitalWrite(SEG_F, HIGH);
digitalWrite(SEG_G, HIGH);
break;
}
}
Схема:
До меня доходили слухи, что использование delay() вместо millis() для мультиплексирования может быть проблематичным. Это то, что здесь происходит?
Заранее благодарим за рассмотрение этой проблемы!
@Thomas Burns, 👍1
Обсуждение3 ответа
Лучший ответ:
Похоже, ваш код инвертирует шаблон переключения цифр. Вместо того, чтобы включать выбранную цифру и выключать две другие, вы делаете обратное.
К сетке трубки VFD должно быть приложено напряжение для освещения выбранных сегментов. Эти сегменты также выбираются при подаче напряжения. Схема, которую вы показали, по умолчанию питает как сети, так и сегменты через резисторы 10k, подключенные к шине питания 25 вольт. Транзисторы, также в uln2803, при включении притягивают сетки и сегменты к земле, тем самым отключая эти элементы. Такая компоновка снижает сложность схемы, устраняя необходимость в переключении на стороне высокого напряжения, но при этом возникают "потери". мощность.
Проблему должно решить простое исправление кода:
// Отключаем цифры
digitalWrite(DIG1, HIGH); // high выключает сетку.
digitalWrite(DIG2, HIGH);
digitalWrite(DIG3, HIGH);
}
if (digit == 1) {
digitalWrite(DIG1, LOW); // цифра один ON
digitalWrite(DIG2, HIGH); // цифра два ВЫКЛ.
digitalWrite(DIG3, HIGH); // цифра три выключена
}
Проделайте то же самое для цифр 2 и 3.
Используйте резисторы (скажем, 1k) последовательно с базами транзисторов, чтобы ограничить ток и защитить контакты Arduino. См. https://learn.sparkfun.com/tutorials/transistors/applications-i-switches.
Вам все еще необходимо убедиться, что провод, соединяющий R9, R10 и R11, полностью подходит к шине +25 В. Из схемы это не ясно.
Большое спасибо за это объяснение! В конце концов я заменил транзисторы 2N3904 на ULN2803, и это решило проблему. Теперь все работает как надо, за исключением одной небольшой особенности: я настроил простой счетчик для циклического перебора чисел и вижу очень слабое свечение на сегментах, на которые не подается питание во время подсчета. Эффект "призрака", так сказать, на всех цифрах. На не выбранные контакты каким-то образом попадает очень низкое напряжение. Любая идея, откуда это может исходить?, @Thomas Burns
@ThomasBurns Если вы получаете ореолы, то перед включением одной цифры сначала выключите две другие, затем настройте сегменты (вызвав display_number() ) и подождите, скажем, 1 мс. Затем включите выбранную цифру. Кроме того, ускорьте мультиплексирование. Вероятно, отображайте каждую цифру в течение примерно 5 мс, чтобы избежать заметного мерцания, но без слишком больших потерь при переключении. Это означает небольшую реструктуризацию вашего кода., @6v6gt
Да, это сработало (пришлось повозиться с этим несколько минут). Большое спасибо за отзыв!, @Thomas Burns
Год или около того назад я сделал часы с частотно-регулируемым приводом, используя классные старые лампы DG10B из раннего калькулятора. У меня было чертовски много времени, чтобы заставить его работать, пока я не решил попробовать решать одну проблему за раз, а затем собрать все вместе.
В своих часах я использовал микросхему драйвера VFD MAX6921, RTC DS3231 с суперконденсатором и XIAO для мозгов. Чип драйвера ЧРП управляется ШИМ/последовательным портом (данные, нагрузка, часы), а RTC работает через I2c.
Вместо того, чтобы пытаться мультиплексировать их, я просто заставил их работать одновременно, я сделал хороший медленный подсчет всех включенных цифр и отображал одни и те же цифры. Это помогло мне обнаружить пару неисправностей проводки и выяснить, какие сегменты должны светиться для каждого числа, которое я хотел отобразить. (цифры на моих трубках совершенно уникальны!)
как только у меня появились "шрифты" разобравшись с регистром для каждой цифры, я создал простой цикл, который считал от 0 до 9 на всех цифрах со всеми четырьмя включенными. 4444, 5555 и т. д.
Затем я начал пытаться загорать только одну цифру за раз. (это помогло мне найти другую проблему с проводкой) // [pihgfedcba------1234}; //так выглядит поток данных при отправке драйверу // ...где первые 10 цифр — это сегменты, а последние 4 — сетки для каждой цифры слева направо 1-4. // Остальные в настоящее время не используются и должны быть дополнены нулями или единицами)
Затем я сделал цикл, который будет проверять время и распечатывать цифры. Я ДЕЙСТВИТЕЛЬНО использую delay() в своем коде, чтобы преднамеренно мерцать мои трубки (для эффекта античного стимпанка) Но вот в чем дело, я считаю, что мой код проверяет время для каждой отдельной цифры. цикл говорит для каждой цифры 1-4 (время проверки, отображаемая цифра)
было гораздо больше вовлечено, и я уже давно не работал над этим, поэтому я не уверен, что могу быть здесь полезен. Я просто хотел предложить вам следовать хорошему процессу устранения неполадок. (мелкие проблемы легче решить)
Это было чрезвычайно полезно. Ваш подход привел меня к выводу, что я использовал неправильную распиновку для микросхемы UNL2803. Исправление этого решило проблемы с моим сегментом. Все еще работаю над выяснением того, что происходит с цифрами. Спасибо! Также хотел быстро сказать, что ваша техника макета вдохновляет — моя выглядит значительно менее организованной., @Thomas Burns
Ха-ха, да, мой пансион для хлеба немного одержим. -и я рад, что смог помочь. Дисплеи VFD настолько увлекательны. Надеюсь, ваш проект окажется таким, каким вы хотите его себе представить. :), @Jon Dresser
Я хотел бы получить в свои руки некоторые из этих трубок VFD с их грубыми рукописными шрифтами. Но я знаю, что такие странные дисплеи с мячами трудно достать, и, вероятно, они выходят за рамки любого разумного бюджета на хобби., @6v6gt
Для будущих искателей, я, наконец, получил эту схему с использованием двух массивов транзисторов ULN2803 вместо дискретных транзисторов для цифровых соединений. Вот окончательная схема:
Вы можете узнать больше об окончательном проекте здесь. Большое спасибо тем, кто прокомментировал — ваш отзыв был очень полезен!
ваша окончательная схема все еще содержит ошибки. Вы исправили отсутствующий GND в драйверах ULN2803. Но входы COM (контакт 10) и три резистора для сети должны быть подключены к +24В!, @Landroval
@Landroval Спасибо, что указали на это! Я заменил схему на исправленную версию., @Thomas Burns
- Использование библиотеки емкостных датчиков с мультиплексором 74HC4067
- Использование CD74HC4067 16-канальный аналоговый мультиплексор Демультиплексор работает не так, как ожидалось
- Могу ли я подключить аналоговый мультиплексор к Arduino Nano?
- Изменить значение только одного регистра на 8-разрядной регистровой интегральной схеме (74hc273 / DM74LS273)?
- Выход TPIC6B595 не может обеспечить подачу питания на 7-сегментный дисплей
- avrdude ser_open() can't set com-state
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Какое максимальное энергопотребление Arduino Nano 3.0?
То, как вы подключили его, когда вы включаете цифру, вам нужно отправить НИЗКИЙ уровень на соответствующий контакт и ВЫСОКИЙ уровень на два других контакта с двумя цифрами. У вас это перевернуто. Я предполагаю, что провод, соединяющий R9, R10 и R11, идет до 25 вольт. Базовые резисторы на транзисторах не помешали бы., @6v6gt
Спасибо. Мое понимание использования транзистора 2N3904 в качестве переключателя заключается в том, что на базе необходим высокий контакт, чтобы «открыть» переключатель и позволить току течь от коллектора к эмиттеру. Пожалуйста, помогите мне понять необходимость низкого штифта на базе, чтобы это работало. Я новичок в транзисторах. :), @Thomas Burns
Это правильно, но в вашем случае включение транзисторов притягивает сетки к земле, тем самым отключая дисплеи. Я добавил более полное объяснение ниже в качестве ответа., @6v6gt
Для будущих искателей вы можете проверить окончательный проект [здесь](https://www.hackster.io/tmburns/driving-vfd-tubes-with-an-arduino-nano-14f71e). Большое спасибо тем, кто прокомментировал — ваши отзывы были чрезвычайно полезны., @Thomas Burns