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

Миниатюрные светодиодные матричные часы

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

Arduino Nano R3
× 1
Maxim Integrated DS3231M - ± 5ppm, часы реального времени I2C
× 1
Кнопочный переключатель, мгновенный
× 2
Модуль светодиодной матрицы 32x8
× 1

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

Паяльник (универсальный)

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

IDE Arduino

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

На странице "Nick's LED Projects" я нашел проект часов, который показывает время на 4-х матрицах со светодиодами 8x8. Он построил часы с матрицами из магазина "ICStation", который продает наборы для сборки матричных модулей и панелей.

С минимальным изменением кода я сделал свои часы с точечным матричным модулем MAX7219, микроконтроллером, четыре в одном, дисплей, который полностью сложен и намного дешевле. Купил на AliExpress.

У часов много функций:

- Базовый режим с большими цифрами

- Режим слайдов, в котором цифры отображаются на экране и за его пределами

- Маленькие цифры в режиме секунд

- Время написано словами, например «Десять минут первого»

- Отображение даты

- 12/24 часа

- Параметр яркости

- Опция режима случайных часов, которая меняет режим отображения каждые несколько часов.

- Меню, управляемые кнопками, для настройки и выбора отображения.

Как вы можете видеть на схеме, кроме матриц нам понадобится плата Arduino, модуль часов реального времени и две кнопки для настроек. Вы можете скачать библиотеки и модифицированный код по ссылкам ниже.

Код

  • код
  • Библиотеки
код Arduino
 / ********************************************* ************************* Mini Clock v1.0, июль 2014 г., Ник Холл Распространяется на условиях GPL. Для помощи в создании часы см. мой блог:http://123led.wordpress.com/ Протестировано на IDE v1.6.5 **************************** ***************************************** /// включаем библиотеки:#include "LedControl.h" #include  // Библиотека шрифтов # include  // Часы DS1307 # include "RTClib.h" // Часы DS1307 # include  // Библиотека кнопок от Александр Бревиг // Настройка светодиодной матрицы // контакт 12 подключен к DataIn на дисплее // контакт 11 подключен к CLK на дисплее // контакт 10 подключен к LOAD на дисплееLedControl lc =LedControl (12, 11, 10, 4); // устанавливает 3 контакта как 12, 11 и 10, а затем устанавливает 4 дисплея (максимум 8 дисплеев) // глобальные переменныеbytecence =7; // Интенсивность / яркость по умолчанию (0-15) byte clock_mode =0; // Режим часов по умолчанию. По умолчанию =0 (basic_mode) bool random_mode =0; // Определить случайный режим - меняет тип отображения каждые несколько часов. По умолчанию =0 (выкл.) Байт old_mode =clock_mode; // Сохраняет предыдущий режим часов, поэтому, если мы перейдем к дате или чему-то еще, мы знаем, в какой режим вернуться после .bool ampm =0; // Определяем 12- или 24-часовое время. 0 =24 часа. 1 =12 часов change_mode_time =0; // Удерживает час, когда режим часов в следующий раз изменится, если в случайном режиме. Unsigned long delaytime =500; // Мы всегда немного ждем между обновлениями displayint rtc [7]; // Удерживает часы реального времени outputchar days [7] [4] ={"вс", "пн", "вт", "ср", "чт", "пт", "сб"}; // дневной массив - используется в режимах слайда, basic_mode и jumble (DS1307 выводит 1-7 значений для дня недели) char daysfull [7] [9] ={"воскресенье", "понедельник", "вторник", "среда" "," Четверг "," пятница "," суббота "}; суффикс символа [4] [3] ={" st "," nd "," rd "," th "}; // массив суффиксов даты, используемый в режимах слайда, basic_mode и jumble. e, g, 1st 2nd ... // определить константы #define NUM_DISPLAY_MODES 3 // Режимы отображения чисел (с сохранением нуля в качестве первого режима) #define NUM_SETTINGS_MODES 4 // Режимы настройки числа =6 (с сохранением нуля в качестве первого режима) # define SLIDE_DELAY 20 // Время в миллисекундах для эффекта слайда на символ в режиме слайда. Увеличьте это значение для более медленного эффекта # define cls clear_display // Очистить displayRTC_DS1307 ds1307; // Создаем объект RTCButton buttonA =Button (2, BUTTON_PULLUP); // Настройка кнопки A (с использованием библиотеки кнопок) Button buttonB =Button (3, BUTTON_PULLUP); // Настройка кнопки B (с использованием библиотеки кнопок) void setup () {digitalWrite (2, HIGH); // включаем подтягивающий резистор для кнопки на выводе 2 digitalWrite (3, HIGH); // включаем подтягивающий резистор для кнопки на выводе 3 digitalWrite (4, HIGH); // включаем подтягивающий резистор для кнопки на выводе 4 Serial.begin (9600); // запуск последовательного порта // инициализация 4 матричных панелей // мы уже установили количество устройств при создании LedControl int devices =lc.getDeviceCount (); // мы должны запустить все устройства в цикле for (int address =0; address  =0 &&x <=7) {адрес =3; } if (x> =8 &&x <=15) {адрес =2; х =х - 8; } if (x> =16 &&x <=23) {адрес =1; х =х - 16; } если (x> =24 &&x <=31) {адрес =0; х =х - 24; } если (val ==1) {lc.setLed (адрес, y, x, истина); } else {lc.setLed (адрес, y, x, ложь); }} // очищаем screenvoid clear_display () {for (byte address =0; address <4; address ++) {lc.clearDisplay (address); }} // уменьшение интенсивности экрана внизvoid fade_down () {// уменьшение глобальной интенсивности до 1 for (byte i =интенсивность; i> 0; i--) {for (byte address =0; address <4; address ++) {lc .setIntensity (адрес, i); } задержка (30); // измените это, чтобы изменить скорость затухания} clear_display (); // полностью очищаем отображение (выкл.) // сбрасываем интентность на глобальное значение для (адрес байта =0; адрес <4; адрес ++) {lc.setIntensity (адрес, интенсивность); }} // включение светодиодного индикатора и отображение номера версии программного обеспеченияvoid printver () {byte i =0; char ver_a [9] =«Версия 1.0»; char ver_b [9] ="Привет!"; // тестируем все светодиоды. для (байт х =0; х <=31; х ++) {для (байт у =0; у <=7; у ++) {график (х, у, 1); }} задержка (500); fade_down (); в то время как (ver_a [i]) {puttinychar ((i * 4), 1, ver_a [i]); задержка (35); я ++; } задержка (700); fade_down (); я =0; в то время как (ver_b [i]) {puttinychar ((i * 4), 1, ver_b [i]); задержка (35); я ++; } задержка (700); fade_down ();} // puttinychar // Скопируйте символ 3x5 из структуры данных myfont для отображения памяти с его левым верхним уголком в заданной координате // Это неоптимизировано и просто использует plot () для рисования каждой точки .void puttinychar (байт x, байт y, char c) {байтовые точки; if (c> ='A' &&c <='Z' || (c> ='a' &&c <='z')) {c &=0x1F; // A-Z сопоставляется с 1-26} else if (c> ='0' &&c <='9') {c =(c - '0') + 32; } иначе, если (c =='') {c =0; // пробел} else if (c =='.') {c =27; // точка остановки} else if (c ==':') {c =28; // двоеточие} else if (c =='\' ') {c =29; // одинарная кавычка} else if (c =='!') {c =30; // одинарная кавычка} else if (c =='?') {c =31; // одинарная кавычка} для (byte col =0; col <3; col ++) {dots =pgm_read_byte_near (&mytinyfont [c] [col]); for (char row =0; row <5; row ++) {if (dots &(16>> row)) plot (x + col, y + row, 1); иначе сюжет (x + col, y + row, 0); }}} void putnormalchar (byte x, byte y, char c) {байтовые точки; // if (c> ='A' &&c <='Z' || (c> ='a' &&c <='z')) {// c &=0x1F; // A-Z соответствует 1-26 //} if (c> ='A' &&c <='Z') {c &=0x1F; // A-Z сопоставляется с 1-26} else if (c> ='a' &&c <='z') {c =(c - 'a') + 41; // A-Z соответствует 41-67} else if (c> ='0' &&c <='9') {c =(c - '0') + 31; } иначе, если (c =='') {c =0; // пробел} else if (c =='.') {c =27; // точка остановки} else if (c =='\' ') {c =28; // одинарная кавычка} else if (c ==':') {c =29; // стрелка селектора clock_mode} else if (c =='>') {c =30; // стрелка селектора clock_mode} else if (c> =-80 &&c <=-67) {c * =-1; } для (char col =0; col <5; col ++) {точки =pgm_read_byte_near (&myfont [c] [col]); for (char row =0; row <7; row ++) {// проверяем координаты на экране перед попыткой построения // if ((x> =0) &&(x <=31) &&(y> =0) &&(y <=7)) {if (dots &(64>> row)) {// только 7 строк. сюжет (x + col, y + row, 1); } else {plot (x + col, y + row, 0); } //}}}} // small_mode // показывать время маленькими символами 3x5 с секундами displayvoid small_mode () {char textchar [8]; // 16 символов на дисплее байт mins =100; // мин. байт secs =rtc [0]; // байт секунд old_secs =secs; // содержит старое значение секунд - с момента последнего обновления секунд o display - используется для проверки того, изменились ли секунды cls (); // запускаем основной цикл часов, пока run_mode возвращает true while (run_mode ()) {get_time (); // проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); возвращение; } // если секунды изменились, то обновим их на дисплее secs =rtc [0]; if (secs! =old_secs) {// secs char buffer [3]; итоа (секунды, буфер, 10); // исправить - как иначе, если в начале num стоит ноль, например "03" сек, itoa заменяет это на символы с пробелом "3". если (секунд <10) {буфер [1] =буфер [0]; буфер [0] ='0'; } puttinychar (20, 1, ':'); // секунды двоеточие puttinychar (24, 1, buffer [0]); // секунды puttinychar (28, 1, buffer [1]); // секунды old_secs =secs; } // если минуты меняются, меняем время if (mins! =rtc [1]) {// сбрасываем их для сравнения в следующий раз mins =rtc [1]; байтовые часы =rtc [2]; if (часы> 12) {часы =часы - ampm * 12; } if (часы <1) {часы =часы + ampm * 12; } // байт dow =rtc [3]; // DS1307 выводит 0-6, где 0 =воскресенье0-6, где 0 =воскресенье. // байтовая дата =rtc [4]; // установить символы char buffer [3]; итоа (часы, буфер, 10); // исправить - как иначе, если в начале num стоит ноль, например "03" часов, itoa заменяет это на символы с пробелом "3". если (часов <10) {буфер [1] =буфер [0]; // если мы находимся в 12-часовом режиме, пустой ведущий ноль. если (ampm) {буфер [0] =''; } еще {буфер [0] ='0'; }} // устанавливаем часы chars textchar [0] =buffer [0]; textchar [1] =буфер [1]; textchar [2] =':'; итоа (минуты, буфер, 10); если (мин <10) {буфер [1] =буфер [0]; буфер [0] ='0'; } // устанавливаем минимальные символы textchar [3] =buffer [0]; textchar [4] =буфер [1]; // делаем секунды textchar [5] =':'; буфер [3]; сек =rtc [0]; итоа (секунды, буфер, 10); // исправить - как иначе, если в начале num стоит ноль, например "03" сек, itoa заменяет это на символы с пробелом "3". если (секунд <10) {буфер [1] =буфер [0]; буфер [0] ='0'; } // устанавливаем секунды textchar [6] =buffer [0]; textchar [7] =буфер [1]; байт x =0; байт y =0; // выводим каждый символ для (byte x =0; x <6; x ++) {puttinychar (x * 4, 1, textchar [x]); }} задержка (50); } fade_down ();} // basic_mode () // показать время в 5x7 символовvoid basic_mode () {cls (); char buffer [3]; // для преобразования int в char для преобразования значений rtc в символы мы можем напечатать на экране byte offset =0; // используется для смещения положения цифр по оси x и центрирования дисплея, когда мы находимся в 12-часовом режиме, а часы показывают только 3 цифры. например 3:21 байт x, y; // используется для рисования прозрачной рамки над левой цифрой «1» дисплея, когда мы переключаемся с 12:59 на 1:00 в 12-часовом режиме. // выполнить преобразование 12/24 часов, если ampm установлен в 1 байт hours =rtc [2]; if (часы> 12) {часы =часы - ampm * 12; } if (часы <1) {часы =часы + ampm * 12; } // выполняем преобразование смещения if (ampm &&hours <10) {offset =2; } // устанавливаем следующую минуту, мы показываем дату // set_next_date (); // изначально устанавливаем mins на значение 100 - так что оно никогда не будет равно rtc [1] в первом цикле часов, то есть мы рисуем отображение часов, когда вводим функцию byte secs =100; байт мин =100; int count =0; // запускаем основной цикл часов до тех пор, пока run_mode возвращает true while (run_mode ()) {// получаем время от микросхемы часов get_time (); // проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); возвращение; } // проверяем, пора ли автоматически отображать дату // check_show_date (); // рисуем мигание:как если бы секунды изменились. if (secs! =rtc [0]) {// обновить секунды с новым значением secs =rtc [0]; // рисование:plot (15 - смещение, 2, 1); // график верхней точки (15 - смещение, 5, 1); // количество нижней точки =400; } // если счетчик закончился, выключаем:if (count ==0) {plot (15 - offset, 2, 0); // график верхней точки (15 - смещение, 5, 0); // нижняя точка} else {count--; } // повторно отрисовываем дисплей, если кнопка нажата или если mins! =rtc [1] т.е. если время изменилось с того, что мы сохранили в минутах (также запускается при первом входе в функцию, когда mins равно 100) if (mins! =rtc [1]) {// обновляем минуты и часы новыми значениями mins =rtc [1]; часы =rtc [2]; // настраиваем часы ampm на 12-часовой режим if (hours> 12) {hours =hours - ampm * 12; } if (часы <1) {часы =часы + ampm * 12; } itoa (часы, буфер, 10); // если часы <10, число, например "3" часа, itoa заменяет это символами пробелом "3", который нам не нужен if (hours <10) {buffer [1] =buffer [0]; буфер [0] ='0'; } // печатаем часы // если мы в 12-часовом режиме и часы <10, то не выводим начальный ноль, а устанавливаем смещение, поэтому мы центрируем отображение по 3 цифрам. если (ampm &&часов <10) {смещение =2; // если время 1:00, очищаем весь дисплей, поскольку смещение изменяется в это время, и нам нужно очистить старое 12:59 if ((hours ==1 &&mins ==0)) {cls (); }} else {// иначе без смещения и печатаем часы с десятками цифр смещение =0; // если время 10:00, очищаем весь дисплей, поскольку в это время смещение изменяется, и нам нужно очистить старые 9:59 if (hours ==10 &&mins ==0) {cls (); } putnormalchar (1, 0, буфер [0]); } // вывести часы из одной цифры putnormalchar (7 - смещение, 0, buffer [1]); // печать минут // добавление нуля в начале, если mins <10 itoa (mins, buffer, 10); если (мин <10) {буфер [1] =буфер [0]; буфер [0] ='0'; } // выводим минимальные цифры десятков и единиц putnormalchar (19 - смещение, 0, buffer [0]); putnormalchar (25 - смещение, 0, буфер [1]); }} fade_down ();} // как basic_mode, но с эффектом слайдаvoid slide () {byte digits_old [4] ={99, 99, 99, 99}; // старые значения, в которых мы сохраняем время. Установите что-то, что никогда не будет соответствовать времени изначально, поэтому все цифры выводятся, когда режим запускается byte digits_new [4]; // время новых цифр будет скользить, чтобы показать байт digits_x_pos [4] ={25, 19, 7, 1}; // позиция x, для которой отрисовывается каждая цифра char old_char [2]; // используется, когда мы используем itoa для транспонирования текущей цифры (типа byte) в символ для передачи в функцию анимации char new_char [2]; // используется, когда мы используем itoa для транспонирования новой цифры (байта типа) в символ для передачи функции анимации // old_chars - сохраняет на дисплее символы суффикса дня и даты 5. например "пн" и "ул". Мы загружаем их в анимацию слайда как текущий символ, когда эти символы обновляются. // Мы изначально отправили их как A, которые используются, когда clocl входит в режим и последние символы не сохраняются. // char old_chars [6] ="AAAAA"; // выводим двоеточие часов на дисплей cls (); putnormalchar (13, 0, ':'); байт old_secs =rtc [0]; // сохраняем секунды в old_secs. Сравниваем секунды и старые секунды. КОГДА они разные, мы перерисовываем отображение // основного цикла запуска часов, пока run_mode возвращает true while (run_mode ()) {get_time (); // проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); возвращение; } // если секунды изменились, то обновляем отображение if (rtc [0]! =old_secs) {old_secs =rtc [0]; // выполнить преобразование 12/24 часов, если ampm установлен в 1 байт hours =rtc [2]; if (часы> 12) {часы =часы - ampm * 12; } if (часы <1) {часы =часы + ampm * 12; } // разбиваем всю дату и время на отдельные цифры - вставляем в массив digits_new // rtc [0] =secs // позиция массива и сохраняемая цифра // digits_new [0] =(rtc [0]% 10); // 0 - секундные // digits_new [1] =((rtc [0] / 10)% 10); // 1 - десятки секунд // rtc [1] =mins digits_new [0] =(rtc [1]% 10); // 2 - единица минут digits_new [1] =((rtc [1] / 10)% 10); // 3 - десятки минут // rtc [2] =часы digits_new [2] =(часы% 10); // 4-х часовые digits_new [3] =((hours / 10)% 10); // 5 - часовые десятки // rtc [4] =date // digits_new [6] =(rtc [4]% 10); // 6 - даты // digits_new [7] =((rtc [4] / 10)% 10); // 7 - дата десятки // отрисовка начального экрана всех символов. После этого просто рисуем изменения. // сравниваем цифры от 0 до 3 (минуты и часы) for (byte i =0; i <=3; i ++) {// смотрим, изменилась ли цифра ... if (digits_old [i]! =digits_new [i]) {// запускаем 9-шаговую анимационную последовательность для каждого по очереди for (byte seq =0; seq <=8; seq ++) {// преобразовываем цифру в строку itoa (digits_old [i], old_char, 10); itoa (digits_new [i], new_char, 10); // если установлен 12-часовой режим и мы находимся на цифре 2 (режим десятков часов), то проверяем, равен ли он нулю. Если это так, очистите его, чтобы мы получили 14:00, а не 14:00 if (ampm &&i ==3) {if (digits_new [3] ==0) {new_char [0] =''; } если (digits_old [3] ==0) {old_char [0] =''; }} // рисуем кадр анимации для каждой цифры слайданим (digits_x_pos [i], 0, seq, old_char [0], new_char [0]); задержка (SLIDE_DELAY); }}} / * // сравниваем цифру даты 6 (единицы) и (7) десятки - если что-то из этого изменится, нам нужно обновить строку даты. Мы сравниваем десятки дат, скажем, с 31 января -> 01 февраля, тогда единичная цифра не меняется if ((digits_old [6]! =Digits_new [6]) || (digits_old [7]! =Digits_new [7])) { // изменить отображаемый день. Цикл ниже проходит по каждому из 3 символов по очереди, например. "MON" for (byte day_char =0; day_char <=2; day_char ++) {// запускаем последовательность анимации для каждого символа for (byte seq =0; seq <=8; seq ++) {// день (0-6 ) Считайте это число в массиве дней. число секунд в массиве 0-2 получает 3 символа названия дня, например. m o n slideanim (6 * day_char, 8, seq, old_chars [day_char], days [rtc [3]] [day_char]); // 6 x day_char дает нам позицию x для задержки символа (SLIDE_DELAY); } // сохраняем старые дневные символы в массив old_chars в массиве pos 0-2. Мы используем это в следующий раз, когда изменим день и передадим его в анимацию как текущий символ. Обновленный символ вводится как новый символ. old_chars [day_char] =дни [rtc [3]] [day_char]; } // меняем дату в разряде десятков (при необходимости) и единиц. (единичная цифра даты всегда изменится, но включение ее в цикл if делает код более аккуратным.) for (byte i =7; i> =6; i -) {if (digits_old [i] ! =digits_new [i]) {для (байта seq =0; seq <=8; seq ++) {itoa (digits_old [i], old_char, 10); itoa (digits_new [i], new_char, 10); слайданим (digits_x_pos [i], 8, seq, old_char [0], new_char [0]); задержка (SLIDE_DELAY); }}} // выводим суффикс дня «nd» «rd» «th» и т. д. Дата окончания работы 2-буквенный суффикс - например, st, nd, rd, th byte s =3; // позиция для чтения нашего суффиксного массива. байтовая дата =rtc [4]; если (дата ==1 || дата ==21 || дата ==31) {s =0; } else if (date ==2 || date ==22) {s =1; } else if (date ==3 || date ==23) {s =2; } for (byte suffix_char =0; suffix_char <=1; suffix_char ++) {for (byte seq =0; seq <=8; seq ++) {slideanim ((suffix_char * 6) + 36,8, seq, old_chars [suffix_char + 3 ], суффикс [s] [суффикс_чар]); // мы передаем массив old_char char как текущий char и массив суффиксов как новый char delay (SLIDE_DELAY); } // сохраняем достаточный символ в старом массиве символов в массиве pos 3 и 5. Мы используем эти символы в следующий раз, когда изменим суффикс и передадим его в анимацию как текущий символ. Обновленный символ вводится как новый символ. old_chars [суффикс_чар + 3] =суффикс [ы] [суффикс_чар]; }} // конец строки даты * / // сохранение массива цифр tol old для сравнения следующий цикл for (byte i =0; i <=3; i ++) {digits_old [i] =digits_new [i]; }} // secs / oldsecs} // while loop fade_down ();} // вызывается слайдом // это отрисовывает анимацию скольжения одного символа и сползания другого. В анимации 8 шагов, мы вызываем функцию для рисования одного из шагов от 0 до 7 // входы - это символы x и y, последовательность кадров анимации (0-7), а также текущий и новый рисуемые символы. slideanim (byte x, byte y, byte sequence, char current_c, char new_c) {// Чтобы сдвинуть один символ, а другой включить, нам нужно последовательно 9 шагов или кадров ... // seq # 0123456 <- строки дисплея // | ||||||| // seq0 0123456 START - все строки дисплея 0-6 показывают текущие символы строки 0-6 // seq1 012345 текущий символ перемещается на одну строку вниз на дисплее. Мы видим только строки 0-5. Есть в позициях отображения 1-6. Вверху вставлена ​​пустая строка // seq2 6 01234 текущий символ перемещается на 2 строки вниз. теперь мы видим только строки 0-4 при отображении строк 2-6 на дисплее. Строка 1 дисплея пуста. Строка 0 показывает строку 6 нового символа // seq3 56 0123 // seq4 456012 наполовину старого / наполовину нового символа // seq5 3456 01 // seq6 23456 0 // seq7 123456 // seq8 0123456 END - все строки показывают новый char // сверху мы можем видеть ... // currentchar запускает 0-6, затем 0-5, затем 0-4 полностью до 0. Начальная позиция Y увеличивается на 1 строку каждый раз. // новый символ запускает 6, затем 5-6, затем 4-6, затем 3-6. начальная позиция Y увеличивается на 1 строку каждый раз. // если порядковый номер меньше 7, нам нужно нарисовать текущий символ if (sequence <7) {byte dots; // if (current_c> ='A' &&|| (current_c> ='a' &¤t_c <='z')) {// current_c &=0x1F; // A-Z соответствует 1-26 //} if (current_c> ='A' &¤t_c <='Z') {current_c &=0x1F; // A-Z сопоставляется с 1-26} else if (current_c> ='a' &¤t_c <='z') {current_c =(current_c - 'a') + 41; // A-Z соответствует 41-67} else if (current_c> ='0' &¤t_c <='9') {current_c =(current_c - '0') + 31; } иначе, если (current_c =='') {current_c =0; // пробел} else if (current_c =='.') {current_c =27; // точка остановки} else if (current_c =='\' ') {current_c =28; // одинарная кавычка} else if (current_c ==':') {current_c =29; // двоеточие} else if (current_c =='>') {current_c =30; // стрелка селектора clock_mode} byte curr_char_row_max =7 - последовательность; // максимальное количество строк для рисования - 6 - порядковый номер byte start_y =sequence; // Начальная позиция y - такая же, как порядковый номер. Мы добавляем этот каждый цикл // строим каждую строку до максимума строки (рассчитанного по порядковому номеру) for (byte curr_char_row =0; curr_char_row <=curr_char_row_max; curr_char_row ++) {for (byte col =0; col <5; col ++) {dots =pgm_read_byte_near (&myfont [current_c] [col]); if (точки &(64>> curr_char_row)) plot (x + col, y + start_y, 1); // график вел на else plot (x + col, y + start_y, 0); // иначе график отключен} start_y ++; // добавляем единицу к y, чтобы нарисовать следующую строку на одну вниз}} // рисуем пустую строку между символами, если последовательность находится между 1 и 7. Если мы этого не сделаем, мы получим остатки текущих символов последняя позиция слева на дисплее if (последовательность> =1 &&последовательность <=8) {for (byte col =0; col <5; col ++) {plot (x + col, y + (sequence - 1), 0); // позиция y для рисования линии эквивалентна порядковому номеру - 1}} // если последовательность больше 2, нам также нужно начать рисовать новый char if (sequence> =2) {// вычислить char byte точки; // если (new_c> ='A' &&new_c <='Z' || (new_c> ='a' &&new_c <='z')) {// new_c &=0x1F; // A-Z соответствует 1-26 //} if (new_c> ='A' &&new_c <='Z') {new_c &=0x1F; // A-Z соответствует 1-26} else if (new_c> ='a' &&new_c <='z') {new_c =(new_c - 'a') + 41; // A-Z соответствует 41-67} else if (new_c> ='0' &&new_c <='9') {new_c =(new_c - '0') + 31; } иначе, если (new_c =='') {new_c =0; // пробел} else if (new_c =='.') {new_c =27; // точка остановки} else if (new_c =='\' ') {new_c =28; // одинарная кавычка} else if (new_c ==':') {new_c =29; // стрелка селектора clock_mode} else if (new_c =='>') {new_c =30; // стрелка селектора clock_mode} byte newcharrowmin =6 - (последовательность - 2); // минимальный номер строки для рисования для нового символа - это генерирует вывод от 6 до 0 при подаче порядковых номеров 2-8. Это минимальная строка, которую нужно нарисовать для нового байта символа start_y =0; // Начальная позиция y - такая же, как порядковый номер. мы добавляем его в каждую строку // строим каждую строку вверх от минимума строки (рассчитанного по порядковому номеру) до 6 для (byte newcharrow =newcharrowmin; newcharrow <=6; newcharrow ++) {for (byte col =0; col <5; col ++ ) {точки =pgm_read_byte_near (&myfont [new_c] [col]); if (точки &(64>> newcharrow)) plot (x + col, y + start_y, 1); // график вел на else plot (x + col, y + start_y, 0); // иначе график отключен} start_y ++; // прибавляем единицу к y, чтобы нарисовать следующую строку на одну вниз}}} // печатать часы, используя слова, а не числаvoid word_clock () {cls (); char numbers [19] [10] ={"один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять", "десять", «одиннадцать», «двенадцать», «тринадцать», «четырнадцать», «пятнадцать», «шестнадцать», «семнадцать», «восемнадцать», «девятнадцать»}; char numberstens [5] [7] ={"десять", "двадцать", "тридцать", "сорок", "пятьдесят"}; // потенциально 3 строки для отображения char str_a [8]; char str_b [8]; char str_c [8]; // байт hours_y, mins_y; // часы и минуты и позиции для строк часов и минут byte hours =rtc [2]; if (часы> 12) {часы =часы - ampm * 12; } if (часы <1) {часы =часы + ampm * 12; } get_time (); // получаем время из байт микросхемы часов old_mins =100; // сохраняем минуты в old_mins. Мы сравниваем минуты и старые минуты, и когда они различаются, мы перерисовываем отображение. Изначально установите значение 100, чтобы изображение отображалось при запуске режима. байтовые минуты; // запускаем основной цикл часов, пока run_mode возвращает true while (run_mode ()) {// проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); } get_time (); // получаем время от микросхемы часов mins =rtc [1]; // получить минуты // если минуты отличаются от old_mins - перерисовать отображение if (mins! =old_mins) {// обновить old_mins текущим значением mins old_mins =mins; // сбрасываем их для сравнения в следующий раз mins =rtc [1]; часы =rtc [2]; // переводим часы в 12-часовой формат if (hours> 12) {hours =hours - 12; } если (часы ==0) {часы =12; } // разделяем минимальное значение на две отдельные цифры int minsdigit =rtc [1]% 10; байт minsdigitten =(rtc [1] / 10)% 10; // если mins <=10, то верхняя строка должна читать "minsdigti past", а нижняя строка - часы if (mins <10) {strcpy (str_a, numbers [minsdigit - 1]); strcpy (str_b, «ПРОШЛОЕ»); strcpy (str_c, числа [часы - 1]); } // если mins =10, нельзя использовать minsdigit, как указано выше, поэтому в официальном случае вывести 10 прошедших / n час. если (mins ==10) {strcpy (str_a, numbers [9]); strcpy (str_b, «ПРОШЛОЕ»); strcpy (str_c, числа [часы - 1]); } // если время не совпадает с часом - т.е. обе цифры минут не равны нулю, // тогда первая строка должна читаться как «часы», а вторая и третья строки читаются как «minstens» «mins», например, "три / п двадцать / один" иначе, если (цифра-мин! =0 &&цифра-мин! =0) {strcpy (str_a, числа [часы - 1]); // если mins находится в диапазоне teens, используйте teens из массива чисел для 2-й строки, например "пятнадцать" // if (mins> =11 &&mins <=19) {if (mins <=19) {strcpy (str_b, numbers [mins - 1]); } else {strcpy (str_b, numberstens [minsdigitten - 1]); strcpy (str_c, числа [minsdigit - 1]); }} // если минимальная цифра равна нулю, не выводить ее. читать читать "часы" "минстены" например "три / п двадцать" иначе, если (minsdigitten! =0 &&minsdigit ==0) {strcpy (str_a, numbers [часы - 1]); strcpy (str_b, numberstens [minsdigitten - 1]); strcpy (str_c, ""); } // если обе минуты равны нулю, то есть это час, в верхней строке указано «часы», а в нижней строке - «часы», иначе if (minsdigitten ==0 &&minsdigit ==0) {strcpy (str_a, числа [часы - 1]); strcpy (str_b, «ЧАСЫ»); strcpy (str_c, ""); }} // время окончания работы // выполнение цикла // вывод строки «двенадцать» байтов len =0; в то время как (str_a [len]) {len ++; }; // получаем длину байта сообщения offset_top =(31 - ((len - 1) * 4)) / 2; // // строим байт линии часов i =0; в то время как (str_a [i]) {puttinychar ((i * 4) + offset_top, 1, str_a [i]); я ++; } // удерживаем отображение, но проверяем нажатия кнопок int counter =1000; while (counter> 0) {// проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); } задержка (1); прилавок--; } fade_down (); // выводим строку b len =0; в то время как (str_b [len]) {len ++; }; // получаем длину сообщения offset_top =(31 - ((len - 1) * 4)) / 2; я =0; в то время как (str_b [i]) {puttinychar ((i * 4) + offset_top, 1, str_b [i]); я ++; } // удерживаем отображение, но проверяем нажатия кнопок counter =1000; в то время как (счетчик> 0) {если (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); } задержка (1); прилавок--; } fade_down (); // выводим строку c, если есть. len =0; в то время как (str_c [len]) {len ++; }; // получаем длину сообщения offset_top =(31 - ((len - 1) * 4)) / 2; я =0; в то время как (str_c [i]) {puttinychar ((i * 4) + offset_top, 1, str_c [i]); я ++; } counter =1000; while (counter> 0) {// проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); } задержка (1); прилавок--; } fade_down (); // удерживаем отображение пустым, но проверяем нажатия кнопок перед повторным запуском. counter =1000; while (counter> 0) {// проверяем нажатие кнопки if (buttonA.uniquePress ()) {switch_mode (); возвращение; } если (buttonB.uniquePress ()) {display_date (); } задержка (1); прилавок--; }} fade_down ();} /// сообщение прокрутки - в настоящее время не используется - слишком медленно .void scroll () {char message [] ={"Hello There"}; cls (); байт p =6; // текущая позиция в строковом байте chara [] ={0, 1, 2, 3, 4, 5}; // символы из строки int x [] ={0, 6, 12, 18, 24, 30}; // xpos для каждого байта символа y =0; // y pos // clear_buffer (); while (message [p]! ='\ 0') {// рисуем все 6 символов для (byte c =0; c <6; c ++) {putnormalchar (x [c], y, message [chara [c]] ); // рисуем линию пикселей, выключенных после каждого символа, иначе в промежутках между символами остались пиксели из предыдущего символа for (byte yy =0; yy <8; yy ++) {plot (x [c] + 5, гг, 0); } // снимаем по одному с каждой позиции символа x [c] =x [c] - 1; } // сбрасываем символ, если он ушел за пределы экрана для (byte i =0; i <=5; i ++) {if (x [i] <-5) {x [i] =31; чара [я] =р; p ++; }}}} // display_date - распечатать день недели, число и месяц с мигающим курсором effectvoid display_date () {cls (); // считываем дату из байта DS1307 dow =rtc [3]; // день недели 0 =воскресенье byte date =rtc [4]; байт месяц =​​rtc [5] - 1; // массив названий месяцев для вывода на дисплей. Некоторые сокращены, так как у нас есть только 8 символов в ширину, чтобы играть с char monthnames [12] [9] ={«Январь», «Февраль», «Март», «Апрель», «Май», «Июнь», «Июль» , «Август», «Сентябрь», «Октябрь», «Ноябрь», «Декабрь»}; // распечатываем название дня // получаем длину текста в пикселях, таким образом мы можем центрировать его на дисплее, divindin оставшиеся пиксели b2 и используя это как смещение byte len =0; в то время как (daysfull [доу] [лен]) {лен ++; }; байтовое смещение =(31 - ((len-1) * 4)) / 2; //our offset to centre up the text //print the name int i =0; while(daysfull[dow][i]) { puttinychar((i*4) + offset , 1, daysfull[dow][i]); i++; } задержка (1000); fade_down(); cls(); // print date numerals char buffer[3]; itoa(date,buffer,10); offset =10; //offset to centre text if 3 chars - e.g. 3rd // first work out date 2 letter suffix - eg st, nd, rd, th etc // char suffix[4][3]={"st", "nd", "rd", "th" }; is defined at top of code byte s =3; if(date ==1 || date ==21 || date ==31) { s =0; } else if (date ==2 || date ==22) { s =1; } else if (date ==3 || date ==23) { s =2; } //print the 1st date number puttinychar(0+offset, 1, buffer[0]); //if date is under 10 - then we only have 1 digit so set positions of sufix etc one character nearer byte suffixposx =4; //if date over 9 then print second number and set xpos of suffix to be 1 char further away if (date> 9){ suffixposx =8; puttinychar(4+offset, 1, buffer[1]); offset =8; //offset to centre text if 4 chars } //print the 2 suffix characters puttinychar(suffixposx+offset, 1, suffix[s][0]); puttinychar(suffixposx+4+offset, 1, suffix[s][1]); задержка (1000); fade_down(); //print the month name //get length of text in pixels, that way we can centre it on the display by divindin the remaining pixels b2 and using that as an offset len =0; while(monthnames[month][len]) { len++; }; offset =(31 - ((len-1)*4)) / 2; //our offset to centre up the text i =0; while(monthnames[month][i]) { puttinychar((i*4) +offset, 1, monthnames[month][i]); i++; } задержка (1000); fade_down();}//dislpay menu to change the clock modevoid switch_mode() { //remember mode we are in. We use this value if we go into settings mode, so we can change back from settings mode (6) to whatever mode we were in. old_mode =clock_mode; char* modes[] ={ "Basic", "Small", "Slide", "Words", "Setup" }; byte next_clock_mode; byte firstrun =1; //loop waiting for button (timeout after 35 loops to return to mode X) for (int count =0; count <35; count++) { //if user hits button, change the clock_mode if (buttonA.uniquePress() || firstrun ==1) { count =0; cls(); if (firstrun ==0) { clock_mode++; } if (clock_mode> NUM_DISPLAY_MODES + 1 ) { clock_mode =0; } //print arrown and current clock_mode name on line one and print next clock_mode name on line two char str_top[9]; //strcpy (str_top, "-"); strcpy (str_top, modes[clock_mode]); next_clock_mode =clock_mode + 1; if (next_clock_mode> NUM_DISPLAY_MODES + 1 ) { next_clock_mode =0; } byte i =0; while (str_top[i]) { putnormalchar(i * 6, 0, str_top[i]); i++; } firstrun =0; } задержка (50); }}//run clock main loop as long as run_mode returns truebyte run_mode() { //if random mode is on... check the hour when we change mode. if (random_mode) { //if hour value in change mode time =hours. then reurn false =i.e. exit mode. if (change_mode_time ==rtc[2]) { //set the next random clock mode and time to change it set_next_random(); //exit the current mode. возврат 0; } } //else return 1 - keep running in this mode return 1;}//set the next hour the clock will change mode when random mode is onvoid set_next_random() { //set the next hour the clock mode will change - current time plus 1 - 4 hours get_time(); change_mode_time =rtc[2] + random (1, 5); //if change_mode_time now happens to be over 23, then set it to between 1 and 3am if (change_mode_time> 23) { change_mode_time =random (1, 4); } //set the new clock mode clock_mode =random(0, NUM_DISPLAY_MODES + 1); //pick new random clock mode}//dislpay menu to change the clock settingsvoid setup_menu() { char* set_modes[] ={ "Rndom", "24 Hr","Set", "Brght", "Exit"}; if (ampm ==0) { set_modes[1] =("12 Hr"); } byte setting_mode =0; byte next_setting_mode; byte firstrun =1; //loop waiting for button (timeout after 35 loops to return to mode X) for(int count=0; count <35; count++) { //if user hits button, change the clock_mode if(buttonA.uniquePress() || firstrun ==1){ count =0; cls(); if (firstrun ==0) { setting_mode++; } if (setting_mode> NUM_SETTINGS_MODES) { setting_mode =0; } //print arrown and current clock_mode name on line one and print next clock_mode name on line two char str_top[9]; strcpy (str_top, set_modes[setting_mode]); next_setting_mode =setting_mode + 1; if (next_setting_mode> NUM_SETTINGS_MODES) { next_setting_mode =0; } byte i =0; while(str_top[i]) { putnormalchar(i*6, 0, str_top[i]); i++; } firstrun =0; } задержка (50); } //pick the mode switch(setting_mode){ case 0:set_random(); ломать; case 1:set_ampm(); ломать; case 2:set_time(); ломать; case 3:set_intensity(); ломать; case 4://exit menu break; } //change the clock from mode 6 (settings) back to the one it was in before clock_mode=old_mode;}//toggle random mode - pick a different clock mode every few hoursvoid set_random(){ cls(); char text_a[9] ="Off"; char text_b[9] ="On"; byte i =0; //if random mode is on, turn it off if (random_mode){ //turn random mode off random_mode =0; //print a message on the display while(text_a[i]) { putnormalchar((i*6), 0, text_a[i]); i++; } } else { //turn randome mode on. random_mode =1; //set hour mode will change set_next_random(); //print a message on the display while(text_b[i]) { putnormalchar((i*6), 0, text_b[i]); i++; } } delay(1500); //leave the message up for a second or so}//set 12 or 24 hour clockvoid set_ampm() { // AM/PM or 24 hour clock mode - flip the bit (makes 0 into 1, or 1 into 0 for ampm mode) ampm =(ampm ^ 1); cls();}//change screen intensityintensityvoid set_intensity() { cls(); byte i =0; char text[7] ="Bright"; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i++; } //wait for button input while (!buttonA.uniquePress()) { levelbar (0,6,(intensity*2)+2,2); //display the intensity level as a bar while (buttonB.isPressed()) { if(intensity ==15) { intensity =0; cls (); } else { intensity++; } //print the new value i =0; while(text[i]) { puttinychar((i*4)+4, 0, text[i]); i++; } //display the intensity level as a bar levelbar (0,6,(intensity*2)+2,2); //change the brightness setting on the displays for (byte address =0; address <4; address++) { lc.setIntensity(address, intensity); } delay(150); } }}// display a horizontal bar on the screen at offset xposr by ypos with height and width of xbar, ybarvoid levelbar (byte xpos, byte ypos, byte xbar, byte ybar) { for (byte x =0; x  
LibrariesArduino
 Нет предварительного просмотра (только загрузка). 

Схема


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

  1. Светодиодный секвенсор
  2. Часы с кукушкой
  3. MATLAB — Матрица
  4. Битва с мини-боссом
  5. Основные часы
  6. Берлинские часы
  7. Светодиодные часы POV в аналоговом стиле
  8. Светодиодная матрица + датчик движения дверной дисплей [Arduino Holiday]
  9. 8-кратное светодиодное освещение со звуком
  10. Четвероногий Arduino