Aquasys - удобрения нового поколения
Украинский форум аквариумистов

Здравствуйте, гость ( Вход | Регистрация )




> Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++, Контроллер на базе Arduino, миф или реальность?
Ruslan.Kuchma
сообщение 17.12.2015, 13:47
Сообщение #1


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif Приветствую всех, кто умеет, а также не умеет читать.

В тот момент, когда в аквариумистику ворвалась LED-технология, настал насущный вопрос, как управлять всем этим «добром»?
На многих Аква-форумах поднималась данная тема, много всяких обсуждений вокруг подобных тем.
Но для большинства всё это остаётся из области фантастики, многие видя множество комментариев прощаются с этой затеей, многим кажется это очень сложно и непонятно. Многие со старта, не вникнув в суть вопроса покупают кучу модулей, а только потом включают мозг и начинают задавать вопросы.
Я тоже так когда-то читал, вникал, и к сожалению, не понимал о чём речь. Но знаете, как оно, «Когда хочется - это хуже, чем болит».

Как всё начиналось (можно пропустить wink.gif ) Читать
Ещё в не столь далёком 2012, «покурив» хорошенько просторы интернета, нашёл схему Arduino 168, нашёл шаблон печатной платы, вытравил, спаял и столкнулся с банальной проблемой, в моём компьютере не оказалось COM порта.
А руки то чешутся…
Спустя некоторое время таки нашёл средства и купил контроллер Arduino Duemilanove, стоил он тогда недёшево и купить было непросто, не то что сейчас, можно купить всё и за вполне адекватные деньги.
Купил включил, обалдеть, светодиод мигает…
Что делать дальше я не представлял, понемногу начал изучать основы программирования, и через некоторое время уже стало что-то вырисовываться. На данный момент я понимаю, что всё что было сделано ранее не представляло никакой ценности кроме опыта, и все первые попытки сделать контроллер на Arduino заканчивались не то чтоб неудачно, но как-то без восторга…

Эту часть наверно тоже пропустим smile.gif Читать
Много проб и неудач меня толкало на поиски новой информации. И вот наткнулся, на всем известном форуме «Аква лого», на одну занимательную тему, посвящённую 6-ти канальному контроллеру с тач экраном. К тому времени там было порядка 40-45 страниц бурных обсуждений. Долго читал, вникал, но ни черта не мог понять, к сожалению, а может и нет, меня эта тема зацепила.

Заказал Arduino MEGA 2560, шилд-переходник, экран 3.2” (на то время это было дорого)

Первые попытки повторить заканчивались неудачно, но я не сдавался и продолжал упорно разбираться с кодом (если честно, то смотря на очень-очень длинный код, я нифига не понимал), обратится к автору Jamie Jardin, но увы за открытый исходный код затребовали немного не мало 10фунтов. Послал я автора, и решил, а чем я хуже? Если он смог, то значит это может каждый!
Начал писать свою программу и скажу, что кое-что из этого получалось. Через некоторое время чисто случайно набрёл в инете на ещё один контроллер на Arduino. И автор не брал мзду! Он то и послужил более-менее отправной точкой и окончательным видом моего контроллера.
Но суть этой темы заключается не в том, чтоб просто выложить список компонентов и исходный код. Мне хочется, чтоб с помощью данной темы каждый желающий смог сделать свой собственный контроллер.

Сама по себе платформа Arduino MEGA 2560 не представляет из себя ничего, просто микропроцессор AVR с минимальной обвязкой, и по задумке производителя это конструктор, который помогает развиваться. И с помощью разных шилдов выполнять ту или иную задачу.
Для Аква-контроллера нужен специальный шилд который будет выполнять поставленные задачи, конечно он существует, и стоит денег и возможно справляется с возложенными на него задачами, я лично не проверял. И даже есть люди, которые разработали такой шилд и успешно его реализовали в жизнь.
Отвлёкся… blush.gif


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


Барабанная дробь… И, стандартная фраза...
Из модулей понадобится Читать
Прикрепленное изображение

Сердце контроллера, Arduino Mega 2560
Прикрепленное изображение

Устройство ввода/вывода информации, 3,2" TFT LCD Touch
Прикрепленное изображение

Шилд, Arduino LCD TFT 3.2" Mega Shield V2.2, для подключения экрана.
Прикрепленное изображение
Прикрепленное изображение

Часы реального времени, Real Time Clock Модуль (DS1307) или Real Time Clock Модуль (DS3231)
Прикрепленное изображение

Блок питания. (Лучше брать с запасом)
Прикрепленное изображение

Ну и конечно провода, много проводов, куда без них…

Это так для старта, конечно ещё нужны будут LED драйвера и не только…

Прикрепленное изображение

В дальнейшем это не будет выглядеть так, и все по той же причине - это конструктор.

У многих может появится вопрос почему именно Arduino:
  • дешево
  • гибко
  • функционально

Почему с тач дисплеем:
  • удобный, интуитивно понятный интерфейс
  • вся информация выводится на дисплей
  • настройки производятся при помощи дисплея
  • ненужно разрабатывать сложное древовидное меню
  • ненужно подключаться по Bluetooth или Wi-Fi для настройки
  • ненужно подключаться к компьютеру, к Android или к Apple

В дальнейшем всё будет пошагово расписано, так что запасайтесь терпением...
На этом, пожалуй, прервусь, а вы уважаемые читатели решайте нужно это Вам или нет, комментируйте, критикуйте, задавайте вопросы и т.д. А я не спеша подготовлю следующий шаг.
Также большая просьба, не засоряйте тему ссылками типа: кто, где и за сколько покупал, для этого есть:
  • Личная переписка!
  • Интернет-магазины
  • Аукро
  • OLX
  • Ebay
  • Aliexpress
  • И другие торговые площадки

P.S. если у кого возникнут проблемы с приобретением, могу помочь лично.

Примечание:
  • Если вы не знаете, что такое паяльник остановитесь.
  • Я, не заставляю Вас делать также.
  • Я, показываю, как делал.
  • Если вы сожгли процессор или модуль, из-за неправильного подключения, моей вины в этом нет.
  • Если сгорел Ваш дом, из-за неправильного подключения, моей вины в этом нет.
  • Если от Вас ушла жена, из-за нового увлечения, моей вины в этом нет.
  • Если Вы потеряете работу, из-за нового увлечения, моей вины в этом нет.
  • Если на вашем банковском счёте закончатся деньги, из-за нового увлечения, моей вины в этом нет.

Подключение
Вводный инструктаж
Управление светом
Спящий режим
Тестовый режим
Микшер
Звук
Управление нагрузкой (помпа, фильтр)
Температура воды
Температура светильника
Режим кормления
Режим обслуживания


Список библиотек Читать

Прикрепленный файл  DS1307new.zip ( 9.36 килобайт ) Кол-во скачиваний: 482

Прикрепленный файл  UTFT.zip ( 2.52 мегабайт ) Кол-во скачиваний: 478

Прикрепленный файл  UTouch.zip ( 423.85 килобайт ) Кол-во скачиваний: 473


Продолжение следует…

Сообщение отредактировал Ruslan.Kuchma - 5.1.2016, 11:41


--------------------


7
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
3 страниц V   1 2 3 >
Ответов (1 - 19)
Chumak
сообщение 17.12.2015, 14:20
Сообщение #2


Активный аквариумист
***
Группа: Партнёры
Сообщений: 403
Регистрация: 16.3.2013
Из: Днепр
Украина
Благодарности: 413 раз(а)


Акваконтроллер своїми руками на Ардуїно - це реальність і не складно. Якщо пощастить знайти підходящу прошивку, не потрібно буде навіть писати свою. Наприклад, завдяки старанням автора. Ви же відкриєте код своєї програми?

Я собі контролер зібрав теж на базі Меги. Тільки на TFT-дисплей грошей пошкодував, взяв звичайний 2-х рядковий LCD-дисплей з вбудованими кнопками для управління. Реалізував всі налаштування, програми для автоматичної зміни освітлення. Планував зробити управління контроллером з комп'ютера через COM-порт та Bluetooth. Але до цього руки не дійшли через сімейні обставини - часу тепер немає. Думаю, через рік буду вільніший і таки закінчу справу.

А поки що він керує трьома саморобними світильниками як є. Раз налаштував і забув...

А ви в чому пишете програму - у рідній Arduino IDE чи щось інше?
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 17.12.2015, 14:56
Сообщение #3


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


Chumak, Да пишу на родной Arduino IDE, так как не вижу смысла писать на чём-то другом, тем более сейчас она развивается с большой скоростью, и с каждой новой версией приятно радует... Не библиотеку ведь писать нужно. smile.gif
Зачем мне открывать свой код? Если на протяжении 3-х лет он постоянно меняется, что-то добавляется, что-то убирается...
В этой теме, я поставил цель объяснить, как это работает...
Если понять, как это работает, то каждый сможет "собрать" свою прошивку.
Оффтоп Читать
Меня неоднократно просили сделать контроллер, я делал, все оставались довольны, и при этом у каждого были свои требования. Кому-то нужен только свет, кому-то нужно 4, а кому-то 10 каналов освещения, кто-то вообще хотел выкрутить максимум.

Зря пожалели денег на TFT дисплей, весчь! good1.gif

Также сам собой напрашивается вопрос, зачем управлять с компьютера или по Bluetooth, если есть встроенные кнопки? Где логика?


--------------------
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Chumak
сообщение 17.12.2015, 15:23
Сообщение #4


Активный аквариумист
***
Группа: Партнёры
Сообщений: 403
Регистрация: 16.3.2013
Из: Днепр
Украина
Благодарности: 413 раз(а)


Моя прошивка з претензією на універсальність. В ній можна задати конфігурацію каналів мікроконтроллера. Тобто, визначити, що, наприклад, у тебе є 2 канала для вентиляторів, 5 каналів з ШІМ-регулюванням для світлодіодів, 3 канала для підключення пристроїв з управлінням увімк./вимк., 1 канал для датчика температури, 1 канал для датчиків типу "сухий контакт". Тобто, прошивка одна, а кількість периферії може змінюватися. І не треба змінювати код програми.
І є інтерфейс для налаштування алгортмів, як цим усім управляти. Поки що не встиг дописати функціональність, коли алгоритм би враховував у своїй роботі датчик. Тобто, вентилятор може або просто крутитися, або ні. :-)
Але налаштовувати все це за допомогою усього лише 5-х кнопок на дисплею 2х16 символів не дуже зручно. Тому задумав програму для комп'ютера. Бо налаштувати той же світанок/захід мишею в GUI буде зручніше. :-)
Я обрав собі за інструмент AVR плагін для Eclipse. Просто я без Eclipse, як без рук. :-) Але це несумісний з Arduino IDE код (хоча версію 1.6 не пробував).
Може, коли все дороблю і не буде сороно показати іншим, теж створю свою тему. :-)
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
yarishNEW
сообщение 17.12.2015, 15:55
Сообщение #5


Читатель, звать Олег
*****
Группа: Журналисты
Сообщений: 11 751
Регистрация: 11.1.2010
Из: Кременчуг
Украина Украина
Благодарности: 22516 раз(а)


Подпишусь-ка, нужно уже давно безграмотность shok.gif ликвидировать в этом направлении blush.gif .


--------------------
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 17.12.2015, 16:02
Сообщение #6


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


Цитата(Chumak @ 17.12.2015, 15:23) *
Але налаштовувати все це за допомогою усього лише 5-х кнопок на дисплею 2х16 символів не дуже зручно.

Именно по этому, будет использоваться сенсорный дисплей, причём кому 3.2" мало, могут взять себе 4.3" или 5" или 7", всё зависит от толщины кошелька. Я не уверен, что у всех компьютер стоит рядом с аквариумом.
Совет Читать
Если планируете управлять с компьютера, убирайте бесполезный LCD Keypad Shield, поставьте вместо него экран побольше, к примеру символьный 20X4, и выводите на него информацию по I2C шине, освободите много пинов!


--------------------


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 18.12.2015, 11:56
Сообщение #7


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif
Подключение
Очень важно при подключении!
В независимости сколько у вас будет модулей и источников питания "МАССА или GND", всех устройств должна быть общая!
Исключением является только подключение светодиодов к драйверам!

В ходе написания текста возникла идея и появился второй способ подключения. Первый более сложный, второй несильно отличается от первого… Я отдаю предпочтение первому.
Сейчас у многих отпадёт желание особенно у тех, кто не держал в руках паяльник, но надеюсь таких меньшинство, да и когда-то нужно начинать…
Первый способ Читать
Все ваши модули должны избавиться от разъёмов PBD, PBS и PLS, наверное, перегнул…
Прикрепленное изображение
Прикрепленное изображение
Прикрепленное изображение

Проще говоря нужно выпаять все разъёмы и штырьки.
stop.gif
В Arduino оставляем, разъёмы USB и питания.
В шилде оставляем, разъём подключения дисплея.

Проще это сделать если есть "оловоотсос", если нет, спросить у соседа, если нет у соседа, ничего страшного. Можно поступить немного варварским способом, при помощи тонкой отвёртки. Загоняем отвёртку между платой и разъёмом и покачивая стягиваем пластмассовую часть разъёма, только без фанатизма, надеюсь вы знаете где нужна спешка…
Должно получиться приблизительно так
Прикрепленное изображение

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

Сразу расскажу, что куда паять, всё просто, на начальном этапе нужно соединить нужные пины Arduino с шилдом, см. ниже, подключаем к синим контактам.
Прикрепленное изображение


Второй способ Читать
Несильно отличается от первого с разницей только что получится некий «бутерброд». На Arduino удалить придётся все верхние (цифровые) и нижние (аналоговые разъёмы), в разъёме питания оставить два +5 и GND они нужны для питания шилда. На шилде тоже удаляем лишние контакты, оставим только +5 и GND, и добавим пять перемычек далее всё понятно с картинок…
Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение


Можно подключить конечно и другими способами, но я считаю их менее предпочтительными.
Если Вы знакомы с ARDUINO IDE, то можете залить следующий код и проверить работоспособность!
Проверочный код Читать
CODE
#include <UTFT.h>
#include <UTouch.h>

extern uint8_t BigFont[];

UTFT myGLCD(ITDB32S, 38, 39, 40, 41);
UTouch myTouch(46, 45, 44, 43, 42);

int x, y;
char stCurrent[20] = "";
int stCurrentLen = 0;
char stLast[20] = "";

/*************************
** Custom functions **
*************************/

void drawButtons()
{
for (x = 0; x < 5; x++)
{
myGLCD.setColor(0, 0, 255);
myGLCD.fillRoundRect (10 + (x * 60), 10, 60 + (x * 60), 60);
myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (10 + (x * 60), 10, 60 + (x * 60), 60);
myGLCD.printNumI(x + 1, 27 + (x * 60), 27);
}
for (x = 0; x < 5; x++)
{
myGLCD.setColor(0, 0, 255);
myGLCD.fillRoundRect (10 + (x * 60), 70, 60 + (x * 60), 120);
myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (10 + (x * 60), 70, 60 + (x * 60), 120);
if (x < 4)
myGLCD.printNumI(x + 6, 27 + (x * 60), 87);
}
myGLCD.print("0", 267, 87);
myGLCD.setColor(0, 0, 255);
myGLCD.fillRoundRect (10, 130, 150, 180);
myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (10, 130, 150, 180);
myGLCD.print("Clear", 40, 147);
myGLCD.setColor(0, 0, 255);
myGLCD.fillRoundRect (160, 130, 300, 180);
myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (160, 130, 300, 180);
myGLCD.print("Enter", 190, 147);
myGLCD.setBackColor (0, 0, 0);
}

void updateStr(int val)
{
if (stCurrentLen < 20)
{
stCurrent[stCurrentLen] = val;
stCurrent[stCurrentLen + 1] = '\0';
stCurrentLen++;
myGLCD.setColor(0, 255, 0);
myGLCD.print(stCurrent, LEFT, 224);
}
else
{
myGLCD.setColor(255, 0, 0);
myGLCD.print("BUFFER FULL!", CENTER, 192);
delay(500);
myGLCD.print(" ", CENTER, 192);
delay(500);
myGLCD.print("BUFFER FULL!", CENTER, 192);
delay(500);
myGLCD.print(" ", CENTER, 192);
myGLCD.setColor(0, 255, 0);
}
}

void waitForIt(int x1, int y1, int x2, int y2)
{
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (x1, y1, x2, y2);
while (myTouch.dataAvailable(smile.gif
myTouch.read();
myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (x1, y1, x2, y2);
}

void setup()
{
myGLCD.InitLCD();
myGLCD.clrScr();

myTouch.InitTouch();
myTouch.setPrecision(PREC_MEDIUM);

myGLCD.setFont(BigFont);
myGLCD.setBackColor(0, 0, 255);
drawButtons();
}

void loop()
{
while (true)
{
if (myTouch.dataAvailable(smile.gif
{
myTouch.read();
x = myTouch.getX();
y = myTouch.getY();

if ((y >= 10) && (y <= 60:) // Upper row
{
if ((x >= 10) && (x <= 60:) // Button: 1
{
waitForIt(10, 10, 60, 60);
updateStr('1');
}
if ((x >= 70) && (x <= 120:) // Button: 2
{
waitForIt(70, 10, 120, 60);
updateStr('2');
}
if ((x >= 130) && (x <= 180:) // Button: 3
{
waitForIt(130, 10, 180, 60);
updateStr('3');
}
if ((x >= 190) && (x <= 240:) // Button: 4
{
waitForIt(190, 10, 240, 60);
updateStr('4');
}
if ((x >= 250) && (x <= 300:) // Button: 5
{
waitForIt(250, 10, 300, 60);
updateStr('5');
}
}

if ((y >= 70) && (y <= 120:) // Center row
{
if ((x >= 10) && (x <= 60:) // Button: 6
{
waitForIt(10, 70, 60, 120);
updateStr('6');
}
if ((x >= 70) && (x <= 120:) // Button: 7
{
waitForIt(70, 70, 120, 120);
updateStr('7');
}
if ((x >= 130) && (x <= 180:) // Button: 8
{
waitForIt(130, 70, 180, 120);
updateStr('8');
}
if ((x >= 190) && (x <= 240:) // Button: 9
{
waitForIt(190, 70, 240, 120);
updateStr('9');
}
if ((x >= 250) && (x <= 300:) // Button: 0
{
waitForIt(250, 70, 300, 120);
updateStr('0');
}
}

if ((y >= 130) && (y <= 180:) // Upper row
{
if ((x >= 10) && (x <= 150:) // Button: Clear
{
waitForIt(10, 130, 150, 180);
stCurrent[0] = '\0';
stCurrentLen = 0;
myGLCD.setColor(0, 0, 0);
myGLCD.fillRect(0, 224, 319, 239);
}
if ((x >= 160) && (x <= 300:) // Button: Enter
{
waitForIt(160, 130, 300, 180);
if (stCurrentLen > 0)
{
for (x = 0; x < stCurrentLen + 1; x++)
{
stLast[x] = stCurrent[x];
}
stCurrent[0] = '\0';
stCurrentLen = 0;
myGLCD.setColor(0, 0, 0);
myGLCD.fillRect(0, 208, 319, 239);
myGLCD.setColor(0, 255, 0);
myGLCD.print(stLast, LEFT, 208);
}
else
{
myGLCD.setColor(255, 0, 0);
myGLCD.print("BUFFER EMPTY", CENTER, 192);
delay(500);
myGLCD.print(" ", CENTER, 192);
delay(500);
myGLCD.print("BUFFER EMPTY", CENTER, 192);
delay(500);
myGLCD.print(" ", CENTER, 192);
myGLCD.setColor(0, 255, 0);
}
}
}
}
}
}

Если нет, то сообщите, и я уделю немного времени wink.gif

Ну и чтоб некоторое время не возвращаться к паяльнику, можно сразу подключить, первый очень важный модуль RTC, проще говоря часы, подойдут как DS1307 так DS3231, вторые немного дороже, но гораздо точнее и доставляют гораздо меньше хлопот.
В независимости от вашего выбора подключение одинаковое
+5V <--> +5V
GND <--> GND
SDA <--> SDA
SLC <--> SLC

Кто более внимательно рассмотрел плату Arduino, наверное, заметил, что она имеет 2 дополнительных контакта SDA и SLC, куда подключать выбор за Вами, они дублирующие.
Сразу добавлю, большинство модулей имеет питание 5 вольт. Платформа Arduino не имеет достаточного количества выводов и имеет ограничение по току. Поэтому лучше сразу потратить 25-30грн. На приобретение понижающего преобразователя, и для всяких модулей выделить отдельную линию питания 5 вольт.

Продолжение следует…

Сообщение отредактировал Ruslan.Kuchma - 21.12.2015, 15:18


--------------------


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 21.12.2015, 15:10
Сообщение #8


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif
Вводный инструктаж.

Очень важно чётко понять, что именно должно получится в конечном результате.
Для этого нужен алгоритм работы. Сложно всё представить себе в голове, последовательность всех действий, для этого лучше всего воспользоваться листом бумаги и карандашом.
Многие должны знать, что такое алгоритм со школы
Так выглядит «базовый» алгоритм работы контроллера.
Прикрепленное изображение

У многих ошибка, все задачи ставить в основную функцию LOOP (), этого делать ненужно. Программа получается рабочая, но очень-очень медленная. Так как ей приходится вычислять ненужное… Чтоб этого избежать нужно создать отдельные функции, к которым программа будет обращаться только если это нужно…
Например, нет смысла выводить значение времени на экран 1000 раз в секунду, достаточно скажем 1 раз в пять секунд проверить изменилось оно или нет. Если да, выводим новое время, если нет, оставляем всё как есть.

Тоже самое делается и с остальной отображаемой информацией, особенно с той которая отображена один раз, и не меняется вообще…

search.gif Программу лучше сразу разбить на блоки это облегчит поиск по очень-очень длинному коду.
Обязательно оставляйте как можно больше комментариев, в дальнейшем это окажет незаменимую помощь.


Пример Читать
Код
// --- Подключаем нужные библиотеки
// можно подключить и ненужные;)

// --- Инициализируем устройства
// Дисплей
// Сенсор
// Разные датчики

// --- Подключаем шрифты

// --- Назначаем выводы

// --- Настройки
// Задаём статические переменные

// --- Переменные
// Задаём глобальные переменные
// Номер Экрана
// Координаты Touch
// Счётчики
// Координаты кнопок

// --- Функции
// тут будут прописаны разные пассивные функции
// такие как:
// очистка экрана
// заголовок экрана
// работа с EEPROM
// работа со временем
// отображение всяких кнопок
// отображение информации на экране
// работа с сенсором

// ---
void setup()
{
// Функция setup() вызывается, когда стартует скетч.
// Используется для инициализации переменных,
// определения режимов работы выводов,
// запуска используемых библиотек и т.д.
// Функция setup запускает только один раз,
// после каждой подачи питания или сброса платы Arduino.
}

// ---
void loop()
{
// После вызова функции setup(),
// которая инициализирует и устанавливает первоначальные значения,
// функция loop() делает точь-в-точь то, что означает её название,
// и крутится в цикле,
// позволяя вашей программе совершать вычисления и реагировать на них.
// Используйте её для активного управления платой Arduino.
}


Сообщение отредактировал Ruslan.Kuchma - 21.12.2015, 20:25


--------------------


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 23.12.2015, 13:41
Сообщение #9


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif
Управление светом.
Несколько дней просидел, рассматривая исходник. Искал более-менее оптимальное решение, но как говорится, из песни слов не выкинуть.
Эта часть, неминуемо, будет самой сложной. Так как в ней заложен основной минимум.
Решил остановится на 6-ти каналах света, как бы золотая середина, кому нужно будет уменьшить скажем до 4-х легко исправить, кому увеличить до 8-и легко добавить. Больше можно, но уже будет сложнее в плане графики, и понадобится дисплей с большим разрешением. Для дисплея 3.2” с разрешением 320х240, я писал максимум 10 каналов, но там функционал был ограничен (для человека, который просил это сделать, от контроллера нужен был только свет). Но опять же, всё зависит от желания.
Ниже представлен код, с комментариями, может конечно, что-то и упустил. unknown.gif
Исходный код Читать
Код
// --- Библиотеки
#include <UTFT.h>
#include <UTouch.h>
#include <DS1307new.h>
#include <EEPROM.h>

// --- Инициализируем устройства
UTFT myGLCD(ITDB32S, 38, 39, 40, 41); // Дисплей
UTouch myTouch(46, 45, 44, 43, 42); // Сенсор

// --- Подключаем шрифты

extern uint8_t BigFont[];
extern uint8_t SmallFont[];
extern uint8_t SevenSegNumFontPlus[];

#define LARGE true
#define SMALL false

// --- Назначаем выводы

const byte ledPinCh1 = 7;  // канал 1
const byte ledPinCh2 = 8;  // канал 2
const byte ledPinCh3 = 9;  // канал 3
const byte ledPinCh4 = 10; // канал 4
const byte ledPinCh5 = 11; // канал 5
const byte ledPinCh6 = 12; // канал 6

// --- Настройки

const byte numberOfCh = 6; // количество каналов
const char *namesCh[] = {" ", "NAME1", "NAME2", "NAME3", "NAME4", "NAME5", "NAME6"}; // имя каналов (не более 5 символов)
const char *namesChMix[] = {" ", "Ch1", "Ch2", "Ch3", "Ch4", "Ch5", "Ch6"};
const byte rgbCh1[] = {0, 0, 255};     // цвет канала 1 RGB
const byte rgbCh2[] = {255, 255, 255}; // цвет канала 2 RGB
const byte rgbCh3[] = {238, 130, 238}; // цвет канала 3 RGB
const byte rgbCh4[] = {0, 225, 225};   // цвет канала 4 RGB
const byte rgbCh5[] = {255, 0, 0};     // цвет канала 5 RGB
const byte rgbCh6[] = {255, 0, 170};   // цвет канала 6 RGB

const boolean BUCKPUCK  = true; // реверс ШИМ
const boolean readEEonStart = 1; // читать EEPROM при загрузке вкл/выкл

// первоначальная настройка каналов,
// используется один раз при первой загрузке
// при условии, что в EEPROM нет данных
// в дальнейшем эти данные читаются с EEPROM
byte ch1led[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9
  0, 0, 0, 0, 0, 0, 0, 0,  //10 - 11
  0, 0, 0, 0, 0, 0, 0, 0,  //12 - 13
  0, 0, 0, 0, 0, 0, 0, 0,  //14 - 15
  0, 0, 0, 0, 0, 0, 0, 0,  //16 - 17
  0, 0, 0, 0, 0, 0, 0, 0,  //18 - 19
  0, 0, 0, 0, 0, 0, 0, 0,  //20 - 21
  0, 0, 0, 0, 0, 0, 0, 0   //22 - 23
};
byte ch2led[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9
  0, 0, 0, 0, 0, 0, 0, 0,  //10 - 11
  0, 0, 0, 0, 0, 0, 0, 0,  //12 - 13
  0, 0, 0, 0, 0, 0, 0, 0,  //14 - 15
  0, 0, 0, 0, 0, 0, 0, 0,  //16 - 17
  0, 0, 0, 0, 0, 0, 0, 0,  //18 - 19
  0, 0, 0, 0, 0, 0, 0, 0,  //20 - 21
  0, 0, 0, 0, 0, 0, 0, 0   //22 - 23
};
byte ch3led[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9
  0, 0, 0, 0, 0, 0, 0, 0,  //10 - 11
  0, 0, 0, 0, 0, 0, 0, 0,  //12 - 13
  0, 0, 0, 0, 0, 0, 0, 0,  //14 - 15
  0, 0, 0, 0, 0, 0, 0, 0,  //16 - 17
  0, 0, 0, 0, 0, 0, 0, 0,  //18 - 19
  0, 0, 0, 0, 0, 0, 0, 0,  //20 - 21
  0, 0, 0, 0, 0, 0, 0, 0   //22 - 23
};
byte ch4led[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9
  0, 0, 0, 0, 0, 0, 0, 0,  //10 - 11
  0, 0, 0, 0, 0, 0, 0, 0,  //12 - 13
  0, 0, 0, 0, 0, 0, 0, 0,  //14 - 15
  0, 0, 0, 0, 0, 0, 0, 0,  //16 - 17
  0, 0, 0, 0, 0, 0, 0, 0,  //18 - 19
  0, 0, 0, 0, 0, 0, 0, 0,  //20 - 21
  0, 0, 0, 0, 0, 0, 0, 0   //22 - 23
};
byte ch5led[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9
  0, 0, 0, 0, 0, 0, 0, 0,  //10 - 11
  0, 0, 0, 0, 0, 0, 0, 0,  //12 - 13
  0, 0, 0, 0, 0, 0, 0, 0,  //14 - 15
  0, 0, 0, 0, 0, 0, 0, 0,  //16 - 17
  0, 0, 0, 0, 0, 0, 0, 0,  //18 - 19
  0, 0, 0, 0, 0, 0, 0, 0,  //20 - 21
  0, 0, 0, 0, 0, 0, 0, 0   //22 - 23
};
byte ch6led[96] = {
  0, 0, 0, 0, 0, 0, 0, 0,  //0 - 1
  0, 0, 0, 0, 0, 0, 0, 0,  //2 - 3
  0, 0, 0, 0, 0, 0, 0, 0,  //4 - 5
  0, 0, 0, 0, 0, 0, 0, 0,  //6 - 7
  0, 0, 0, 0, 0, 0, 0, 0,  //8 - 9
  0, 0, 0, 0, 0, 0, 0, 0,  //10 - 11
  0, 0, 0, 0, 0, 0, 0, 0,  //12 - 13
  0, 0, 0, 0, 0, 0, 0, 0,  //14 - 15
  0, 0, 0, 0, 0, 0, 0, 0,  //16 - 17
  0, 0, 0, 0, 0, 0, 0, 0,  //18 - 19
  0, 0, 0, 0, 0, 0, 0, 0,  //20 - 21
  0, 0, 0, 0, 0, 0, 0, 0   //22 - 23
};

// --- Переменные

byte dispScreen = 0; // Номер Экрана
int x, y; // Координаты Touch

// Счётчики
unsigned long prevMillis5 = 0;
unsigned long prevMillis600 = 0;
unsigned long prevMillis900 = 0;

// LED переменные
int LedChangeTime = 0;
int selectChannel;
char tChar30[30];
int min_cnt;
int tled[96];
byte *LEDval_arr[] = {ch1led, ch2led, ch3led, ch4led, ch5led, ch6led};
byte LEDch_out[6];
byte prevLEDch_out[6];
byte LEDpin[] = {ledPinCh1, ledPinCh2, ledPinCh3, ledPinCh4, ledPinCh5, ledPinCh6};
char ch1Descr[15],  ch2Descr[15], ch3Descr[15], ch4Descr[15], ch5Descr[15], ch6Descr[15];
const byte *rgbChann[] = {rgbCh1, rgbCh2, rgbCh3, rgbCh4, rgbCh5, rgbCh6};

// переменные для часов и вывода времени/даты
char *Day[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char *Mon[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};


struct RTC_T
{
  int tHour;
  int tMinute;
  int tDow;
  int tDay;
  int tMonth;
  int tYear;
}
tempRTC, prevRTC;

// координаты кнопок
// * главный экран
const int KeyMenu[] = {0, 18, 189, 115}; // Меню

// * установка времени/даты
const int HourUp[] = {130, 22 - 2};
const int HourDown[] = {130, 71 - 2};
const int MinUp[] = {190, 22 - 2};
const int MinDown[] = {190, 71 - 2};
const int DayUp[] = {120, 111 - 6};
const int DayDown[] = {120, 160 - 6};
const int MonthUp[] = {179, 111 - 6};
const int MonthDown[] = {179, 160 - 6};
const int YearUp[] = {250, 111 - 6};
const int YearDown[] = {250, 160 - 6};

// * кнопки меню
const int KeyMenu1[] = {4, 21, 158, 59};
const int KeyMenu3[] = {4, 61, 158, 99};
const int KeyMenu5[] = {4, 101, 158, 139};
const int KeyMenu7[] = {4, 141, 158, 179};
const int KeyMenu2[] = {161, 21, 315, 59};
const int KeyMenu4[] = {161, 61, 315, 99};
const int KeyMenu6[] = {161, 101, 315, 139};
const int KeyMenu8[] = {161, 141, 315, 179};

// * кнопки подтверждения/отмены
const int KeyCancel[] = {161, 195, 315, 221};   //standard cancel
const int KeyOK[] = {4, 195, 158, 221};     //standard ok

// --- Функции

void initSettings()
{
  strcat(ch1Descr, namesChMix[1]);
  strcat(ch1Descr, "(" );
  strcat(ch1Descr, namesCh[1]);
  strcat(ch1Descr, ")" );
  strcat(ch2Descr, namesChMix[2]);
  strcat(ch2Descr, "(" );
  strcat(ch2Descr, namesCh[2]);
  strcat(ch2Descr, ")" );
  strcat(ch3Descr, namesChMix[3]);
  strcat(ch3Descr, "(" );
  strcat(ch3Descr, namesCh[3]);
  strcat(ch3Descr, ")" );
  strcat(ch4Descr, namesChMix[4]);
  strcat(ch4Descr, "(" );
  strcat(ch4Descr, namesCh[4]);
  strcat(ch4Descr, ")" );
  strcat(ch5Descr, namesChMix[5]);
  strcat(ch5Descr, "(" );
  strcat(ch5Descr, namesCh[5]);
  strcat(ch5Descr, ")" );
  strcat(ch6Descr, namesChMix[6]);
  strcat(ch6Descr, "(" );
  strcat(ch6Descr, namesCh[6]);
  strcat(ch6Descr, ")" );
}

// Очистка экрана
void clearScreen()
{
  myGLCD.setColor(0, 0, 0);
  myGLCD.fillRect(1, 1, 318, 225);
}

// заголовок экрана
void printHeader(char* headline)
{
  changeFont(SMALL, 255, 255, 255, 255, 255, 255);
  myGLCD.fillRect (1, 1, 318, 15);
  myGLCD.setColor(0, 0, 0);
  myGLCD.print(headline, CENTER, 2);
}

// работа с EEPROM
// * запись
void SaveToEEPROM(int what)
{
  switch (what)
  {
    case 1: // сохранить значения для канала 1
      EEPROM.update(0, 121);
      delay(5);
      for (int i = 0; i < 96; i++)
      {
        EEPROM.update(i + 1, ch1led[i]);
        delay(5);
      }
      break;
    case 2: // сохранить значения для канала 2
      EEPROM.update(97, 122);
      delay(5);
      for (int i = 0; i < 96; i++)
      {
        EEPROM.update(i + 98, ch2led[i]);
        delay(5);
      }
      break;
    case 3: // сохранить значения для канала 3
      EEPROM.update(194, 123);
      delay(5);
      for (int i = 0; i < 96; i++)
      {
        EEPROM.update(i + 195, ch3led[i]);
        delay(5);
      }
      break;
    case 4: // сохранить значения для канала 4
      EEPROM.update(291, 124);
      delay(5);
      for (int i = 0; i < 96; i++)
      {
        EEPROM.update(i + 292, ch4led[i]);
        delay(5);
      }
      break;
    case 5: // сохранить значения для канала 5
      EEPROM.update(388, 125);
      delay(5);
      for (int i = 0; i < 96; i++)
      {
        EEPROM.update(i + 389, ch5led[i]);
        delay(5);
      }
      break;
    case 6: // сохранить значения для канала 6
      EEPROM.update(485, 126);
      delay(5);
      for (int i = 0; i < 96; i++)
      {
        EEPROM.update(i + 486, ch6led[i]);
        delay(5);
      }
      break;
  }
}
// * чтение
void ReadFromEEPROM()
{
  int k = EEPROM.read(0); // читает сохраненные значения для 1 канала
  delay(5);
  if (k == 121)
  {
    for (int i = 0; i < 96; i++)
    {
      ch1led[i] = EEPROM.read(i + 1);
      delay(5);
    }
  }

  k = EEPROM.read(97); // читает сохраненные значения для 2 канала
  delay(5);
  if (k == 122)
  {
    for (int i = 0; i < 96; i++)
    {
      ch2led[i] = EEPROM.read(i + 98);
      delay(5);
    }
  }

  k = EEPROM.read(194); // читает сохраненные значения для 3 канала
  delay(5);
  if (k == 123)
  {
    for (int i = 0; i < 96; i++)
    {
      ch3led[i] = EEPROM.read(i + 195);
      delay(5);
    }
  }

  k = EEPROM.read(291); // читает сохраненные значения для 4 канала
  delay(5);
  if (k == 124)
  {
    for (int i = 0; i < 96; i++)
    {
      ch4led[i] = EEPROM.read(i + 292);
      delay(5);
    }
  }

  k = EEPROM.read(388); // читает сохраненные значения для 5 канала
  delay(5);
  if (k == 125)
  {
    for (int i = 0; i < 96; i++)
    {
      ch5led[i] = EEPROM.read(i + 389);
      delay(5);
    }
  }

  k = EEPROM.read(485); // читает сохраненные значения для 6 канала
  delay(5);
  if (k == 126)
  {
    for (int i = 0; i < 96; i++)
    {
      ch6led[i] = EEPROM.read(i + 486);
      delay(5);
    }
  }
}

// сохранить время
void SaveRTC()
{
  RTC.stopClock();
  RTC.fillByYMD(tempRTC.tYear, tempRTC.tMonth, tempRTC.tDay);
  RTC.fillByHMS(tempRTC.tHour, tempRTC.tMinute, 0);
  RTC.setTime();
  delay(10);
  RTC.startClock();
  delay(10);
}

// Шрифт
void changeFont(int font, byte cr, byte cg, byte cb, byte br, byte bg, byte bb)
{
  myGLCD.setBackColor(br, bg, bb);
  myGLCD.setColor(cr, cg, cb);
  if (font == LARGE)
    myGLCD.setFont(BigFont);
  else if (font == SMALL)
    myGLCD.setFont(SmallFont);
}

// Печатает Кнопки
void printUpButton(int x, int y)  // вверх размер 29x23px
{
  myGLCD.setColor(255, 255, 255);
  myGLCD.fillRect(x, y + 22, x + 29, y + 23);
  myGLCD.setColor(255, 255, 255);
  for (int i = 0; i < 15; i++)
    myGLCD.drawLine(x + 4 + (i / 1.5), y + 17 - i, x + 25 - (i / 1.5), y + 17 - i);
}

void printDownButton(int x, int y) // вниз размер 29x23px
{
  myGLCD.setColor(255, 255, 255);
  myGLCD.fillRect(x, y, x + 29, y + 1);
  myGLCD.setColor(255, 255, 255);
  for (int i = 0; i < 15; i++)
    myGLCD.drawLine(x + 4 + (i / 1.5), y + 7 + i, x + 25 - (i / 1.5), y + 7 + i);
}

void hlightUpButton(int x, int y) // подсветка нажатия вверх
{
  myGLCD.setColor(0, 200, 0);
  for (int i = 0; i < 15; i++)
    myGLCD.drawLine(x + 4 + (i / 1.5), y + 17 - i, x + 25 - (i / 1.5), y + 17 - i);
  while (myTouch.dataAvailable())
  {
    myTouch.read();
  }
  myGLCD.setColor(255, 255, 255);
  for (int i = 0; i < 15; i++)
    myGLCD.drawLine(x + 4 + (i / 1.5), y + 17 - i, x + 25 - (i / 1.5), y + 17 - i);
}

void hlightDownButton(int x, int y) // подсветка нажатия вниз
{
  myGLCD.setColor(0, 200, 0);
  for (int i = 0; i < 15; i++)
    myGLCD.drawLine(x + 4 + (i / 1.5), y + 7 + i, x + 25 - (i / 1.5), y + 7 + i);
  while (myTouch.dataAvailable())
  {
    myTouch.read();
  }
  myGLCD.setColor(255, 255, 255);
  for (int i = 0; i < 15; i++)
    myGLCD.drawLine(x + 4 + (i / 1.5), y + 7 + i, x + 25 - (i / 1.5), y + 7 + i);
}

// печатает кнопки меню
void drawMenuButton()
{
  for (y = 0; y < 4; y++)
  {
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRect(4, 21 + (y * 40), 158, 59 + (y * 40));
    myGLCD.drawRect(161, 21 + (y * 40), 315, 59 + (y * 40));
  }
}

void drawRegButton()
{
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect(4, 195, 158, 221);
  myGLCD.drawRoundRect(161, 195, 315, 221);
}

// подписывает кнопку меню
void printButton(char* text, int x1, int y1, int x2, int y2)
{
  int stl = strlen(text);
  int fx, fy;
  fx = x1 + (((x2 - x1) - (stl * 8)) / 2);
  fy = y1 + (((y2 - y1 - 1) - 8) / 2);
  changeFont(SMALL, 255, 255, 255, 0, 0, 0);
  myGLCD.print(text, fx, fy);
}
// подсветка нажатия меню
void hlightButton(char* text, int x1, int y1, int x2, int y2)
{
  int stl = strlen(text);
  int fx, fy;

  fx = x1 + (((x2 - x1) - (stl * 8)) / 2);
  fy = y1 + (((y2 - y1 - 1) - 8) / 2);

  myGLCD.setColor(0, 200, 0);
  myGLCD.fillRect (x1 + 4, y1 + 4, x2 - 4, y2 - 4);
  changeFont(SMALL, 255, 255, 255, 0, 200, 0);
  myGLCD.print(text, fx, fy);
  while (myTouch.dataAvailable()) {
    myTouch.read();
  }
  myGLCD.setColor(0, 0, 0);
  myGLCD.fillRect (x1 + 4, y1 + 4, x2 - 4, y2 - 4);
  changeFont(SMALL, 255, 255, 255, 0, 0, 0);
  myGLCD.print(text, fx, fy);
}

// Печатает LEDs область
void drawLedBar(int bary, byte ch)
{
  int barLength;
  char barLevel[7];
  itoa(LEDch_out[ch - 1], barLevel, 10);
  strcat(barLevel, "%");
  barLength = LEDch_out[ch - 1] * 1;  //!
  myGLCD.setColor(0, 0, 0);
  myGLCD.fillRect(46, bary, 189, (bary + 12));    //!
  changeFont(SMALL, rgbChann[ch - 1][0], rgbChann[ch - 1][1], rgbChann[ch - 1][2], 0, 0, 0);
  myGLCD.print(namesCh[ch], 5, bary);
  myGLCD.drawLine(47, (bary + 1), 47, (bary + 11));
  myGLCD.fillRect(49, (bary + 2), (barLength + 49), (bary + 10));
  myGLCD.print(barLevel, (barLength + 51), bary);
}

void printVBar(int val, int x1, int y1, const byte rgb[])
{
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRect (x1, y1 + 22, x1 + 29, y1 + 124);
  myGLCD.setColor(rgb[0], rgb[1], rgb[2]);
  myGLCD.fillRect (x1 + 1, y1 + (124 - val), x1 + 28, y1 + 124);
  myGLCD.setColor(0, 0, 0);
  myGLCD.fillRect (x1 + 1, y1 + 22, x1 + 28, y1 + (124 - val));
  printUpButton(x1, y1);
  printDownButton(x1, y1 + 124);
  changeFont(SMALL, 255, 255, 255, 0, 0, 0);
  if (val > -1)
    myGLCD.printNumI(val, x1 + 16 - (intlen(val) * 4), y1 + 66);
}

// печатает время
void printTime(int thour, int tminute, int posx, int posy)
{
  char tmpTime[6], charT[3];
  tmpTime[0] = '\0';

  if (thour >= 0 && thour <= 9)
  {
    strcat(tmpTime, "0");
    itoa(thour, charT, 10);
    strcat(tmpTime, charT);
  }
  else
    itoa(thour, tmpTime, 10);

  strcat(tmpTime, ":");

  if (tminute >= 0 && tminute <= 9)
  {
    strcat(tmpTime, "0");
    itoa(tminute, charT, 10);
    strcat(tmpTime, charT);
  }
  else
  {
    itoa(tminute, charT, 10);
    strcat(tmpTime, charT);
  }
  myGLCD.print(tmpTime, posx, posy);
}

// печатает дату

void printDate(int x, int y)
{
  char  chDate[25], tmpChar[5];
  strcat(chDate, "  ");
  chDate[0] = '\0';
  strcat(chDate, Day[RTC.dow]);
  strcat(chDate, ",");
  itoa(RTC.day, tmpChar, 10);
  strcat(chDate, tmpChar);
  strcat(chDate, " ");
  strcat(chDate, Mon[RTC.month]);
  strcat(chDate, " ");
  itoa(RTC.year, tmpChar, 10);
  strcat(chDate, tmpChar);
  myGLCD.print(chDate, x, y);
}

int intlen(int number)
{
  int length1;
  char tmpChar[7];
  itoa(number, tmpChar, 10);
  length1 = strlen(tmpChar);
  return length1;
}

int stringCenter (char *myString, boolean font = false)
{
  int chLen;
  if (font)                                   //large font
    chLen = (strlen(myString) * 8) - 1;
  else                                         //small font
    chLen = (strlen(myString) * 4) - 1;
  return chLen;
}

// --- LED levels
void LED_levels_output()
{
  int sector, sstep, t1, t2;
  int l_out;

  min_cnt = (RTC.hour * 60) + RTC.minute;
  if (min_cnt >= 1440)
  {
    min_cnt = 1;
  }

  sector = min_cnt / 15;
  sstep = min_cnt % 15;
  t1 = sector;
  if (t1 == 95)
  {
    t2 = 0;
  }
  else
  {
    t2 = t1 + 1;
  }

  for (int i = 0; i < numberOfCh; i++)
  {
    if (sstep == 0)
      LEDch_out[i] = LEDval_arr[i][t1];
    else
      LEDch_out[i] = check(&LEDval_arr[i][t1], &LEDval_arr[i][t2], sstep);

    if (BUCKPUCK)
      l_out = LEDch_out[i];
    else
      l_out = 100 - LEDch_out[i];
    l_out = map(l_out, 0, 100, 0, 255);
    analogWrite(LEDpin[i], l_out);
  }
}
int check( byte *pt1, byte *pt2, int lstep)
{
  int result;
  float fresult;

  if (*pt1 == *pt2)
  {
    result = *pt1;
  }
  else if (*pt1 < *pt2)
  {
    fresult = ((float(*pt2 - *pt1) / 15.0) * float(lstep)) + float(*pt1);
    result = int(fresult);
  }
  else
  {
    fresult = -((float(*pt1 - *pt2) / 15.0) * float(lstep)) + float(*pt1);
    result = int(fresult);
  }
  return result;
}

void printChangeLED()
{
  myGLCD.setColor(255, 0, 0);
  myGLCD.fillRect((LedChangeTime * 26) + 5, 20, (LedChangeTime * 26) + 29, 42);
  changeFont(SMALL, 255, 255, 255, 255, 0, 0);
  myGLCD.printNumI((LedChangeTime * 2), (LedChangeTime * 26) + 19 - (intlen(LedChangeTime * 2) * 4), 20);
  myGLCD.printNumI(((LedChangeTime * 2) + 1), (LedChangeTime * 26) + 19 - (intlen(LedChangeTime * 2) * 4), 31);

  for (int i = 0; i < 8; i++)
  {
    int k = (LedChangeTime * 8) + i;
    printVBar( tled[k], (i * 38) + 10, 44, rgbChann[selectChannel - 1]);
  }
}

///////////////////
// *** Экран *** //
///////////////////

/// --- Главный --- dispScreen=0
void mainScreen(boolean refreshAll = false)
{
  int h1, t1, by, bary;
  char tmpChar[10], charTmp[3];
  by = 118;

  Serial.println(refreshAll);

  if (refreshAll) // рисует статические элементы (те которые прорисовываются один раз)
  {
    myGLCD.setColor(255, 255, 255);
    myGLCD.drawRect(6, 17, 313, 18);
  }

  // время
  changeFont(LARGE, 0, 255, 0, 0, 0, 0);
  if ((RTC.hour != prevRTC.tHour) || (RTC.minute != prevRTC.tMinute) || refreshAll)
  {
    prevRTC.tHour = RTC.hour;
    prevRTC.tMinute = RTC.minute;
    printTime(RTC.hour, RTC.minute, 220, 1);
  }

  // дата
  changeFont(SMALL, 0, 255, 0, 0, 0, 0);
  if ((RTC.day != prevRTC.tDay) || (RTC.month != prevRTC.tMonth) || (RTC.year != prevRTC.tYear) || refreshAll)
  {
    prevRTC.tDay = RTC.day;
    prevRTC.tMonth = RTC.month;
    prevRTC.tYear = RTC.year;
    printDate(15, 5);
  }

  // led панель
  for (int i = 0; i < numberOfCh; i++)
  {
    if ((prevLEDch_out[i] != LEDch_out[i]) || refreshAll)
    {
      bary = 8 + 12 + ((by - 11) / (numberOfCh + 1)) * (i + 1) - 12;
      drawLedBar(bary, i + 1);
      prevLEDch_out[i] = LEDch_out[i];
    }
  }
}

// --- экран меню --- dispScreen=1

void menuScreen()
{
  printHeader("Choose setting");
  drawMenuButton();
  drawRegButton();

  printButton("SET TIME & DATE", KeyMenu1[0], KeyMenu1[1], KeyMenu1[2], KeyMenu1[3]);
  printButton("", KeyMenu3[0], KeyMenu3[1], KeyMenu3[2], KeyMenu3[3]);
  printButton("", KeyMenu5[0], KeyMenu5[1], KeyMenu5[2], KeyMenu5[3]);
  printButton("", KeyMenu7[0], KeyMenu7[1], KeyMenu7[2], KeyMenu7[3]);
  printButton("LEDs OUTPUT", KeyMenu2[0], KeyMenu2[1], KeyMenu2[2], KeyMenu2[3]);
  printButton("", KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);
  printButton("", KeyMenu6[0], KeyMenu6[1], KeyMenu6[2], KeyMenu6[3]);
  printButton("", KeyMenu8[0], KeyMenu8[1], KeyMenu8[2], KeyMenu8[3]);
  printButton("CANCEL", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
  printButton("", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
}

// --- экран становки время/дата --- dispScreen=2

void clockScreen(boolean refreshAll = false)
{
  char char1[4], tmp[3];

  if (refreshAll)
  {
    tempRTC.tHour = RTC.hour;
    tempRTC.tMinute = RTC.minute;
    tempRTC.tDow = RTC.dow;
    tempRTC.tDay = RTC.day;
    tempRTC.tMonth = RTC.month;
    tempRTC.tYear = RTC.year;

    printHeader("Time and Date settings");

    myGLCD.setColor(255, 255, 255);
    myGLCD.drawLine(6, 98, 313, 98);

    changeFont(LARGE, 255, 255, 0, 0, 0, 0);
    myGLCD.print("Time:", 20, 51 - 2);
    myGLCD.print("Date:", 20, 140 - 6);

    printUpButton(HourUp[0], HourUp[1]);
    printDownButton(HourDown[0], HourDown[1]);
    printUpButton(MinUp[0], MinUp[1]);
    printDownButton(MinDown[0], MinDown[1]);

    printUpButton(DayUp[0], DayUp[1]);
    printDownButton(DayDown[0], DayDown[1]);
    printUpButton(MonthUp[0], MonthUp[1]);
    printDownButton(MonthDown[0], MonthDown[1]);
    printUpButton(YearUp[0], YearUp[1]);
    printDownButton(YearDown[0], YearDown[1]);

    drawRegButton();
    printButton("SAVE", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
    printButton("CANCEL", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
  }

  changeFont(LARGE, 255, 255, 255, 0, 0, 0);

  char1[0] = '\0';
  if (tempRTC.tHour <= 9)
  {
    strcat(char1, "0");
    itoa(tempRTC.tHour, tmp, 10);
    strcat(char1, tmp);
  }
  else
    itoa(tempRTC.tHour, char1, 10);
  myGLCD.print("0", HourUp[0], 51 - 2);
  myGLCD.print(char1, HourUp[0] + 14 - stringCenter(char1, LARGE), 51 - 2);
  myGLCD.print(":", 168, 51 - 2);

  char1[0] = '\0';
  if (tempRTC.tMinute <= 9)
  { //print minutes
    strcat(char1, "0");
    itoa(tempRTC.tMinute, tmp, 10);
    strcat(char1, tmp);
  }
  else
    itoa(tempRTC.tMinute, char1, 10);
  myGLCD.print("0", MinUp[0], 51 - 2);
  myGLCD.print(char1, MinUp[0] + 14 - stringCenter(char1, LARGE), 51 - 2);

  char1[0] = '\0';
  if (tempRTC.tDay <= 9)
  {
    strcat(char1, "0");
    itoa(tempRTC.tDay, tmp, 10);
    strcat(char1, tmp);
  }
  else
    itoa(tempRTC.tDay, char1, 10);
  myGLCD.print("0", DayUp[0], 140 - 6);
  myGLCD.print(char1, DayUp[0] + 14 - stringCenter(char1, LARGE), 140 - 6);

  myGLCD.print(Mon[tempRTC.tMonth], MonthUp[0] + 14 - stringCenter(Mon[tempRTC.tMonth], LARGE), 140 - 6); //print month

  char1[0] = '\0';
  itoa(tempRTC.tYear, char1, 10);
  myGLCD.printNumI(tempRTC.tYear, YearUp[0] + 14 - stringCenter(char1, LARGE), 140 - 6);
}

// --- Led меню (список каналов) --- dispScreen=3

void LEDmenuScreen()
{
  printHeader("Select LED channel:");

  printButton(ch1Descr, KeyMenu1[0], KeyMenu1[1], KeyMenu1[2], KeyMenu1[3]);
  printButton(ch2Descr, KeyMenu2[0], KeyMenu2[1], KeyMenu2[2], KeyMenu2[3]);

  if (numberOfCh > 2)
    printButton(ch3Descr, KeyMenu3[0], KeyMenu3[1], KeyMenu3[2], KeyMenu3[3]);

  if (numberOfCh > 3)
    printButton(ch4Descr, KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);

  if (numberOfCh > 4)
    printButton(ch5Descr, KeyMenu5[0], KeyMenu5[1], KeyMenu5[2], KeyMenu5[3]);

  if (numberOfCh > 5)
    printButton(ch6Descr, KeyMenu6[0], KeyMenu6[1], KeyMenu6[2], KeyMenu6[3]);

  drawMenuButton();
  drawRegButton();

  printButton("CANCEL", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
}

// --- текущие значения канала --- dispScreen=4
void ledSetScreen()
{
  int a;

  tChar30[0] = '\0';

  switch (selectChannel) {
    case 1:
      for (int i = 0; i < 96; i++)
        tled[i] = ch1led[i];
      strcat(tChar30, ch1Descr);
      strcat(tChar30, "output values %" );
      printHeader(tChar30);
      break;
    case 2:
      for (int i; i < 96; i++)
        tled[i] = ch2led[i];
      strcat(tChar30, ch2Descr);
      strcat(tChar30, "output values %" );
      printHeader(tChar30);
      break;
    case 3:
      for (int i; i < 96; i++)
        tled[i] = ch3led[i];
      strcat(tChar30, ch3Descr);
      strcat(tChar30, "output values %" );
      printHeader(tChar30);
      break;
    case 4:
      for (int i; i < 96; i++)
        tled[i] = ch4led[i];
      strcat(tChar30, ch4Descr);
      strcat(tChar30, "output values %" );
      printHeader(tChar30);
      break;
    case 5:
      for (int i; i < 96; i++)
        tled[i] = ch5led[i];
      strcat(tChar30, ch5Descr);
      strcat(tChar30, "output values %" );
      printHeader(tChar30);
      break;
    case 6:
      for (int i; i < 96; i++)
        tled[i] = ch6led[i];
      strcat(tChar30, ch6Descr);
      strcat(tChar30, "output values %" );
      printHeader(tChar30);
      break;
  }

  changeFont(SMALL, 255, 255, 255, 0, 0, 0);
  for (int i = 0; i < 12; i++)
  {
    myGLCD.setColor(255, 255, 0);
    myGLCD.printNumI((i * 2), (i * 26) + 19 - (intlen(i * 2) * 4), 21);
    myGLCD.printNumI(((i * 2) + 1), (i * 26) + 19 - (intlen(i * 2) * 4), 32);
    for (int j = 0; j < 8; j++)
    {
      a = (i * 8) + j;
      myGLCD.setColor(255, 255, 255);
      myGLCD.printNumI(tled[a], (i * 26) + 19 - (intlen(tled[a]) * 4), (j * 16) + 49);
      myGLCD.setColor(100, 100, 100);
      myGLCD.drawRect((i * 26) + 4, (j * 16) + 47, (i * 26) + 30, (j * 16) + 63);
    }
  }

  drawRegButton();
  printButton("CHANGE", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
  printButton("BACK", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
}

// изменение настроек значений канала --- dispScreen=5

void ledChangeScreen()
{
  printHeader(tChar30);

  changeFont(SMALL, 0, 255, 255, 0, 0, 0);
  for (int i = 0; i < 12; i++)
  {
    myGLCD.setColor(255, 255, 0);
    myGLCD.printNumI((i * 2), (i * 26) + 19 - (intlen(i * 2) * 4), 20);
    myGLCD.printNumI(((i * 2) + 1), (i * 26) + 19 - (intlen(i * 2) * 4), 31);
    myGLCD.setColor(100, 100, 100);
    myGLCD.drawRect((i * 26) + 4, 19 , (i * 26) + 30, 43);
  }
  printChangeLED();

  drawRegButton();
  printButton("SAVE", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
  printButton("BACK", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
}

// Режим ожидания --- Dispscreen=100
/*
  void standby(boolean refreshAll = false) //(boolean refreshAll=false)
  {
  dispScreen = 100;

  if (refreshAll)
  {
    changeFont(SMALL, 135, 206, 250, 0, 0, 0);
    myGLCD.print("TOUCH", CENTER, 200);
  }

  if ((RTC.hour != prevRTC.tHour) || (RTC.minute != prevRTC.tMinute) || (RTC.day != prevRTC.tDay) || (RTC.month != prevRTC.tMonth) || (RTC.year != prevRTC.tYear) || refreshAll)
  {
    myGLCD.setColor(135, 206, 250);
    myGLCD.setFont(SevenSegNumFontPlus);
    prevRTC.tHour = RTC.hour;
    prevRTC.tMinute = RTC.minute;
    printTime(RTC.hour, RTC.minute, CENTER, 65);
    changeFont(LARGE, 135, 206, 250, 0, 0, 0);
    prevRTC.tDay = RTC.day;
    prevRTC.tMonth = RTC.month;
    prevRTC.tYear = RTC.year;
    printDate(CENTER, 120);
  }

  //printBell (KeyBell[0], KeyBell[1]);
  printATO (KeyATO[0], KeyATO[1]);
  printTemp (KeyTempWater[0], KeyTempWater[1]);
  printService (serviceFlag, KeyService[0], KeyService[1]);
  printWaterTap (waterTapFlag, KeyWaterTap[0], KeyWaterTap[1]);
  printSound (soundFlag, KeySound[0], KeySound[1]);

  printTempWater (218, 140);
  }*/

///////////////////////////////////
// ***   ---   TOUCH   ---   *** //
///////////////////////////////////

void processMyTouch()
{
  myTouch.read();
  x = myTouch.getX();
  y = myTouch.getY();

  prevMillis600 = millis();
  if ((x >= KeyCancel[0]) && (x <= KeyCancel[2]) && (y >= KeyCancel[1]) && (y <= KeyCancel[3]) && (dispScreen != 0) && (dispScreen != 4) && (dispScreen != 5)) //press cancel
  {
    hlightButton("CANCEL", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
    dispScreen = 0;
    clearScreen();
    mainScreen(true);
  }
  else
  {
    switch (dispScreen)
    {
      case 0: // dispScreen 0
        if ((x >= KeyMenu[0]) && (x <= KeyMenu[2]) && (y >= KeyMenu[1]) && (y <= KeyMenu[3]))
        {
          dispScreen = 1;
          clearScreen();
          menuScreen();
        }
        break;

      case 1: // dispScreen 1

        if ((x >= KeyMenu1[0]) && (x <= KeyMenu1[2]))
        {
          if ((y >= KeyMenu1[1]) && (y <= KeyMenu1[3]))
          {
            hlightButton("SET TIME & DATE", KeyMenu1[0], KeyMenu1[1], KeyMenu1[2], KeyMenu1[3]);
            dispScreen = 2;
            clearScreen();
            clockScreen(true);
          }
          if ((y >= KeyMenu3[1]) && (y <= KeyMenu3[3]))
          {
            hlightButton("   ", KeyMenu3[0], KeyMenu3[1], KeyMenu3[2], KeyMenu3[3]);
          }
          if ((y >= KeyMenu5[1]) && (y <= KeyMenu5[3]))
          {
            hlightButton("   ", KeyMenu5[0], KeyMenu5[1], KeyMenu5[2], KeyMenu5[3]);
          }
          if ((y >= KeyMenu7[1]) && (y <= KeyMenu7[3]))
          {
            hlightButton("   ", KeyMenu7[0], KeyMenu7[1], KeyMenu7[2], KeyMenu7[3]);
          }
          if  ((y >= KeyOK[1]) && (y <= KeyOK[3]))
          {
            hlightButton("   ", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
          }
        }
        if ((x >= KeyMenu2[0]) && (x <= KeyMenu2[2]))
        {
          if  ((y >= KeyMenu2[1]) && (y <= KeyMenu2[3]))
          {
            hlightButton("LEDs OUTPUT", KeyMenu2[0], KeyMenu2[1], KeyMenu2[2], KeyMenu2[3]);
            dispScreen = 3;
            clearScreen();
            LEDmenuScreen();
          }
          if ((y >= KeyMenu4[1]) && (y <= KeyMenu4[3]))
          {
            hlightButton("   ", KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);
          }
          if ((y >= KeyMenu6[1]) && (y <= KeyMenu6[3]))
          {
            hlightButton("   ", KeyMenu6[0], KeyMenu6[1], KeyMenu6[2], KeyMenu6[3]);
          }
          if ((y >= KeyMenu8[1]) && (y <= KeyMenu8[3]))
          {
            hlightButton("   ", KeyMenu8[0], KeyMenu8[1], KeyMenu8[2], KeyMenu8[3]);
          }
        }
        break;

      case 2: // dispScreen 2
        if ((x >= KeyOK[0]) && (x <= KeyOK[2]) && (y >= KeyOK[1]) && (y <= KeyOK[3]))
        {
          hlightButton("SAVE", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
          SaveRTC();
          dispScreen = 0;
          clearScreen();
          mainScreen(true);
        }
        else {
          if ((y >= HourUp[1]) && (y <= HourUp[1] + 23)) {
            if ((x >= HourUp[0]) && (x <= HourUp[0] + 29)) {
              hlightUpButton(HourUp[0], HourUp[1]);
              tempRTC.tHour++;
              if (tempRTC.tHour >= 24) {
                tempRTC.tHour = 0;
              }
            }
            if ((x >= MinUp[0]) && (x <= MinUp[0] + 29)) {
              hlightUpButton(MinUp[0], MinUp[1]);
              tempRTC.tMinute++;
              if (tempRTC.tMinute >= 60) {
                tempRTC.tMinute = 0;
              }
            }
          }
          else if ((y >= HourDown[1]) && (y <= HourDown[1] + 23))
          {
            if ((x >= HourDown[0]) && (x <= HourDown[0] + 29))
            {
              hlightDownButton(HourDown[0], HourDown[1]);
              tempRTC.tHour--;
              if (tempRTC.tHour < 0)
              {
                tempRTC.tHour = 23;
              }
            }
            if ((x >= MinDown[0]) && (x <= MinDown[0] + 29))
            {
              hlightDownButton(MinDown[0], MinDown[1]);
              tempRTC.tMinute--;
              if (tempRTC.tMinute < 0)
              {
                tempRTC.tMinute = 59;
              }
            }
          }
          else if ((y >= DayUp[1]) && (y <= DayUp[1] + 23))
          {
            if ((x >= DayUp[0]) && (x <= DayUp[0] + 29))
            {
              hlightUpButton(DayUp[0], DayUp[1]);
              tempRTC.tDay++;
              if (tempRTC.tDay > 31)
              {
                tempRTC.tDay = 1;
              }
            }
            if ((x >= MonthUp[0]) && (x <= MonthUp[0] + 29))
            {
              hlightUpButton(MonthUp[0], MonthUp[1]);
              tempRTC.tMonth++;
              if (tempRTC.tMonth > 12)
              {
                tempRTC.tMonth = 1;
              }
            }
            if ((x >= YearUp[0]) && (x <= YearUp[0] + 29))
            {
              hlightUpButton(YearUp[0], YearUp[1]);
              if (tempRTC.tYear < 2100)
                tempRTC.tYear++;
            }
          }
          else if ((y >= DayDown[1]) && (y <= DayDown[1] + 23))
          {
            if ((x >= DayDown[0]) && (x <= DayDown[0] + 29))
            {
              hlightDownButton(DayDown[0], DayDown[1]);
              tempRTC.tDay--;
              if (tempRTC.tDay <= 0)
              {
                tempRTC.tDay = 31;
              }
            }
            if ((x >= MonthDown[0]) && (x <= MonthDown[0] + 29))
            {
              hlightDownButton(MonthDown[0], MonthDown[1]);
              tempRTC.tMonth--;
              if (tempRTC.tMonth <= 0)
              {
                tempRTC.tMonth = 12;
              }
            }
            if ((x >= YearDown[0]) && (x <= YearDown[0] + 29))
            {
              hlightDownButton(YearDown[0], YearDown[1]);
              if (tempRTC.tYear > 2000)
                tempRTC.tYear--;
            }
          }
          clockScreen(false);
        }
        break;

      case 3: // dispScreen 3
        if ((x >= KeyMenu1[0]) && (x <= KeyMenu1[2]))
        { //first column
          if ((y >= KeyMenu1[1]) && (y <= KeyMenu1[3]))
          {
            hlightButton(ch1Descr, KeyMenu1[0], KeyMenu1[1], KeyMenu1[2], KeyMenu1[3]);
            selectChannel = 1;
            dispScreen = 4;
            clearScreen();
            ledSetScreen();
          }
          if ((y >= KeyMenu3[1]) && (y <= KeyMenu3[3]) && (numberOfCh > 2))
          {
            hlightButton(ch3Descr, KeyMenu3[0], KeyMenu3[1], KeyMenu3[2], KeyMenu3[3]);
            selectChannel = 3;
            dispScreen = 4;
            clearScreen();
            ledSetScreen();
          }
          if ((y >= KeyMenu5[1]) && (y <= KeyMenu5[3]) && (numberOfCh > 4))
          {
            hlightButton(ch5Descr, KeyMenu5[0], KeyMenu5[1], KeyMenu5[2], KeyMenu5[3]);
            selectChannel = 5;
            dispScreen = 4;
            clearScreen();
            ledSetScreen();
          }
        }
        if ((x >= KeyMenu2[0]) && (x <= KeyMenu2[2]))
        {
          if ((y >= KeyMenu2[1]) && (y <= KeyMenu2[3]))
          {
            hlightButton(ch2Descr, KeyMenu2[0], KeyMenu2[1], KeyMenu2[2], KeyMenu2[3]);
            selectChannel = 2;
            dispScreen = 4;
            clearScreen();
            ledSetScreen();
          }
          if ((y >= KeyMenu4[1]) && (y <= KeyMenu4[3]) && (numberOfCh > 3))
          {
            hlightButton(ch4Descr, KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);
            selectChannel = 4;
            dispScreen = 4;
            clearScreen();
            ledSetScreen();
          }
          if ((y >= KeyMenu6[1]) && (y <= KeyMenu6[3]) && (numberOfCh > 5))
          {
            hlightButton(ch6Descr, KeyMenu6[0], KeyMenu6[1], KeyMenu6[2], KeyMenu6[3]);
            selectChannel = 6;
            dispScreen = 4;
            clearScreen();
            ledSetScreen();
          }
        }
        break;

      case 4: // dispScreen 4
        if ((x >= KeyOK[0]) && (x <= KeyOK[2]) && (y >= KeyOK[1]) && (y <= KeyOK[3]))
        {
          hlightButton("CHANGE", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
          dispScreen = 5;
          clearScreen();
          ledChangeScreen();
        }
        else if ((x >= KeyCancel[0]) && (x <= KeyCancel[2]) && (y >= KeyCancel[1]) && (y <= KeyCancel[3])) //press BACK
        {
          hlightButton("BACK", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
          dispScreen = 3;
          clearScreen();
          LEDmenuScreen();
        }
        break;

      case 5: // dispScreen 5
        if ((x >= KeyCancel[0]) && (x <= KeyCancel[2]) && (y >= KeyCancel[1]) && (y <= KeyCancel[3])) //press CANCEL
        {
          hlightButton("BACK", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
          dispScreen = 4;
          clearScreen();
          ledSetScreen();
        }
        if ((x >= KeyOK[0]) && (x <= KeyOK[2]) && (y >= KeyOK[1]) && (y <= KeyOK[3]))
        {
          hlightButton("SAVE", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);

          switch (selectChannel)
          {
            case 1:
              for (int i = 0; i < 96; i++)
                ch1led[i] = tled[i];
              SaveToEEPROM(1);
              break;
            case 2:
              for (int i = 0; i < 96; i++)
                ch2led[i] = tled[i];
              SaveToEEPROM(2);
              break;
            case 3:
              for (int i = 0; i < 96; i++)
                ch3led[i] = tled[i];
              SaveToEEPROM(3);
              break;
            case 4:
              for (int i = 0; i < 96; i++)
                ch4led[i] = tled[i];
              SaveToEEPROM(4);
              break;
            case 5:
              for (int i = 0; i < 96; i++)
                ch5led[i] = tled[i];
              SaveToEEPROM(5);
              break;
            case 6:
              for (int i = 0; i < 96; i++)
                ch6led[i] = tled[i];
              SaveToEEPROM(6);
              break;
          }
          dispScreen = 4;
          clearScreen();
          ledSetScreen();
        }

        else if ((y >= 15) && (y <= 35))
        {
          if ((x >= 4) && (x <= 316))
          {
            int oldLCT = LedChangeTime;
            LedChangeTime = map(x, 4, 316, 0, 12);
            if (oldLCT != LedChangeTime)
            {
              printChangeLED();
              myGLCD.setColor(0, 0, 0);
              myGLCD.fillRect((oldLCT * 26) + 5, 20, (oldLCT * 26) + 29, 42);
              changeFont(SMALL, 255, 255, 0, 0, 0, 0);
              myGLCD.printNumI((oldLCT * 2), (oldLCT * 26) + 19 - (intlen(oldLCT * 2) * 4), 20);
              myGLCD.printNumI(((oldLCT * 2) + 1), (oldLCT * 26) + 19 - (intlen(oldLCT * 2) * 4), 31);
            }
          }
        }
        else if ((y >= 44) && (y <= 65))
        {
          for (int i = 0; i < 8; i++)
          {
            if ((x >= (i * 38) + 10) && (x <= (i * 38) + 29 + 10))
            {
              int k = (LedChangeTime * 8) + i;
              if (tled[k] < 100)
                tled[k]++;
              printVBar( tled[k], (i * 38) + 10, 44, rgbChann[selectChannel - 1]);
            }
          }
        }
        else if ((y >= 67) && (y <= 166))
        {
          for (int i = 0; i < 8; i++)
          {
            if ((x >= (i * 38) + 10) && (x <= (i * 38) + 29 + 10))
            {
              int k = (LedChangeTime * 8) + i;
              tled[k] = 166 - y;
              printVBar( tled[k], (i * 38) + 10, 44, rgbChann[selectChannel - 1]);
            }
          }
        }
        else if ((y >= 168) && (y <= 190))
        {
          for (int i = 0; i < 8; i++)
          {
            if ((x >= (i * 38) + 10) && (x <= (i * 38) + 29 + 10))
            {
              int k = (LedChangeTime * 8) + i;
              if (tled[k] > 0)
                tled[k]--;
              printVBar( tled[k], (i * 38) + 10, 44, rgbChann[selectChannel - 1]);
            }
          }
        }
        break;
    }
  }
}

void setup()
{
  initSettings();

  // настройка выводов
  pinMode(ledPinCh1, OUTPUT);
  digitalWrite(ledPinCh1, LOW);
  pinMode(ledPinCh2, OUTPUT);
  digitalWrite(ledPinCh2, LOW);
  pinMode(ledPinCh3, OUTPUT);
  digitalWrite(ledPinCh3, LOW);
  pinMode(ledPinCh4, OUTPUT);
  digitalWrite(ledPinCh4, LOW);
  pinMode(ledPinCh5, OUTPUT);
  digitalWrite(ledPinCh5, LOW);
  pinMode(ledPinCh6, OUTPUT);
  digitalWrite(ledPinCh6, LOW);

  // настройка дисплея
  myGLCD.InitLCD(LANDSCAPE);
  myGLCD.clrScr();
  // настройка сенсора
  myTouch.InitTouch(LANDSCAPE);
  myTouch.setPrecision(PREC_MEDIUM);

  // читает EEPROM если нет сохраненных данных
  if (readEEonStart)
  {
    ReadFromEEPROM();
  }
  // читает значение RTC
  RTC.getTime();
  // включает свет
  LED_levels_output();

  // прорисовывает рамку, (позже переедет в отдельную функцию)
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRect(0, 0, 319, 239);
  myGLCD.fillRect(0, 226, 319, 239);
  changeFont(SMALL, 0, 0, 0, 255, 255, 255);
  myGLCD.print("Aquarium Controller", CENTER, 227);
  myGLCD.print("v.1.0", RIGHT, 227);
  // отрисовывает главный экран
  clearScreen();
  mainScreen(true);
  Serial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();

  if (myTouch.dataAvailable()) // проверяет сенсор
  {
    processMyTouch();
  }

  else if (currentMillis - prevMillis5 > 5000) // 5сек проверяем, что изменилось
  {
    prevMillis5 = currentMillis;
    RTC.getTime();
    LED_levels_output();

    if (dispScreen == 0)
      mainScreen();
  }
  else if (currentMillis - prevMillis600 > 600000) // 10 мин, проверяем состояние экрана
  {
    prevMillis600 = currentMillis;
    if (dispScreen != 0)
    {
      dispScreen = 0;
      clearScreen();
      mainScreen(true);
    }
  }
}

shok.gif Обещаю, больше не выкладывать такой длинный код, а только дополнения...
Библиотеки можно скачать в первом посте этой темы.

Если Вам этого достаточно, то можете смело корректировать главный экран, по своему вкусу.

Если этого недостаточно, подписывайтесь, приглашайте друзей и знакомых friends.gif , ждите обновлений. Всё только началось... komp_r.gif

Схема подключения Читать
Прикрепленное изображение

Продолжение следует…

Прикрепленный файл  aqua_v1_0.zip ( 8.16 килобайт ) Кол-во скачиваний: 466


Сообщение отредактировал Ruslan.Kuchma - 24.12.2015, 15:39


--------------------


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ye_Lviv
сообщение 25.12.2015, 1:23
Сообщение #10


Аквариумист
**
Группа: Пользователи
Сообщений: 75
Регистрация: 28.11.2008
Из: Львов
Украина Украина
Благодарности: 209 раз(а)


Цитата(Chumak @ 17.12.2015, 14:20) *
Акваконтроллер своїми руками на Ардуїно - це реальність і не складно.

Схильний думати, що Ардуніо не найкращий варіант і далеко не дешевий. Для загального розвитку штука непогана але в перспекиві бачу масу обмежень.
Набагато перспективніше брати за основу Разбері. На нього портовано кілька лінуксів в тому числі Убунта і навіть андроїд, хоча не розумію навіщо потрібний громіздкий Андроїд якщо є Убунта але це справа вибору відповідного софта.
Маючи разбері для вас відкриваються всі мережні технології Лан, ВайФай, Блютуз тощо Фтіпі, Сфтп, Самба що дасть змогу підєднати вебкамеру та здійснювати дистанційне керування засобами ссгаш чи навіть впн віддаленої консолі.
На додаток Разбері теж має масу програм та пристроїв дисплеїв з сенсорними екранами не кажучи про СПІАЙ шини і масу готових програм для маси пристроїв. Є ГДеМІАЙ вихід на монітор для фул ГД є аналоговий відевихід слот на мініфлешку ЮСБІ хаб і тд і тп.
Єдине не варто брати Разбері китайського виробника так як там лоадер не стандартний і вимагає компілювати програми в бінарні коди і тільки такі програми розуміє той лоадер, що в рази збільшує трудоємкість встановлювання програм на комп.
Хоч Ардуніо і хороша штука і софта до нього вистарчає всеж то достатньо комерціалізована система і вона аж ніяк не зможе змагатися з розробниками софта для Лінукса як по кількості так і по якості.
А гілка разбері розвивається вже є і Банани і Оранж тощо можна навіть сумістити акваконтролер з ТВ сервером особливо така система буде перспективна для тих хто обслуговує багато акваріумів так як на разбері можна встановити бездротові модеми чи засабами ВІФІ або ЛАн підєднати систему в інтернет якщо такий є у споживача і моніторити стан акваріума через віддалене спостереження веб камери. Доречі для Разбері є маса дешевих веб камер.
Тож Ардуніо для розминки непогано але як перспектива не дуже.
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 25.12.2015, 9:14
Сообщение #11


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


Ye_Lviv, Ооооо, ну тут явный перебор...

Цитата
Схильний думати, що Ардуніо не найкращий варіант і далеко не дешевий.

Ну конечно, Raspberry Pi в оригинале, дешевле Arduino...

Цитата
Хоч Ардуніо і хороша штука і софта до нього вистарчає всеж то достатньо комерціалізована система і вона аж ніяк не зможе змагатися з розробниками софта для Лінукса як по кількості так і по якості.

И если открытый исходный код - это коммерция...

Цитата
Тож Ардуніо для розминки непогано але як перспектива не дуже.

А я тут распинаюсь....

После таких слов, наверное тему можно закрывать...


--------------------
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
chetalex
сообщение 25.12.2015, 19:32
Сообщение #12


Aquafanatic
*****
Группа: Журналисты
Сообщений: 1 005
Регистрация: 16.4.2012
Из: Александрия
Украина Украина
Благодарности: 2868 раз(а)


Цитата(Ruslan.Kuchma @ 25.12.2015, 9:14) *
наверное тему можно закрывать...


Не согласен. В любом случае начатое нужно довести до конца. Вы решили помочь людям разобраться с Ардуино. И продолжайте. Те, кто читают подобные темы, прежде чем что-то сделать ищут кучу альтернатив и в итоге каждый выберет для себя то, что посчитает нужным.
Кому-то да пригодится komp_r.gif


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
kostyan_inter1
сообщение 25.12.2015, 20:57
Сообщение #13


Аквариумист
**
Группа: Пользователи
Сообщений: 40
Регистрация: 13.2.2015
Из: Днепр
Украина
Благодарности: 30 раз(а)


COM порт? - сегодня для ARDUINO это вообще не проблема, есть куча вариантов адаптеров (например: у китайцев "Pl2303 PL2303HX чип USB модуль адаптер конвертер в RS232 TTL USB-TTL" - $ 0.67)

ARDUINO это дорого? Попробуйте убедить меня в обратном:
сейчас собираю аква контроллер на ARDUINO (пользуюсь информацией с открытого форума с открытыми исходными кодами и т.д.) с таким функционалом - энергонезависимые часы реального времени; графический экран с регулировкой яркости подсветки и контрастности; управление 13-ю нагрузками (в том числе и канал ШИМ для рассвета-заката); куча таймеров (до 500); поддержка режима «кормление» - фильтр становится в паузу; цифровой термометр - управление нагревателем и охладителем.

А теперь внимание, стоимость "материнской части" $5.04:
контроллер (PRO Mini ATMEGA328P) - $1.49
часы реального времени (I2C RTC DS1307 AT24C32 Real Time Clock Module for Arduino) - $0.58
индикатор (84*48 84x84 LCD Module White backlight adapter PCB for Nokia 5110 Arduino) - $1.87
Влагозащищенный цифровой датчик температуры (DS18b20 Waterproof Temperature Sensors ) - $1.10
Реальные цены, бесплатная доставка из поднебесной, жду посылку.

Понятно что это еще не все компоненты для создания полноценного акваконтроллера, но остальные элементы приблизительно будут общими как для ARDUINO так и для Raspberry Pi:
например блок питания - купил на "развес" на блошином рынке БП зарядки для телефонов приблизительно 0.40 $/шт;
силовая часть у тех же китайцев - релейные модули от 1 до 16 каналов в принципе до бесконечности например модуль 5В на 4 канала стоит 2.4 $
и т.д. и т.п.

Просто нужно решить для себя, что мы хотим? Функциональное недорогое устройство, которое будет нам помогать в поддержании аквариума, когда нет никого рядом. Или красивая, но дорогая игрушка с разными цветными дисплеями, кучей Wi-Fi-ями, Bluetooth-ми, вебкамерами для подглядывания за своими питомцами и прочими всевозможными примочками (не спорю, при этом тоже достаточно функциональное).
hi.gif


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Chumak
сообщение 25.12.2015, 21:35
Сообщение #14


Активный аквариумист
***
Группа: Партнёры
Сообщений: 403
Регистрация: 16.3.2013
Из: Днепр
Украина
Благодарности: 413 раз(а)


Цитата(Ruslan.Kuchma @ 23.12.2015, 13:41) *
Схема подключения

А у вас годинник нормально при такому підключенні працює? У мене, правда, модуль на базі DS1307. І без додаткових резисторів не можу нормально зчитати час. Ненадійно працює.

Ye_Lviv, імхо Ардуіно - вдалий вибір для такої одноразової розробки. Тут не потрібні навороти Расбері. І ціна менша. Взяв готові плати, з’єднав - і все працює.
Звісно, для (дрібно)серійного виробництва можна пошукати і іншу платформу. Але для себе або для друга на замовлення щось склепати - саме те, що треба!

Сообщение отредактировал Chumak - 25.12.2015, 21:39


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ye_Lviv
сообщение 27.12.2015, 12:00
Сообщение #15


Аквариумист
**
Группа: Пользователи
Сообщений: 75
Регистрация: 28.11.2008
Из: Львов
Украина Украина
Благодарности: 209 раз(а)


Цитата(Chumak @ 25.12.2015, 22:35) *
Ye_Lviv, імхо Ардуіно - вдалий вибір для такої одноразової розробки.

Якщо не потрібні ВЕБ технології то ніхто і не буде сперечаєтися, відносно ціни то на разбері старих моделей вона падає. А вибір того чи іншого пристрою повинен визначатися в основному затратами вкладеної праці і якщо Ардуніо забере менше часу для вирішення поставленої задачі то і говорити нема про що. dry.gif
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 31.12.2015, 11:53
Сообщение #16


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif
Спасибо за поддержку!
На счёт закрывать тему, погорячился. blush.gif
Цитата
А у вас годинник нормально при такому підключенні працює? У мене, правда, модуль на базі DS1307. І без додаткових резисторів не можу нормально зчитати час. Ненадійно працює.

Да, другого подключения просто быть не может.
DS1307 вечная проблема. Если удастся найти кварц от старой материнской платы, то показания будут стабильнее.
Но советую перейти на DS3231.

Цитата
COM порт? - сегодня для ARDUINO это вообще не проблема, есть куча вариантов адаптеров (например: у китайцев "Pl2303 PL2303HX чип USB модуль адаптер конвертер в RS232 TTL USB-TTL" - $ 0.67

На дворе был 2012 год, о каком Китае могла идти речь? Сейчас понятное дело, сейчас и Arduino самому паять ненужно, а на то время была такая проблема.



--------------------
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 31.12.2015, 12:47
Сообщение #17


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif
Спящий режим
На примере управления светом очень сложно объяснить, как и что устроено, поэтому я не стал сильно нагружать информацией. (Даже если добавить комментарий к каждой строке)
Сегодня более детально рассмотрим новую функцию, «спящий режим»
Суть заключается в том, что к примеру, через 15мин. С экрана стираем всю информацию и выводим только время.

Подключим новый шрифт, так как используемые ранее шрифты очень маленькие для пустого экрана
Для этого нужно скачать новый шрифт Прикрепленный файл  SevenSegNumFontPlus.zip ( 811 байт ) Кол-во скачиваний: 347
и поместить его в корневую папку библиотеки UTFT

Переходим к программе:
  • Подключаем этот шрифт добавив строку:

Код
extern uint8_t SevenSegNumFontPlus[];

  • Нужна новая переменная для сброса таймера.

Ищем метку «// счётчики» и добавим туда:
Код
unsigned long prevMillis900 = 0;


Приступим к новому экрану.
  1. Прописываем новый экран:

    CODE

    // Режим ожидания --- Dispscreen=100

    void standby(boolean refreshAll = false) // Объявляем новую функцию, она имеет булевую переменную «refreshAll» и присваиваем ей значение 0
    {
    if (refreshAll) // Проверяем, значение «refreshAll»
    { // если оно true или неравно 0, то выполняем то что в фигурных скобках
    // если refreshAll == 0 то эта часть игнорируется
    changeFont(SMALL, 135, 206, 250, 0, 0, 0); // объявляем шрифт с параметрами
    myGLCD.print("TOUCH", CENTER, 200); // выводим текст на экран
    }
    if ( (RTC.hour != prevRTC.tHour) || // если текущее показание часа не равно предыдущему
    (RTC.minute != prevRTC.tMinute) || // или текущее показание минуты не равно предыдущему
    (RTC.day != prevRTC.tDay) || // или текущее показание дня не равно предыдущему
    (RTC.month != prevRTC.tMonth) || // или текущее показание месяца не равно предыдущему
    (RTC.year != prevRTC.tYear) || // или текущее показание года не равно предыдущему
    refreshAll // или refreshAll неравно 0
    )
    {
    myGLCD.setColor(135, 206, 250); // устанавливает цвет «чернил» для всех команд печати и рисования графических примитивов.
    myGLCD.setFont(SevenSegNumFontPlus); // устанавливает шрифт для команд печати. В качестве параметра передается имя шрифта.
    prevRTC.tHour = RTC.hour; // присваиваем новое значение часа
    prevRTC.tMinute = RTC.minute; // присваиваем новое значение минуты
    printTime(RTC.hour, RTC.minute, CENTER, 65); // выводим время на экран
    changeFont(LARGE, 135, 206, 250, 0, 0, 0); // объявляем шрифт с параметрами
    prevRTC.tDay = RTC.day; // присваиваем новое значение дня
    prevRTC.tMonth = RTC.month; // присваиваем новое значение месяца
    prevRTC.tYear = RTC.year; // присваиваем новое значение года
    printDate(CENTER, 120); // выводим даты на экран
    }
    }


  2. Далее это затрагивает функцию сенсора, изменений немного, но они есть.

    Ищем строку:
    Код
    if ((x >= KeyCancel[0]) && (x <= KeyCancel[2]) && (y >= KeyCancel[1]) && (y <= KeyCancel[3]) && (dispScreen != 0) && (dispScreen != 4) && (dispScreen != 5))

    и объявляем, что если dispScreen равен значению 100, то нажатие игнорируется
    меняем на:
    Код
    if ((x >= KeyCancel[0]) && (x <= KeyCancel[2]) && (y >= KeyCancel[1]) && (y <= KeyCancel[3]) && (dispScreen != 0) && (dispScreen != 4) && (dispScreen != 5) && (dispScreen != 100))

    В case 0 перед break; добавим ручной переход к спящему режиму:
    Код
            else if ((x >= 0) && (x <= 319) && (y >= 0) && (y <= 16))
            {
              dispScreen = 100;
              clearScreen();
              standby(true);
            }

    Также появилась необходимость вернуться к главному экрану, для этого сделаем следующее добавим ещё один процесс в Switch:
    Код
          case 100:
            if ((x >= 0) && (x <= 319) && (y >= 120) && (y <= 239))
            {
              dispScreen = 0;
              clearScreen();
              mainScreen(true);
            }
            break;

  3. Теперь всё готово для того чтоб основная функция loop() узнала о новых функциях и могла корректно их выполнять.

    У нас есть уже два прерывания по времени, первое 5сек, второе 10мин.
    Проверка значений времени каждые 5сек, устраивает. Значит можно добавить ещё один экран на который следует обращать программе
    Ищем:
    Код
      else if (currentMillis - prevMillis5 > 5000) // 5сек проверяем, что изменилось
      {
        prevMillis5 = currentMillis;
        RTC.getTime();
        LED_levels_output();

        if (dispScreen == 0)
          mainScreen();

      }

    Меняем на:
    Код
      else if (currentMillis - prevMillis5 > 5000) // 5сек проверяем, что изменилось
      {
        prevMillis5 = currentMillis;
        RTC.getTime();
        LED_levels_output();

        if (dispScreen == 0)
          mainScreen();

        if (dispScreen == 100) // Если переменная dispScreen равняется 100 то выполняем
          standby();
      }

    Также есть проверка состояния экрана, тут нужно добавить, что если в режиме ожидания, то ничего делать ненужно.
    Ищем строку:
    Код
    if (dispScreen != 0)

    Меняем на:
    Код
    if ((dispScreen != 0) && (dispScreen != 100))

    Ну и осталось последнее! Сказать, когда нужно перейти в режим ожидания, для этого нужно перед самой последней фигурной скобкой добавить следующее:
    Код
      else if (currentMillis - prevMillis900 > 900000) // 15 мин, проверяем состояние экрана
      {
        prevMillis900 = currentMillis;
        if (dispScreen == 0) // переход в режим ожидания только если главный экран
        {
          dispScreen = 100;
          clearScreen();
          standby(true);
        }
      }


Сообщение отредактировал Ruslan.Kuchma - 5.1.2016, 12:20
Прикрепленные файлы
Прикрепленный файл  aqua_v1_1.zip ( 8.67 килобайт ) Кол-во скачиваний: 347
 


--------------------


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Ruslan.Kuchma
сообщение 5.1.2016, 11:38
Сообщение #18


Аквариумист
**
Группа: Журналисты
Сообщений: 53
Регистрация: 13.11.2012
Из: Краматорск
Украина
Благодарности: 89 раз(а)


hi.gif
Тестовый режим
Всегда после настройки освещения хочется посмотреть, как будет выглядеть тот же рассвет/закат. Для этого можно написать функцию тестирования. Тем более особо ничего изобретать ненужно.
Ищем «экран меню», назначаем кнопку которая отвечает за переход на экран тестового режима.
В этой части кода уже всё есть нужно только подписать кнопку, я выбрал KeyMenu4
Код
printButton("TEST LEDs", KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);

Добавим новый экран:
CODE

// LED test screen --- dispScreen=6

void testScreen(boolean refreshAll = false)
{
int bary;

if (refreshAll)
{
printHeader("Test LEDs output settings");
myGLCD.setColor(0, 0, 0);
myGLCD.fillRect (2, 17, 317, 155);
myGLCD.fillRect(testStartStop[0], testStartStop[1], testStartStop[2], testStartStop[3]);

printButton ("START TEST", testStartStop[0], testStartStop[1], testStartStop[2], testStartStop[3]); //start
printButton ("-10m", testMinus[0], testMinus[1], testMinus[2], testMinus[3]); //-10m
printButton ("+10m", testPlus[0], testPlus[1], testPlus[2], testPlus[3]); //+10m

myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (4, 155, 68, 179);
myGLCD.drawRoundRect (251, 155, 315, 179);
myGLCD.drawRoundRect (71, 155, 248, 179);

drawRegButton();
printButton("RESET", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
printButton("CANCEL", KeyCancel[0], KeyCancel[1], KeyCancel[2], KeyCancel[3]);
}

if (LEDtestFlag == 1)
{
myGLCD.setColor(255, 0, 0);
myGLCD.fillRect (testStartStop[0] + 4, testStartStop[1] + 4, testStartStop[2] - 4, testStartStop[3] - 4);
changeFont(SMALL, 255, 255, 255, 255, 0, 0);
myGLCD.print("STOP TEST", 123, 162);
changeFont(LARGE, 255, 255, 255, 0, 0, 0);
myGLCD.print("Time:", 70, 135);

while (LEDtestFlag > 0)
{
unsigned long cMillis = millis();

if (myTouch.dataAvailable(smile.gif
{
processMyTouch();
}

if ((cMillis - prevMillis05 > 500) && (LEDtestFlag == 1:)
{
prevMillis05 = cMillis;

min_cnt++;
if (min_cnt > 1440)
min_cnt = 0;
int tmphour = min_cnt / 60;
int tmpminut = min_cnt % 60;
changeFont(LARGE, 255, 255, 0, 0, 0, 0);
printTime(tmphour, tmpminut, 162, 135);

for (int i = 0; i < numberOfCh; i++)
{
if ((prevLEDch_out[i] != LEDch_out[i]) || refreshAll)
{
bary = 3 + (130 / (numberOfCh + 1:) * (i + 1);
drawLedBar(bary, i + 1);
prevLEDch_out[i] = LEDch_out[i];
}
}

LED_levels_output();

}
}
}
}

Как видите ничего сложного в этой функции кроме прорисовки графики повторяется часть кода, написанная ранее для вычисления мощности канала света.
Добавим не хватающих переменных:
  1. На экране появились новые кнопки
    Код
    // --- test LEDs
    const int testStartStop[] = {71, 155, 248, 179};    //start/stop
    const int testMinus[] = {4, 155, 68, 179};      //-10m
    const int testPlus[] = {251, 155, 315, 179};   //+10m

  2. В LED переменные добавим флаг, указывающий на то что управление освещением в режиме тестирования
    Код
    byte LEDtestFlag = 0; //0-выкл, 1-тест выполняется, 2-тест остановлен

  3. Новая переменная для сброса таймера
    Код
    unsigned long prevMillis05 = 0;

  4. В функции «LED_levels_output()», добавим условие при котором она будет игнорироваться.
    Ищем строку
    Код
    min_cnt = (RTC.hour * 60) + RTC.minute;

    добавим перед ней
    Код
    if (LEDtestFlag == 0)

Теперь можно перейти к управлению.
  1. В функции processMyTouch(), ищем часть которая отвечает за управление меню, находится она в case 1:, ищем нужную кнопку и говорим ей что нужно выполнить при нажатии.
    меняем:
    Код
              if ((y >= KeyMenu4[1]) && (y <= KeyMenu4[3]))
              {
                hlightButton("   ", KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);
              }

    на:
    Код
              if ((y >= KeyMenu4[1]) && (y <= KeyMenu4[3]))
              {
                hlightButton("TEST LEDs", KeyMenu4[0], KeyMenu4[1], KeyMenu4[2], KeyMenu4[3]);
                dispScreen = 6;
                clearScreen();
                testScreen(true);
              }

  2. Для кнопки CANCEL добавим ещё одно действие
    Код
        LEDtestFlag = 0;

  3. Добавим управление непосредственно режимом тестирования. Ищем case 100: и перед ним добавим следующую часть кода:
    CODE

    case 6:
    if ((x >= KeyOK[0]) && (x <= KeyOK[2]) && (y >= KeyOK[1]) && (y <= KeyOK[3]smile.gif
    { //reset
    hlightButton("RESET", KeyOK[0], KeyOK[1], KeyOK[2], KeyOK[3]);
    LEDtestFlag = 0;
    min_cnt = 0;
    for (int i = 0; i < numberOfCh; i++)
    {
    prevLEDch_out[i] = 255;
    LEDch_out[i] = 0;
    }
    testScreen(true);
    }
    else if ((x >= testStartStop[0]) && (x <= testStartStop[2]) && (y >= testStartStop[1]) && (y <= testStartStop[3]smile.gif //press start/stop test
    {
    if (LEDtestFlag == 1)
    { //stop
    hlightButton("RESUME TEST", testStartStop[0], testStartStop[1], testStartStop[2], testStartStop[3]);
    LEDtestFlag = 2;
    testScreen();
    }
    else
    { //start
    hlightButton("STOP TEST", testStartStop[0], testStartStop[1], testStartStop[2], testStartStop[3]);
    if (LEDtestFlag == 0)
    {
    min_cnt = 0;
    for (int i = 0; i < numberOfCh; i++)
    {
    prevLEDch_out[i] = 255;
    LEDch_out[i] = 0;
    }
    }
    LEDtestFlag = 1;
    testScreen();
    }
    }
    else
    {
    if ((x >= testMinus[0]) && (x <= testMinus[2]) && (y >= testMinus[1]) && (y <= testMinus[3]smile.gif //press -10m
    {
    hlightButton("-10m", testMinus[0], testMinus[1], testMinus[2], testMinus[3]);
    min_cnt -= 10;
    if (min_cnt < 0)
    {
    min_cnt = 0;
    }
    delay(50);
    }
    if ((x >= testPlus[0]) && (x <= testPlus[2]) && (y >= testPlus[1]) && (y <= testPlus[2]smile.gif //press +10m
    {
    hlightButton("+10m", testPlus[0], testPlus[1], testPlus[2], testPlus[3]);
    min_cnt += 10;
    delay(50);
    }
    }
    break;


Сообщение отредактировал Ruslan.Kuchma - 5.1.2016, 12:19
Прикрепленные файлы
Прикрепленный файл  aqua_v1_2.zip ( 9.44 килобайт ) Кол-во скачиваний: 416
 


--------------------


Благодарности:
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Arafrael
сообщение 1.4.2016, 13:05
Сообщение #19


Я присматриваюсь...

Группа: Присматриваюсь
Сообщений: 4
Регистрация: 31.3.2016
Из: Светловодск
Украина Украина
Благодарности: 2 раз(а)


подскажи какие драйвера для сетодиодов использовались и где покупались, а то найти не могу. буду теститьспасибо
Перейти в начало страницы
Вставить ник
+Цитировать сообщение
Юрий77
сообщение 1.4.2016, 13:14
Сообщение #20


Студент
*****
Группа: Журналисты
Сообщений: 2 142
Регистрация: 16.7.2009
Из: Днепр
Украина
Благодарности: 3307 раз(а)


У кого в какую цифру влился такой контролёр?


--------------------
AquascapeTV/videos
Aquaticstory/videos.
Опыт — это слово, которым люди называют свои ошибки.
Перейти в начало страницы
Вставить ник
+Цитировать сообщение

3 страниц V   1 2 3 >
Начать новую темуОтветить в данную тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

Свернуть

> Похожие темы

  Тема Ответов Автор Просмотров Последнее сообщение
Нет новых сообщений Уголок проходной AQUAXER, 1/4", под шланг 8 мм.
0 Arowana Info 1 024 17.10.2023, 8:04 Посл. сообщение: Arowana Info
Нет новых сообщений Соединитель AQUAXER, штуцер 1/4", под шланг 4 мм.
0 Arowana Info 2 813 8.8.2023, 9:30 Посл. сообщение: Arowana Info
Нет новых сообщений Застежка "Американка" №00, Корея, 10 шт.
0 Arowana Info 2 520 15.6.2023, 14:46 Посл. сообщение: Arowana Info
Нет новых сообщений Застежка "Американка" №0, Корея, 10 шт.
0 Arowana Info 2 688 15.6.2023, 14:46 Посл. сообщение: Arowana Info
Нет новых сообщений Застежка "Американка" №0, Корея, 100 шт.
0 Arowana Info 2 824 5.7.2022, 8:28 Посл. сообщение: Arowana Info

 



Перейти в начало страницы RSS Текстовая версия Сейчас: 29.3.2024, 3:19