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

Анализатор / часы DCF77 v2.0

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

Arduino Mega 2560
× 1
Arduino UNO
× 1

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

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

Как и все, я начал с основных набросков, но вскоре захотелось сделать что-нибудь полезное. Поскольку мне всегда нравились радиочасы (в моем случае они синхронизируются с сигналом DCF77 из Германии), я решил сделать часы, которые не только показывают время, но и показывают, что происходит.

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

Фото и видео DCF77 Analyzer / Clock v1.0:

Но позже я обнаружил суперфильтр DCF77 от Удо Кляйна, который обеспечивает чистый сигнал, когда радиосигнал не очень хороший.

Это отдельная плата Arduino Uno с программным обеспечением Superfilter (вы можете рассматривать ее как отдельный «черный ящик», фильтрующий сигнал), подключенная между антенной DCF77 и Arduino Mega, на которой запущен мой эскиз.

Итак, я сделал версию 2.0 первых часов:

  • полностью переписанный код
  • подробно прокомментирован, поэтому, надеюсь, любой сможет понять, что происходит.
  • добавлен датчик движения PIR для снижения энергопотребления.
  • добавлен суперфильтр DCF77
  • дополнительный дисплей для температуры или другого использования (например, восхода / захода солнца)

Фотографии и видео о новом анализаторе / часах DCF77 v2.0:

Демо

для просмотра видео нажмите ЗДЕСЬ

Встроить "Дедушкины часы"

для просмотра видео нажмите ЗДЕСЬ

Дизайн

Лицевая панель и корпус:

Дизайн передней панели был выполнен в бесплатной программе под названием Inkscape (см. URL-адрес загрузки в начале этой страницы).

На самом деле изготовление передней панели оказалось самым сложным делом. Я потратил много денег, пытаясь сделать это в местной FabLab, используя лазерный резак и особый вид акрила с алюминиевым покрытием. Идея заключалась в том, чтобы вырезать отверстия лазером и выгравировать текст и линии, выжигая очень тонкое покрытие, обнажающее черный акрил внизу. Но это был кошмар, поскольку лазерный резак не мог работать с требуемыми мне допусками из-за интенсивного использования и «неправильного обращения» со стороны многих пользователей.

Затем я наткнулся на онлайн-сервис фотографий. Они печатают на самых разных материалах, и одним из них была панель DiBond. Цена была очень хорошей, 28 евро, включая почтовые расходы. Но результат поначалу был разочаровывающим, потому что мой дизайн напечатали не 1:1, а в небольшом увеличении. Так что будьте осторожны, если решите использовать этот метод. Сначала позвоните им и спросите, можно ли распечатать 1:1.

После телефонного звонка мне прислали еще одну панель нужных размеров. Получилось лучше, чем ожидалось, отлично!

Тогда потребовалось много сверления и фрезерования:

Код

  • DCF Analyzer / Clock v2.1
  • Эскиз суперфильтра
DCF Analyzer / Clock v2.1 Arduino
2020-01-18 выпуск ошибки:исправлен переключатель энергосбережения
 / * ================================================================================Анализатор DCF77 / Версия часов 2 ================================================================================Этот эскиз является бесплатным программным обеспечением; вы можете распространять и / или изменять его в соответствии с условиями Стандартной общественной лицензии ограниченного применения GNU, опубликованной Free Software Foundation; либо версии 2.1 Лицензии, либо (по вашему выбору) любой более поздней версии. Этот скетч распространяется в надежде, что он будет полезен, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; даже без подразумеваемых гарантий ТОВАРНОЙ ПРИГОДНОСТИ или ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. Подробнее см. Стандартную общественную лицензию ограниченного применения GNU. Вы должны были получить копию Стандартной общественной лицензии ограниченного применения GNU вместе с этой библиотекой; в противном случае напишите в Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ================================================================================Этот код C ++ далек от оптимизации, потому что я сам новичок в Arduino и C ++. Но даже после того, как я узнал что-то еще, я хочу, чтобы код оставался простым и читабельным. Вот почему я, возможно, переоценил код, чтобы понять, что происходит. Эрик де Руйтер 2014-2020 Май 2014 Первая версия Март 2016 - капитальный ремонт ... Июль 2016 - Начните с создания 2.0 Clock и адаптации скетча Версия 2.1, дата 2020-01-18 - Исправлена ​​функция Powersafe. Версия 2.0 - Этот скетч адаптирован для моей версии 2.0 DCF / Analyzer Clock. По умолчанию он использовал Arduino MEGA и DCF Superfilter, а для управления многими отдельными светодиодами я теперь использую порты Arduino Mega вместо чипа Maxim 7219. Это связано с тем, что управление светодиодами с различными характеристиками напряжения / тока с микросхемой Maxim проблематично. Например, включение дополнительных светодиодов повлияет на уже включенные светодиоды (тускло). Поскольку я не инженер-электронщик, единственным решением было использование дополнительных портов Arduino Mega. Конечно, вы можете использовать транзисторы или дополнительные микросхемы для управления светодиодами, но для меня это было очевидным решением. - Удален весь код дисплея Maxim Common Anode Версия 1.72 - Опция:используйте дешевый детектор Ebay PIR, чтобы отключать выбираемые дисплеи, когда не обнаруживается никакой активности. Пользователь может установить задержку выключения, чтобы предотвратить отключение дисплея, если человек не двигается, но дисплей должен быть включен. - Теперь отключение дисплея в ночное время можно отключить, установив оба значения «POWERSAVINGOFFTIME» и «POWERSAVINGONTIME» равными нулю. - Исправлена ​​ошибка, при которой отображение температуры не отключалось в режиме энергосбережения. - errorCounter display не сбрасывался каждый час - исправлено Версия 1.71 - Пользовательская опция для сброса памяти min / max температуры в полночь Версия 1.7:- Разрешение отображения температуры улучшено:с 0,5 до 0,1 градуса Цельсия Из-за времени датчика DS18B20 необходимо преобразовать температуру и сохранить код чистым, отображение температуры обновляется раз в минуту. - Оптимизирована процедура проверки четности. - Более надежная проверка на наличие неверных данных DCF, предотвращающая обновление RTC с недопустимыми данными. - Ошибка EoB теперь очищает внутреннее светодиодное кольцо должным образом. - Светодиод DCF OK теперь более надежно отображает состояние сигнала DCF. Немедленно выключается при возникновении ошибки и включается только тогда, когда все 3 бита четности в порядке. Версия 1.6:- Изменена функция температуры, чтобы рассчитывать только один раз в минуту. Перед изменением были странные ошибки, потому что я использовал задержку в 100 мс, чтобы дать датчику DS18B20 время для расчета температуры. Но функция задержки - очень плохая идея в большинстве программ на C ++, поэтому я наконец избавился от нее. Версия 1.5:- Полный пересмотр функции scanSignal и остального кода! Моя первая попытка сработала, но ее можно было улучшить ... - Светодиоды rPW и rPT работали не так, как я предполагал, поэтому теперь это исправлено. - Подпрограмма проверки ошибок конца буфера теперь работает должным образом. - Я включил проверку четности входящего сигнала DCF. В сигнале отправляются 3 бита четности, поэтому теперь они проверяются, и только если все три в порядке, полученная информация о времени принимается, дисплей обновляется и синхронизируется RTC. при желании вы можете присоединить 3 дополнительных двухцветных светодиода (общий катод), чтобы увидеть, в порядке ли каждый из 3 бит четности или нет. - Я значительно упростил подключение (или изменение проводки), я думаю, поместив всю конфигурацию PIN-кодов в одну легко читаемую таблицу - Пока вы используете 1 темп. sensor, я отредактировал код, поэтому вам больше не нужно выяснять адрес устройства I2C. - Большая очистка кода ... - Энергосбережение за счет отключения дисплеев (часы продолжают работать в обычном режиме) теперь можно настроить несколько проще, отредактировав две переменные POWERSAVINGONTIME и POWERSAVINGOFFTIME. - изменены некоторые имена переменных:- Экземпляры Maxim 'lc' и 'lc1' теперь являются MaximCC и MaximCA - Описание дисплея MaximDcfTime теперь отображается как DisplayTempWeek - DCF77SOUNDPIN теперь называется BUZZERSWITCHPIN - Тест светодиодов / дисплея после включения питания теперь встроен Краткое описание:Power On:После включения сначала выполняется проверка светодиодов. Светодиоды и дисплеи загораются последовательно, чтобы снизить энергопотребление. Затем часы начинают получать импульсы DCF, и при обнаружении Минутной метки (2-секундный интервал) загорается индикатор Минутной метки, и счетчик буфера сбрасывается. Внутреннее светодиодное кольцо теперь будет показывать входящие импульсы DCF, которые также хранятся в буфере. В 3 момента во время приема данных биты DCF четности проверяются, чтобы убедиться, что данные действительны. Получены достоверные данные:когда в конце минуты после обнаружения Минутной метки (горит светодиод BF (Buffer Full)) все три бита четности в норме (горит светодиод DCF OK), информация о буфере используется для извлечения информации о времени и дате. Затем часы RTC обновляются (горит светодиод «RTC Synced»), и информация о внутреннем светодиодном кольце копируется на внешнее светодиодное кольцо. Отображение времени, даты и недели, светодиодного индикатора дня, летнего / зимнего времени и светодиодной информации високосного года обновляется с учетом новой информации о времени. Нет достоверных данных:когда один или несколько битов четности не в порядке из-за зашумленного сигнала, получение информации DCF продолжается, но не будет использоваться для обновления RTC, дисплеев и светодиодов. Внешнее светодиодное кольцо, светодиоды «RTC synced» и «DCF OK» будут сброшены. Время, дата, неделя, индикатор дня недели, индикатор летнего / зимнего времени и индикатор високосного года не изменяются и продолжают отображать последние полученные действительные значения. Светодиодные индикаторы ошибки «Period Time» и / или «Period With» будут указывать на ошибку (ошибки), и дисплей счетчика ошибок обновляется. Каждый час на дисплее ошибки ставка будет обнуляться. Индикатор EoB, End of Buffer загорается, когда поступает больше импульсов DCF до того, как будет обнаружена метка минуты из-за зашумленного сигнала. (При обнаружении минутной метки у нас должно быть не более 58 бит / импульсов). После обнаружения минутной метки запускается новый цикл. Температура:через 30 секунд дисплей температуры покажет максимальное и минимальное значения за прошедший период после последнего сброса. Звонок:если переключатель ГОНГ находится в положении ВКЛ / ВЫСОКИЙ, то в начале каждого часа будет звучать звонок (если он подключен). В ночное время, время, установленное пользователем в самом коде, звонок отключен. Энергосбережение - отключение дисплея. Это будет работать, только если переключатель режима энергосбережения находится в ВЫСОКОМ положении:1. ВЫКЛЮЧЕНИЕ НОЧЬЮ В часы, установленные пользователем, дисплеи отключаются на ночь и включаются утром. Посмотрите на переменные POWERSAVINGOFFTIME и POWERSAVINGONTIME. Отметьте функцию , чтобы выбрать, КАКИЕ дисплеи вы хотите отключать на ночь. 2. ДАТЧИК PIR Подключите датчик PIR и активируйте опцию PIR POWERSAVE_BY_PIR и задержку в PIR_DELAY_TIME. Каждый раз, когда детектор PIR обнаруживает движение, счетчик минут сбрасывается, но если движение не обнаруживается дольше PIR_DELAY_TIME, дисплеи отключаются. Когда происходит движение, сразу включаются дисплеи. Примечание:как было сказано ранее, часы будут работать нормально, пока дисплеи выключены. Звуковой сигнал DCF:С переключателем, подключенным к контакту BUZZERSWITCHPIN, вы можете услышать поступающие принятые биты DCF. Продолжительность тонального сигнала эквивалентна ширине импульса битов DCF, то есть 100 или 200 мс. Неправильно:когда батарея RTC разряжена или обнаружена ошибка соединения, загорается светодиод ошибки RTC. ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:Я многому научился у Маттиаса Дальхеймера и Тайса Эленбааса, которые сделали свои собственные декодеры DCF77. Без их работы я бы не знал, с чего начать. Я закончил тем, что написал свой собственный код (используя кусочки их идей), чтобы я мог понять, что происходит ... Мой код далек от эффективного или продвинутого, но он действительно работает, и я знаю, что происходит. Интересные сайты:- Brett Oliver:http://home.btconnect.com/brettoliver1/ - Joop Tap:http://www.jooptap.nl - Thijs Ellenbaas:http://thijs.elenbaas.net/2012/04/ arduino-dcf77-radio-clock-Receiver-hardware-2 / - Матиас Дальхаймер:https://github.com/roddi/DCF77-Arduino/blob/master/DCF77Servoclock/DCF77.h - Википедия DCF77:https:// en .wikipedia.org / wiki / DCF77 - Еще больше информации о DCF77:http://www.picbasic.nl/indexes_uk.htm - Мой сайт Flickr:https://www.flickr.com/photos/edr1924/albums - Мой Github сайт:https://github.com/deruiter * /// ----------------------------------- -------------------------------------------------- --------------------- // Библиотеки // ------------------------ -------------------------------------------------- -------------------------------- // Arduino (новая) Библиотека времени .......... .......................... http://www.pjrc.com/teensy/td_libs_Time.html#include  // Включите эту строку, если используете Arduino Uno, Mega и т. Д. # Include  // базовую библиотеку DS1307 y, который возвращает время как time_t .......... http://www.pjrc.com/teensy/td_libs_DS1307RTC.html#include  // Maxim 7219 отображает библиотеку ..... .............................. http://playground.arduino.cc/Main/LEDMatrix// !!! ПРИМЕЧАНИЕ:вы должны использовать специальную версию библиотеки Ledcontrol.h, чтобы получить поддержку Common Anode // потому что микросхема Maxim обычно подходит только для обычных дисплеев CATHODE! #Include  // Библиотека интерфейса SPI .... ...................................... http://arduino.cc/en/Reference/ SPI # include  // OneWire позволяет получить доступ к 1-проводным устройствам производства Maxim / Dallas, // таким как DS18S20, DS18B20, DS1822 ................. ............. http://www.pjrc.com/teensy/td_libs_OneWire.html// Библиотека DallasTemperature может сделать всю эту работу за вас! ... http://milesburton.com/Dallas_Tempera_Control_Library#include  // ----------------------------- -------------------------------------------------- --------------------------- // Соединения выводов Arduino UNO в удобной для чтения таблице //// ввод - Rx - используется для программирования / связь с ПК // выход - Tx - используется для программирования / связи с ПК # define DCF77PIN 2 // вход - сигнал DCF от платы антенны. Контакт должен быть входом прерывания! #Define PIRDETECTORPIN 3 // вход - ИК-датчик:проверьте активность в комнате для активации дисплеев # define BUZZERSWITCHPIN 4 // вход - SWITCH - включить / выключить пьезозуммер DCF77 'beep' / ON =HIGH , OFF =LOW # определить ПЕРЕКЛЮЧАТЕЛЬ 5 // вход - SWITCH - включить / выключить ежечасный звук звонка / ON =HIGH, OFF =LOW # определить POWERSAVESWITCHPIN 6 // вход - SWITCH - включить / выключить функцию энергосбережения, чтобы отобразить всегда включен / ON =HIGH, OFF =LOW # определить TEMPSENSORPIN 8 // вход - датчик температуры Dallas One Wire DS18B20 # определить TEMPRESETPIN 9 // вход - PUSH BUTTON - сбросить минимальную / максимальную температуру памяти / HIGH =сбросить # определить MAXIMCCLD 10 // output - CS / LOAD - псевдо SPI-соединение с микросхемой Maxim 7219 - 7 сегментных дисплеев # define MAXIMCCCLK 11 // output - CLOCK - псевдо SPI-соединение с микросхемой Maxim 7219 - 7-сегментные дисплеи # define MAXIMCCDATA 12 // выход - DATA - псевдо SPI подключение к микросхеме Maxim 7219 - 7 сегментных дисплеев // !! Контакты с 22 по 53 должны использоваться только для светодиодов # define LED_SUNDAY 22 // output - LED - Sunday #define LED_MONDAY 23 // output - LED - Monday #define LED_TUESDAY 24 // output - LED - Tuesday # define LED_WEDNESDAY 25 // output - LED - Wednesday #define LED_THURSDAY 26 // output - LED - Thursday # define LED_FRIDAY 27 // output - LED - Friday # define LED_SATURDAY 28 // output - LED - Saturday # define LED_CEST 29 // output - LED - Summertime CEST #define LED_CET 30 // вывод - LED - Wintertime CET # define LED_LEAPYEAR 31 // вывод - LED - Високосный год # define LED_RTCERROR 32 // вывод - LED - проблема чтения данных RTC (разряженная батарея / соединение) #define LED_RTCSYNC 33 // output - LED - Горит, когда RTC успешно синхронизирован с временем DCF # define LED_TEMP 34 // output - LED - отображается температура # define LED_OPTION1 35 // output - LED - отображаются дополнительные данные 1 # define LED_OPTION2 36 // output - LED - отображаются дополнительные 2 данных # define LED_ERRORPT 37 // output - LED - DCF Period Time error # define LED_ ERRORPW 38 // выход - светодиод - ошибка ширины периода DCF # define LED_BUFFERFULL 39 // выход - светодиод - индикатор заполнения буфера, затем данные будут проанализированы # define LED_MINUTEMARKER 40 // выход - светодиод - конец потока данных DCF обнаружен до буфера заполнено, данные повреждены #define LED_BUFFEROVERFLOW 41 // выход - светодиод - за одну минуту получено больше данных, чем ожидалось из-за плохого сигнала #define LED_DCFSTATUS 42 // выход - светодиод - горит, когда у нас есть хорошие данные DCF #define LED_POWERSAVE 43 / / output - LED - режим энергосбережения активирован, некоторые дисплеи выключены # define LED_PARITY1PASS 44 // выход - LED - бит четности 1 в норме # define LED_PARITY1FAIL 45 // выход - LED - четность 1 бит FAILED # define LED_PARITY2PASS 46 // output - LED - Бит четности 2 в норме # define LED_PARITY2FAIL 47 // выход - LED - бит четности 2 FAILED # define LED_PARITY3PASS 48 // выход - LED - бит четности 3 в норме # define LED_PARITY3FAIL 49 // выход - LED - Parity 3 bit FAILED # define LED_PIRMOTION 50 // output - LED - Горит, когда PIR обнаруживает движение / / Аналоговые контакты # define BUZZER A7 // выход - Пьезозуммер для DCF77 'beep' (к '+' зуммера) #define SPEAKERVOLPIN A6 // выход - Громкость звуковой платы - LOW =громкость на одну ступень ниже. SPEAKERVOLUME определяет, сколько раз этот выход активируется после включения питания # define CHIMEPIN A5 // output - Chime Activate - OUTPUT LOW =Активировать звуковой сигнал на Adafruit Soundboard FX // ИСПОЛЬЗУЕТСЯ для DS1307 RTC // I2C DATA - подключиться к плате часов реального времени / / ИСПОЛЬЗУЕТСЯ для DS1307 RTC // ЧАСЫ I2C - подключение к плате часов реального времени // -------------------------------- -------------------------------------------------- ------------------------ // Инициализация DS18B20 // -------------------- -------------------------------------------------- ------------------------------------ OneWire ds (TEMPSENSORPIN); // определяем экземпляр DS Onewire // ------------------------------------------ -------------------------------------------------- -------------- // Инициализация матричного дисплея Maxim 7219 // --------------------------- -------------------------------------------------- ----------------------------- / * clearDisplay (int addr) .............. ............................... очищает выбранный дисплей MaximCC.shutdown (int addr, boolean) ...... .......................... выводить MAX72XX из режима энергосбережения (true =спящий режим, false =пробуждение) MaximCC.setIntensity (int addr , значение) .............................. установите среднюю яркость светодиодов (0 =мин - 15 =макс) MaximCC .setLed (int addr, int row, int col, логическое состояние) .......... включить светодиод в строке, столбце. помните, что индексы начинаются с 0! MaximCC.setRow (int addr, int row, byte value) ...................... эта функция принимает 3 аргумента. пример:MaximCC.setRow (0,2, B10110000); MaximCC.setColumn (int addr, int col, byte value) ................... эта функция принимает 3 аргумента. пример:MaximCC.setColumn (0,5, B00001111); MaximCC.setDigit (int addr, int digit, byte value, boolean dp) ...... эта функция принимает аргумент типа byte и печатает соответствующую цифру в указанном столбце. Диапазон допустимых значений составляет от 0 до 15. Все значения между 0..9 печатаются как цифры, значения между 10..15 печатаются как их шестнадцатеричный эквивалент MaximCC.setChar (int addr, int digit, char value, boolean dp) ....... отобразит:0 1 2 3 4 5 6 7 8 9 ABCDEFHLP; -. , _ <ПРОБЕЛ> (пробел или пробел) POWERSAVESWITCHPIN ***** Пожалуйста, установите количество имеющихся у вас устройств ***** Но максимальное значение по умолчанию 8 MAX72XX также будет работать. LedConrol (DATAIN, CLOCK, CS / LOAD, КОЛИЧЕСТВО МАКСИМАЛЬНЫХ ЧИПОВ) * /// lc для Maxim отображаетLedControl MaximCC =LedControl (MAXIMCCDATA, MAXIMCCCLK, MAXIMCCLD, 7, false); // Определяем пины для Maxim 72xx и сколько 72xx мы используем // ----------------------------------- -------------------------------------------------- --------------------- // Пользовательские настройки, определения переменных и массивов // ------------------ -------------------------------------------------- -------------------------------------- // Значение ниже не является ПИН-кодом, а значение, чтобы установить, сколько раз будет активирован вход «Уменьшить громкость» на звуковой плате // чтобы можно было при желании уменьшить громкость звуковой платы после включения питания. # define SPEAKERVOLUME 12 // Выберите, хотите ли вы, чтобы проверка всех светодиодов и дисплеев после запуска // '1' =Да, '0' =Нет # define PERFORM_LED_TEST 1 // Задержка между каждым 7-сегментным отображением в мс # define LEDTEST_DELAY_DISPLAYS 600 // Задержка между каждым светодиодом в светодиодном кольце и другие светодиоды в мс # define LEDTEST_DELAY_LED_RING 20 // Выберите, хотите ли вы настроить датчик температуры DS18B20 ОДИН РАЗ на самое высокое разрешение. // это необходимо после использования датчика для пихты й раз. После запуска программного обеспечения // с этим параметром ON один раз выключите его. // '1' =ON, '0' =OFF # определить CONFIGURE_DS18B20 0 // POWERSAVE TIME - ОБЯЗАТЕЛЬНЫЕ значения! //// для определения дня и ночное время. Это используется для отображения времени включения и выключения энергосбережения // И для определения, будет ли включен звонок (в дневное время) .//// ТОЛЬКО дисплеи отключаются во время энергосбережения, часы остаются полностью активными. / ЧТОБЫ ОТКЛЮЧИТЬ отключение питания дисплея в любое время, просто установите переключатель энергосбережения в положение ВЫКЛ. //// Переключатель энергосбережения ВКЛ:дисплеи будут выключены в установленное ночное время // И если функция POWERSAVE_BY_PIR если активирована и есть нет // движения для установленного PIR_DELAY_TIME .// Переключатель режима энергосбережения ВЫКЛ:отображается всегда, звонок только в дневное время. или 8 вечера ... # define POWERSAVINGOFFTIME 9 // дисплеи активированы # define POWERSAVINGONTIME 22 // дисплеи выключены // Пользовательская опция:активировать дисплеи только когда в комнате есть активность // '1' =ON, '0 '=OFF # define POWERSAVE_BY_PIR 1 // задержка в МИНУТАХ для ожидания после отсутствия обнаружения перед отключением дисплеев # define PIR_DELAY_TIME 30 // Пользовательская опция для сброса минимальной температуры / максимальный объем памяти в полночь // '1' =сброс в полночь, '0' =только ручной сброс # определить TEMPRESET_MIDNIGHT 1 // ---------------------- -------------------------------------------------- ------- // определение дополнительных параметров # define DS1307_I2C_ADDRESS 0x68 // определение адреса RTC I2C # define DCF_INTERRUPT 0 // номер прерывания, связанного с выводом // определение номера дисплея Maxim 7219, последовательность подключения // первый Maxim 7219 в подключение daisychain должно быть 0, затем 1 и т.д. / определение уровней яркости дисплея # определить BrightnessLedRingOuter 1 # определить BrightnessLedRingInner 1 # определить BrightnessDisplayTime 1 # определить BrightnessDisplayDate 7 # определить BrightnessDisplayTempWeek 15 # определить BrightnessDisplayPeriodPulse 2 # определить BrightnessDisplayBufferBitError 15 // Pulse tatic unsigned long trailingEdge =0; unsigned long previousLeadingEdge =0; // используется в  volatile unsigned int DCFSignalState =0; // переменные прерывания ВСЕГДА нуждаются в квалификаторе volatile !! // используется в 
 int previousSecond =0; unsigned int previousSignalState =0; // Буферы и индикаторы DCFstatic int DCFbitBuffer [59]; // здесь сохраняются полученные DCF-битыconst int bitValue [] ={1, 2, 4, 8, 10, 20, 40, 80}; // это десятичные значения полученных DCF-битов // только после запуска в новую минуту, отображать полученные биты на внутреннем светодиоде ringboolean MinuteMarkerFlag =false; int bufferPosition =0; int previousMinute =0; int previousHour =0; // переменные чтобы проверить, являются ли биты DCF valdbool dcfValidSignal =false; int dcfP1counter =0; int dcfP2counter =0; int dcfP3counter =0; int dcfParityCheckP1 =0; int dcfParityCheckP2 =0; int dcfParity =0; inint dcfMinute =0; int dcfHour =0; int dcfDay =0; int dcfWeekDay =0; int dcfMonth =0; int dcfYear =0; int dcfDST =0; int leapYear =0; // переменные, используемые для хранения значений номера недели и дня dayNumber; int weekNumber; // переменная счетчика ошибок int errorCounter =0; логическая ошибка; int maxTemp =0; int minTemp =0; int lowByte =0; int hi ghByte =0; float tempReading =0; int tempCelsius =0; boolean tempResetButton =false; // Переменные детектора PIR int pirActivity =0; int pirDisplaysState =1; unsigned int pirTimer =0; unsigned long previousTimePIR =0; // ==============================================================================// НАСТРОЙКА // ==============================================================================void setup () {// инициализировать последовательную связь Serial.begin (9600); // инициализировать PIN-соединения pinMode (DCF77PIN, INPUT); pinMode (TEMPRESETPIN, INPUT); pinMode (BUZZERSWITCHPIN, ВХОД); pinMode (ПЕРЕКЛЮЧАТЕЛЬ, ВХОД); pinMode (POWERSAVESWITCHPIN, ВХОД); pinMode (PIRDETECTORPIN, INPUT); pinMode (ШИМПИН, ВЫХОД); pinMode (SPEAKERVOLPIN, ВЫХОД); // инициализируем выводы 22-50 светодиодов для (int i1 =22; i1 <=50; i1 ++) {pinMode (i1, OUTPUT); } // Инициализируем переменные, светодиодные индикаторы и светодиоды initialize (); // Инициализируем импульсное прерывание DCF77 на выводе DCF_INTERRUPT, ищем изменение сигнала, // чтобы импульсы нарастающего или спадающего фронта запускали обработчик прерывания и // выполняли функцию int0handler. attachInterrupt (DCF_INTERRUPT, int0handler, ИЗМЕНИТЬ); // Инициализируем RTC и устанавливаем как SyncProvider. // Позже RTC будет синхронизирован с DCF time setSyncProvider (RTC.get); // функция для получения времени от RTC // проверяем, установил ли RTC системное время if (timeStatus ()! =timeSet) {// Невозможно синхронизировать с RTC - активируйте RTCError LED digitalWrite (LED_RTCERROR, HIGH); } else {// RTC установил системное время - затемнить RTCError LED digitalWrite (LED_RTCERROR, LOW); } // После включения установите громкость динамика Adafruit Audio Board // инициализируйте оба вывода на НИЗКИЙ, что является выходным состоянием по умолчанию digitalWrite (SPEAKERVOLPIN, LOW); digitalWrite (CHIMEPIN, LOW); // уменьшаем громкость звуковой платы по умолчанию с помощью шагов 'SPEAKERVOLUME' для (int i =0; i <=SPEAKERVOLUME; i ++) {digitalWrite (SPEAKERVOLPIN, HIGH); задержка (100); digitalWrite (SPEAKERVOLPIN, LOW); задержка (100); } // Следующая функция должна запускаться только один раз. // Используется для настройки температурного разрешения датчика DS18B20 if (CONFIGURE_DS18B20 ==1) {configureDS18B20 (); } // использовать в тестовых целях и / или установить время RTC вручную // setTime (23, 59, 40, 31, 12, 13); // RTC.set (now ()); // Запросить преобразование температуры calculateTemp (); // проверяем, нужен ли тест светодиодов if (PERFORM_LED_TEST ==1) {// проводим тест светодиодов ledTest (); } else {// если тест светодиодов не выполняется, нам нужно немного подождать, пока датчик DS18B20 не будет готов к работе delay (750); } // Теперь получаем температуру от датчика и отображаем ее displayTemp (); // активируем отображение счетчика ошибок после проверки светодиодов ledDisplay (DisplayBufferBitError, "R", 0);} // ==============================================================================// ЦИКЛ // ================================================================================void loop () {// сначала проверяем, изменилось ли направление импульса (нарастание или падение) // иначе мы бы продолжали вычислять тот же импульс if (DCFSignalState! =previousSignalState) {// состояние "сброса" переменной previousSignalState =DCFSignalState; // оценка входящего импульса scanSignal (); } // проверяем, изменены ли переключатели, и действуем в соответствии с этим checkSwitches (); // проверка движения PIR checkPIR (); // выполняем задачи, которые должны выполняться только раз в секунду, минуту или час // --------------------------------- ------------------------------------------- tasksEverySecond (); tasksEveryMinute (); tasksEveryHour ();} // ================================================================================================================//// Имя функции:processDcfBit // вызывается из: //// Цель:оценивает сигнал по мере его получения. Определяет, получили ли мы «1» или «0» // и выполняем проверки, чтобы увидеть, находится ли время импульса в установленных пределах // Параметры:нет // Возвращаемое значение:нет //// ================================================================================================================/ * ширина импульса ширина импульса | - - | | - - | | ----- Маркер КОНЕЦ МИНУТ:2000 мс ----- | ___ _______ ___ ___ _______ | 0 | | 1 | | 0 | | 0 | | 1 | | | | | | | | | | | | | | | | | | | | | ______ | | _______________ | | ___________ | | ___________________________________ | | _______________ | | __ _ _ _ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 1000 2100 2000 2200 3000 3100 NO PULSE 5000 5100 6000 6200 <<пример значения millis () =индикация конца минуты ^ ^ ^ ^ ^ DCFbit # 56 DCFbit # 57 DCFbit # 58 DCFbit # 0 DCFbit # 1 и т. Д. <<Получен бит DCF ^ ^ ^ предыдущий передний задний край переднего фронта ^ ^ flanktime (возрастающий или спадающий) * / void scanSignal () {// ---- -------------------------------------------------- -------------- // Check for Rising-Edge signal and perform checks //----------------------- --------------------------------------------- if (DCFSignalState ==1) { // store Rising-Edge Time to check later if the time between two pulses is valid leadingEdge =millis(); // not much to do now so exit. возвращение; } //-------------------------------------------------------------------- // Check for Falling-Edge signal and perform checks //-------------------------------------------------------------------- if (DCFSignalState ==0) { // store Trailing-Edge Time to check later if the Pulse Width is valid trailingEdge =millis(); // display period width time on "L"eft side of the 8 digit Maxim 72xx LED display ledDisplay(DisplayPeriodPulse, "L", (leadingEdge - previousLeadingEdge)); // display pulse width time on the "R"ight side of the 8 digit Maxim 72xx LED display ledDisplay(DisplayPeriodPulse, "R", (trailingEdge - leadingEdge)); //-------------------------------------------------------------------------------- // Check PERIOD TIME //-------------------------------------------------------------------------------- // If this flank UP is detected quickly after previous flank UP this is an incorrect // Period Time (should be 1000ms -or 2000ms after second 58-) that we shall reject if ((leadingEdge - previousLeadingEdge) <900) { // rPW - ERROR:Periode Time (rising flank to rising flank) time is too short -> REJECTED error(LED_ERRORPW); errorCondition =true; } //-------------------------------------------------------------------------------- // CHECK PULSE TIME //-------------------------------------------------------------------------------- // If the detected pulse is too short it will be an incorrect pulse that we shall reject // should be 100 and 200 ms ideally if (((trailingEdge - leadingEdge) <70) || ((trailingEdge - leadingEdge)> 230)) { //rPT - ERROR:Pulse Width too short or too long -> REJECTED error(LED_ERRORPT); errorCondition =true; } // if we had an error return and start over if (errorCondition ==true) { errorCondition =false; // although we have an error, store current rising edge time to compare at the next Rising-Edge. previousLeadingEdge =leadingEdge; возвращение; } //-------------------------------------------------------------------- // no errors found so now we can continue //-------------------------------------------------------------------- // first we turn any error Led's OFF digitalWrite(LED_ERRORPW, LOW); digitalWrite(LED_ERRORPT, LOW); digitalWrite(LED_BUFFERFULL, LOW); // previous BF digitalWrite(LED_BUFFEROVERFLOW, LOW); // previous EoB digitalWrite(LED_MINUTEMARKER, LOW); // previous EoM // END OF MINUTE check, looking for a gap of approx. 2000ms if (leadingEdge - previousLeadingEdge> 1900 &&leadingEdge - previousLeadingEdge <2100) { // end of minute detected:finalizeBuffer(); } // refresh previousLeadingEdge time with the new leading edge time previousLeadingEdge =leadingEdge; //-------------------------------------------------------------------------------- // process DCF bits //-------------------------------------------------------------------------------- // distinguish between long and short pulses if (trailingEdge - leadingEdge <170) { // call processDcfBit function and sent it the value '0' processDcfBit(0); // if switch is HIGH, the DCF pulses are audible if (dcf77SoundSwitch ==1) buzzer(100); } else { // call processDcfBit function and sent it the value '1' processDcfBit(1); // if switch is HIGH, the DCF pulses are audible if (dcf77SoundSwitch ==1) buzzer(200); } } // if (DCFSignalState ==0)} // void scanSignal();//================================================================================================================//// Function name :processDcfBit// called from ://// Purpose :after reception of one good DCF bit, do some checks and save it in the DCFbitBuffer array// Parameters :none// Return value :none////================================================================================================================void processDcfBit(int dcfBit){ //-------------------------------------------------------------------- // display values on the 7 segment displays //-------------------------------------------------------------------- // display bufferPosition, digits 7,6 MaximCC.setChar(DisplayBufferBitError, 7, bufferPosition / 10, false); MaximCC.setChar(DisplayBufferBitError, 6, bufferPosition % 10, false); // display received DCFbit, digit 4 MaximCC.setChar(DisplayBufferBitError, 4, dcfBit, false); //-------------------------------------------------------------------- // display incoming DCF bits on inner LED ring //-------------------------------------------------------------------- // only if we have valid DCF data or after an Minute Mark (EoM) signal // activate the inner LED ring and diplay incoming data if (dcfValidSignal ==true || MinuteMarkerFlag ==true) { // display received bits on inner LED ring MaximCC.setLed(LedRingInner, bufferPosition / 8, bufferPosition % 8, dcfBit); } //-------------------------------------------------------------------- // // Fill DCFbitBuffer array with DCFbit //-------------------------------------------------------------------- DCFbitBuffer[bufferPosition] =dcfBit; //-------------------------------------------------------------------- // Parity check //-------------------------------------------------------------------- // DURING reception of the DCF bits, calculate and display the results of the DCF parity check. // // There is a Parity bit for the minutes, the hours and for the date. // DCF77 works with EVEN parity, this works as follows:// The hours for example have 6 bits plus a paritybit. The bits with value 1 are add up including the paritybit, // the result must be an even number. If there is a bit wrong received, a 0 is as 1, or a 1 is as 0 received, // then the result is uneven. source:http://www.picbasic.nl/frameload_uk.htm?http://www.picbasic.nl/info_dcf77_uk.htm if (bufferPosition ==0) { // reset the parity LED's digitalWrite(LED_PARITY1PASS, LOW); digitalWrite(LED_PARITY1FAIL, LOW); digitalWrite(LED_PARITY2PASS, LOW); digitalWrite(LED_PARITY2FAIL, LOW); digitalWrite(LED_PARITY3PASS, LOW); digitalWrite(LED_PARITY3FAIL, LOW); // reset variables dcfP1counter =0; dcfP2counter =0; dcfP3counter =0; dcfParityCheckP1 =0; dcfParityCheckP2 =0; dcfParityCheckP3 =0; } // ---------------------------------------- // First parity check:minute bits // ---------------------------------------- if (bufferPosition ==28) { for (int i =21; i <=27; i++) { // count the number of bits with the value '1' dcfP1counter +=DCFbitBuffer[i]; } // perform P1 parity check. Parity is OK if the sum is an EVEN value if ((DCFbitBuffer[28] + dcfP1counter) % 2 ==0) { // Parity1 PASS LED ON digitalWrite(LED_PARITY1PASS, HIGH); // Parity P1 PASS dcfParityCheckP1 =1; } else { // Parity1 FAIL LED ON digitalWrite(LED_PARITY1FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } } // ---------------------------------------- // Second parity check:hour bits // ---------------------------------------- if (bufferPosition ==35) { for (int i =29; i <=34; i++) { dcfP2counter +=DCFbitBuffer[i]; } // perform P2 parity check. Parity is OK if the sum is an EVEN value if ((DCFbitBuffer[35] + dcfP2counter) % 2 ==0) { // Parity2 PASS LED ON digitalWrite(LED_PARITY2PASS, HIGH); // Parity P2 PASS dcfParityCheckP2 =1; } else { // Parity2 FAIL LED ON digitalWrite(LED_PARITY2FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } } // ---------------------------------------- // Third parity check:date bits // ---------------------------------------- if (bufferPosition ==58) { for (int i =36; i <=57; i++) { dcfP3counter +=DCFbitBuffer[i]; } // perform P3 parity check. Parity is OK if the sum is an EVEN value (DCFbitBuffer[58] + dcfP3counter) % 2 ==0 ? dcfParityCheckP3 =1 :dcfParityCheckP3 =0; // Turn Parity2 'PASS' or 'FAIL' LED ON if (dcfParityCheckP3 ==1) { // Parity2 PASS LED ON digitalWrite(LED_PARITY3PASS, HIGH); // Parity P3 PASS dcfParityCheckP3 =1; } else { // Parity2 FAIL LED ON digitalWrite(LED_PARITY3FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } // ---------------------------------------- // finally, check all Parity bits // ---------------------------------------- dcfParityCheckP1 + dcfParityCheckP2 + dcfParityCheckP3 ==3 ? dcfValidSignal =true :dcfValidSignal =false; } //-------------------------------------------------------------------- // before continuing with the next bit, increment counter //-------------------------------------------------------------------- bufferPosition++; //-------------------------------------------------------------------- // check if we have not received too many pulses? //-------------------------------------------------------------------- if (bufferPosition> 59) { // Buffer Overflow ERROR - we have received more pulses before reaching // the 2 second 'gap' signalling the end of the minute. //This error may be due to a noisy signal giving addition peaks/dcfBits // So clear both DCFbit displays and start again. // Reset buffer counter bufferPosition =0; // clear inner LED ring MaximCC.clearDisplay(LedRingInner); // turn Buffer Overflow Error LED ON error(LED_BUFFEROVERFLOW); // exit return; } //-------------------------------------------------------------------- // everything OK so we wait for next incoming DCFbit //--------------------------------------------------------------------}//================================================================================================================//// Function name :finalizeBuffer// called from ://// Purpose :Process the succesfully received DCF data of one minute// Parameters :none// Return value :none////================================================================================================================void finalizeBuffer(void){ //-------------------------------------------------------------------- // We are here because of the detected 2 second 'gap'. // Now check if it correspondends with the buffer counter // 'bufferPosition' which should be value 59 //-------------------------------------------------------------------- if (bufferPosition ==59 &&dcfValidSignal ==true) { // bufferPosition ==59 so turn Buffer Full LED ON digitalWrite(LED_BUFFERFULL, HIGH); // Turn DCF OK LED ON digitalWrite(LED_DCFSTATUS, HIGH); // Reset inner LED ring (incoming time information) MaximCC.clearDisplay(LedRingInner); // copy 'contents' of inner LED ring to the outer LED ring (current time information) for (int i =0; i <59; i++) { MaximCC.setLed(LedRingOuter, i / 8, i % 8, DCFbitBuffer[i]); } // process buffer and extract data sync the time with the RTC decodeBufferContents(); // set Arduino time and after that set RTC time setTime(dcfHour, dcfMinute, 0, dcfDay, dcfMonth, dcfYear); RTC.set(now()); // activate Synced LED digitalWrite(LED_RTCSYNC, HIGH); // Reset running buffer bufferPosition =0; // Reset DCFbitBuffer array, positions 0-58 (=59 bits) for (int i =0; i <59; i++) { DCFbitBuffer[i] =0; } // reset flag MinuteMarkerFlag =false; } // if (bufferPosition ==59) //-------------------------------------------------------------------- // The buffer is not yet filled although the 2 second 'gap' was detected. // Can be result of a noisy signal, starting in middle of receiving data etc. // Turn 'Minute Mark' LED ON //-------------------------------------------------------------------- else { digitalWrite(LED_MINUTEMARKER, HIGH); // Clear displays MaximCC.clearDisplay(LedRingInner); MaximCC.clearDisplay(LedRingOuter); // Reset running buffer and start afresh. Now we are in sync with the incoming data bufferPosition =0; // Reset DCFbitBuffer array, positions 0-58 (=59 bits) for (int i =0; i <59; i++) { DCFbitBuffer[i] =0; } // set flag so we can display incoming pulsed on the inner LED ring. MinuteMarkerFlag =true; }}//================================================================================================================//// Function name :decodeBufferContents// called from ://// Purpose :Evaluates the information stored in the buffer.// This is where the DCF77 signal is decoded to time and date information// Parameters :none// Return value :none////================================================================================================================void decodeBufferContents(void){ // Buffer is full and ready to be decoded dcfMinute =bitDecode(21, 27); dcfHour =bitDecode(29, 34); dcfDay =bitDecode(36, 41); dcfWeekDay =bitDecode(42, 44); dcfMonth =bitDecode(45, 49); dcfYear =bitDecode(50, 57); //call function to calculate day of year and weeknumber dayWeekNumber(dcfYear, dcfMonth, dcfDay, dcfWeekDay); // Get value of Summertime DCFbit. '1' =Summertime, '0' =wintertime dcfDST =bitDecode(17, 17); // determine Leap Year leapYear =calculateLeapYear(dcfYear);}//================================================================================================================//// bitDecode//// called from //================================================================================================================int bitDecode(int bitStart, int bitEnd){ // reset 'bitValue-array' counter int i =0; int value =0;...This file has been truncated, please download it to see its full contents.
Superfilter sketchArduino
//// This is the Superfilter sketch I use with the DCF Analyzer/Clock 2.0 // Udo Klein did an amazing job with this filter//// Erik de Ruiter/* Arduino Uno pin connections I used for the DCF Analyzer Clock DCF input ................. A5 (19) =dcf77_sample_pin Output DCF Filtered ....... 12 =dcf77_filtered_pin Output DCF Semi Synthesized A2 (16) =dcf77_semi_synthesized_pin Output DCF Synthesized .... 6 =dcf77_synthesized_pin LED DCF output filtered ... A4 (18) =dcf77_monitor_pin =DCF Monitor LED LED 1 Hz pulse ............ 10 =dcf77_second_pulse_pin =Filter Locked LED LED DCF OK ................ 13 =dcf77_signal_good_indicator_pin =Signal Quality LED LED Difference Filtered ... 7 =dcf77_filter_diff_pin \ LED Difference Semi Synth.. A0 =dcf77_semi_synthesized_diff_pin -> =Signal Difference LED LED Difference Synthesized 4 =dcf77_synthesized_diff_pin /*/ //// www.blinkenlight.net//// Copyright 2014, 2015 Udo Klein//// This program is free software:you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see http://www.gnu.org/licenses/#include /*const uint8_t pon_pin =51; // connect pon to ground !!!const uint8_t data_pin =19;const uint8_t gnd_pin =51;const uint8_t vcc_pin =49;*/const uint8_t dcf77_analog_samples =false;const uint8_t dcf77_analog_sample_pin =5;const uint8_t dcf77_sample_pin =19; // A5const uint8_t dcf77_inverted_samples =0;#if defined(__AVR__)#define ledpin(led) (led)#else#define ledpin(led) (led<14? led:led+(54-14))#endifconst uint8_t dcf77_monitor_pin =ledpin(18); // A4const bool provide_filtered_output =true;const uint8_t dcf77_filtered_pin =ledpin(12);const uint8_t dcf77_inverted_filtered_pin =ledpin(11);const uint8_t dcf77_filter_diff_pin =ledpin(7);const bool provide_semi_synthesized_output =true;const uint8_t dcf77_semi_synthesized_pin =ledpin(16);const uint8_t dcf77_inverted_semi_synthesized_pin =ledpin(15);const uint8_t dcf77_semi_synthesized_diff_pin =ledpin(14);const bool provide_synthesized_output =true;const uint8_t dcf77_synthesized_pin =ledpin(6);const uint8_t dcf77_inverted_synthesized_pin =ledpin(5);const uint8_t dcf77_synthesized_diff_pin =ledpin(4);const uint8_t dcf77_second_pulse_pin =ledpin(10);const uint8_t dcf77_signal_good_indicator_pin =ledpin(13);volatile uint16_t ms_counter =0;volatile Internal::DCF77::tick_t tick =Internal::DCF77::undefined;template void set_output(uint8_t clock_state, uint8_t sampled_d ata, uint8_t synthesized_signal){ if (enable) { const uint8_t filtered_output =clock_state  200) :digitalRead(dcf77_sample_pin)); #else dcf77_inverted_samples ^ digitalRead(dcf77_sample_pin); #endif digitalWrite(dcf77_monitor_pin, sampled_data); digitalWrite(dcf77_second_pulse_pin, ms_counter <500 &&clock_state>=Clock::locked); const uint8_t synthesized_signal =tick ==Internal::DCF77::long_tick ? ms_counter <200:tick ==Internal::DCF77::short_tick ? ms_counter <100:tick ==Internal::DCF77::sync_mark ? 0:// tick ==DCF77::undefined --> default handling // allow signal to pass for the first 200ms of each second (ms_counter <=200 &&sampled_data) || // if the clock has valid time data then undefined ticks // are data bits --> first 100ms of signal must be high ms_counter <100; set_output (clock_state, sampled_data, synthesized_signal); set_output (clock_state, sampled_data, synthesized_signal); set_output (clock_state, sampled_data, synthesized_signal); ms_counter+=(ms_counter <1000); scope_1.process_one_sample(sampled_data); scope_2.process_one_sample(digitalRead(dcf77_synthesized_pin)); return sampled_data;}void output_handler(const Clock::time_t &decoded_time) { // reset ms_counter for 1 Hz ticks ms_counter =0; // status indicator --> always on if signal is good // blink 3s on 1s off if signal is poor // blink 1s on 3s off if signal is very poor // always off if signal is bad const uint8_t clock_state =DCF77_Clock::get_clock_state(); digitalWrite(dcf77_signal_good_indicator_pin, clock_state>=Clock::locked ? 1:clock_state ==Clock::unlocked? (decoded_time.second.digit.lo &0x03) !=0:clock_state ==Clock::free ? (decoded_time.second.digit.lo &0x03) ==0:0); // compute output for signal synthesis Internal::DCF77_Encoder now; now.second =BCD::bcd_to_int(decoded_time.second); now.minute =decoded_time.minute; now.hour =decoded_time.hour; now.weekday =decoded_time.weekday; now.day =decoded_time.day; now.month =decoded_time.month; now.year =decoded_time.year; now.uses_summertime =decoded_time.uses_summertime; now.leap_second_scheduled =decoded_time.leap_second_scheduled; now.timezone_change_scheduled =decoded_time.timezone_change_scheduled; now.undefined_minute_output =false; now.undefined_uses_summertime_output =false; now.undefined_abnormal_transmitter_operation_output =false; now.undefined_timezone_change_scheduled_output =false; now.advance_minute(); tick =now.get_current_signal();}void setup_serial() { Serial.begin(115200);}void output_splash_screen() { Serial.println(); Serial.println(F("DCF77 Superfilter 3.0")); Serial.println(F("(c) 2015 Udo Klein")); Serial.println(F("www.blinkenlight.net")); Serial.println (); Serial.print(F("Sample Pin:")); Serial.println(dcf77_sample_pin); Serial.print(F("Inverted Mode:")); Serial.println(dcf77_inverted_samples); #if defined(__AVR__) Serial.print(F("Analog Mode:")); Serial.println(dcf77_analog_samples); #endif Serial.print(F("Monitor Pin:")); Serial.println(dcf77_monitor_pin); Serial.println (); if (provide_filtered_output) { Serial.println(F("Filtered Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_filtered_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_filter_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_filtered_pin); Serial.println (); } if (provide_semi_synthesized_output) { Serial.println(F("Semi Synthesized Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_semi_synthesized_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_semi_synthesized_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_semi_synthesized_pin); Serial.println (); } if (provide_synthesized_output) { Serial.println(F("Synthesized Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_synthesized_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_synthesized_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_synthesized_pin); Serial.println (); } Serial.print(F("Second Pulse Pin:")); Serial.println(dcf77_second_pulse_pin); Serial.print(F("Signal Good Pin:")); Serial.println(dcf77_signal_good_indicator_pin); Serial.println (); Serial.println (); Serial.println(F("Initializing...")); Serial.println();};void setup_pins() { if (provide_filtered_output) { pinMode(dcf77_filtered_pin, OUTPUT); pinMode(dcf77_filter_diff_pin, OUTPUT); pinMode(dcf77_inverted_filtered_pin, OUTPUT); } if (provide_semi_synthesized_output) { pinMode(dcf77_semi_synthesized_pin, OUTPUT); pinMode(dcf77_semi_synthesized_diff_pin, OUTPUT); pinMode(dcf77_inverted_semi_synthesized_pin, OUTPUT); } if (provide_synthesized_output) { pinMode(dcf77_synthesized_pin, OUTPUT); pinMode(dcf77_synthesized_diff_pin, OUTPUT); pinMode(dcf77_inverted_synthesized_pin, OUTPUT); } pinMode(dcf77_monitor_pin, OUTPUT); pinMode(dcf77_signal_good_indicator_pin, OUTPUT); pinMode(dcf77_second_pulse_pin, OUTPUT); pinMode(dcf77_sample_pin, INPUT); digitalWrite(dcf77_sample_pin, HIGH);}void setup_clock() { DCF77_Clock::setup(); DCF77_Clock::set_input_provider(sample_input_pin); DCF77_Clock::set_output_handler(output_handler);}void setup() { setup_serial(); output_splash_screen(); setup_pins(); setup_clock();/* pinMode(gnd_pin, OUTPUT); digitalWrite(gnd_pin, LOW); pinMode(pon_pin, OUTPUT); digitalWrite(pon_pin, LOW); pinMode(vcc_pin, OUTPUT); digitalWrite(vcc_pin, HIGH); */}void loop() { Clock::time_t now; DCF77_Clock::get_current_time(now); if (now.month.val> 0) { Serial.println(); Serial.print(F("Decoded time:")); DCF77_Clock::print(now); Serial.println (); } Serial.print(DCF77_Clock::get_clock_state()); Serial.print(' '); DCF77_Clock::debug(); scope_1.print(); scope_2.print();}

Изготовленные на заказ детали и корпуса

This is a PCB I made for the Time and Date displays Maxim_7219_LED_display_unit_for_Adafruit_0_56inch_7_segment_v1_1.zipThis is my PCB design for the very compact smaller 7 segment displays Maxim_7219_LED_display_unit_for_KingBright_7_segment_SC39_11SRWAv1_1.zipTicking sound and Chime sound, see text for explanation Grandfather_Clock_Sound_files.zip

Схема

DOWNLOAD to view details! dcf77-analyzer-clock-v2_1_jVZT5sqIwn.zip

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

  1. Часы с кукушкой
  2. Часы видения Arduino pov
  3. Самодельные простейшие часы Numitron IV9 с Arduino
  4. Простые настенные часы с использованием Adafruit 1/4 60 Ring Neopixel
  5. Простые часы со словами (Arduino)
  6. Часы Arduino с исламским временем молитв
  7. Arduino Spybot
  8. FlickMote
  9. Основные часы
  10. Простой будильник с DS1302 RTC