СОДЕРЖАНИЕ ►
Часы на адресной светодиодной ленте ws2812b — проект, который можно собрать на Arduino Nano. Для реализации этого проекта можно использовать датчик температуры и влажности DHT11 (DHT22) или датчик атмосферного давления BMP180 (GY-68). Для обоих вариантов электронных часов на Ардуино вы найдете далее электрическую схему для сборки устройства и рабочую программу для микроконтроллера.

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

Для сборки проекта потребуется изготовить корпус для светодиодной матрицы, закрепить адресную ленту и спаять ее согласно представленной схеме ниже. Если у вас уже есть в наличии матрица на ws2812b светодиодах и ее схема сборки отличается от представленной нами, то вы тоже сможете ее использовать, изменив настройки для подключения матрицы к микроконтроллеру Ардуино в коде программы.
Arduino часы из адресной ленты своими руками
Для этого проекта потребуется:
- Arduino Uno / Arduino Nano / Arduino Mega;
- адресная LED лента ws2812b;
- блок питания 5 Вольт;
- датчик DHT11 / BMP180;
- корпус для светодиодного табло;
- провода «папа-папа», «папа-мама».

После сборки корпуса для часов на ws2812b светодиодной ленте следует подключить матрицу и необходимые модули к микроконтроллеру. Далее размещены два варианта электрической схемы сборки электронных часов на адресных светодиодах. Все необходимые библиотеки для работы проекта, макет для резки корпуса на лазерном станке и представленные скетчи можно скачать одним архивом здесь.
Схема часов Arduino на ws2812b с датчиком DHT11

Для питания светодиодной матрицы, а также микроконтроллера со всеми датчиками и модулями можно использовать один источник питания 5 Вольт с достаточной силой тока. Адресная лента подключается к порту 9 через резистор 200-400 Ом для защиты пина от выгорания. Модуль часов подключается к микроконтроллеру по шине IIC к портам A4 и A5, если используется плата Arduino Mega — то порты 20 и 21.
Скетч для часов на Ардуино с температурой воздуха
#include "Adafruit_GFX.h" // библиотеки для работы с адресной лентой #include "Adafruit_NeoMatrix.h" #include "Adafruit_NeoPixel.h" #include "DHT.h" // библиотека для датчика DHT11 #include "iarduino_RTC.h" // библиотека для модуля часов iarduino_RTC time(RTC_DS3231); #define DHT_PIN 2 // порт подключения датчика DHT11 #define LED_PIN 9 // порт подключения адресной ленты #define WIDTH 30 // ширина матрицы в пикселях #define ROWS 7 // количество строк в матрице boolean humidity = true; // выводить влажность воздуха - true/false unsigned int timer = 50; // скорость бегущей строки unsigned int pausa1 = 10000; // на сколько мсек остановится время на табло unsigned int pausa2 = 1000; // на сколько мсек остановится температура и влажность unsigned int brightness = 200; // яркость матрицы с адресной лентой // настройки матрицы (если текст выводится некорректно, следует их изменить) Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(WIDTH, ROWS, 1, 1, LED_PIN, NEO_MATRIX_RIGHT + NEO_MATRIX_BOTTOM + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800); DHT dht(DHT_PIN, DHT11); // создаем объект для датчика температуры byte w, t, h; int x = WIDTH; void setup() { dht.begin(); // запускаем датчик давления Serial.begin(9600); // запускаем монитор порта matrix.begin(); matrix.fillScreen(0); // установка цветовой палитры адресной ленты (RGB) matrix.setTextColor(matrix.Color(0, 0, 255)); matrix.setTextWrap(false); matrix.setBrightness(brightness); time.begin(); // после установки времени и загрузки скетча в плату Ардуино // закомментируйте следующую строчку и снова загрузите скетч в плату time.settime(0, 35, 17, 12, 14, 21, 2); // сек, мин, час, число, месяц, год, день недели } void loop() { // выводим на монитор порта: температуру, влажность и время t = dht.readTemperature(); h = dht.readHumidity(); Serial.print(t); Serial.println("°C"); Serial.print(h); Serial.println("%"); Serial.println(time.gettime("H:i")); // два варианта вывода информации на табло (ненужный можно удалить) variant1(); // первый вариант с бегущей строкой variant2(); // второй вариант с плавным затуханием } void variant1() { matrix.setBrightness(brightness); matrix.fillScreen(0); w = 1; // == выводим время (часы и минуты) на светодиодное табло == // while (w == 1) { matrix.fillScreen(0); matrix.setCursor(x, 0); matrix.print(time.gettime("H:i")); matrix.show(); delay(timer); x--; // когда текст оказывается посередине табло - делаем паузу if (x == -1) { delay(pausa1); } if (x < - WIDTH) { x = WIDTH; w = 2; } } // == выводим температуру воздуха на светодиодное табло == // while (w == 2) { matrix.fillScreen(0); matrix.setCursor(x, 0); matrix.print(t); matrix.print("'C"); matrix.show(); delay(timer); x--; // когда текст оказывается посередине табло - делаем паузу if (x == 3) { delay(pausa2); } if (x < - WIDTH && humidity == true) { x = WIDTH; w = 3; } if (x < - WIDTH && humidity == false) { x = WIDTH; w = 0; } } // == выводим влажность воздуха на светодиодное табло == // while (w == 3) { matrix.fillScreen(0); matrix.setCursor(x, 0); matrix.print(h); matrix.print("%"); matrix.show(); delay(timer); x--; // когда текст оказывается посередине табло - делаем паузу if (x == 6) { delay(pausa2); } if (x < - WIDTH) { x = WIDTH; w = 0; } } } void variant2() { matrix.setBrightness(0); matrix.fillScreen(0); w = 1; // == плавное появление/исчезновение времени на табло == // while (w == 1) { for (byte i = 0; i < brightness; i++) { matrix.setBrightness(i); matrix.setCursor(0, 0); matrix.print(time.gettime("H:i")); matrix.show(); delay(timer / 10); } delay(pausa1); // пауза перед затуханием надписи for (byte i = brightness; i > 0; i--) { matrix.setBrightness(i); matrix.setCursor(0, 0); matrix.print(time.gettime("H:i")); matrix.show(); delay(timer / 10); } matrix.setBrightness(0); delay(timer * 10); w = 2; } // == плавное появление/исчезновение температуры воздуха == // while (w == 2) { for (byte i = 0; i < brightness; i++) { matrix.setBrightness(i); matrix.setCursor(4, 0); matrix.print(t); matrix.print("'C"); matrix.show(); delay(timer / 10); } delay(pausa2); // пауза перед затуханием надписи for (byte i = brightness; i > 0; i--) { matrix.setBrightness(i); matrix.setCursor(4, 0); matrix.print(t); matrix.print("'C"); matrix.show(); delay(timer / 10); } matrix.setBrightness(0); delay(timer * 2); if (humidity == true) { w = 3; } if (humidity == false) { w = 0; } } // == плавное появление/исчезновение влажности воздуха == // while (w == 3) { for (byte i = 0; i < brightness; i++) { matrix.setBrightness(i); matrix.setCursor(6, 0); matrix.print(h); matrix.print("%"); matrix.show(); delay(timer / 10); } delay(pausa2); // пауза перед затуханием надписи for (byte i = brightness; i > 0; i--) { matrix.setBrightness(i); matrix.setCursor(6, 0); matrix.print(h); matrix.print("%"); matrix.show(); delay(timer / 10); } matrix.setBrightness(0); delay(timer * 10); w = 0; } }
Пояснения к коду:
- после установки времени на модуле часов, закомментируйте строчку time.settime(); и снова загрузите скетч в плату — иначе после каждой перезагрузки микроконтроллера время будет устанавливаться по новому;
- ненужный цикл void variant1() или void variant2() можно удалить, а также удалить команду для вызова соответствующего цикла;
- если текст выводится (останавливается) не по центру led матрицы, то измените позицию текста в функции matrix.setCursor();.
Схема часов Arduino на ws2812b с датчиком BMP180
Датчик BMP180 Arduino позволяет узнать не только атмосферное давление, но и температуру воздуха в диапазоне от 0 до 65 градусов. Датчик давления подключается к микроконтроллеру по шине IIC, параллельно с модулем часов реального времени. После сборки схемы загрузите следующий код в плату — основные настройки (цвет, яркость матрицы и скорость прокрутки текста) можно изменить в начале скетча.

Скетч для часов на Ардуино с атмосферным давлением
#include "Adafruit_GFX.h" // библиотеки для работы с адресной лентой #include "Adafruit_NeoMatrix.h" #include "Adafruit_NeoPixel.h" #include "Wire.h" // библиотеки для датчика BMP180 #include "SFE_BMP180.h" #include "iarduino_RTC.h" // библиотека для модуля часов iarduino_RTC time(RTC_DS3231); #define LED_PIN 9 // порт подключения адресной ленты #define WIDTH 30 // ширина матрицы в пикселях #define ROWS 7 // количество строк в матрице #define ALTITUDE 166.0 // высота над уровнем моря, в метрах boolean davlenie = true; // выводить атмосферное давление - true/false unsigned int timer = 50; // скорость бегущей строки unsigned int pausa1 = 10000; // на сколько мсек остановится время на табло unsigned int pausa2 = 1000; // на сколько мсек остановится температура и давление unsigned int brightness = 200; // яркость матрицы с адресной лентой // настройки матрицы (если текст выводится некорректно, следует их изменить) Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(WIDTH, ROWS, 1, 1, LED_PIN, NEO_MATRIX_RIGHT + NEO_MATRIX_BOTTOM + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800); SFE_BMP180 pressure; // создаем объект для датчика давления char status; double t0, p, p0, a; int t, p_in, p_mm; byte w; int x = WIDTH; void setup() { pressure.begin(); // запускаем датчик давления Serial.begin(9600); // запускаем монитор порта matrix.begin(); matrix.fillScreen(0); // установка цветовой палитры адресной ленты (RGB) matrix.setTextColor(matrix.Color(0, 0, 255)); matrix.setTextWrap(false); matrix.setBrightness(brightness); time.begin(); // после установки времени и загрузки скетча в плату Ардуино // закомментируйте следующую строчку и снова загрузите скетч в плату time.settime(0, 35, 17, 12, 14, 21, 2); // сек, мин, час, число, месяц, год, день недели } void loop() { // выводим на монитор порта: температуру, давление и время status = pressure.startTemperature(); if (status != 0) { delay(status); // измерение температуры status = pressure.getTemperature(t0); if (status != 0) { t = (int)t0; Serial.print(t); Serial.println("°C"); // измерение давления status = pressure.startPressure(3); if (status != 0) { delay(status); status = pressure.getPressure(p, t0); p0 = pressure.sealevel(p, ALTITUDE); // абсолютное давление p_mm = (int)p0 * 0.7501; // давление в мм ртутного столба Serial.print(p0); Serial.print(" mb, "); Serial.print(p_mm); Serial.println(" mmHg"); } } } Serial.println(time.gettime("H:i")); // два варианта вывода информации на табло (ненужный можно удалить) variant1(); // первый вариант с бегущей строкой variant2(); // второй вариант с плавным затуханием } void variant1() { matrix.setBrightness(brightness); matrix.fillScreen(0); w = 1; // == выводим время (часы и минуты) на светодиодное табло == // while (w == 1) { matrix.fillScreen(0); matrix.setCursor(x, 0); matrix.print(time.gettime("H:i")); matrix.show(); delay(timer); x--; // когда текст оказывается посередине табло - делаем паузу if (x == -1) { delay(pausa1); } if (x < - WIDTH) { x = WIDTH; w = 2; } } // == выводим температуру воздуха на светодиодное табло == // while (w == 2) { matrix.fillScreen(0); matrix.setCursor(x, 0); matrix.print(t); matrix.print("'C"); matrix.show(); delay(timer); x--; // когда текст оказывается посередине табло - делаем паузу if (x == 3) { delay(pausa2); } if (x < - WIDTH && davlenie == true) { x = WIDTH; w = 3; } if (x < - WIDTH && davlenie == false) { x = WIDTH; w = 0; } } // == выводим атмосферное давление на светодиодное табло == // while (w == 3) { matrix.fillScreen(0); matrix.setCursor(x, 0); matrix.print(p_mm); matrix.print("mm"); matrix.show(); delay(timer); x--; // когда текст оказывается посередине табло - делаем паузу if (x == 0) { delay(pausa2); } if (x < - WIDTH) { x = WIDTH; w = 0; } } } void variant2() { matrix.setBrightness(0); matrix.fillScreen(0); w = 1; // == плавное появление/исчезновение времени на табло == // while (w == 1) { for (byte i = 0; i < brightness; i++) { matrix.setBrightness(i); matrix.setCursor(0, 0); matrix.print(time.gettime("H:i")); matrix.show(); delay(timer / 10); } delay(pausa1); // пауза перед затуханием надписи for (byte i = brightness; i > 0; i--) { matrix.setBrightness(i); matrix.setCursor(0, 0); matrix.print(time.gettime("H:i")); matrix.show(); delay(timer / 10); } matrix.setBrightness(0); delay(timer * 10); w = 2; } // == плавное появление/исчезновение температуры воздуха == // while (w == 2) { for (byte i = 0; i < brightness; i++) { matrix.setBrightness(i); matrix.setCursor(4, 0); matrix.print(t); matrix.print("'C"); matrix.show(); delay(timer / 10); } delay(pausa2); // пауза перед затуханием надписи for (byte i = brightness; i > 0; i--) { matrix.setBrightness(i); matrix.setCursor(4, 0); matrix.print(t); matrix.print("'C"); matrix.show(); delay(timer / 10); } matrix.setBrightness(0); delay(timer * 2); if (davlenie == true) { w = 3; } if (davlenie == false) { w = 0; } } // == плавное появление/исчезновение атмосферное давление == // while (w == 3) { for (byte i = 0; i < brightness; i++) { matrix.setBrightness(i); matrix.setCursor(0, 0); matrix.print(p_mm); matrix.print("mm"); matrix.show(); delay(timer / 10); } delay(pausa2); // пауза перед затуханием надписи for (byte i = brightness; i > 0; i--) { matrix.setBrightness(i); matrix.setCursor(0, 0); matrix.print(p_mm); matrix.print("mm"); matrix.show(); delay(timer / 10); } matrix.setBrightness(0); delay(timer * 10); w = 0; } }
Пояснения к коду:
- данная программа от предыдущей отличается только сменой датчика;
- установите значение boolean davlenie = false;, если вам не требуется выводить атмосферное давление на матрице ws2812b.
Заключение. Проект часов на адресной светодиодной ленте можно развивать и улучшать бесконечно, например, добавить функцию настройки яркости и цвета матрицы или сделать управление ws2812b матрицы через Bluetooth или Wi-Fi. Если у вас остались вопросы или замечания по данному проекту — оставляйте их в комментариях к этой записи, мы обязательно ответим на все ваши вопросы.










Спасибо. Для меня приятная новость что можно просто физически параллелить 2 датчика на пинах 4 и 5. Все очень познавательни и легко читается. Из минусов могу сказать разве что если в момент индикации времени меняется минута (с часом наверно то же самое будет) то горят все светодиоды на 2 цифры, не обновляется сегмент. А так все супер!
Доброго дня.
Можно подключить матрицу 8*32 на МАХ7219?
Что для этого надо поправить?
Может есть уже готовый вариант скетча, буду благодарен.
Интересует первый скетч — температура-влажность.
Здравствуйте уважаемые авторы проекта «Часы на адресной матрице ws2812b Arduino» Повторил Ваш проект, все заработало. Но в связи с тем, что я только начинающий Ардуинщик и не в силах внести изменения в проект прошу Вашей помощи (мне кажется, что Вы сами понимаете проект в таком состоянии сырой, время выводится не из памяти модуля DS3231, питание пропадает и время сбивается)
Чтобы время не сбивалось, после корректной установки времени, удалите строчку time.settime(); и снова загрузите программу. Без этой операции у вас при каждой перезагрузке платы время будет устанавливаться по-новому. Если вы это сделаете, то кнопки для корректировки времени не понадобятся лет 10-15 (пока батарейка не сядет).
Со временем разобрался, спасибо.
Подскажите чтобы дветочие замигало в ходе появления часов, какую строку скетчи необходимо добавить ли подправить. Заранее благодарен
Первый раз сталкиваюсь с адресными светодиодами. Скажите пожалуйста сколько должно быть светодиодов (шт) в строке? Я понял должно быть 7 строк. Схему сборки я понял.
Все же написано в коде:
#define WIDTH 30 // ширина матрицы в пикселях
ДОБРЫЙ ДЕНЬ! ПОДСКАЖИТЕ ПОЖАЛУСТА КАК ИЗМЕНИТЬ СКЕТЧ ЕСЛИ У МЕНЯ УСТАНОВЛЕН МОДУЛЬ ЧАСОВ DS-1302. ЧТО НУЖНО СДЕЛАТЬ???????????
Изменить строчку
iarduino_RTC time(RTC_DS3231);
на
iarduino_RTC time(RTC_DS1302,6,8,7);
А еще лучше изучить модуль — здесь
Прошу подсказки. Происходит ошибка в строе — iarduino_RTC time(RTC_DS3231).
‘arduino RTC time’ redeclared as different kind of symbol
«Время iarduino_RTC» переопределено как символ другого типа.
Здравствуйте.
Проект очень хороший.
Когда будет продолжение с новыми функциями ?
Спасибо.
Добрый день
Как поправить скетч чтобы работал с матрицей 18×6?
Заранее благодарен
Надо указать ширину и высоту матрицы в пикселях:
#define WIDTH 18 // ширина матрицы в пикселях
#define ROWS 6 // количество строк в матрице
Изменил, но часы отображаются некорректно
Отображаются только минуты на табло
Вы уверены что на вашей матрице достаточно ширины для отображения часов и минут?
Здравствуйте.Всё красиво, только как сделать чтобы датчик DHT22 показывал уличную температуру с —
Надо подключить dht22 вместо dht11 (указать это еще в программе) и вывести сам датчик на улицу
Здравствуйте. Проект очень хороший, но не показывает минусовую температуру. На табло выводится 254 С. Датчик DHT 22. В чём причина. Положительная температура выводится нормально. Как можно в скетче заменить DHT 22 на DS18b20
Спасибо за проект. Запустился сразу. Переделал на DS18b20. Так же сделал для часов и температуры разные цвета.
Здравствуйте.Подскажите, что переделать в скетче для работы с DS18b20. Мой E-mail — volodja52@mail.ru
Мне нужно для уличной температуры. На DHT-22 минусовую температуру показывает 225 градусов. Спасибо.
Или, если можно, Ваш скетч.
Здравствуйте. Поделитесь скетчем с датчиком DS18b20 mail — aleks_vag@list.ru
Доброго времени суток, не могли вы бы поделится скетчем для DS18B20? Спасибо ,с уважением Вячеслав. Мой адрес camrem78@mail.ru
Что то не могу сделать мигающие точки в часах. Подскажите пожалуйста.
Всё точки сделал, мигают:)
Часы работают с марта месяца, всё хорошо. Но. Время ушло немного в перёд и , что бы подкорректировать надо подключатся к компьютеру и снова загружать скетч. Уважаемый автор помогите подключить кнопки для корректировки часов, без них не очень удобно.
Добрый день.У меня матрица 8 строк в каждой строке по 31 диоду как указать ширину матрици в скече.Указал в скече 8 строк ширину 30 показывает не понятно что.
Схема подключений строк такая же, как на схеме? Если да, то проверьте надежность соединения контактов. Если нет, то меняйте схему или настройки для матрицы в скетче в строке:
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(WIDTH, ROWS, 1, 1, LED_PIN, NEO_MATRIX_RIGHT + NEO_MATRIX_BOTTOM + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800);Спасибо за помощь все работает. Как поменять цвет на матрице?
Доброго времени.
Попробовал повторить ваши часики, вроде получилось. Но возникла маленькая загвоздка.
Помогите пожалуйста, хотел подключить BMP280 вместо BMP180, никак не получается.
пробовал разные библиотеки- результат нулевой.
Здравствуйте. У кого-нибудь получилось отображать отрицательную температуру? Переделал на датчик DS18B20, в мониторе порта отрицательная температура отображается, а на матрице так же как и с датчиком DHT-22 показывает 255.
для отрицательных значений следует использовать тип данных int для переменной температуры (t) Надеюсь понятно объяснил?
Спасибо за ответ. Попробую разобраться. Это моя первая конструкция на ардуино.
Здравствуйте, такая проблема, при подключении питания то горит, но моргает последний седьмой ряд и то не все светодиоды. Остальные ряды вообще не горят, в чем может быть проблема?
Здравствуйте! Хочу сделать часы с секундами на матрице 7 на 48. Мне кажется AdafruitNeoMatrix
не потянет так как там в ней везде uint_8. Какой выход?
Здравствуйте. Повторил Ваш проект ,все работает,но хотелось бы использовать DS18B20, и как прописать вывод даты. Новичок .Если можно скетч отправить на Slovak23@yandex.ru
Нашел нужную библиотеку, скетч загрузился, но на экране белиберда. Какие данные поменять в настройке матрицы? Схема подключения как у Вас. Размер 21Х7.
Есть ли те кто могут продать данный проект? У самого не получается его сделать. Нужен для курсовой работы в колледж.
Всем доброго времени! В чем может быть проблема, если все показания передаются зеркально? Если на зеркало направить матрицу тогда понятно )
У Вас матрица спаяна на выворот) Начало, как правило, снизу слева.
Всем привет! Пара вопросов по проекту.
1. Как решали вопрос по питанию? Судя по спецификации тут нужен источник на 60Вт (5в,12А). Что ставили один мощный или несколько слабеньких?
2. Светодиоды греются? основа из фанеры нормально подходит или лучше делать подложку металлическую?
1. один мощный источник
2. светодиоды не греются
Здравствуйте. Подскажите почему зажигает не все пикселы в верхней строке 2,3,5,6,7,,8,9 Спасибо.
Спасибо за скетч всё работает. Добавил библиотеку (wire.h)