СОДЕРЖАНИЕ ►
Еще один проект часов на Ардуино с дисплеем OLED i2c 128×64 и датчиком температуры и влажности воздуха DHT11 (можно заменить на датчик давления BMP180). Мы разместили сразу два варианта — с модулем часов реального времени RTC (время можно установить только в самой программе) и без модуля RTC (время настроить можно в любой момент). Оба варианта с функцией будильника.

Ардуино часы на OLED i2c с датчиком DHT11
Если вы используете плату Arduino Mega, то на этой плате порты SDA и SCL для расположены на 20 и 21 пине. У платы Arduino Nano распиновка такая же, как на Uno и дисплей подключается к портам A4 (SDA) и A5 (SCL). Кнопки подключаются к цифровым портам Arduino, сконфигурированных в режиме INPUT_PULLUP — при таком способе подключения можно считывать количество нажатий на кнопку.
Для этого проекта потребуется:
- Arduino Uno / Arduino Nano / Arduino Mega
- дисплей oled 128×64
- датчик DHT11 / модуль RTC
- 2 тактовые кнопки и пьезодинамик
- макетная плата
- провода «папа-мама», «папа-папа»

| OLED i2c 0,96 | Arduino Uno | Arduino Nano | Arduino Mega |
| GND | GND | GND | GND |
| VDD | 5V | 5V | 5V |
| SDA | A4 | A4 | 20 |
| SCL | A5 | A5 | 21 |
На картинке выше изображена схема сборки проекта, а в таблице указаны пины подключения OLED дисплея к плате Ардуино. Для работы с дисплеем потребуется библиотека OLED_I2C.h, а для датчика температуры DHT.h. Архивы с библиотеками можно скачать на нашем сайте здесь. После сборки схемы и установки нужных библиотек загрузите следующую программу в микроконтроллер Ардуино.
Скетч. Часы на OLED дисплее без модуля RTC
#include "DHT.h" DHT dht(2, DHT11); #include "OLED_I2C.h" OLED myOLED(SDA, SCL, 8); extern uint8_t SmallFont[]; extern uint8_t BigNumbers[]; // переменные для отсчета времени и будильника byte SEC = 0; byte MIN = 59; byte HOUR = 7; byte MIN_A = 0; byte HOUR_A = 8; unsigned long timer; // переменные для считывания нажатия на кнопки boolean button1WasUp = true; boolean button2WasUp = true; boolean button1IsUp; boolean button2IsUp; boolean alarm = true; byte w, i; void setup() { pinMode(9, INPUT_PULLUP); // подключаем тактовые кнопки pinMode(8, INPUT_PULLUP); pinMode(5, OUTPUT); // подключаем пьезодинамик dht.begin(); myOLED.begin(); timer = millis(); } void loop() { int h = dht.readHumidity(); int t = dht.readTemperature(); // узнаем текущее состояние кнопки button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 нажата, заходим в настройки (цикл while) if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { SEC = 0; w = 1; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата выключаем будильник if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { alarm = !alarm; } } button2WasUp = button2IsUp; // если прошло 1000 мс - прибавляем одну секунду if (millis() - timer > 1000) { timer = millis(); SEC++; // если прошло 59 секунд, прибавляем 1 минуту if (SEC > 59) { SEC = 0; MIN++; } // если прошло 59 минут, прибавляем 1 час if (MIN > 59) { MIN = 0; HOUR++; } if (HOUR > 23) { HOUR = 0; } // включение будильника в течении 1 минуты if (alarm == true && HOUR == HOUR_A && MIN == MIN_A && i < 60) { tone(5, 50); i++; } if (i >= 60) { noTone(5); alarm == false; i = 0; } myOLED.clrScr(); // очищаем дисплей myOLED.setFont(BigNumbers); // подключаем шрифт для цифр // выводим текущее время if (HOUR < 10) { myOLED.print("0" + String(HOUR) + "-", 8, 20); } if (HOUR >= 10) { myOLED.print(String(HOUR) + "-", 8, 20); } if (MIN < 10) { myOLED.print("0" + String(MIN) + "-", 50, 20); } if (MIN >= 10) { myOLED.print(String(MIN) + "-", 50, 20); } if (SEC < 10) { myOLED.print("0" + String(SEC), 92, 20); } if (SEC >= 10) { myOLED.print(String(SEC), 92, 20); } myOLED.setFont(SmallFont); // подключаем шрифт для текста // выводим состояние будильника if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } // выводим температуру и влажность myOLED.print(String(t) + "' / " + String(h) + "% ", RIGHT, 55); myOLED.update(); noTone(5); } while (w == 1) { myOLED.clrScr(); myOLED.setFont(BigNumbers); if (HOUR > 23) { HOUR = 0; } if (HOUR < 10) { myOLED.print("0" + String(HOUR) + "-", 8, 20); } if (HOUR >= 10) { myOLED.print(String(HOUR) + "-", 8, 20); } if (MIN < 10) { myOLED.print("0" + String(MIN) + "-", 50, 20); } if (MIN >= 10) { myOLED.print(String(MIN) + "-", 50, 20); } myOLED.print("00", 92, 20); myOLED.setFont(SmallFont); if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } myOLED.print("HOUR SETTING", CENTER, 55); myOLED.update(); button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 была нажата, переходим во 2 цикл while if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 2; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата, прибавляем 1 час if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { HOUR++; } } button2WasUp = button2IsUp; } while (w == 2) { myOLED.clrScr(); myOLED.setFont(BigNumbers); if (MIN > 59) { MIN = 0;} if (HOUR < 10) { myOLED.print("0" + String(HOUR) + "-", 8, 20); } if (HOUR >= 10) { myOLED.print(String(HOUR) + "-", 8, 20); } if (MIN < 10) { myOLED.print("0" + String(MIN) + "-", 50, 20); } if (MIN >= 10) { myOLED.print(String(MIN) + "-", 50, 20); } myOLED.print("00", 92, 20); myOLED.setFont(SmallFont); if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } myOLED.print("MINUTE SETTING", CENTER, 55); myOLED.update(); button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 была нажата, переходим в 3 цикл while if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 3; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата, прибавляем 1 минуту if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { MIN++; } } button2WasUp = button2IsUp; } while (w == 3) { myOLED.clrScr(); myOLED.setFont(BigNumbers); if (MIN_A > 59) { MIN_A = 0; HOUR_A++; } if (HOUR_A > 23) { HOUR_A = 0; } if (HOUR_A < 10) { myOLED.print("0" + String(HOUR_A) + "-", 8, 20); } if (HOUR_A >= 10) { myOLED.print(String(HOUR_A) + "-", 8, 20); } if (MIN_A < 10) { myOLED.print("0" + String(MIN_A) + "-", 50, 20); } if (MIN_A >= 10) { myOLED.print(String(MIN_A) + "-", 50, 20); } myOLED.print("00", 92, 20); myOLED.setFont(SmallFont); if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } myOLED.print("ALARM SET HOUR", CENTER, 55); myOLED.update(); button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 была нажата, переходим в 4 цикл while if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 4; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата, прибавляем 1 час if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { HOUR_A++; } } button2WasUp = button2IsUp; } while (w == 4) { myOLED.clrScr(); myOLED.setFont(BigNumbers); if (MIN_A > 59) { MIN_A = 0; HOUR_A++; } if (HOUR_A > 23) { HOUR_A = 0; } if (HOUR_A < 10) { myOLED.print("0" + String(HOUR_A) + "-", 8, 20); } if (HOUR_A >= 10) { myOLED.print(String(HOUR_A) + "-", 8, 20); } if (MIN_A < 10) { myOLED.print("0" + String(MIN_A) + "-", 50, 20); } if (MIN_A >= 10) { myOLED.print(String(MIN_A) + "-", 50, 20); } myOLED.print("00", 92, 20); myOLED.setFont(SmallFont); if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } myOLED.print("ALARM SET MINUTE", CENTER, 55); myOLED.update(); button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 была нажата, выходим из цикла if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 0; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата, прибавляем 1 минуту if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { MIN_A++; } } button2WasUp = button2IsUp; } }
Пояснения к коду:
- в скетче предусмотрена возможность настройки времени и будильника;
- значения времени и будильника можно изменить в начале программы.

Второй вариант часов предусматривает использование модуля часов реального времени RTC на базе чипа DS1302/DS1307 с использованием библиотеки iarduino_RTC.h. Схема подключения модуля и дисплея к Ардуино изображена на картинке выше. Настройки даты и времени в программе устанавливаются функцией watch.settime();, с помощью кнопок можно будет настроить только будильник.
Скетч. Часы на OLED дисплее с модулем RTC
#include "DHT.h" DHT dht(2, DHT11); #include "OLED_I2C.h" OLED myOLED(SDA, SCL, 8); #include "Wire.h" #include "iarduino_RTC.h" iarduino_RTC watch(RTC_DS1302, 5, 6, 7); // RTC на базе чипа DS1302, RST, CLK, DAT. // iarduino_RTC watch(RTC_DS1307); // RTC на базе чипа DS1307, I2C. // iarduino_RTC watch(RTC_DS3231); // RTC на базе чипа DS3231, I2C. extern uint8_t SmallFont[]; extern uint8_t BigNumbers[]; // переменные для отсчета времени и будильника byte MIN_A = 0; byte HOUR_A = 8; unsigned long timer; // переменные для считывания нажатия на кнопки boolean button1WasUp = true; boolean button2WasUp = true; boolean button1IsUp; boolean button2IsUp; boolean alarm = true; byte w, i; void setup() { pinMode(9, INPUT_PULLUP); // подключаем тактовые кнопки pinMode(8, INPUT_PULLUP); pinMode(3, OUTPUT); // подключаем пьезодинамик dht.begin(); myOLED.begin(); timer = millis(); watch.begin(); // записываем время - 0 сек, 59 мин, 7 час, 16, февраля, 2022 года, среда watch.settime(0, 59, 7, 16, 02, 22, 3); } void loop() { int h = dht.readHumidity(); int t = dht.readTemperature(); // узнаем текущее состояние кнопки button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 нажата, заходим в настройки (цикл while) if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 1; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата выключаем будильник if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { alarm = !alarm; } } button2WasUp = button2IsUp; // если прошло 1000 мс - прибавляем одну секунду if (millis() - timer > 1000) { timer = millis(); // включение будильника в течении 1 минуты if (alarm == true && watch.Hours == HOUR_A && watch.minutes == MIN_A && i < 60) { tone(3, 50); i++; } if (i >= 60) { noTone(3); alarm == false; i = 0; } myOLED.clrScr(); // очищаем дисплей myOLED.setFont(BigNumbers); // подключаем шрифт для цифр // выводим текущее время myOLED.print(watch.gettime("H-i-s"), CENTER, 20); myOLED.setFont(SmallFont); // подключаем шрифт для текста // выводим температуру, влажность и состояние будильника if (alarm == true) { myOLED.print(String(t) + "' / " + String(h) + "% / on ", RIGHT, 3); } if (alarm == false) { myOLED.print(String(t) + "' / " + String(h) + "% / off", RIGHT, 3); } // выводим дату myOLED.print(watch.gettime("d.m.Y, D"), CENTER, 55); myOLED.update(); noTone(3); } while (w == 1) { myOLED.clrScr(); myOLED.setFont(BigNumbers); if (MIN_A > 59) { MIN_A = 0; HOUR_A++; } if (HOUR_A > 23) { HOUR_A = 0; } if (HOUR_A < 10) { myOLED.print("0" + String(HOUR_A) + "-", 8, 20); } if (HOUR_A >= 10) { myOLED.print(String(HOUR_A) + "-", 8, 20); } if (MIN_A < 10) { myOLED.print("0" + String(MIN_A) + "-", 50, 20); } if (MIN_A >= 10) { myOLED.print(String(MIN_A) + "-", 50, 20); } myOLED.print("00", 92, 20); myOLED.setFont(SmallFont); if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } myOLED.print("ALARM SET HOUR", CENTER, 55); myOLED.update(); button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 была нажата, переходим во 2 цикл while if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 2; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата, прибавляем 1 час if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { HOUR_A++; } } button2WasUp = button2IsUp; } while (w == 2) { myOLED.clrScr(); myOLED.setFont(BigNumbers); if (MIN_A > 59) { MIN_A = 0; HOUR_A++; } if (HOUR_A > 23) { HOUR_A = 0; } if (HOUR_A < 10) { myOLED.print("0" + String(HOUR_A) + "-", 8, 20); } if (HOUR_A >= 10) { myOLED.print(String(HOUR_A) + "-", 8, 20); } if (MIN_A < 10) { myOLED.print("0" + String(MIN_A) + "-", 50, 20); } if (MIN_A >= 10) { myOLED.print(String(MIN_A) + "-", 50, 20); } myOLED.print("00", 92, 20); myOLED.setFont(SmallFont); if (alarm == true) { myOLED.print("on ", RIGHT, 3); } if (alarm == false) { myOLED.print("off", RIGHT, 3); } myOLED.print("ALARM SET MINUTE", CENTER, 55); myOLED.update(); button1IsUp = digitalRead(9); button2IsUp = digitalRead(8); // если кнопка 1 была нажата, выходим из цикла if (button1WasUp && !button1IsUp) { delay(10); button1IsUp = digitalRead(9); if (!button1IsUp) { w = 0; } } button1WasUp = button1IsUp; // если кнопка 2 была нажата, прибавляем 1 минуту if (button2WasUp && !button2IsUp) { delay(10); button2IsUp = digitalRead(8); if (!button2IsUp) { MIN_A++; } } button2WasUp = button2IsUp; } }
Пояснения к коду:
- после прошивки модуля RTC и установки нужной даты с временем, закомментируйте или удалите строчку watch.settime(0, 59, 7, 16, 02, 22, 3); в программе и снова загрузите код в Ардуино;
- в этом варианте прошивки часов нет возможности настраивать время с помощью кнопок, можно установить только будильник.
Заключение. Мы представили сразу два варианта часов на OLED дисплее — с модулем реального времени RTC и без него. Также на нашем сайте есть пример программы со схемой сборки часов на LCD дисплее. Все вопросы или полезные замечания по этому проекту вы можете оставлять в комментариях к этой записи.










Здравствуйте!
А в какой программе Вы собирали схему?
fritzing
Здравствуйте! К чему подходит pin5 на схеме часов без модуля RTC? В списке того, что потребуется для данного проекта, я не нашла, что это?
Если честно, сам не понимаю, что это было. Схему исправили
Подключил всё правильно, но DHT не показывает температуру и влажность
Два бесполезных проекта. Одни часы с точностью пару минут в сутки, вторые — без возможности установки времени. Ну и зачем это надо? Для «наполнения сайта»?
Видимо так.
Уважаемые юзеры, Не будьте занудами, лучше выкладывайте свои — полезные и безошибочные проекты. Люди м.б. учатся, постигают программирование, а вы их сразу… фейсом об тэйбл! Нельзя так! Лучше сказать спасибо и внести дополнения, улучшающие проект!
Собрал вторые часы,все работает,спасибо автору за полезные проекты,написано выше что нет возможности установить время,как же нельзя?в в скетче есть настройка времени
Спасибо! Только начал в этом разбираться, очень помогла статья, все понятно, даже мне)))