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

Arduino Shield NCS314 Tubes Clock IN-14

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

Shield Nixie Tubes IN-14 NCS314 Arduino для Nixie Tubes Clock и т. д. .
Щит на трубках Nixie Tubes IN-14
× 1
Shield Nixie Tubes Clock IN-12 NCS312 для xUSSR Nixie Tubes
× 1
Arduino UNO
Shield поддерживает Arduino UNO / Genuino или Arduino MEGA
× 1
Arduino Mega 2560
Shield поддерживает Arduino UNO / Genuino или Arduino MEGA
× 1
Блок питания 12 В, 1 А
× 1
Акриловый футляр для SHIELD NCS314
Красивая акриловая модель корпуса ACNS314 полностью совместима с версиями Nixie Arduino Shield NCS314 HW v1.X - 2 .X
× 1

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

Обзор

Изначально, когда у нас был доступ к почти неисчерпаемым запасам советских ламп Nixie отличного качества IN-12, IN-14 и IN-18, мы собирались сделать простую демонстрацию ламп Nixie как Shield для Arduino. Ардуино на тот момент у нас уже было, так что корпус остался за малым (так мы думали в то время). В то время мы ничего не знали о том, как обращаться с такими лампами.

Очень быстро мы нашли в интернете схему питания таких ламп:

ДА! Сияет! То, что мы увидели, просто ошеломило нас, как маленькое чудо, и мы поняли, что находимся на правильном пути. Сразу началась фотосессия:

На следующий день начали обсуждать концепцию будущего проекта:для упрощения и удешевления было решено использовать схему с принципом динамического отображения, но позже было решено отказаться от нее в пользу схемы с полностью статический режим отображения. Хотя для ламп IN-14 Nixie визуальная разница не заметна, но для ламп IN-18 заметна разница - в динамическом режиме они работают не так ярко, у многих из них проявляется так называемый эффект синих пятен:

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

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

Затем начался подбор оборудования, которым можно было бы переключать катоды (номера) в лампах. Выбор был очевиден - регистры сдвига с SPI для сохранения выводов MCU. Но так как напряжение питания ламп очень высокое - до 200 вольт, то вариантов не так уж и много:HV513, HV5812, HV5122. И пока мы собираем устройство на каждом из этих чипов, мы остановились на HV5812 (в новой версии Shields NCS314 V2.X и NCS312 V1.X использовалась IC HV5122). Эта микросхема очень удобна тем, что позволяет одновременно управлять двумя лампами, как 20-битным регистром.

Для управления 6 лампами нам понадобится три таких цепи, соединенных последовательно друг с другом. Это позволяет один раз отправить пакет через SPI и не заботиться об обновлении информации о трубках, как это было бы в случае с алгоритмом динамического отображения. То есть другими словами - пока нам не нужно менять информацию на трубках, MCU может быть занят другими задачами, даже спать!

Отдельно хочется сказать о передаче данных по SPI. Arudino может передавать за один раз только 8 бит. И нам нужно 60, ближайшее большее целое число, делимое на 8, равно 64, и поэтому нужно применить битовую магию - сформировать одну большую переменную типа unsigned long long var64 бит для каждого регистра и передать 8 раз по 8 бит каждый раз сдвиг всех битов внутри переменной вправо:

  SPI.transfer (var64); SPI.transfer (var64>> 48); SPI.transfer (var64>> 40); SPI.transfer (var64>> 32); SPI.transfer (var64>> 24); SPI.transfer (var64>> 16); SPI.transfer (var64>> 8); SPI.transfer (iTmp);  

Те задачи, которые были поставлены и достигнуты, были выполнены:

  • Статическое отображение на основе регистров сдвига.
  • Игровой автомат (отравление Ани)
  • Обеспечьте стандартные функции для часов, часов, даты, времени, будильника.
  • RTC (часы реального времени) с батареей CR1220. (В новой версии платы V1.2-2.X используется высокоточная микросхема времени RTC DS3231).
  • Измерение температуры DS18B20 [Цельсия или Фаренгейта].
  • Управление через ИК-порт TSOP4836 (Работает только Mega). Проверено с пультом Sony RM-X151, но возможен и другой пульт с частотой 36кГц.
  • Синхронизация времени с внешним GPS (только для работы Mega)
  • Простое меню.
  • Раздельное ведение толстой кишки (нижняя и верхняя точки)
  • Цвета подсветки RGB с плавным переходом
  • Рингтон RTTTL для будильника (язык передачи сигнала вызова)
  • Игровой автомат (для предотвращения отравления индикаторов)
  • На самопроверке. (Проверьте все числа на каждом дисплее от 0 до 9, чтобы проверить все светодиоды, последовательный переключатель цвета синий, красный, зеленый, проверка звука (воспроизведение мелодий)

Те задачи, которые не удалось реализовать в полной мере.

  • Датчик освещенности

Код

  • Файл без названия
Файл без названия C / C ++
 const String FirmwareVersion ="010000"; // Формат _X.XX__ // NIXIE CLOCK SHIELD NCS314 от GRA &AFCH ([email protected]) // 25.05.2016 #include  #include  #include  #include  #include  #include  const byte LEpin =7; // Пин Latch Enabled данные принимаются, пока HI levelconst byte DHVpin =5; // выкл. / вкл. MAX1771 Driver Hight Voltage (DHV) 110-220V const byte RedLedPin =9; // вывод WDM MCU для красных светодиодов 9-gconst байт GreenLedPin =6; // Вывод WDM микроконтроллера для зеленых светодиодов 6-битный байт BlueLedPin =3; // Вывод WDM микроконтроллера для синих светодиодов 3-rconst byte pinSet =A0; const byte pinUp =A2; const byte pinDown =A1; const byte pinBuzzer =2; const byte pinUpperDots =12; // ВЫСОКОЕ значение загорается точкойconst байт pinLowerDots =8; // ВЫСОКОЕ значение светится точкамиconst word fpsLimit =16666; // 1/60 * 1.000.000 // ограничить максимальную частоту обновления на 60 fpsString stringToDisplay ="000000"; // Содержимое этой строки будет отображаться на трубках (должно быть длиной 6 символов) int menuPosition =0; // 0 - время // 1 - дата // 2 - будильник // 3 - байт режима 12/24 часов blinkMask =B00000000; // битовая маска для мигающих цифр (1 - мигание, 0 - постоянное свечение) // ------------------------- 0 ----- --1 ---------- 2 ---------- 3 --------- 4 -------- 5 ------ --- 6 --------- 7 --------- 8 --------- 9 ----- // младший байтBytesArray [] ={B11111110, B11111101 , B11111011, B11110111, B11101111, B11011111, B10111111, B01111111, B11111111, B11111111}; // старший байт B00000000; // битовая маска для разделения точек // B00000000 - отключение точек вверх и вниз // B1100000 - отключение всех точек # define DS1307_ADDRESS 0x68byte zero =0x00; // обходной путь для проблемы № 527int RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year, RTC_day_of_week; // - ------------ 0 -------- 1 --- ----- 2 ------- 3 -------- 4 -------- 5 -------- 6 -------- 7 -------- 8 -------- 9 -------- 10 ------- 11 ------- 12 ------- 13 ------- 14 // имена:время, дата, будильник, 12/24 часа, минуты, секунды, день, месяц, год, час, минута, второй будильник 01 hour_format // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 int parent [15] ={0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4}; int firstChild [15] ={4, 7, 10, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int lastChild [15] ={6, 9, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; значение int [15] ={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24}; int maxValue [15] ={0, 0, 0, 0, 23, 59, 59, 31, 12, 99, 23, 59, 59, 1, 24}; int minValue [ 15] ={0, 0, 0, 12, 00, 00, 00, 1, 1, 00, 00, 00, 00, 0, 12}; байт blinkPattern [15] ={B00000000, B00000000, B00000000, B00000000, B00000011, B00001100, B00110000, B00000011, B00001100, B00110000, B00000011, B00001100, B00110000, B110000 00, B00001100}; # define TimeIndex 0 #define DateIndex 1 #define AlarmIndex 2 #define hModeIndex 3 #define TimeHoursIndex 4 #define TimeMintuesIndex 5 # define TimeSecondsIndex 6 # define DateDayIndex 7 #define DateMonthIndexindex 8 #define DateMonthIndexine define AlarmMinuteIndex 11 # определить AlarmSecondIndex 12 # определить Alarm01 13 # определить hModeValueIndex 14bool editMode =false; long downTime =0; long upTime =0; const long settingDelay =150; bool BlinkUp =false; bool BlinkDown =false; unsigned long enterEditModeTime =0; bool RGBLedsOn =true; byte RGBLEDsEEPROMAddress =0; byte HourFormatEEPROMAddress =1; byte AlarmTimeEEPROMAddress =2; // 3,4,5 байта AlarmArmedEEPROMAddress =6; // объявления выводов кнопок /// Tone tone1; #define isdigit (n) (n> ='0' &&n <='9') // char * song ="MissionImp:d =16, o =6, b =95:32d, 32d #, 32d, 32d #, 32d, 32d #, 32d, 32d #, 32d, 32d, 32d #, 32e, 32f, 32f #, 32g, g, 8p, g, 8p, a #, p, c7, p, g, 8p, g, 8p, f, p, f #, p, g, 8p, g, 8p, a #, p, c7, p, g, 8p, g, 8p, f, p, f #, p, a #, g, 2d, 32p, a #, g, 2c #, 32p, a #, g, 2c, a # 5,8c, 2p, 32p, a # 5, g5,2f #, 32p, a # 5, g5,2f, 32p, a # 5, g5,2e, d #, 8d "; char * song =" PinkPanther:d =4, o =5, b =160:8d #, 8e, 2p, 8f #, 8g, 2p, 8d # , 8e, 16p, 8f #, 8g, 16p, 8c6,8b, 16p, 8d #, 8e, 16p, 8b, 2a #, 2p, 16a, 16g, 16e, 16d, 2e "; // char * song =" ВанессаМэй:d =4, o =6, b =70:32c7,32b, 16c7,32g, 32p, 32g, 32p, 32d #, 32p, 32d #, 32p, 32c, 32p, 32c, 32p, 32c7,32b, 16c7,32g #, 32p, 32g #, 32p, 32f, 32p, 16f, 32c, 32p, 32c, 32p, 32c7,32b, 16c7,32g, 32p, 32g, 32p, 32d #, 32p, 32d #, 32p, 32c, 32p, 32c, 32p, 32g, 32f, 32d #, 32d, 32c, 32d, 32d #, 32c, 32d #, 32f, 16g, 8p, 16d7,32c7,32d7,32a #, 32d7,32a, 32d7, 32g, 32d7,32d7,32p, 32d7,3 2p, 32d7,32p, 16d7,32c7,32d7,32a #, 32d7,32a, 32d7,32g, 32d7,32d7,32p, 32d7,32p, 32d7,32p, 32g, 32f, 32d #, 32d, 32c, 32d, 32d #, 32c, 32d #, 32f, 16c "; // char * song =" DasBoot:d =4, o =5, b =100:d # .4,8d4,8c4,8d4,8d # 4,8g4, a # .4,8a4,8g4,8a4,8a # 4,8d, 2f., p, f.4,8e4,8d4,8e4,8f4,8a4, c., 8b4,8a4,8b4,8c, 8e, 2g. , 2p "; // char * song =" Scatman:d =4, o =5, b =200:8b, 16b, 32p, 8b, 16b, 32p, 8b, 2d6,16p, 16c # .6,16p. , 8d6,16p, 16c # 6,8b, 16p, 8f #, 2p., 16c # 6,8p, 16d.6,16p., 16c # 6,16b, 8p, 8f #, 2p, 32p, 2d6,16p , 16c # 6,8p, 16d.6,16p., 16c # 6,16a., 16c # 6,8p, 16d.6,16p., 16c # 6,16b, 8p, 8b, 16b, 32p, 8b, 16b, 32p, 8b, 2d6,16p, 16c # .6,16p., 8d6,16p, 16c # 6,8b, 16p, 8f #, 2p., 16c # 6,8p, 16d.6,16p., 16c # 6,16b, 8p, 8f #, 2p, 32p, 2d6,16p, 16c # 6,8p, 16d.6,16p., 16c # 6,16a., 16p., 8e , 2p., 16c # 6,8p, 16d.6,16p., 16c # 6,16a, 8p, 8e, 2p, 32p, 16f # .6,16p., 16b., 16p. "; // char * song ="Попкорн:d =4, o =5, b =160:8c6,8a #, 8c6,8g, 8d #, 8g, c, 8c6,8a #, 8c6,8g, 8d #, 8g, c, 8c6 , 8d6,8d # 6,16c6,8d # 6,16c6,8d # 6,8d6,16a #, 8d6,16a #, 8d6,8c6,8a #, 8g, 8a #, c6 "; // char * song ="WeWishYou:d =4, o =5, b =200:d, g, 8g, 8a, 8g, 8f #, e, e, e, a, 8a, 8b, 8a, 8g, f #, d, d, б, 8б, 8с6,8б , 8a, g, e, d, e, a, f #, 2g, d, g, 8g, 8a, 8g, 8f #, e, e, e, a, 8a, 8b, 8a, 8g, f #, d, d, b, 8b, 8c6,8b, 8a, g, e, d, e, a, f #, 1g, d, g, g, g, 2f #, f #, g, f #, e, 2d, a, b , 8a, 8a, 8g, 8g, d6, d, d, e, a, f #, 2g "; # определить OCTAVE_OFFSET 0char * p; int notes [] ={0, NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4 , NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_6, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B6, NOTE_C6, NOTE_C5 , NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6, NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7}; int ={0,0,1] 1 -1,0,0, // 2 0,1,0, // 3 0,0, -1, // 4 1,0,0, // 5 0, -1,0}; // массив с правилами RGB (0 - ничего не делать, -1 - уменьшать, +1 - инкрементировать, исключать setRTCDateTime (байт h, байт m, байт s, байт d, байт mon, байт y, байт w =1); int functionDownButton =0; int functionUpButton =0; / **************************************** ************************************************* *********** Программа инициализации ************************************ ************************************************* **************** / void setup () {digitalWrite (DHVpin, LOW); // выкл. MAX1771 Driver Hight Voltage (DHV) 110-220V Wire.begin (); // setRTCDateTime (23,40,00,25,7,15,1); Serial.begin (115200); Serial.println (""); if (EEPROM.read (HourFormatEEPROMAddress)! =12) значение [hModeValueIndex] =24; else value [hModeValueIndex] =12; if (EEPROM.read (RGBLEDsEEPROMAddress)! =0) RGBLedsOn =true; else RGBLedsOn =false; if (EEPROM.read (AlarmTimeEEPROMAddress) ==255) value [AlarmHourIndex] =0; значение [AlarmHourIndex] =EEPROM.read (AlarmTimeEEPROMAddress); если (EEPROM.read (AlarmTimeEEPROMAddress + 1) ==255) значение [AlarmMinuteIndex] =0; e Значение lse [AlarmMinuteIndex] =EEPROM.read (AlarmTimeEEPROMAddress + 1); if (EEPROM.read (AlarmTimeEEPROMAddress + 2) ==255) значение [AlarmSecondIndex] =0; иначе значение [AlarmSecondIndex] =EEPROM.read (AlarmTimeEEPROMAddress + 2); если (EEPROM.read (AlarmArmedEEPROMAddress) ==255) значение [Alarm01] =0; иначе значение [Alarm01] =EEPROM.read (AlarmArmedEEPROMAddress); tone1.begin (pinBuzzer); song =parseSong (песня); pinMode (LEpin, ВЫХОД); pinMode (DHVpin, ВЫХОД); pinMode (RedLedPin, ВЫХОД); pinMode (GreenLedPin, ВЫХОД); pinMode (BlueLedPin, ВЫХОД); // Настройка SPI SPI.begin (); // SPI.setDataMode (SPI_MODE3); // Режим 3 SPI SPI.setClockDivider (SPI_CLOCK_DIV128); // SCK =16MHz / 128 =125kHz // кнопки выводов pinMode (pinSet, INPUT_PULLUP); pinMode (pinUp, INPUT_PULLUP); pinMode (pinDown, INPUT_PULLUP); //////////////////////////// pinMode (pinBuzzer, OUTPUT); // объекты кнопок в них setButton.debounceTime =20; // Таймер устранения дребезга в мс setButton.multiclickTime =30; // Ограничение по времени для мульти-кликов setButton.longClickTime =2000; // время до регистрации "нажатых щелчков" upButton.debounceTime =20; // Таймер устранения дребезга в мс upButton.multiclickTime =30; // Ограничение по времени для мульти-кликов upButton.longClickTime =2000; // время до регистрации "нажатых щелчков" downButton.debounceTime =20; // Таймер устранения дребезга в мс downButton.multiclickTime =30; // Ограничение по времени для мульти-кликов downButton.longClickTime =2000; // время до регистра "нажатых щелчков" // digitalWrite (DHVpin, HIGH); // на MAX1771 драйвер высокого напряжения (DHV) 110–220 В // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!! // doTest (); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! getRTCTime (); setTime (RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year); digitalWrite (DHVpin, LOW); // выкл. MAX1771 Driver Hight Voltage (DHV) 110-220V setRTCDateTime (RTC_hours, RTC_minutes, RTC_seconds, RTC_day, RTC_month, RTC_year, 1); // ���������� ������ ��� ��������� ����� � RTC ����� �������� ����� ���������� digitalWrite (DHVpin, HIGH); // на MAX1771 Высокое напряжение драйвера (DHV) 110–220 В // p =song;} void rotateLeft (uint8_t &bits) {uint8_t high_bit =bits &(1 <<7)? 1:0; биты =(биты <<1) | high_bit;} int rotator =0; // индекс в массиве с «правилами» RGB (увеличивается на единицу каждые 255 циклов) int cycle =0; // циклы counterint RedLight =255; int GreenLight =0; int BlueLight =0; unsigned long prevTime =0; // время зажигания лазерной трубки без знака long prevTime4FireWorks =0; // время последнего изменения RGB // int minuteL =0; // ������� ����� ����� / ***************************** ************************************************* ******************************* ГЛАВНАЯ программа ***************** ************************************************* ****************************************** / void loop () { p =playmusic (p); если ((millis () - prevTime4FireWorks)> 5) {rotateFireWorks (); // изменить цвет (на 1 шаг) prevTime4FireWorks =millis (); } doIndication (); setButton.Update (); upButton.Update (); downButton.Update (); если (editMode ==false) {blinkMask =B00000000; } иначе, если ((millis () - enterEditModeTime)> 60000) {editMode =false; menuPosition =firstChild [menuPosition]; blinkMask =blinkPattern [menuPosition]; } if (setButton.clicks> 0) // короткий щелчок {p =0; // отключаем музыку))) tone1.play (1000,100); enterEditModeTime =millis (); menuPosition =menuPosition + 1; если (menuPosition ==hModeIndex + 1) menuPosition =TimeIndex; Serial.print (F ("menuPosition =")); Serial.println (menuPosition); Serial.print (F ("значение =")); Serial.println (значение [menuPosition]); blinkMask =blinkPattern [menuPosition]; if ((parent [menuPosition-1]! =0) and (lastChild [parent [menuPosition-1] -1] ==(menuPosition-1))) {if ((parent [menuPosition-1] -1 ==1 ) &&(! isValidDate ())) {menuPosition =DateDayIndex; возвращение; } editMode =false; menuPosition =родительский [menuPosition-1] -1; if (menuPosition ==TimeIndex) setTime (значение [TimeHoursIndex], значение [TimeMintuesIndex], значение [TimeSecondsIndex], день (), месяц (), год ()); if (menuPosition ==DateIndex) setTime (час (), минута (), секунда (), значение [DateDayIndex], значение [DateMonthIndex], 2000 + значение [DateYearIndex]); if (menuPosition ==AlarmIndex) {EEPROM.write (AlarmTimeEEPROMAddress, значение [AlarmHourIndex]); EEPROM.write (AlarmTimeEEPROMAddress + 1, значение [AlarmMinuteIndex]); EEPROM.write (AlarmTimeEEPROMAddress + 2, значение [AlarmSecondIndex]); EEPROM.write (AlarmArmedEEPROMAddress, значение [Alarm01]);}; if (menuPosition ==hModeIndex) EEPROM.write (HourFormatEEPROMAddress, значение [hModeValueIndex]); digitalWrite (DHVpin, LOW); // выкл. MAX1771 Driver Hight Voltage (DHV) 110-220V setRTCDateTime (час (), минута (), секунда (), день (), месяц (), год ()% 1000,1); digitalWrite (DHVpin, HIGH); // на MAX1771 Driver Hight Voltage (DHV) 110–220 В} value [menuPosition] =extractDigits (blinkMask); } if (setButton.clicks <0) // долгий щелчок {tone1.play (1000,100); если (! editMode) {enterEditModeTime =millis (); if (menuPosition ==TimeIndex) stringToDisplay =PreZero (час ()) + PreZero (минута ()) + PreZero (секунда ()); // в настройках временно включен 24-часовой формат} menuPosition =firstChild [menuPosition]; if (menuPosition ==AlarmHourIndex) {значение [Alarm01] =1; / * digitalWrite (pinUpperDots, HIGH); * / dotPattern =B10000000;} editMode =! editMode; blinkMask =blinkPattern [menuPosition]; значение [menuPosition] =extractDigits (blinkMask); } если (upButton.clicks! =0) functionUpButton =upButton.clicks; если (upButton.clicks> 0) {p =0; // отключаем музыку))) tone1.play (1000,100); инкрементValue (); } if (functionUpButton ==-1 &&upButton.depressed ==true) {BlinkUp =false; if (editMode ==true) {if ((millis () - upTime)> settingDelay) {upTime =millis (); // + settingDelay; инкрементValue (); }}} еще BlinkUp =true; если (downButton.clicks! =0) functionDownButton =downButton.clicks; если (downButton.clicks> 0) {p =0; // отключаем музыку))) tone1.play (1000,100); dicrementValue (); } если (functionDownButton ==-1 &&downButton.depressed ==true) {BlinkDown =false; if (editMode ==true) {if ((millis () - downTime)> settingDelay) {downTime =millis (); // + settingDelay; dicrementValue (); }}} еще BlinkDown =true; если (! editMode) {если (upButton.clicks <0) {tone1.play (1000,100); RGBLedsOn =true; EEPROM.write (RGBLEDsEEPROMAddress, 1); Serial.println («RGB =вкл»); } если (downButton.clicks <0) {tone1.play (1000,100); RGBLedsOn =false; EEPROM.write (RGBLEDsEEPROMAddress, 0); Serial.println («RGB =выкл»); }} static bool updateDateTime =false; switch (menuPosition) {case TimeIndex:// временной режим stringToDisplay =updateDisplayString (); doDotBlink (); checkAlarmTime (); ломать; case DateIndex:// режим даты stringToDisplay =PreZero (day ()) + PreZero (month ()) + PreZero (year ()% 1000); dotPattern =B01000000; // включаем нижние точки / * digitalWrite (pinUpperDots, LOW); digitalWrite (pinLowerDots, HIGH); * / checkAlarmTime (); ломать; case AlarmIndex:// режим тревоги stringToDisplay =PreZero (значение [AlarmHourIndex]) + PreZero (значение [AlarmMinuteIndex]) + PreZero (значение [AlarmSecondIndex]); if (значение [Alarm01] ==1) / * digitalWrite (pinUpperDots, HIGH); * / dotPattern =B10000000; // включаем верхние точки else {/ * digitalWrite (pinUpperDots, LOW); digitalWrite (pinLowerDots, LOW); * / dotPattern =B00000000; // отключаем верхние точки} checkAlarmTime (); ломать; case hModeIndex:// 12/24-часовой режим stringToDisplay ="00" + String (value [hModeValueIndex]) + "00"; dotPattern =B00000000; // выключить все точки / * digitalWrite (pinUpperDots, LOW); digitalWrite (pinLowerDots, LOW); * / checkAlarmTime (); ломать; }} String PreZero (int digit) {if (digit <10) return String ("0") + String (цифра); иначе return String (цифра);} void rotateFireWorks () {if (! RGBLedsOn) {analogWrite (RedLedPin, 0); analogWrite (GreenLedPin, 0); analogWrite (BlueLedPin, 0); возвращение; } RedLight =RedLight + fireforks [ротатор * 3]; GreenLight =GreenLight + fireforks [ротатор * 3 + 1]; BlueLight =BlueLight + fireforks [ротатор * 3 + 2]; analogWrite (RedLedPin, RedLight); analogWrite (GreenLedPin, GreenLight); analogWrite (BlueLedPin, BlueLight); цикл =цикл + 1; если (цикл ==255) {ротатор =ротатор + 1; цикл =0; } if (rotator> 5) rotator =0;} void doIndication () {// статический байт b =B00000001; статический беззнаковый длинный lastTimeInterval1Started; если ((micros () - lastTimeInterval1Started) > 2; Var64 | =tmpVar64; Вар64 =(Вар64>> 4); беззнаковое int iTmp =0; iTmp =Var64>> 56; SPI.transfer (iTmp); iTmp =Var64>> 48; SPI.transfer (iTmp); iTmp =Var64>> 40; SPI.transfer (iTmp); iTmp =Var64>> 32; SPI.transfer (iTmp); iTmp =Var64>> 24; SPI.transfer (iTmp); iTmp =Var64>> 16; SPI.transfer (iTmp); iTmp =Var64>> 8; SPI.transfer (iTmp); iTmp =Var64; SPI.transfer (iTmp); digitalWrite (LEpin, LOW); // фиксируем данные} byte CheckButtonsState () {статические логические кнопкиWasChecked; статический беззнаковый длинный startBuzzTime; статический беззнаковый длинный lastTimeButtonsPressed; if ((digitalRead (pinSet) ==0) || (digitalRead (pinUp) ==0) || (digitalRead (pinDown) ==0)) {if (buttonsWasChecked ==false) startBuzzTime =millis (); buttonsWasChecked =true; } else buttonsWasChecked =false; если (millis () - startBuzzTime <30) {digitalWrite (pinBuzzer, HIGH); } else {digitalWrite (pinBuzzer, LOW); }} String updateDisplayString () {static unsigned long lastTimeStringWasUpdated; if ((millis () - lastTimeStringWasUpdated)> 1000) {//Serial.println("doDotBlink "); // doDotBlink (); lastTimeStringWasUpdated =миллис (); if (value [hModeValueIndex] ==24) return PreZero (час ()) + PreZero (минута ()) + PreZero (секунда ()); иначе вернуть PreZero (hourFormat12 ()) + PreZero (minute ()) + PreZero (second ()); } return stringToDisplay;} void doTest () {Serial.print (F ("Версия прошивки:")); Serial.println (FirmwareVersion.substring (1,2) + "." + FirmwareVersion.substring (2,4)); Serial.println (F («Начать тест»)); int adc =analogRead (A3); float Uinput =4.6 * (5.0 * adc) /1024.0+0.7; Serial.print (F ("U input =")); Serial.print (Uinput); р =песня; parseSong (p); analogWrite (RedLedPin, 255); задержка (1000); analogWrite (RedLedPin, 0); analogWrite (GreenLedPin, 255); задержка (1000); analogWrite (GreenLedPin, 0); analogWrite (BlueLedPin, 255); задержка (1000); // while (1); String testStringArray [12] ={"000000", "111111", "222222", "333333", "444444", "555555", "666666", "777777", "888888", "999999", "", ""}; если (Uinput <10) testStringArray [10] ="000" + String (int (Uinput * 100)); иначе testStringArray [10] ="00" + String (int (Uinput * 100)); testStringArray [11] =Версия прошивки; int dlay =500; bool test =1; byte strIndex =0; беззнаковый длинный startOfTest =millis (); для (int я =0; я <12; я ++) {если ((millis () - startOfTest)> dlay) {startOfTest =millis (); strIndex =strIndex + 1; если (strIndex ==10) dlay =3000; если (strIndex ==12) test =0; switch (strIndex) {/ * case 10:SPI.transfer ((b | B01000000) &B11111100); ломать; случай 11:SPI.transfer ((b | B01000000) &B11001110); ломать; * / // по умолчанию:SPI.transfer (b | B11000000); по умолчанию:stringToDisplay =testStringArray [strIndex]; }} delayMicroseconds (2000); }; Serial.println (F («Остановить тест»)); } void doDotBlink () {статическое беззнаковое длинное lastTimeBlink =millis (); static bool dotState =0; если ((миллис () - lastTimeBlink)> 1000) {lastTimeBlink =миллис (); dotState =! dotState; если (dotState) {dotPattern =B11000000; / * digitalWrite (pinUpperDots, HIGH); digitalWrite (pinLowerDots, HIGH); * /} еще {dotPattern =B00000000; / * digitalWrite (pinUpperDots, LOW); digitalWrite (pinLowerDots, LOW); * /}}} void setRTCDateTime (байт h, байт m, байт s, байт d, байт mon, байт y, байт w) {Wire.beginTransmission (DS1307_ADDRESS); Wire.write (ноль); // останавливаем осциллятор Wire.write (decToBcd (s)); Wire.write (decToBcd (м)); Wire.write (decToBcd (h)); Wire.write (decToBcd (w)); Wire.write (decToBcd (d)); Wire.write (decToBcd (mon)); Wire.write (decToBcd (y)); Wire.write (ноль); // запускаем Wire.endTransmission ();} byte decToBcd (byte val) {// Преобразуем обычные десятичные числа в двоично-десятичные return ((val / 10 * 16) + (val% 10));} byte bcdToDec (byte val ) {// Преобразование двоично-десятичного числа в обычное десятичное return ((val / 16 * 10) + (val% 16));} void getRTCTime () {Wire.beginTransmission (DS1307_ADDRESS); Wire.write (ноль); Wire.endTransmission (); Wire.requestFrom (DS1307_ADDRESS, 7); RTC_seconds =bcdToDec (Wire.read ()); RTC_minutes =bcdToDec (Wire.read ()); RTC_hours =bcdToDec (Wire.read () &0b111111); // 24-часовое время RTC_day_of_week =bcdToDec (Wire.read ()); // 0-6 -> воскресенье - суббота RTC_day =bcdToDec (Wire.read ()); RTC_month =bcdToDec (Wire.read ()); RTC_year =bcdToDec (Wire.read ());} word doEditBlink (int pos) {if (! BlinkUp) return 0; если (! BlinkDown) вернет 0; int lowBit =blinkMask>> pos; lowBit =lowBit &B00000001; статический беззнаковый длинный lastTimeEditBlink =millis (); static bool blinkState =false; маска слова =0; static int tmp =0; // blinkMask; если ((миллис () - lastTimeEditBlink)> 300) {lastTimeEditBlink =миллис (); blinkState =! blinkState; /*Serial.print("blinkpattern="); Serial.println (blinkPattern [menuPosition]); если (((blinkPattern [menuPosition]>> 8) &1 ==1) &&blinkState ==true) digitalWrite (pinLowerDots, HIGH); иначе digitalWrite (pinLowerDots, LOW); если (((blinkPattern [menuPosition]>> 7) &1 ==1) &&blinkState ==true) digitalWrite (pinUpperDots, HIGH); иначе digitalWrite (pinUpperDots, LOW); * / if (blinkState) tmp =0; иначе tmp =blinkMask; } если (((dotPattern &~ tmp)>> 6) &1 ==1) digitalWrite (pinLowerDots, HIGH); иначе digitalWrite (pinLowerDots, LOW); если (((dotPattern &~ tmp)>> 7) &1 ==1) digitalWrite (pinUpperDots, HIGH); иначе digitalWrite (pinUpperDots, LOW); if ((blinkState ==true) &&(lowBit ==1)) mask =0xFFFF; // маска =B11111111; маска возврата;} int extractDigits (byte b) {String tmp ="1"; /*Serial.print("blink pattern ="); Serial.println (б); Serial.print ("stringToDisplay ="); Serial.println (stringToDisplay); * / if (b ==B00000011) {tmp =stringToDisplay.substring (0,2); /*Serial.print("stringToDisplay1="); Serial.println (stringToDisplay); * /} если (b ==B00001100) {tmp =stringToDisplay.substring (2,4); /*Serial.print("stringToDisplay2="); Serial.println (stringToDisplay); * /} if (b ==B00110000) {tmp =stringToDisplay.substring (4); /*Serial.print("stringToDisplay3="); Serial.println(stringToDisplay);*/ } /*Serial.print("stringToDisplay4="); Serial.println(stringToDisplay);*/ return tmp.toInt();}void injectDigits(byte b, int value){ if (b==B00000011) stringToDisplay=PreZero(value)+stringToDisplay.substring(2); if (b==B00001100) stringToDisplay=stringToDisplay.substring(0,2)+PreZero(value)+stringToDisplay.substring(4); if (b==B00110000) stringToDisplay=stringToDisplay.substring(0,4)+PreZero(value);}bool isValidDate(){ int days[12]={31,28,31,30,31,30,31,31,30,31,30,31}; if (value[DateYearIndex]%4==0) days[1]=29; if (value[DateDayIndex]>days[value[DateMonthIndex]-1]) return false; else return true; }byte default_dur =4;byte default_oct =6;int bpm =63;int num;long wholenote;long duration;byte note;byte scale;char* parseSong(char *p){ // Absolutely no error checking in here // format:d=N,o=N,b=NNN:// find the start (skip name, etc) while(*p !=':') p++; // ignore name p++; // skip ':' // get default duration if(*p =='d') { p++; p++; // skip "d=" num =0; while(isdigit(*p)) { num =(num * 10) + (*p++ - '0'); } if(num> 0) default_dur =num; p++; // skip comma } // get default octave if(*p =='o') { p++; p++; // skip "o=" num =*p++ - '0'; if(num>=3 &&num <=7) default_oct =num; p++; // skip comma } // get BPM if(*p =='b') { p++; p++; // skip "b=" num =0; while(isdigit(*p)) { num =(num * 10) + (*p++ - '0'); } bpm =num; p++; // skip colon } // BPM usually expresses the number of quarter notes per minute wholenote =(60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) return p;} // now begin note loop static unsigned long lastTimeNotePlaying=0; char* playmusic(char *p) { if(*p==0) { return p; } if (millis()-lastTimeNotePlaying>duration) lastTimeNotePlaying=millis(); else return p; // first, get note duration, if available num =0; while(isdigit(*p)) { num =(num * 10) + (*p++ - '0'); } if(num) duration =wholenote / num; else duration =wholenote / default_dur; // we will need to check if we are a dotted note after // now get the note note =0; switch(*p) { case 'c':note =1; ломать; case 'd':note =3; ломать; case 'e':note =5; ломать; case 'f':note =6; ломать; case 'g':note =8; ломать; case 'a':note =10; ломать; case 'b':note =12; ломать; case 'p':default:note =0; } p++; // now, get optional '#' sharp if(*p =='#') { note++; p++; } // now, get optional '.' dotted note if(*p =='.') { duration +=duration/2; p++; } // now, get scale if(isdigit(*p)) { scale =*p - '0'; p++; } else { scale =default_oct; } scale +=OCTAVE_OFFSET; if(*p ==',') p++; // skip comma for next note (or we may be at the end) // now play the note if(note) { tone1.play(notes[(scale - 4) * 12 + note], duration); if (millis()-lastTimeNotePlaying>duration) lastTimeNotePlaying=millis(); else return p; tone1.stop(); } else { return p; } Serial.println(F("Incorrect Song Format!")); возврат 0; //error } void incrementValue() { enteringEditModeTime=millis(); if (editMode==true) { if(menuPosition!=hModeValueIndex) // 12/24 hour mode menu position value[menuPosition]=value[menuPosition]+1; else value[menuPosition]=value[menuPosition]+12; if (value[menuPosition]>maxValue[menuPosition]) value[menuPosition]=minValue[menuPosition]; if (menuPosition==Alarm01) { if (value[menuPosition]==1) /*digitalWrite(pinUpperDots, HIGH);*/dotPattern=B10000000;//turn on all dots /*else digitalWrite(pinUpperDots, LOW); */ dotPattern=B00000000; //turn off all dots } injectDigits(blinkMask, value[menuPosition]); } } void dicrementValue(){ enteringEditModeTime=millis(); if (editMode==true) { if (menuPosition!=hModeValueIndex) value[menuPosition]=value[menuPosition]-1; else value[menuPosition]=value[menuPosition]-12; if (value[menuPosition]1000)) Alarm1SecondBlock=false; if (Alarm1SecondBlock==true) return; if ((hour()==value[AlarmHourIndex]) &&(minute()==value[AlarmMinuteIndex]) &&(second()==value[AlarmSecondIndex])) { lastTimeAlarmTriggired=millis(); Alarm1SecondBlock=true; Serial.println(F("Wake up, Neo!")); p=song; }} 
Prog NIXIE Clock Tubes Shield NCS314
https://github.com/afch/NixeTubesShieldNCS314/

Схема


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

  1. Часы видения Arduino pov
  2. Веб-контроллер DMX
  3. Простые часы со словами (Arduino)
  4. Часы Arduino с исламским временем молитв
  5. Arduino Spybot
  6. Основные часы
  7. Сделайте часы Nixie с Arduino в деревянном корпусе из МДФ
  8. 7-сегментный массив часов
  9. BLUE_P:беспроводной экран программирования Arduino
  10. Простой будильник с DS1302 RTC