В магнитофонах и приёмниках моей юности использовались исчезнувшие ныне ламповые индикаторы уровня на лампах 6E1П или 6Е5С. Сейчас пришла пора ностальгирования по "старым временам" и на алиэкспрессе или амазоне можно купить собранные индикаторы, они почти также популярны как часы на лампах "Никси".

Поскольку лампа требует высокого напряжения для работы, в современных устройствах это решается с помощью преобразователя напряжения на таймере 555 упроавлящим мощным полевым транзистором включенным в первичную обмотку повышающего трансформатора, и дальше вторичная обмотка подключается к умножителю напряжения из 4-5 ступеней. Этого достаточно чтобы преобразовать входные 5 вольт в 250 с током 1-2 ma.

Я хочу поделиться своим домашним проектом, суть которого в эмуляции, насколько возможно, "зелёного глаза" лампы 6E1П с помощью быстрого OLED дисплея, контролируемого платой Arduino:

Самым сложным оказалось подобрать подходящий дисплей. На рынке их огромное количество, и большинство из них легко управляется известной библиотекой Adafruit-GFX-Library . Это прекрасная универсальная библиотека, очень простая в использовании, однако при использовании обычных плат Arduino она слишком медленная и не позволяет выводить качественную анимацию. После большого количества неудач методом проб и ошибок был найден дисплей на чипе SH1106, размером 128х64 точек и с голубым свечением. Для него предлагается библиотека ардуино U8G2. Особенностью этой библиотеки является наличие страничного вывода, т.е. сначала изображение создаётся в памяти контроллера, и затем единственной командой выводится на дисплей. Это позволяет создавать простые анимации с хорошей частотой обновления. Библиотека также содержит команды для построения геометрических примитивов - прямоугольников, треугольников и окружностей. Также возможен вывод простых битмапов, однако он слишком медленный чтобы использовать для анимации. Однако битмапы могут работать как маски для вырезания части изображения, и я использовал такой битмап для придания характерной формы экрана "зеленого глаза" - вертикального прямоугольника с округлой верхней стороной.

Общий принцип построения геометрии из примитивов:

Размеры примитивов меняются динамически в зависимости от напряжения на входе A0 платы Arduino.

Как я уже говорил, эмуляция вполне приблизительная. Хотя геометрию изображения я считаю довольно близкой к оригиналу, монохромность дисплея не позволила создать правильный фон, так что у меня изображение на полностью чёрном фоне, тогда как в оригинальной лампе фон всегда бледно-зелёный.

Была еще одна техническая запинка, которую мне удалось преодолеть. Дисплей этот имеет синее свечение, а мне нужно ярко-зелёное. Проблема решилась с помощью высокотемпературного скотча дюймовой ширины, это интенсивно-жёлтая полиимидная липкая лента, материал также называют "каптон". По ширине она идеально соответствует дисплею и будучи аккуратно наклееной, прекрасно превращает голубое свечение экрана в зелёное, очень близкое по цвету к "ламповому".

Для эффектности я добавил к входу Arduino сигнал с простенькой платы микрофона с усилителем от Adafruit .

Дисплей и несколько дополнительных компонент для микрофона я разместил на вырезаной под размер Arduino простенькой монтажной плате, весь монтаж выполнен проводами:

Диаграмма соединения деталей:

Сидя в карантине, я планирую сделать аналогичный вывод для старинного индикатора 6E5С (это западная лампа E81):

Для любопытствующих приведу мой код для Ардуино. Я отнюдь не считаю себя продвинутым программистом микроконтроллеров и никоим образом не претендую на совершенство стиля и кода, меня вполне устраивает что он просто работает.

Для плавности изображения я использую усреднение по 5 замерам. Усреднение написано "руками", пытался использовать стандартную библиотеку RunningAvg, но для простенькой ArduinoUno вместе с библиотекой дисплея не хватает памяти.

Я взял себе за правило добавлять простой информативный header в свой код а также пару строчек, которые при запуске напоминают из какого файла и когда этот код был залит.

/************************************************************

  • WHEN: 07-SEP-2020

  • WHAT: Magic eye emulator with OLED 1.3″ 128×64 I2C Blue Display I2C address 0x3C

  • https://protosupplies.com/product/oled-1-3-128x64-i2c-blue-display/

  • Uses Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)

  • DETAILS:

  • without RunningAvg library as per

  • https://www.powertronika.com/2020/04/reducing-noise-from-sensor-data.html

  • bitmap for central triangle, side with circle and rectangle

  • On Mega2056 SDA A20, SCL A21

  • On UNO SDA A4, SCL A5

  • Use analogReference() for signal 1-2.5 v

  • Analog input on A0

  • Works on direct input from radio receiver /************************************************************/

#include <Arduino.h> #include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_I2C #include <Wire.h> #endif

#define ARR_SIZE 5

// U8g2 Contructor List (Frame Buffer) // The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8g2setupcpp U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R1, /* reset=*/ U8X8_PIN_NONE); int sum, a, y_max, delta_side,delta_y; //delta_side,delta_y - for small side triangles when a>32; y_max - maximum height float p,p_avg,myRA[ARR_SIZE]; byte index;

#define owl_width 64 #define owl_height 36 static const unsigned char owl_bits[] U8X8_PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff };

void setup(void) { Serial.begin(115200); u8g2.begin(); Serial.print("Sketch: "); Serial.println(FILE); Serial.print("Uploaded: "); Serial.println(DATE);

delta_side=12; delta_y=40; y_max=100; sum=0; index=0; u8g2.setFont(u8g2_font_timR10_tr); u8g2.setFontDirection(2); }

void loop(void) { p=analogRead(A0); //averaging sum=sum-myRA[index]; myRA[index]=p; sum+=p; index=(index+1)%ARR_SIZE; p_avg=sum/ARR_SIZE; //myRA.addValue(p); //p_avg=myRA.getAverage(); a=min(map(p_avg,1,60,1,32),80); //drawScreen(a,p_avg,1); //print amplitude drawScreen(a,p_avg,0); //don't print amplitude }

void drawScreen(int a, int vu, boolean printVU) { int16_t delta, a_x,a_y,a1,r,r1; u8g2.clearBuffer(); delta=min(32,a); a1=min(a,72); a_y=min(map(a,4,32,18,32),50);//70 a_x=map(delta,4,32,16,10); r=map(delta,4,32,11,8); r1=map(delta,4,32,6,0); if (a<6) u8g2.drawBox(29,0,7,y_max); //central triangle else u8g2.drawTriangle(32,0,32-delta,y_max,32+delta,y_max); if (a1>32) { u8g2.drawTriangle(32-delta_side, delta_y,0,y_max,0,y_max-(a1-32)); u8g2.drawTriangle(32+delta_side, delta_y,64,y_max,64,y_max-(a1-32)); } //side triangles
u8g2.drawTriangle(28,10,a_x,a_y,a_x,10); u8g2.drawBox(0,10,a_x,a_y-10); u8g2.drawDisc(r1+1,a_y-r1-2,r,U8G2_DRAW_LOWER_RIGHT|U8G2_DRAW_LOWER_LEFT); u8g2.drawTriangle(36,10,64-a_x,a_y,64-a_x,10); u8g2.drawBox(64-a_x,10,a_x,a_y-10); u8g2.drawDisc(64-r1-1,a_y-r1-2,r,U8G2_DRAW_LOWER_RIGHT|U8G2_DRAW_LOWER_LEFT); u8g2.setDrawColor(0); u8g2.drawBox(0,0,64,14); u8g2.setBitmapMode(1); u8g2.setDrawColor(0); u8g2.drawXBMP(0,64,owl_width, owl_height, owl_bits); u8g2.setDrawColor(1); if (printVU) { u8g2.setCursor(40, 110); u8g2.print(vu); }
u8g2.sendBuffer();
}

.

Комментарии (27)


  1. sav13
    06.09.2021 19:45
    +2

    Поскольку лампа требует высокого напряжения для работы, в современных устройствах это решается с помощью преобразователя напряжения на таймере 555 упроавлящим мощным полевым транзистором включенным в первичную обмотку повышающего трансформатора, и дальше вторичная обмотка подключается к умножителю напряжения из 4-5 ступеней. Этого достаточно чтобы преобразовать входные 5 вольт в 250 с током 1-2 ma

    Можно обойтись без 555, если прямо с ардуины ШИМ брать на MOSFET с диодом и дросселем

    p.s. Проект вызывает мысль о суррогатах. Если уж хочется ностальгии, то почему бы теплые лампы не запустить? Слабо?


    1. engine9
      06.09.2021 20:21
      +1

      Слышал инфу, что есть опасность устроить КЗ если МК зависнет с 1 на выходе ШИМ.


      1. sav13
        06.09.2021 20:28

        Там же дроссель в цепи. Ток ограничит, хоть и нагреется.


        1. sim2q
          07.09.2021 05:05
          +2

          Там же дроссель в цепи. Ток ограничит, хоть и нагреется

          Сработает как ватчдог. Через дроссель закоротится питание и всё запустится заново.
          А может и нет :) Для Ардуино - норма)


      1. Andy_Big
        06.09.2021 20:58
        +2

        Поставить последовательно выходу МК конденсатор и пусть зависает сколько хочет :)


        1. engine9
          06.09.2021 21:02
          +2

          Я в схемотехнике не силён, разве такая схема будет работать? Куда заряд с затвора будет уходить? Вангую, что там поплывут фронты и будет мосфет греться как печка.


          1. Andy_Big
            06.09.2021 21:07
            +1

            Куда заряд с затвора будет уходить?

            В землю через резистор :)
            Вангую, что там поплывут фронты и будет мосфет греться как печка

            Фронты поплывут, конечно, но там же и не нужно амперы прокачивать на сотнях кГц, так что ничего страшного :)


            1. sav13
              07.09.2021 05:47
              +1

              Фронты поплывут, конечно, но там же и не нужно амперы прокачивать на сотнях кГц, так что ничего страшного :)

              К сожалению, нужно. Если изначально питать все это от 5В, а на выходе получать 250В, то при 2мА на выходе через фет идет на меньше 1А. У меня при питании ИН12 и транзистор в ТО220 и дроссель греются. Хоть радиатор ставь.

              Вот думаю, пора возвращаться к аутентичным схемам питания и от сети получать сразу 170В с трансофрматора. А то получается слишком много преобразователей туда-сюда. Или даже 220 через резистор, как в журнале радио публиковали


              1. Andy_Big
                07.09.2021 13:51

                Да, пожалуй соглашусь. Не учел, что требуется такой большой коэффициент повышения напряжения, а при нем скважность ШИМ должна быть близкой к 100%, что требует крутых фронтов и повышает средний ток через ключ.


          1. RTFM13
            06.09.2021 23:13
            +1

            От номиналов зависит. Проблема в другом. При резисторе на землю после конденсатора, напряжение на затворе будет меньше напряжения логической единицы в зависимости от коэффициента заполнения. При коэффициенте заполнения 0,5 напряжение будет 0,5 от логической единицы (при условии что тау RC существенно больше длины импульса). Тогда при логическом уровне 5В еще можно найти мосфет на 2,5В, то для 3,3В пригодных мосфетов думаю не найти или будет работать на пределе с повышенным тепловыделением и переходом в линейный режим при любой просадке.

            Лучше конечно не экономить и поставить драйвер или сразу полумост с логическим входом.


    1. K_Chicago Автор
      06.09.2021 22:27
      +1

      "...почему бы теплые лампы не запустить? Слабо? "

      Даже смешно говорить, это легче лёгкого, и никакой арудины не нужно от слова совсем. Была же статья здесь, супер дотошная. Я по сути уже описал свое устройство. Таймер 40 кгц, вч-трансформатор на ферритовом "горшке" (остался от развлечений с винтажными приемниками), 4 ступени умножителя Кокрофта-Валтона и все работает без проблем. Только кушает очень много, накал плюс трансформатор, только успевай свежие батарейки ставить. Когда лампа разогреется, напряжение падает до 190 вольт, но вполен хорошо светится. Полевик немного тёплый, трансформатор тоже не холодный. Но это именно "суррогат", неинтересно. Я в ардуину лучше. Вот схема таймера, прямо из datasheet (только номиналы другие, 40 кгц подбирал экспериментально по максимальному напряжению на вторичке трансформатора; и ещё с третьей ноги резистор на землю 10к):

      Вот вам мой колхоз:

      И для мучительно ностальгирующих на али есть отлично, прямо-таки образцово выполненная плата как раз для этой лампы. Я знаю про качество потому что раньше купил такую же плату для лампы EM87 (она появилась раньше, а нынешняя совсем недавно) и переделывал её под 6E1П. Но жрёт как не в себя и разъём питания нестандартный.


  1. iliasam
    06.09.2021 21:02
    +1

    В строну таких экранов не смотрели — www.technoblogy.com/show?L6I=?
    Плотность пикселей несколько выше, можно цвет подобрать. Хотя OLED ярче будет, плюс у таких экранов могут быть сложности со скоростным обновлением.


    1. K_Chicago Автор
      06.09.2021 22:30

      Смотрел, а какже. Анимация плохая, тормозит.


      1. Sdima1357
        06.09.2021 23:09
        +1

        Он не очень медленный, это Ардуино медленный. С stm32 или esp32 у этого экрана меньше 40 миллисекунд перерисовки всего фрейма .


        1. K_Chicago Автор
          06.09.2021 23:32

          моя цель здесь была использовать простейшую ардуинку и поэтому я долго подбирал дисплеи и отказался от использования библиотеки для усреднения.

          Разумеется, если пойти по пути подбора микроконтроллеров, а не экранов, можно достичь желаемой скорости с любым почти экраном.


          1. Sdima1357
            06.09.2021 23:50
            +3

            Ардуинка и не проще и не дешевле. Это иллюзия из-за низкого порога вхождения . Именно поэтому Вам и пришлось долго перебирать дисплеи.


            1. K_Chicago Автор
              07.09.2021 00:00

              Вы будете возражать что из всего семейства ардуинок - Arduino Uno простейшая или по крайней мере одна из простейших?


        1. Gdalex
          07.09.2021 23:37
          +1

          Тут проблема не столько в процессоре, а в формате вывода. Контроллеры этих дисплеев (SSD1306 и SH1106) могут работать как по I2C, так и по SPI. Так вот я тоже в своей поделке использовал I2C и библиотеку от Adafruit (кстати, она тоже работает в страничном режиме, формируя изображение в памяти МК, а потом отправляет одной пачкой на экран). Получил скорость обновления порядка 2-4 кадра в секунду. А вот переведя свой дисплей в режим SPI скорость обновления кадров на той же самой Ардуине и в той же программе (только строку инициализации поменял) поднялась до 28 кадров в секунду. Так что, автору надо попробовать изменить схему подключения и качество картинки заметно увеличится. А вот при работе по SPI уже можно смотреть в сторону stm32. :-)


          1. Sdima1357
            08.09.2021 00:05

            Ну i2c для дислеев... Я даже и не вспомнил об этом извращении. А по SPI они вроде до 18Mbsps спокойно работают.


            1. Gdalex
              08.09.2021 10:47
              +2

              Зато автор вспомнил. Судя по диаграмме соединений в статье.

              https://habrastorage.org/r/w1560/getpro/habr/upload_files/f70/d8d/839/f70d8d8396a1a58a12fb9015c56e0d69.jpg

              Потом увидел видео работы дисплея и понял, что он и вправду на I2C висит.


              1. K_Chicago Автор
                08.09.2021 22:06

                Может быть вы даже заметили, что плата дисплея которую я использовал, поддеживает только I2C.

                Так что все эти рассуждения про SPI vs I2C это к данной теме отношения не имеет от слова совсем.


                1. Sdima1357
                  09.09.2021 00:23
                  +1

                  Речь шла не о вашем дисплее , а о https://habr.com/ru/post/576582/comments/#comment_23453480


                1. Gdalex
                  13.09.2021 13:57
                  +1

                  Не скажите, рассуждения на Хабре как раз-таки приветствуются, так как в споре рождается истина.

                  А то, что Вы выбрали не тот дисплей - это же не моя вина, так что не надо грубить. Я просто пытаюсь помочь улучшить неплохой проект. Идея хорошая, реализация очень неплохая, а вот дисплей, подключенный по SPI, поможет повысить частоту кадров и сгладить изображение.


  1. Neuromantix
    06.09.2021 21:09
    +3

    К сожалению, все виденные мной эмуляторы не передают искрящегося зеленого цвета и плавности движения границ сектора. Получается именно светодиодный свет, "жесткий".


    1. K_Chicago Автор
      06.09.2021 22:32

      про оттенок цвета совершенно согласен, это ничем не заменить. С плавностью в моём устройстве всё в порядке, после того как подобрал усреднение и фильтр RC на входе с микрофона.


      1. Moskus
        07.09.2021 01:03

        Ближе всего, возможно, был бы матричный монохромный LCD с электролюминесцентной подсветкой.


  1. tormozedison
    14.09.2021 18:26

    Он даже неравномерно выгорать будет как настоящий.