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

Многоликий ЖК-будильник

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

Arduino UNO
При использовании прилагаемой печатной платы используйте микропроцессор ATmega328 DIL, кристалл 16 МГц, конденсаторы 2x22pf, регулятор 7805, Конденсатор 100 мкФ 16 В, 3 конденсатора по 0,1 мкФ и конденсатор 1 мкФ.
× 1
Резистор 10 кОм
× 4
Резистор в сквозное отверстие, 470 Ом
× 1
Стандартный ЖК-экран Adafruit - 16x2, белый на синем
× 1
Зуммер
× 1
Конденсатор 10 мкФ
× 1
Часы реального времени (RTC)
DS1302 RTC
× 1
Кристалл 32,768 кГц
× 1
Батарея типа "таблетка" CR2032
+ держатель. При использовании печатной платы используйте батарею CR1220 и держатель
× 1
Переключатель наклона, инкапсулированный
Меркурийный переключатель
× 1
Подстроечный потенциометр, 10 кОм
× 1

Необходимые инструменты и машины

3D-принтер (общий)

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

IDE Arduino

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

Можно найти новую версию с 10 циферблатами здесь .


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

Особенности часов

  • Восемь различных стилей отображения
  • Установить время, текущую дату, дату рождения и будильник.
  • Ртутный переключатель для выключения будильника.
  • Управление подсветкой
  • Датчик температуры и влажности DHT21

Макетная версия

Сама электроника довольно проста.

После подключения загрузите скетч в вашу Arduino IDE и загрузите в Arduino UNO. (Не показано, DHT21 подключен к D9)

Использование часов

На часах есть три кнопки - НАСТРОЙКА, УВЕЛИЧЕНИЕ, УМЕНЬШЕНИЕ и переключатель НАКЛОН.

Когда подсветка выключена, нажатие любой кнопки включит подсветку. Если при включенной подсветке не нажимать ни одной кнопки, она выключится через 5 секунд. Пока включена подсветка, кнопки будут выполнять следующие задачи:

НАСТРОЙКА - Появится экран НАСТРОЙКИ. Символ правой угловой скобки - это курсор. Нажатие кнопок INCREMENT или DECREMENT увеличивает или уменьшает значение, на котором находится курсор, соответственно. При повторном нажатии кнопки SETUP курсор будет переключаться между часами, минутами, днем, месяцем, годом, днем ​​рождения, месяцем рождения, годом рождения, часами будильника, минутами будильника и обратно в режим ЧАСОВ.

ПРИРОСТ - Когда не на экранах SETUP, эта кнопка переключает между различными стилями часов.

ЗАЯВЛЕНИЕ - Когда не на экранах SETUP, эта кнопка включает или выключает будильник.

ПЕРЕКЛЮЧАТЕЛЬ НАКЛОНА - Когда срабатывает будильник, наклон часов или нажатие любой кнопки выключит будильник.

Изготовление полностью готовых часов

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

ПРИМЕЧАНИЕ. Поскольку ЖК-дисплей 1602 подключается к основной плате с помощью прямоугольного штыревого разъема, может быть очень сложно вставить плату и дисплей в корпус, когда они уже спаяны вместе. Наличие двусторонней платы со сквозными отверстиями позволит вам припаять дисплей к плате на месте.

Используя детали, которые у меня были в мастерской, Arduino UNO был заменен микросхемой ATMega328 DIL, кристаллом 16 МГц и двумя керамическими конденсаторами 22 пФ. Стабилизатор 5 В представляет собой тип 7805 TO-220 и конденсатор 100 мкФ 16 В для сглаживания. RTC - это DS1302 с часовым кристаллом 32,768 кГц. Динамик представляет собой пассивный зуммер, который изолирован по постоянному току с помощью конденсатора 10 мкФ 16 В. Конденсаторы 0,1 мкФ и 1 мкФ представляют собой монолитные керамические конденсаторы (расстояние между отверстиями 5 мм). Резисторы составляют 5% 1/8 Вт, или вы можете использовать 1/4 Вт, если хотите. Ртутный переключатель может быть любого размера. У меня был диаметр 5 мм, но поменьше будет достаточно. Три тактильные кнопки, установленные на задней части платы, имеют размер 6 мм x 6 мм и стержень 13 мм.

Корпус напечатан на 3D-принтере с толщиной слоя 0,2 мм и без опор. Просверлите отверстия для монтажа на печатной плате сверлом 2,5 мм и нарисуйте резьбу, используя метчик на 3 мм. Используйте винты M3 6 мм, чтобы закрепить плату на месте. Я также просверлил четыре монтажных отверстия на печатной плате до 4 мм, чтобы можно было выполнить любую регулировку, необходимую для предотвращения залипания кнопок на корпусе при закреплении платы.

Кредиты

Эти часы представляют собой смесь часов, созданных разными производителями на протяжении многих лет.

Основа этих часов - цифровые часы Arduino с функцией будильника (настраиваемая печатная плата). Я изменил футляр так, чтобы он был напечатан двумя частями, а не четырьмя.

  • Стандартный дизайн экрана от Михалиса Василакиса
  • Шрифт Dual Thick от Arduino World
  • Шрифт Dual Beveled от Arduino Forum
  • Шрифт Dual Trek от Кэрри Сундра.
  • Шрифт Dual Thin от Arduino World
  • Концепция Word от LAGSILVA
  • Биоритмовые часы Джона Брэднэма
  • Погодные часы от ARDUinoautoMOTIVE

Обновления

29.06.20

  - Исправлены орфографические ошибки в часах WORD 
- Добавлены #defines для управления подсветкой
- Увеличено время ожидания подсветки с 5 до 10 секунд

23.11.20

  - Добавлена ​​настройка даты рождения и хранилище EEPROM 
- Добавлен циферблат биоритмов
- Исправлено кодирование экрана настройки

Предполагается, что в зависимости от даты нашего рождения биоритмы могут определять взлеты и падения нашей жизни. Биоритмы состоят из трех циклов:23-дневного физического цикла, 28-дневного эмоционального цикла и 33-дневного интеллектуального цикла. На часах биоритма каждое состояние отображается в виде полосы.

Полоса показывает, что биоритм находится либо в положительном цикле (верхняя полоса), либо в отрицательном цикле (нижняя полоса). Длина полосы показывает, насколько она положительна или отрицательна в цикле.

12.06.20

  - Добавлена ​​поддержка DHT21 
- Добавлен циферблат термометра и влажности

Добавлен новый циферблат погодных часов. Он считывает датчик температуры и влажности DHT21, добавленный на заднюю часть корпуса. На печатной плате появился 3-контактный разъем для датчика DHT21.


Код

  • DigitalClockAlarmV7.ino
DigitalClockAlarmV7.ino C / C ++
 / * ЖК-будильник 1602 * от Джона Брэднэма ([email protected]) * * Дисплей 16x2:Настройка:Настройка будильника * + ---------------- + + - --------------- + + ---------------- + * | ЧЧ:ММ:СС | ЧЧ:ММ | |> ЧЧ:> ММ | | Установить будильник | * | ДД / ММ / ГГ | БУДИЛЬНИК | |> ДД /> ММ /> ГГГГ | |> ЧЧ:> ММ | * + ---------------- + + ---------------- + + ------------ ---- + * * 25.06.2020 * - В качестве базы кода взяли часы Михалиса Василакиса (https://www.instructables.com/id/Arduino-Digital-Clock-With-Alarm-Function-custom-P/ ) * - Изменено в соответствии с оборудованием - DS1302 RTC и подсветка ЖК-дисплея * - Добавлена ​​поддержка различных стилей отображения * - Стандартный дизайн экрана от Михалиса Василакиса * - Двойной толстый шрифт от Arduino World (https://www.hackster.io/thearduinoworld/ arduino-digital-clock-version-1-b1a328) * - шрифт Dual Bevelled от Arduino Forum (https://forum.arduino.cc/index.php/topic,8882.0.html) * - шрифт Dual Trek от Кэрри Сундра ( https://www.alpenglowindustries.com/blog/the-big-numbers-go-marching-2x2) * - шрифт Dual Thin от Arduino World (https://www.hackster.io/thearduinoworld/arduino-digital-clock -version-2-5bab65) * - Концепция Word от LAGSILVA (https://www.hackster.io/lagsilva/text-clock-bilingual-en-pt-with-arduino-881a6e) * 29/06/20 * - Исправлены орфографические ошибки в часах WORD * - Добавлено #defines в продолжение rol backlight * - Увеличен тайм-аут подсветки с 5 до 10 секунд * 22.11.20 * - Добавлена ​​настройка даты рождения и хранилище EEPROM * - Добавлен циферблат Biorhythm * - Очищено кодирование экрана настройки * xx / xx / 21 * - Добавлен DHT21 Поддержка * - Добавлен циферблат термометра и влажности * /// Библиотеки # include  #include  #include  #include  #include  # include  // раскомментируйте, если вы хотите, чтобы вариант с двойным толстым или тонким дисплеем отображал 12-часовой формат // # define DUAL_THICK_12HR // #define DUAL_THIN_12HR // раскомментируйте для управления подсветкой // # define NO_BACKLIGHT // # define BACKLIGHT_ALWAYS_ON # define BACKLIGHT_TIMEOUT 10000 // раскомментируйте тестовые графики биоритмов // # define TEST_BIO_GRAPHS # define LIGHT 2 // PD2 # define LCD_D7 3 // PD3 #define LCD_D6 4 // PD4 # define LCD_D5 5 // PD5 # define LCD_D4 6 // PD6 #define LCD_E 7 // PD7 # define LCD_RS 8 // PB0 #define BTN_SET A0 // PC0 # define BTN_ADJUST A1 // PC1 # define BTN_ALARM A2 // PC2 # define BTN_TILT A3 // PC3 #define SPEAKER 11 // PB3 # определить DHT 21 9 // PB1 # define RTC_CE 10 // PB2 # define RTC_IO 12 // PB4 # define RTC_SCLK 13 // PB5 // Подключения и константы LiquidCrystal lcd (LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7); DS1302RTC rtc ( RTC_CE, RTC_IO, RTC_SCLK); dht DHT; char daysOfTheWeek [7] [12] ={«Воскресенье», «Понедельник», «Вторник», «Среда», «Четверг», «Пятница», «Суббота»}; const int monthDays [12] ={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; длинный интервал =300; int melody [] ={600, 800, 1000,1200}; // Переменные int DD, MM, YY, H, M, S, temp, hum, set_state, adjust_state, alarm_state, AH, AM, shake_state, BY, BM, BD; int shakeTimes =0; int i =0; String sDD; String sMM; String sYY; String sH; String sM; String sS; String sBD; String sBM; String sBY; String aH ="12"; String aM =" 00 "; String sTMP; String sHUM; // String alarm =" "; long prevAlarmMillis =0; long prevDhtMillis =0; // логические флагиboolean setupScreen =false; boolean alarmON =false; boolean turnItOn =false; enum STYLE {STANDARD, DUAL_THICK, DUAL_BEVEL, DUAL_TREK, DUAL_THIN, WORD, BIO, THERMO}; СТИЛЬ currentStyle =СТАНДАРТ; enum SETUP {ЧАСЫ, TIME_HOUR, TIME_MIN, TIME_DAY, TIME_MONTH_MONTH_MONTH_, TIME_YEAR, ALMINTH}, НАСТРОЙКА; bool backlightOn =false; long backlightTimeout =0; byte customChar [8]; // --------------------- EEPROM --------- --------------------------------- # define EEPROM_AH 0 // Часы будильника # define EEPROM_AM 1 // Минуты будильника # определить EEPROM_AO 2 // Тревога Вкл. / Выкл. # Define EEPROM_CS 3 // Текущий стиль # define EEPROM_BY 4 // Год рождения #define EEPROM_BM 6 // Месяц рождения # define EEPROM_BD 7 // День рождения // --------- ------------ Часы со словом ------------------------------------ --String units [] ={"СОТНИ", "ОДИН", "ДВА", "ТРИ", "ЧЕТЫРЕ", "ПЯТЬ", "ШЕСТЬ", "СЕМЬ", "ВОСЕМЬ", "ДЕВЯТЬ"}; String teens [] ={"ДЕСЯТЬ", "ОДИННАДЦАТЬ", "ДВЕНАДЦАТЬ", "ТРИНАДЦАТЬ", "ЧЕТНАДЦАТЬ", "ПЯТНАДЦАТЬ", "ШЕСТНАДЦАТЬ", "СЕМНАДЦАТЬ", "ВОСЕМНАДЦАТЬ", "ДЕВЯТНАДЦАТЬ"}; Строковые десятки [] ={"", "", "ДВАДЦАТЬ", "ТРИДЦАТЬ", "СОРОК", "ПЯТЬДЕСЯТ"}; // ---------------------- Песочные часы анимация ---------------------------- # определить HOURGLASS_FRAMES 8 # определить HOURGLASS_CHAR 0 # определить FRAME_TIMEOUT 200; int nextFrame =0; long frameTimeout =0; песочные часы константного байта [HOURGLASS_FRAMES] [8] PROGMEM ={{B11111, B11111, B01010, B01010, B01010, B01010, B10001, B11111}, {B11111, B11011, B01110, B010101, B1011, B01110, B010101, B1011, B01110, B010101, B01011, B01110 {B11111, B10001, B01110, B01110, B01010, B01010, B10001, B11111}, {B11111, B10001, B01010, B01110, B01110 , B01010, B10001, B11111}, {B11111, B10001, B01010, B01010, B01110, B01110, B10001, B11111}, {B11111, B10001, B01010, B01010, B01010, B01110, B10111101, {1011110}, {B1011110}, { , B01010, B01010, B01110, B11011, B11111}, {B11111, B10001, B01010, B01010, B01010, B01010, B11111, B11111}, // {B11111, B10001, B01010, B01010}, B11011, B01010, B01010}, B11011, B01010}, B11011,; // ---------------------- Пользовательские символы будильника, часов и DHT ------------------ ---------- # определить BELL_CHAR 1 # определить CLOCK_CHAR 2 # определить THERMOMETER_CHAR 3 # определить DROPLET_CHAR 4const byte bell [8] PROGMEM ={0x4, 0xe, 0xe, 0xe, 0x1f, 0x0, 0x4}; const; byte clock [8] PROGMEM ={0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0}; константный байтовый термометр [8] PROGMEM ={0x4, 0xa, 0xa, 0xe, 0xe, 0x1f, 0x1f, 0xe}; const byte droplet [8] PROGMEM ={0x4, 0x4, 0xa, 0xa, 0x11, 0x11, 0x11, 0xe}; # определить DHT_UPDATE_INTERVAL 6000 // ------------------- --- BioRhythm Clock ---------------------------- // Пользовательские символьные константы (M - старший бит или символ верхней полосы r, L - младший бит или символ нижней полосы # define PHYSICAL_M 3 # define PHYSICAL_L 4 #define EMOTIONAL_M 5 # define EMOTIONAL_L 6 # define INTELLECTUAL_M 7 # define INTELLECTUAL_L 8 // --------------- ------- Толстый квадратный шрифт ---------------------------- # определить C0 3 # определить C1 4 # определить C2 5 #define C3 6const byte C_0 [8] PROGMEM ={0x1F, 0x1F, 0x1F, 0x00,0x00,0x00,0x00,0x00}; const byte C_1 [8] PROGMEM ={0x1F, 0x1F, 0x1F, 0x00,0x00,0x1F, 0x1F, 0x1F}; константный байт C_2 [8] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x1F, 0x1F, 0x1F}; константный байт C_3 [8] PROGMEM ={0x00,0x00,0x0E, 0x0A, 0x0A, 0x0E, 0x00,0x00}; const byte blockChar [11] [2] [3] ={{{255, C0, 255}, {255, C2, 255}}, // 0 {{C0, 255, 32} , {C2, 255, C2}}, // 1 {{C0, C0, 255}, {255, C1, C2}}, // 2 {{C1, C1, 255}, {C1, C1, 255} }, // 3 {{255, C2, 255}, {32, 32, 255}}, // 4 {{255, C1, C1}, {C2, C2, 255}}, // 5 {{255 , C0, C0}, {255, C1, 255}}, // 6 {{C0, C1, 255}, {32, C0, 255}}, // 7 {{255, C1, 255}, {255 , C1, 255}}, // 8 {{255, C1, 255}, {C2, C2, 255}}, // 9 {{32, 32, 32}, {32, 32, 32}}, // Пусто}; // ---------------------- Толстый шрифт со скосом -------------- -------------- # определить LT 0 # определить UB 1 # определить RT 2 # определить LL 3 # определить LB 4 # определить LR 5 # определить UMB 6 # определить LMB 7const byte _LT [8 ] PROGMEM ={B00111, B01111, B11111, B11111, B11111, B11111, B11111, B11111}; константный байт _UB [8] PROGMEM ={B11111, B11111, B11111, B00000, B00000, B00000, B00000, const _000}; [8] PROGMEM ={B11100, B11110, B11111, B11111, B11111, B11111, B11111, B11111}; константный байт _LL [8] PROGMEM ={B11111, B11111, B11111, B11111, B11111, B11111, const, B011}; байт _LB [8] PROGMEM ={B00000, B00000, B00000, B00000, B00000, B11111, B11111, B11111}; константный байт _LR [8] PROGMEM ={B11111, B11111, B11111, B11111, B11111, B1110111, B11111, B11111, B111; константный байт _UMB [8] PROGMEM ={B11111, B11111, B11111, B00000, B00000, B00000, B11111, B11111}; константный байт _LMB [8] PROGMEM ={B11111, B11111, B11111, B11111, B11111, B11111, B1111 B11111}; const byte bevelChar [11] [2] [3] ={{{LT, UB, RT}, {LL, LB, LR} }, // 0 {{UB, RT, 32}, {LB, LMB, LB}}, // 1 {{UMB, UMB, RT}, {LL, LB, LB}}, // 2 {{UMB , UMB, RT}, {LB, LB, LR}}, // 3 {{LL, LB, LMB}, {32, 32, LMB}}, // 4 {{LT, UMB, UMB}, {LB , LB, LR}}, // 5 {{LT, UMB, UMB}, {LL, LB, LR}}, // 6 {{UB, UB, RT}, {32, 32, LT}}, / / 7 {{LT, UMB, RT}, {LL, LB, LR}}, // 8 {{LT, UMB, RT}, {32, 32, LR}}, // 9 {{32, 32, 32}, {32, 32, 32}} // Пусто}; // ---------------------- Шрифт Trek -------- -------------------- # определить K0 0 # определить K1 1 # определить K2 2 # определить K3 3 # определить K4 4 # определить K5 5 # определить K6 6 # определить K7 7константный байт K_0 [8] PROGMEM ={0x1F, 0x1F, 0x00,0x00,0x00,0x00,0x00,0x00}; константный байт K_1 [8] PROGMEM ={0x18,0x18,0x18,0x18,0x18,0x18,0x18, 0x18}; константный байт K_2 [8] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x1F, 0x1F}; константный байт K_3 [8] PROGMEM ={0x1F, 0x1F, 0x03,0x03,0x03,0x03, 0x1F, 0x1F}; константный байт K_4 [8] PROGMEM ={0x1F, 0x1F, 0x18,0x18,0x18,0x18,0x1F, 0x1F}; константный байт K_5 [8] PROGMEM ={0x1F, 0x1F, 0x18,0x18,0x18, 0x18,0x18,0x18}; константный байт K_6 [8] PROGMEM ={0x03,0x03,0x03,0x03, 0x03,0x03,0x1F, 0x1F}; константный байт K_7 [8] PROGMEM ={0x1F, 0x1F, 0x03,0x03,0x03,0x03,0x03,0x03}; константный байт trekChar [11] [2] [2] ={{ {K5, K7}, {255, K6}}, // 0 {{K0, K1}, {K2, 255}}, // 1 {{K0, K3}, {255, K2}}, // 2 {{K0, K3}, {K2, 255}}, // 3 {{K1, 255}, {K0, K1}}, // 4 {{K4, K0}, {K2, 255}}, // 5 {{K5, K0}, {K4, 255}}, // 6 {{K0, 255}, {32, K1}}, // 7 {{255, K3}, {K4, 255}}, / / 8 {{255, K3}, {K2, K6}}, // 9 {{32, 32}, {32, 32}}, // Пусто}; // ---------- ------------ Тонкий шрифт ---------------------------- # define T0 0 # define T1 1 # определить T2 2 # определить T3 3 # определить T4 4 # определить T5 5 # определить T6 6 # определить T7 7const byte T_0 [8] PROGMEM ={0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02}; const байт T_1 [8] PROGMEM ={0x0E, 0x02,0x02,0x02,0x02,0x02,0x02,0x0E}; константный байт T_2 [8] PROGMEM ={0x0E, 0x08,0x08,0x08,0x08,0x08,0x08,0x0E}; const byte T_3 [8] PROGMEM ={0x0E, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0E}; const byte T_5 [8] PROGMEM ={0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0E}; константный байт T_4 [8] PROGMEM ={0x0E, 0x0A, 0x0A, 0x0A, 0x0 A, 0x0A, 0x0A, 0x0A}; константный байт T_6 [8] PROGMEM ={0x0E, 0x02,0x02,0x02,0x02,0x02,0x02,0x02}; константный байт T_7 [8] PROGMEM ={0x18,0x18,0x18, 0x18,0x18,0x1E, 0x1F, 0x1F}; // функции отрисовки символов ЖК-дисплеяconst byte thinChar [11] [2] ={{T4, T5}, // 0 {T0, T0}, // 1 {T1, T2} , // 2 {T1, T1}, // 3 {T5, T6}, // 4 {T2, T1}, // 5 {T2, T3}, // 6 {T6, T0}, // 7 { T3, T3}, // 8 {T3, T1}, // 9 {32, 32} // пусто}; // ---------------------- Общая инициализация ------------------------ ---- void setup () {Serial.begin (115200); // Устанавливаем выходы / входы pinMode (BTN_SET, INPUT); pinMode (BTN_ADJUST, INPUT); pinMode (BTN_ALARM, INPUT); pinMode (BTN_TILT, INPUT); pinMode (ДИНАМИК, ВЫХОД); pinMode (СВЕТ, ВЫХОД); // Проверяем, есть ли у RTC допустимое время / дата, если нет, установите 00:00:00 01/01/2018. // Это будет работать только в первый раз или при низком уровне заряда батарейки. // setSyncProvider () заставляет библиотеку времени синхронизироваться с // внешним RTC, вызывая RTC.get () каждые пять минут по умолчанию. setSyncProvider (rtc.get); if (timeStatus ()! =timeSet) {Serial.println ("Установка времени по умолчанию"); // Установить RTC tmElements_t tm; tm.Year =CalendarYrToTm (2020); tm.Month =06; tm.Day =26; tm.Hour =7; tm.Minute =52; tm.Second =0; time_t t =время изготовления (tm); // используйте значение time_t, чтобы убедиться, что установлен правильный день недели if (rtc.set (t) ==0) {// Успех setTime (t); } else {Serial.println ("Не удалось установить RTC!"); }} задержка (100); // Считываем время тревоги из памяти EEPROM AH =EEPROM.read (EEPROM_AH); AM =EEPROM.read (EEPROM_AM); байт ao =EEPROM.read (EEPROM_AO); alarmON =(ao! =0); байт cs =EEPROM.read (EEPROM_CS); // Проверяем, верны ли числа, которые вы читаете. (Часы:0–23 и минуты:0–59), если (AH> 23) {AH =0; } если (AM> 59) {AM =0; } // Считываем дату рождения из EEPROM BY =(EEPROM.read (EEPROM_BY + 0) <<8) | EEPROM.read (EEPROM_BY + 1); если (BY <1900 || BY> 2099) {BY =2000; } BM =EEPROM.read (EEPROM_BM); если (BM <0 || BM> 12) {BM =1; } BD =EEPROM.read (EEPROM_BD); если (BD <0 || BD> 31) {BD =1; } // Устанавливаем текущий стиль lcd.begin (16,2); currentStyle =(cs> (uint8_t) THERMO)? СТАНДАРТ:(СТИЛЬ) cs; переключатель (currentStyle) {case СТАНДАРТ:lcdStandardSetup (); ломать; case DUAL_THICK:lcdDualThickSetup (); ломать; case DUAL_BEVEL:lcdDualBevelSetup (); ломать; case DUAL_TREK:lcdDualTrekSetup (); ломать; case DUAL_THIN:lcdDualThinSetup (); ломать; case WORD:lcdWordSetup (); ломать; case BIO:lcdBioRhythmSetup (); ломать; case THERMO:lcdThermometerSetup (); ломать; } #ifdef BACKLIGHT_ALWAYS_ON switchBacklight (true); # endif} // ---------------------- Основной цикл программы ----------- ----------------- void loop () {readBtns (); // Считываем кнопки getTimeDate (); // Считываем время и дату из RTC getTempHum (); // Считываем температуру и влажность if (! SetupScreen) {lcdPrint (); // Обычно выводить текущее время / дату / будильник на ЖК-дисплей if (alarmON) {callAlarm (); // и проверяем будильник, если он включен if (turnItOn) {switchBacklight (true); }} //Serial.println("backlightTimeout="+ String (backlightTimeout) +", millis () ="+ String (millis ()) +", backlightOn ="+ String (backlightOn)); # ifdef BACKLIGHT_TIMEOUT if ( backlightOn &&(миллис ()> backlightTimeout)) {switchBacklight (ложь); } #endif} еще {timeSetup (); // Если кнопка нажата, вызываем функцию установки времени switchBacklight (true); }} // ---------------------------------------------- ---- // Считываем состояние кнопок без readBtns () {set_state =digitalRead (BTN_SET); Adjust_state =цифровое чтение (BTN_ADJUST); alarm_state =digitalRead (BTN_ALARM); if (! backlightOn &&! setupScreen) {if (set_state ==LOW || adjust_state ==LOW || alarm_state ==LOW) {// Включаем переключатель подсветкиBacklight (true); // нужно удерживать кнопку не менее 1/2 секунды задержки (500); }} else {если (! setupScreen) {if (alarm_state ==LOW) {alarmON =! alarmON; EEPROM.write (EEPROM_AO, (alarmON)? 1:0); задержка (500); switchBacklight (правда); } иначе, если (adjust_state ==LOW) {currentStyle =(currentStyle ==THERMO)? СТАНДАРТ:(СТИЛЬ) ((int) currentStyle + 1); EEPROM.write (EEPROM_CS, (байт) currentStyle); переключатель (currentStyle) {case СТАНДАРТ:lcdStandardSetup (); ломать; case DUAL_THICK:lcdDualThickSetup (); ломать; case DUAL_BEVEL:lcdDualBevelSetup (); ломать; case DUAL_TREK:lcdDualTrekSetup (); ломать; case DUAL_THIN:lcdDualThinSetup (); ломать; case WORD:lcdWordSetup (); ломать; case BIO:lcdBioRhythmSetup (); ломать; case THERMO:lcdThermometerSetup (); ломать; } lcd.clear (); lcdPrint (); задержка (500); switchBacklight (правда); }} если (set_state ==LOW) {setupMode =(setupMode ==ALARM_MIN)? ЧАСЫ:(НАСТРОЙКА) ((int) setupMode + 1); если (setupMode! =ЧАСЫ) {setupScreen =true; если (setupMode ==TIME_HOUR) {lcd.clear (); lcd.setCursor (0,0); lcd.print ("------ НАБОР ------"); lcd.setCursor (0,1); lcd.print ("- ВРЕМЯ и ДАТА-"); задержка (2000); lcd.clear (); }} еще {lcd.clear (); // Установить RTC tmElements_t tm; tm.Year =CalendarYrToTm (YY); tm.Month =MM; tm.Day =DD; tm.Hour =H; tm.Minute =M; tm.Second =0; time_t t =время изготовления (tm); // используйте значение time_t, чтобы убедиться, что установлен правильный день недели if (rtc.set (t) ==0) {// Успех setTime (t); } else {Serial.println ("Не удалось установить RTC!"); } //rtc.adjust(DateTime(YY, MM, DD, H, M, 0)); // Сохраняем время и дату в RTC IC EEPROM.write (EEPROM_AH, AH); // Сохраняем часы срабатывания будильника в EEPROM EEPROM.write (EEPROM_AM, AM); // Сохраняем протокол тревоги в EEPROM EEPROM.write (EEPROM_BY + 0, BY>> 8); // Сохраняем год рождения в EEPROM EEPROM.write (EEPROM_BY + 1, BY &0xFF); // Сохраняем год рождения в EEPROM EEPROM.write (EEPROM_BM, BM); // Сохраняем месяц рождения в EEPROM EEPROM.write (EEPROM_BD, BD); // Сохраняем день рождения в EEPROM lcd.print ("Сохранение ...."); задержка (2000); lcd.clear (); setupScreen =false; setupMode =ЧАСЫ; switchBacklight (правда); } задержка (500); }}} // --------------------------------------------- ----- // Считываем время и дату из rtc icvoid getTimeDate () {if (! SetupScreen) {// DateTime now =rtc.now (); time_t t =сейчас (); DD =день (t); ММ =месяц (т); YY =год (t); H =час (т); M =минута (t); S =второй (t); } // Вносим некоторые исправления ... sDD =((DD <10)? "0":"") + String (DD); sMM =((MM <10)? "0":"") + String (MM); sYY =строка (YY-2000); sH =((H <10)? "0":"") + String (H); sM =((M <10)? "0":"") + String (M); sS =((S <10)? "0":"") + String (S); sBD =((BD <10)? "0":"") + Строка (BD); sBM =((BM <10)? "0":"") + String (BM); sBY =Строка (BY); aH =((AH <10)? "0":"") + строка (AH); aM =((AM <10)? "0":"") + String (AM);} // ------------------------- ------------------------- // Каждые 6 секунд считываем температуру и влажность с датчика DHTvoid getTempHum () {unsigned long currentMillis =millis (); если (currentMillis - prevDhtMillis> =DHT_UPDATE_INTERVAL) {int chk =DHT.read21 (DHT21); prevDhtMillis =currentMillis; hum =min (круглый (DHT. влажность), 99); temp =min (круглый (DHT.температура), 99); sTMP =((temp>
 9)? "":"") + String (temp); sHUM =((гул> 9)? "":"") + String (гул); }} // ---------------------------------------------- ---- // Включение или выключение подсветкиvoid switchBacklight (bool on) {#ifdef NO_BACKLIGHT digitalWrite (LIGHT, LOW); backlightOn =true; // Обманывать программу, заставляя думать, что она работает, даже если это не #else #ifdef BACKLIGHT_ALWAYS_ON digitalWrite (LIGHT, HIGH); backlightOn =true; #else digitalWrite (LIGHT, (on)? HIGH:LOW); backlightOn =on; backlightTimeout =миллис () + BACKLIGHT_TIMEOUT; #endif #endif} // ------------------------------------------- ------- // Печатать значения в displayvoid lcdPrint () {switch (currentStyle) {case STANDARD:lcdStandardLayout (); ломать; case DUAL_THICK:lcdDualThickLayout (); ломать; case DUAL_BEVEL:lcdDualBevelLayout (); ломать; case DUAL_TREK:lcdDualTrekLayout (); ломать; case DUAL_THIN:lcdDualThinLayout (); ломать; case WORD:lcdWordLayout (); ломать; case BIO:lcdBioRhythmLayout (); ломать; case THERMO:lcdThermometerLayout (); ломать; }} // ---------------------------------------------- - Стандартный макет ---------------------------------------------- ----------------------- void lcdStandardSetup () {} void lcdStandardLayout () {String line1 =sH + ":" + sM + ":" + sS + "| "+ aH +":"+ aM; Строка line2 =SDD + "/" + sMM + "/" + sYY + "|" + ((alarmON &&(S &0x01))? "ALARM":""); lcd.setCursor (0,0); // Первая строка lcd.print (line1); lcd.setCursor (0,1); // Вторая строка lcd.print (line2); } // Создаем собственный символ из памяти программыvoid createCharP (байтовый слот, byte * p) {for (int i =0; i <8; i ++) {customChar [i] =pgm_read_byte (p ++); } lcd.createChar (slot, customChar);} // ------------------------------------- ----------- Двойной толстый макет ------------------------------------ --------------------------------- void lcdDualThickSetup () {createCharP (C0, C_0); createCharP (C1, C_1); createCharP (C2, C_2); createCharP (C3, C_3); createCharP (BELL_CHAR, bell);} void lcdDualThickLayout () {# ifdef DUAL_THICK_12HR int h =(H> =12)? H - 12:H; если (h ==0) {h =12; } lcdDualThickPrintNumber (8, M, истина); lcdDualThickPrintNumber (0, h, ложь); lcd.setCursor (15,0); lcd.print ((H> =12)? "p":"a"); lcd.setCursor (15,1); lcd.print ("м"); #else lcdDualThickPrintNumber (8, M, истина); lcdDualThickPrintNumber (0, H, истина); bool alarm =(S &0x01); lcdWordShowBell (15, 0, тревога, BELL_CHAR); // нижний правый угол lcdWordShowBell (15, 1,! alarm, BELL_CHAR); // нижний правый угол #endif byte c =(S &1)? С3:32; lcd.setCursor (7,0); lcd.write (c); lcd.setCursor (7,1); lcd.write (c);} // Нарисуйте номер из 2 строк // pos - позиция x для рисования // число - значение для рисования // leadZero - должны ли отображаться ведущие нулиvoid lcdDualThickPrintNumber (int pos, int number, int leadZero) {int t =число / 10; int u =число% 10; если (t ==0 &&! leadZero) {t =11; } lcdDualThickPrintDigit (pos, t); lcdDualThickPrintDigit (pos + 4, u);} // Рисуем 2-строчную цифру // pos - x позиция для рисования number // number - значение для рисованияvoid lcdDualThickPrintDigit (int pos, int number) {for (int y =0; y <2; y ++) {lcd.setCursor (pos, y); для (int x =0; x <3; x ++) {lcd.write (blockChar [число] [y] [x]); }}} // --------------------------------------------- --- Макет с двойным скосом -------------------------------------------- ------------------------- void lcdDualBevelSetup () {createCharP (LT, _LT); createCharP (UB, _UB); createCharP (RT, _RT); createCharP (LL, _LL); createCharP (LB, _LB); createCharP (LR, _LR); createCharP (UMB, _UMB); createCharP (LMB, _LMB);} void lcdDualBevelLayout () {# ifdef DUAL_THICK_12HR int h =(H> =12)? H - 12:H; если (h ==0) {h =12; } lcdDualBevelPrintNumber (8, M, истина); lcdDualBevelPrintNumber (0, h, ложь); lcd.setCursor (15,0); lcd.print ((H> =12)? "p":"a"); lcd.setCursor (15,1); lcd.print ("м"); #else lcdDualBevelPrintNumber (8, M, истина); lcdDualBevelPrintNumber (0, H, истина); bool alarm =(S &0x01); lcdWordShowBell (15, 0, будильник, 65); // нижний правый угол lcdWordShowBell (15, 1,! alarm, 65); // нижний правый угол #endif byte c =(S &1)? 58:32; lcd.setCursor (7,0); lcd.write (c); lcd.setCursor (7,1); lcd.write (c);} // Нарисуйте номер из 2 строк // pos - позиция x для рисования number // number - значение для рисования // leadingZero - должны ли отображаться ведущие нулиvoid lcdDualBevelPrintNumber (int pos, int number, int leadZero) {int t =число / 10; int u =число% 10; если (t ==0 &&! leadZero) {t =11; } lcdDualBevelPrintDigit (pos, t); lcdDualBevelPrintDigit (pos + 4, u);} // Нарисуйте 2-строчную цифру // pos - x положение для рисования числа // число - значение для рисованияvoid lcdDualBevelPrintDigit (int pos, int number) {for (int y =0; y <2; y ++) {lcd.setCursor (pos, y); для (int x =0; x <3; x ++) {lcd.write (bevelChar [число] [y] [x]); }}} // --------------------------------------------- --- Схема Dual Trek -------------------------------------------- ------------------------- void lcdDualTrekSetup () {createCharP (K0, K_0); createCharP(K1, K_1); createCharP(K2, K_2); createCharP(K3, K_3); createCharP(K4, K_4); createCharP(K5, K_5); createCharP(K6, K_6); createCharP(K7, K_7);}void lcdDualTrekLayout(){ lcdDualTrekPrintNumber(10, S, true); lcdDualTrekPrintNumber(5, M, true); lcdDualTrekPrintNumber(0, H, true); byte c =(S &1) ? 165 :32; lcd.setCursor (4,0); lcd.write(c); lcd.setCursor (4,1); lcd.write(c); lcd.setCursor(9,0); lcd.write(c); lcd.setCursor(9,1); lcd.write(c); bool alarm =(S &0x01); lcdWordShowBell(15, 0, alarm, 65); //bottonm right corner lcdWordShowBell(15, 1, !alarm, 65); //bottonm right corner}//Draw a 2 line number// pos - x position to draw number// number - value to draw// leadingZero - whether leading zeros should be displayedvoid lcdDualTrekPrintNumber(int pos, int number, int leadingZero){ int t =number / 10; int u =number % 10; if (t ==0 &&!leadingZero) { t =11; } lcdDualTrekPrintDigit(pos, t); lcdDualTrekPrintDigit(pos + 2, u);}//Draw a 2 line digit// pos - x position to draw number// number - value to drawvoid lcdDualTrekPrintDigit(int pos, int number){ for (int y =0; y <2; y++) { lcd.setCursor(pos, y); for (int x =0; x <2; x++) { lcd.write(trekChar[number][y][x]); } }}//------------------------------------------------ Dual Thin layout ---------------------------------------------------------------------void lcdDualThinSetup(){ createCharP(T0, T_0); createCharP(T1, T_1); createCharP(T2, T_2); createCharP(T3, T_3); createCharP(T4, T_4); createCharP(T5, T_5); createCharP(T6, T_6); createCharP(T7, T_7);}void lcdDualThinLayout(){ #ifdef DUAL_THIN_12HR int h =(H>=12) ? H - 12 :H; if (h ==0) { h =12; } lcdDualThinPrintNumber(6, S, true); lcdDualThinPrintNumber(3, M, true); lcdDualThinPrintNumber(0, h, false); lcd.setCursor(9,0); lcd.print((H>=12) ? "p" :"a"); lcd.setCursor(9,1); lcd.print("m"); #else lcdDualThinPrintNumber(6, S, true); lcdDualThinPrintNumber(3, M, true); lcdDualThinPrintNumber(0, H, true);#endif byte c =(S &1) ? 165 :32; lcd.setCursor (2,0); lcd.write(c); lcd.setCursor(2,1); lcd.write(c); lcd.setCursor(5,0); lcd.write(c); lcd.setCursor(5,1); lcd.write(c); String line1 =aH+":"+aM; String line2 =(alarmON &&(S &0x01)) ? "ALARM" :" "; lcd.setCursor(11,0); //First row lcd.print(line1); lcd.setCursor(11,1); //Second row lcd.print(line2); }//Draw a 2 line number// pos - x position to draw number// number - value to draw// leadingZero - whether leading zeros should be displayedvoid lcdDualThinPrintNumber(int pos, int number, int leadingZero){ int t =number / 10; int u =number % 10; if (t ==0 &&!leadingZero) { t =11; } lcdDualThinPrintDigit(pos, t); lcdDualThinPrintDigit(pos + 1, u);}//Draw a 2 line digit// pos - x position to draw number// number - value to drawvoid lcdDualThinPrintDigit(int pos, int number){ for (int y =0; y <2; y++) { lcd.setCursor(pos, y); lcd.write(thinChar[number][y]); }}//------------------------------------------------ Word layout ---------------------------------------------------------------------void lcdWordSetup(){ createCharP(BELL_CHAR, &bell[0]);}void lcdWordLayout(){ String line1 =numberToWord(H, false); String line2 =numberToWord(M, true); lcd.setCursor (0,0); //First row printClear(line1, 13); lcd.setCursor (0,1); //Second row printClear(line2, 14); if (millis()> frameTimeout) { frameTimeout =millis() + FRAME_TIMEOUT; //lcd.createChar(HOURGLASS_CHAR, &hourglass[nextFrame][0]); createCharP(HOURGLASS_CHAR, &hourglass[nextFrame][0]); nextFrame =(nextFrame + 1) % HOURGLASS_FRAMES; lcd.setCursor(13,0); //First row lcd.write((int)HOURGLASS_CHAR); lcd.print(sS); } bool alarm =(S &0x01); lcdWordShowBell(14, 1, alarm, BELL_CHAR); //Second row lcdWordShowBell(15, 1, !alarm, BELL_CHAR); //Second row}//Display the bell symbol if alarm is on// x - x position (0..15)// y - y position (0..1)// show - true to showvoid lcdWordShowBell(int x, int y, bool show, byte chr) { lcd.setCursor(x,y); lcd.print(" "); if (alarmON &&show) { lcd.setCursor(x,y); lcd.write(chr); }}//Print character string and clear to right// s - String to print...This file has been truncated, please download it to see its full contents.

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

stl_files_ZuDXHCHZCl.zip

Схема

Schematic and PCB in Eagle files eagle_files_ZN59zdeNf5.zip

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

  1. Сигнализация о воде Raspberry Pi 2 с t сапожником плюс
  2. ЖК-панель с Arduino для симулятора полета
  3. Будильник, который действительно помогает встать с постели по утрам
  4. Самодельные простейшие часы Numitron IV9 с Arduino
  5. Часы Arduino с исламским временем молитв
  6. Word Clock с минутным разрешением времени в словах
  7. Arduino Temp. Монитор и часы реального времени с дисплеем 3.2
  8. Цифровые часы TM1637 с функцией настройки времени и будильника
  9. Отображение изображения на ЖК-экране TFT с помощью Arduino UNO!
  10. Простой будильник с DS1302 RTC