На днях я решил создать часы на arduino с отображением времени, текущей даты, дня недели и температуры воздуха на OLED дисплее. Что из этого получилось смотрите на видео.
Список необходимых компонентов:
- Часовой модуль DS1307 – 1 шт.
- Датчик температуры DS18B20 – 1 шт.
- OLED I2C дисплей 0.96″ – 1 шт.
- Плата Arduino nano V 3.0 – 1 шт.
Для начала нам потребуется скачать и установить необходимые библиотеки:
Далее подключаем все по схеме
и загружаем первый пробный скетч для проверки работоспособности дисплея и часового модуля
#include <OLED_I2C.h> // Подключение библиотеки для дисплея OLED myOLED(SDA, SCL, 8); extern uint8_t MegaNumbers[]; // Подключение больших шрифтов extern uint8_t SmallFont[]; // Подключение маленьких шрифтов #include <DS1307.h> // Подключение библиотеки для часового модуля DS1307 rtc(A0, A1); void setup() { myOLED.begin(); rtc.halt(false); rtc.setDOW(SUNDAY); // Настройка дня недели rtc.setTime(12, 0, 0); // Настройка времени rtc.setDate(10, 05, 2015); // Настройка даты } void loop(){ myOLED.setFont(SmallFont); myOLED.print(rtc.getDOWStr(), CENTER, 0); // Отображение дня недели String stringOne = rtc.getTimeStr(); myOLED.setFont(MegaNumbers); myOLED.print(stringOne.substring(0,2), 4, 12); // Отображение часов myOLED.print("/", 51, 12); // Отображение двоеточия myOLED.print(stringOne.substring(3,5), 75, 12); // Отображение минут myOLED.setFont(SmallFont); myOLED.print(rtc.getDateStr(), CENTER, 57); // Отображение даты myOLED.update(); delay(500); myOLED.setFont(MegaNumbers); // Скрытие двоеточия myOLED.print("-", 51, 12); myOLED.update(); delay(500); }
после загрузки скетча у нас на дисплее отобразятся часы как на фото
Как видим все отображается нормально, но что бы добавить русские названия дней недели нам потребуется инициализировать русские шрифты добавив строку в скетч
extern uint8_t RusFont[];
и еще добавить строки которые помогут нам определить порядковый номер дня недели и отобразить название дня на русском языке.
switch (t.dow) { case 1: myOLED.print("GJYTLTKMYBR", CENTER, 0); break; case 2: myOLED.print("DNJHYBR", CENTER, 0); break; case 3: myOLED.print("CHTLF", CENTER, 0); break; case 4: myOLED.print("XTNDTHU", CENTER, 0); break; case 5: myOLED.print("GZNYBWF", CENTER, 0); break; case 6: myOLED.print("CE<<JNF", CENTER, 0); break; case 7: myOLED.print("DJCRHTCTYMT", CENTER, 0); break; }
и еще закомментируем строки
// rtc.setDOW(MONDAY); // rtc.setTime(13, 25, 0); // rtc.setDate(27, 04, 2015);
что бы при повторной загрузке скетча не устанавливать заново время. После этого день недели на нашем дисплее отобразится на русском языке.
теперь изменим отображения месяца, добавив в скетч строки
switch (t.mon) { case 1: myOLED.print(String(t.date), 30, 57); myOLED.print("ZYDFHZ", CENTER, 57); myOLED.print(String(t.year), 88, 57); break; case 2: myOLED.print(String(t.date), 26, 57); myOLED.print("ATDHFKZ", CENTER, 57); myOLED.print(String(t.year), 92, 57); break; case 3: myOLED.print(String(t.date), 30, 57); myOLED.print("VFHNF", CENTER, 57); myOLED.print(String(t.year), 88, 57); break; case 4: myOLED.print(String(t.date), 30, 57); myOLED.print("FGHTKZ", CENTER, 57); myOLED.print(String(t.year), 88, 57); break; case 5: myOLED.print(String(t.date), 36, 57); myOLED.print("VFZ", CENTER, 57); myOLED.print(String(t.year), 82, 57); break; case 6: myOLED.print(String(t.date), 35, 57); myOLED.print("B>YZ", CENTER, 57); myOLED.print(String(t.year), 81, 57); break; case 7: myOLED.print(String(t.date), 35, 57); myOLED.print("B>KZ", CENTER, 57); myOLED.print(String(t.year), 81, 57); break; case 8: myOLED.print(String(t.date), 28, 57); myOLED.print("FDUECNF", CENTER, 57); myOLED.print(String(t.year), 90, 57); break; case 9: myOLED.print(String(t.date), 24, 57); myOLED.print("CTYNZ<HZ", CENTER, 57); myOLED.print(String(t.year), 94, 57); break; case 10: myOLED.print(String(t.date), 26, 57); myOLED.print("JRNZ<HZ", CENTER, 57); myOLED.print(String(t.year), 92, 57); break; case 11: myOLED.print(String(t.date), 28, 57); myOLED.print("YJZ<HZ", CENTER, 57); myOLED.print(String(t.year), 90, 57); break; case 12: myOLED.print(String(t.date), 26, 57); myOLED.print("LTRF<HZ", CENTER, 57); myOLED.print(String(t.year), 92, 57); break; }
Теперь наши часики будут выглядеть как на фото.
Для тех, кому было лень править скетч, ниже есть готовый скетч.
#include <OLED_I2C.h> OLED myOLED(SDA, SCL, 8); extern uint8_t MegaNumbers[]; extern uint8_t RusFont[]; extern uint8_t SmallFont[]; #include <DS1307.h> DS1307 rtc(A0, A1); Time t; void setup() { myOLED.begin(); rtc.halt(false); // rtc.setDOW(WEDNESDAY); // rtc.setTime(10, 02, 0); // rtc.setDate(29, 4, 2015); } void loop() { myOLED.setFont(RusFont); t = rtc.getTime(); switch (t.dow) { case 1: myOLED.print("GJYTLTKMYBR", CENTER, 0); break; case 2: myOLED.print("DNJHYBR", CENTER, 0); break; case 3: myOLED.print("CHTLF", CENTER, 0); break; case 4: myOLED.print("XTNDTHU", CENTER, 0); break; case 5: myOLED.print("GZNYBWF", CENTER, 0); break; case 6: myOLED.print("CE<<JNF", CENTER, 0); break; case 7: myOLED.print("DJCRHTCTYMT", CENTER, 0); break; } String stringOne = rtc.getTimeStr(); myOLED.setFont(MegaNumbers); myOLED.print(stringOne.substring(0, 2), 4, 12); myOLED.print("/", 51, 12); myOLED.print(stringOne.substring(3, 5), 75, 12); myOLED.setFont(RusFont); switch (t.mon) { case 1: myOLED.print(String(t.date), 30, 57); myOLED.print("ZYDFHZ", CENTER, 57); myOLED.print(String(t.year), 88, 57); break; case 2: myOLED.print(String(t.date), 26, 57); myOLED.print("ATDHFKZ", CENTER, 57); myOLED.print(String(t.year), 92, 57); break; case 3: myOLED.print(String(t.date), 30, 57); myOLED.print("VFHNF", CENTER, 57); myOLED.print(String(t.year), 88, 57); break; case 4: myOLED.print(String(t.date), 30, 57); myOLED.print("FGHTKZ", CENTER, 57); myOLED.print(String(t.year), 88, 57); break; case 5: myOLED.print(String(t.date), 36, 57); myOLED.print("VFZ", CENTER, 57); myOLED.print(String(t.year), 82, 57); break; case 6: myOLED.print(String(t.date), 35, 57); myOLED.print("B>YZ", CENTER, 57); myOLED.print(String(t.year), 81, 57); break; case 7: myOLED.print(String(t.date), 35, 57); myOLED.print("B>KZ", CENTER, 57); myOLED.print(String(t.year), 81, 57); break; case 8: myOLED.print(String(t.date), 28, 57); myOLED.print("FDUECNF", CENTER, 57); myOLED.print(String(t.year), 90, 57); break; case 9: myOLED.print(String(t.date), 24, 57); myOLED.print("CTYNZ<HZ", CENTER, 57); myOLED.print(String(t.year), 94, 57); break; case 10: myOLED.print(String(t.date), 26, 57); myOLED.print("JRNZ<HZ", CENTER, 57); myOLED.print(String(t.year), 92, 57); break; case 11: myOLED.print(String(t.date), 28, 57); myOLED.print("YJZ<HZ", CENTER, 57); myOLED.print(String(t.year), 90, 57); break; case 12: myOLED.print(String(t.date), 26, 57); myOLED.print("LTRF<HZ", CENTER, 57); myOLED.print(String(t.year), 92, 57); break; } myOLED.update(); delay(500); myOLED.setFont(MegaNumbers); myOLED.print("-", 51, 12); myOLED.update(); delay(500); }
Ну а теперь, еще более усовершенствуем наши OLED часы и добавим к ним отображение температуры, которую мы будем считывать с датчика температуры DS18B20.
Для отображения рисунка с градусником на OLED дисплее и значка градуса выберем картинку с рисунком градусника и с помощью графического редактора сохраним ее в формате GIF с именем term.gif, и тоже самое проделаем с картинкой с значком градуса — сохраним ее как grad.gif.
картинки должны быть двухцветными (белый и черный), доступные форматы картинок png, jpg, gif
У меня картинка term.bmp имеет размеры 19×40 пикселей, а картинка grad.bmp 13×12 пикселей. Потом нам потребуется конвертировать две картинки с помощью онлайн-сервиса www.rinkydinkelectronics.com
выбираем наш файл изображения и жмем Make File
Жмем на Click here to download your file и сохраняем файл grad.c в папку с нашим скетчем, тоже самое проделываем с другим изображением. Сохраняем и закрываем скетч. При повторном открытии он будет иметь еще две вкладки с файлами изображений.
После этого добавим две строки в скетч, которые инициализируют наши файлы изображений
extern uint8_t term[]; extern uint8_t grad[];
а потом отобразим наши изображения на экране OLED дисплея, добавив строки
myOLED.drawBitmap(4, 12, term, 19, 40); myOLED.drawBitmap(92, 12, grad, 13, 12);
Добавим в наш скетч на два цикла. В первом цикле у нас будет отображаться время – назовем его void watch(); Второй цикл будет считывать и отображать температуру void temp();
А в основном цикле void loop(); пропишем для ротации циклов несколько строчек кода
if (x >= 10) { temp(); x=0; } else { watch(); } x++;
В цикле void temp(); пропишем кусочек кода для считывания и отображения температуры
for(int x = 0; x < 10; x++){ byte data[2]; ds.reset(); ds.write(0xCC); ds.write(0x44); delay(150); ds.reset(); ds.write(0xCC); ds.write(0xBE); data[0] = ds.read(); data[1] = ds.read(); int Temp = (data[1] << 8) + data[0]; Temp = Temp >> 4; String stringOne = rtc.getTimeStr(); myOLED.clrScr(); myOLED.setFont(SmallFont); myOLED.print(stringOne.substring(0, 5), 98, 0); myOLED.print(rtc.getDateStr(), 0, 0); myOLED.setFont(RusFont); myOLED.print("NTVGTHFNEHF", CENTER, 57); myOLED.drawBitmap(4, 12, term, 19, 40); myOLED.setFont(MegaNumbers); myOLED.print(String(Temp), CENTER, 12); myOLED.drawBitmap(92, 12, grad, 13, 12); myOLED.update(); myOLED.clrScr(); }
В цикле void watch(); пропишем наш код, который отвечает за отображение времени
После заливки скетча, наши OLED часы сначала должны отображать время, а потом температуру как на видео в начале статьи.
Полный скетч можно загрузить по ссылке OLED_watch_temp.rar
Обсуждение статьи доступно в нашей группе vk.com
ссылка на оригинал статьи http://habrahabr.ru/post/257659/
Добавить комментарий