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

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




История благодарностей участнику Ruslan.Kuchma ::: Спасибо сказали: 89 раз(а)
Дата поста: В теме: За сообщение: Спасибо сказали:
3.1.2020, 11:09 НАНО-РИФ (перезагрузка)
dishu1, Даже не знаю, предположительно 15-20см
drv,
7.4.2016, 22:06 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
Arafrael, hi.gif
Смотрите, настройка простая. Если я правильно понял о чём речь.
[attachment=301505:DSC_1099.jpg]

Интервал для значения 15мин.
[attachment=301506:0_24.jpg]
Реализовано так, что если текущее значение к примеру 50, а следующее 75, то в течении 15мин оно вырастет до 75.
Организованно в этой части кода:
CODE

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;
}


Arafrael, kostyan_inter1, macik, yarishNEW,
1.4.2016, 19:09 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
Arafrael, Покупал тут, хорошие драйвера 700 mA
Юрий77, По цене сложно сказать, доллар нестабилен, нужно считать... mail1.gif

Ну и программа ещё не дописана, времени вообще нет blush.gif , ну и интереса к теме большого не вижу, а из-за этого руки опускаются, и продолжать не хочется... sad.gif
kostyan_inter1, macik,
27.3.2016, 11:28 НАНО-РИФ (перезагрузка)
dishu1, Нормальный, со своими обязанностями справляется, по качеству отличный good.gif.
Камень(распылитель) как расходник 2-3 месяца и менять...
Чаша маленькая, но имеет штуцер для слива.
Быстро заростает, так как на него попадает свет, лучше конечно разместить в сампе.
dishu1,
4.3.2016, 11:05 НАНО-РИФ (перезагрузка)
hi.gif
04.03.2016
[attachment=298253:DSC_1018.jpg]
Последние 5 дней аквариум выглядит сносно хорошо.
  • Вода чистая
  • Динофи́товые во́доросли почти исчезли
  • Нитка присутствует в небольшом количестве.

Осталось снизить количество нитратов и можно заселять.
drv, Julia84,
19.1.2016, 11:25 Дорога к морю...
От айптазий есть хороший способ, креветка вундермани...
drv, sviridov80,
11.1.2016, 9:11 Дорога к морю...
Druid, Возьмите лучше хороший СРК, черноморский попадается неплохой, но в большинстве случаев он неважный, как на вид так и по пористости. ИМХО
sviridov80,
9.1.2016, 16:08 Светодиодное освещение для глубокого аквариума
Да-да, определённо с подключением промашка...
Почитайте про кристаллы с разными цветами и материалами.
Этой статьи хватит, чтоб понять почему сгорают, через пол дня после установки
drv, yarishNEW,
5.1.2016, 11:38 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
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;
kostyan_inter1, yarishNEW, Юрий77, ~~DANILA~~,
4.1.2016, 9:26 НАНО-РИФ (перезагрузка)
hi.gif
04.01.2016
Бурые водоросли начали сдавать позиции, на их место пришла зелёнка.
[attachment=293170:DSC_0874.jpg]
Всё идёт по плану good.gif
drv, Julia84, sviridov80,
31.12.2015, 17:53 НАНО-РИФ (перезагрузка)
hi.gif
31.12.2015
Баночка зреет.
Дискосома значительно прибавила в весе
[attachment=293022:PC310762.JPG]
Диатомовые атакуют aggres.gif , всё в буром налёте.
Была мысль, что это дино, но вооружившись микроскопом окончательно убедился, что диатомовые
[attachment=293023:DSC_0864.jpg]
Зонтики чувствуют не очень sad.gif
[attachment=293024:PC310777.JPG]
Похоже сильно много света...
Serdgios, sviridov80,
31.12.2015, 12:47 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
hi.gif
Спящий режим
На примере управления светом очень сложно объяснить, как и что устроено, поэтому я не стал сильно нагружать информацией. (Даже если добавить комментарий к каждой строке)
Сегодня более детально рассмотрим новую функцию, «спящий режим»
Суть заключается в том, что к примеру, через 15мин. С экрана стираем всю информацию и выводим только время.

Подключим новый шрифт, так как используемые ранее шрифты очень маленькие для пустого экрана
Для этого нужно скачать новый шрифт [attachment=292999:SevenSeg...FontPlus.zip] и поместить его в корневую папку библиотеки 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);
        }
      }
kostyan_inter1, yarishNEW,
23.12.2015, 13:41 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
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

Схема подключения Читать
[attachment=292333:scheme1.jpg]

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

[attachment=292457:aqua_v1_0.zip]
yarishNEW, ~~DANILA~~,
21.12.2015, 15:10 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
hi.gif
Вводный инструктаж.

Очень важно чётко понять, что именно должно получится в конечном результате.
Для этого нужен алгоритм работы. Сложно всё представить себе в голове, последовательность всех действий, для этого лучше всего воспользоваться листом бумаги и карандашом.
Многие должны знать, что такое алгоритм со школы
Так выглядит «базовый» алгоритм работы контроллера.
[attachment=292110:main_cycle.png]
У многих ошибка, все задачи ставить в основную функцию LOOP (), этого делать ненужно. Программа получается рабочая, но очень-очень медленная. Так как ей приходится вычислять ненужное… Чтоб этого избежать нужно создать отдельные функции, к которым программа будет обращаться только если это нужно…
Например, нет смысла выводить значение времени на экран 1000 раз в секунду, достаточно скажем 1 раз в пять секунд проверить изменилось оно или нет. Если да, выводим новое время, если нет, оставляем всё как есть.

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

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


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

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

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

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

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

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

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

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

// ---
void loop()
{
// После вызова функции setup(),
// которая инициализирует и устанавливает первоначальные значения,
// функция loop() делает точь-в-точь то, что означает её название,
// и крутится в цикле,
// позволяя вашей программе совершать вычисления и реагировать на них.
// Используйте её для активного управления платой Arduino.
}
kolyanich, yarishNEW,
20.12.2015, 11:10 НАНО-РИФ (перезагрузка)
hi.gif
Вчера вечером рассматривая аквариум aqua.gif тот что побольше, чисто случайно нашёл две головы зонтиков, не знаю unknown.gif , как это объяснить.
Выловил их и приклеил на камушек, покрутив его в руках, решил ну раз это находка то отправим новых жителей в новый аквариум.
Утром новые жители открылись, думаю будут жить.
sviridov80,
18.12.2015, 12:07 Пико-риф "из топора" (10л)
hi.gif
Как пенник, оправдывает затраченных денег или можно было сэкономить?
richmond,
18.12.2015, 11:56 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
hi.gif
Подключение
Очень важно при подключении!
В независимости сколько у вас будет модулей и источников питания "МАССА или GND", всех устройств должна быть общая!
Исключением является только подключение светодиодов к драйверам!

В ходе написания текста возникла идея и появился второй способ подключения. Первый более сложный, второй несильно отличается от первого… Я отдаю предпочтение первому.
Сейчас у многих отпадёт желание особенно у тех, кто не держал в руках паяльник, но надеюсь таких меньшинство, да и когда-то нужно начинать…
Первый способ Читать
Все ваши модули должны избавиться от разъёмов PBD, PBS и PLS, наверное, перегнул…
[attachment=291674:pbd.jpg][attachment=291675:pbs.jpg][attachment=291676:pls.jpg]
Проще говоря нужно выпаять все разъёмы и штырьки.
stop.gif
В Arduino оставляем, разъёмы USB и питания.
В шилде оставляем, разъём подключения дисплея.

Проще это сделать если есть "оловоотсос", если нет, спросить у соседа, если нет у соседа, ничего страшного. Можно поступить немного варварским способом, при помощи тонкой отвёртки. Загоняем отвёртку между платой и разъёмом и покачивая стягиваем пластмассовую часть разъёма, только без фанатизма, надеюсь вы знаете где нужна спешка…
Должно получиться приблизительно так
[attachment=291678:DSC_0812.jpg]
После греем каждый контакт и пинцетом извлекаем остатки разъёмов.
В дальнейшем все модули собираются при помощи проводов, ничего сложного, главное всё сделать аккуратно и внимательно, чтоб потом не переделывать.
[attachment=291679:DSC_0780.jpg]
Сразу расскажу, что куда паять, всё просто, на начальном этапе нужно соединить нужные пины Arduino с шилдом, см. ниже, подключаем к синим контактам.
[attachment=291680:tft_lcd_chema.png]

Второй способ Читать
Несильно отличается от первого с разницей только что получится некий «бутерброд». На Arduino удалить придётся все верхние (цифровые) и нижние (аналоговые разъёмы), в разъёме питания оставить два +5 и GND они нужны для питания шилда. На шилде тоже удаляем лишние контакты, оставим только +5 и GND, и добавим пять перемычек далее всё понятно с картинок…
[attachment=291683:DSC_0815.jpg]
[attachment=291684:DSC_0822.jpg]
[attachment=291686:DSC_0832.jpg]
[attachment=291687:DSC_0824.jpg]
[attachment=291688:DSC_0825.jpg]
[attachment=291689:DSC_0830.jpg]

Можно подключить конечно и другими способами, но я считаю их менее предпочтительными.
Если Вы знакомы с 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 вольт.

Продолжение следует…
chetalex, ded_andrey, kolyanich, yarishNEW, ~~DANILA~~,
17.12.2015, 16:02 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
Цитата(Chumak @ 17.12.2015, 15:23) *
Але налаштовувати все це за допомогою усього лише 5-х кнопок на дисплею 2х16 символів не дуже зручно.

Именно по этому, будет использоваться сенсорный дисплей, причём кому 3.2" мало, могут взять себе 4.3" или 5" или 7", всё зависит от толщины кошелька. Я не уверен, что у всех компьютер стоит рядом с аквариумом.
Совет Читать
Если планируете управлять с компьютера, убирайте бесполезный LCD Keypad Shield, поставьте вместо него экран побольше, к примеру символьный 20X4, и выводите на него информацию по I2C шине, освободите много пинов!
Chumak,
17.12.2015, 13:47 Контроллер на базе Arduino Mega 2560 + 3,2" TFT LCD Touch +++
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


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

Барабанная дробь… И, стандартная фраза...
Из модулей понадобится Читать
[attachment=291566:arduino_...0_ch340g.png]
Сердце контроллера, Arduino Mega 2560
[attachment=291567:3_2_TFT_LCD_Touch.jpg]
Устройство ввода/вывода информации, 3,2" TFT LCD Touch
[attachment=291599:Mega_Shield_V2_2.jpg]
Шилд, Arduino LCD TFT 3.2" Mega Shield V2.2, для подключения экрана.
[attachment=291569:ds1307_1.jpg] [attachment=291570:DS3132.jpg]
Часы реального времени, Real Time Clock Модуль (DS1307) или Real Time Clock Модуль (DS3231)
[attachment=291571:power.jpg]
Блок питания. (Лучше брать с запасом)
[attachment=291572:dupont.jpg]
Ну и конечно провода, много проводов, куда без них…

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

[attachment=291574:s_l300.jpg]
В дальнейшем это не будет выглядеть так, и все по той же причине - это конструктор.

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

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

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

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

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

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


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

[attachment=292183:DS1307new.zip]
[attachment=292185:UTFT.zip]
[attachment=292186:UTouch.zip]

Продолжение следует…
AleFF_DN, Chumak, kostyan_inter1, likuz1973, Maverick, ukropchik18, Vido, yarishNEW, Геннадий 61, Юрий77, ~~DANILA~~,
17.12.2015, 0:05 НАНО-РИФ (перезагрузка)
hi.gif
Прошло некоторое время, и стало скучно смотреть на пустой аквариум, выкинуть жалко, продавать неохота. Решил по-новому запустить мини - море. hom.gif
Тем более вроде как всё есть.

Запуск на СРК, так как после печального опыта с живыми камнями, понял, что от них толку почти нет, а проблем больше в разы (Это сугубо моё мнение, и решение) … Песочек тоже ни разу не живой. Ну и воду из действующего аквариума решил не доливать. Думал добавить, Prodibio Start Up nano, в продаже не оказалось sad.gif.

Привёл в порядок свет, конечно ещё есть над чем поработать, но пока будет так.
[attachment=291533:DSC_0755.jpg] [attachment=291534:DSC_0756.jpg]

Навёл порядок в системе управления. ohmy.gif
[attachment=291535:DSC_0757.jpg]

11.11.2015
Соорудил непонятную композицию из высушенных камней. Дизайнер с меня не очень... blush.gif
Набрал водички 2/3 объёма.
Включил помпу течения.
[attachment=291536:DSC_0759.jpg]

14.11.2015
Прошло 3 дня, пока, всё просто замечательно...
Вода немного мутная, плотность 1.020г/см3
Закинул "дюжину" моллинезий... Так как жить им больше негде, избавился от пресного. Большая часть скорее обречена, но кто ни будь выживет wink.gif. На удивление чувствуют они себя превосходно good.gif . Ощипывают с камней, раскисшие остатки, маян и айптазий. Постепенно буду повышать плотность.

20.11.2015
Довёл соленость до нормы 1.027г/см3
Окончательно переубедил себя в том, что 30 литровая системе не сможет хорошо функционировать без дополнительной фильтрации.
Был приобретён и установлен фильтр, Hagen Fluval C3
[attachment=291540:filtr_fl...3_vnejsi.jpg]
О фильтре Читать
Первые впечатления были на позитиве!
Всё сделано качественно. Привлекательный вид и функционал. Большой объем фильтрующих секций. Простота в разборке и промывке.
Но после включения, позитив сменился на негатив. Он оказался не чуть не тише дешёвого SunSun или Resun.
Может конечно приработается, но не думаю.
Если кто знает, что может шуметь буду очень признателен.

Что касается фильтрации, убрал мочалку, которая была в комплекте, вместо неё поставил синтепон, для механической очистки. Чуть позже для биологической очистки, набью СРК или закажу Matrix от Seachem, ещё не решил... Секция для химической очистки будет заполняться временно в зависимости от потребностей системы, но в большей части времени будет пустовать...


22.11.2015
С появлением фильтра, испарение воды достигло гуманной нормы, и стало напрягать. По-быстрому к контроллеру прописалась функция автодолива. На 3D-принтере был сделан кронштейн для поплавка и носик подачи воды (готового решения не нашёл).
[attachment=291542:DSC_0769.jpg] [attachment=291538:DSC_0773.jpg] [attachment=291541:DSC_0835.jpg]
И стало немного страшновато mad.gif , функция обкатана на системе с сампом, и вроде как за 2 года проблем не было, поплавок был установлен в возвратном отсеке, а вода доливалась в первый отсек, но как она себя поведёт в системе без сампа я не знал. В итоге всё обошлось, работает отлично smile.gif

26.11.2015
Нашёл старый тест "TETRA marine", сделал замер, понимаю, что он неточный, но процесс пошёл.
Нитриты, нитраты - зашкаливают...
Моллинезии чувствуют себя просто обалденно good.gif , потерь нет.

02.12.2015
На камнях появились диатомовые(бурые) водоросли...
[attachment=291539:DSC_0788__1_.jpg]

15.12.2015
Сделал тест воды, нитраты ещё зашкаливают, всё остальное более-менее в норме.
Появился первый житель shok.gif
[attachment=291543:DSC_0839.jpg]
Дискосома(Discosoma) зелёная, может и не выживет, но в принципе они не убиваемые. А если и не выживет, не велика потеря, их много и девать их некуда...
sviridov80, Vallacrim,
15.12.2015, 21:49 Мой первый НАНО-РИФ
Vallacrim, В хорошем качестве нет, да собственно там то и смотреть не на что… Подогнали мне ЖК со всеми своими прелестями, а именно АЙПТАЗИИ. Бороться с ними очень сложно, камни сильно пористые.
Ну и учитывая, что цены сильно выросли как-то пыл с приобретением новой живности, поутих…
Сейчас перезапустил наник, скоро напишу в новой теме…
Vallacrim,
15.12.2015, 21:22 Мой первый НАНО-РИФ
hi.gif
В общем как-то не сложилось…
Не знаю почему, может из-за нехватки времени, а может от того что писать то и нечего было. Вскоре была запущена система немного побольше, но тут неприятные события на востоке страны, и всё затянулось очень на долго, перебои электро и водо снабжения внесли свою лепту в неокрепшую систему, долго боролся с циано, и был на грани перезапуска, но останавливала цена затрат, так как цены стремительно рванули вверх в погоне за долларом.
Постепенно проблемы с балансом были решены, и вся живность перекочевала в больший объём.
Вот так и закончилась первая жизнь НАНО-объёма…
Vallacrim, vok,
6.12.2013, 16:34 52 литра моря с нуля
Цитата(Erik @ 6.12.2013, 11:36) *
- так и можно обойтись без красных диодов.. даже не все оригинальные светильники идут с красными диодами.

Оригинальные КИТАЙСКИЕ не все!...
А брендовых без красного нет... Кроме вариантов, когда это не светильник, а лунная подсветка.
Старичёк-Моховичёк,
5.12.2013, 21:48 52 литра моря с нуля
По сути дела ДИОДЫ уже на радиаторе, термопасты нужно немного, чем толще слой тем хуже проводимость!
Лучше озадачьте этой проблемой своего знакомого электронщика, он вам посоветует или термоскотч, ну или на винты, а с супер-клеем это не тот вариант, хотя если испортить, то Супер-клей ЛУЧШЕ!...
Да, и термопаста очень "жирная", спиртом с трудом оттирается...
Ну а вообще хозяин-барин...
Erik,
23.11.2013, 11:23 Мой первый НАНО-РИФ
23.11.2013
А жизнь то по немного налаживается...
Сделал очередные тесты воды, был приятно удивлён

Соленость: 1,024
NO₃ - 0-10mg/l
NO₂ - 0mg/l
Ca - 400mg/l
KH - 10°d
pH - 8,3

Диатомовые прекратили рост, а те, которые есть на песке, камнях и на стёклах начали приобретать беловатый оттенок...
Я так понимаю можно отправляться на поиски живности smile.gif
cuca1250,
14.11.2013, 10:12 Мой первый НАНО-РИФ
Нужна помощь!
Добавил ещё диодов в крышку.
Итого сейчас светит 6-royal, 4-blue, 8-cool white из них 2 на токе 1А, а 6 на токе ~400mA.
Вопрос в следующем: как лучше настроить продолжительность освещения? Контроллер ещё не подключен, всё регулируется вручную реостатами...

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

По контроллеру работа кипит!..
[attachment=216665:PB140068.JPG] [attachment=216666:PB140072.JPG] [attachment=216668:PB140075.JPG] [attachment=216667:PB140074.JPG]

Столкнулся с некоторыми трудностями, кнопки меню убраны с главного экрана и перемещены на отдельный экран, добавлен экран: микшера и тестового режима.
Сейчас всё в стадии тестирования!
cuca1250, DIESEL, richmond,
11.11.2013, 14:41 Мой первый НАНО-РИФ
Начал работу над контроллером... hom.gif
Собрал купленные модули, прикрутил часы на DS 1307...
Сделал:
Главный экран
[attachment=216313:PB070070.JPG],
Экран режима ожидания
[attachment=216314:PB070058.JPG],
и экран установки времени
[attachment=216315:PB070073.JPG]...

А в аквариуме всё как и прежде... Ждем! shok.gif
[attachment=216316:PB110038.JPG][attachment=216317:PB110039.JPG]
cuca1250, DIESEL, richmond,
7.11.2013, 12:11 Мой первый НАНО-РИФ
Получил немного модулей для контроллера, конечно не всё, но достаточно для того чтоб начать работу...
За основу взята платформа ARDUINO, соглашусь, что не самая мощная, но на данный момент пожалуй самая гибкая и доступная...
1. Arduino Mega 2560 R3
[attachment=215848:arduino_mega_2560.jpg]
2. TFTLCD Mega Shield V2.0
[attachment=215849:tft_lcd_...eld_v2_2.png]
3. 3.2" TFT LCD
[attachment=215850:3.2_TFT_LCD.jpg]

Есть много контроллеров на базе Arduino, например "JARDUINO AQUARIUM CONTROLER" - полный отстой, сырая не обкатанная программа за которую нехило рубят 10 фунтов mad.gifwacko.gif
Также есть "STILO Aquarium Controller" hi.gif снимаю шляпу, всё работает, совершенно бесплатно...

Конечно можно и не заморачиваться, просто взять уже готовую программную часть, "залить", собрать всё, и всё...
Но я так и не нашёл хорошего конечного результата, который полностью удовлетворил все мои желания...
Буду делать свой контроллер, на базе контроллера "STILO"...
cuca1250, DIESEL, mityasky, richmond, Старичёк-Моховичёк,
3.11.2013, 10:07 Мой первый НАНО-РИФ
03.11.2013

Тест воды.

Соленость: 1,024
NO₃ - 10mg/l
NO₂ - 0,5mg/l
Ca - 400mg/l
KH - 10
pH - 8,2

Глобально ничего не изменилось, возможно тесты "кривые", или в связи с тем, что аквариум пуст глобально нечего и не должно меняться...
richmond,
30.10.2013, 19:38 Мой первый НАНО-РИФ
30.10.2013
Вроде как началось good.gif
На песке замечены небольшие очаги диатомовых(бурых) водорослей...
А то думал, что за хрень?, даже низшие не растут wacko.gif
Наверно нужно снижать интенсивность освещения... ohmy.gif
richmond, Женя),
28.10.2013, 11:25 Мой первый НАНО-РИФ
Цитата(Старичёк-Моховичёк @ 28.10.2013, 10:09) *
Я конечно не берусь гарантировать на 100%, но по моему в этой части:

Цитата
Ca - 500mg/l
KH - 10
pH - 8,2


Тетровские тесты своей соли очень сильно льстят:)

Во первых - достаточно странное соотношение впринципе (нереально высокий кальций для таких показателей Kh/Ph), он должен был достаточно быстро выпасть в осадок.
Во вторых - в тетровской соли столько кальция отродясь не водилось((

Так что - или была ошибка в процедуре замера, или на будущее (не близкое пока) нужно поискать альтернативу для проведения замеров.

ЗЫ

Нужен СВЕТ! smile.gif



По тестам, тоже вижу, что лажа...
Но думаю, может это из-за неправильного подключения осмоса, воду для аквариума не с той трубочки отбирал... blush.gif
Свет есть, но не совсем тот, что нужно...
Сейчас светят 6шт. ROYAL BLUE.
Сегодня ещё придет посылка добавятся 6шт. COOL WHITE 10000к
ну, а там посмотрим, насколько это ускорит...

Да!! Чуть не забыл, в конце недели буду в Крыму, может чё из моря выловить, чтоб ускорить процесс ну или может там живет чё полезное, что в дальнейшем пригодится??
richmond, Старичёк-Моховичёк,
27.10.2013, 10:03 Мой первый НАНО-РИФ
27.10.2013

Сегодня сделал первый тест воды.

Соленость: 1,024
NO₃ - 10mg/l
NO₂ - 0,5mg/l
Ca - 500mg/l
KH - 10
pH - 8,2
richmond, Старичёк-Моховичёк,
25.10.2013, 10:35 Мой первый НАНО-РИФ
Собственно старт был 15.10.2013
Всё выглядело как и у всех...
[attachment=213885:PA150091.JPG]
[attachment=213886:PA150098.JPG]

На следующий день немного лучше...
Были добавлены бактерии "Prodibio Start Up nano"[attachment=213894:7.png]
[attachment=213887:PA160100.JPG]

Сейчас выглядит так...
[attachment=213888:PA240067.JPG]
Ждём.... wacko.gif
cuca1250, DIESEL, Peterbold, Старичёк-Моховичёк, ~~DANILA~~,
25.10.2013, 10:23 Мой первый НАНО-РИФ
Желание обладать морским аквариумом возникло, наверное, как и у многих, после увиденного в интернете.
Меня настораживала сложность содержания морского аквариума.
Но, яркие и насыщенные цвета морских животных, включая, конечно, кораллы, просто завораживали!
Сдерживающие факторы: стоимость, отсутствие магазинов и людей, занимающихся морской аквариумистикой непосредственно в моём городе "Ближайшее место, где хоть как то что-то есть за 100км!".
Значительное время пришлось затратить на изучение основ морской аквариумистики. Удивительной оказалась сложность "добывания" полезной информации для новичка, среди "тонны" бесполезных или "сложных" обсуждений на форумах. Простая информация, доступная для понимания новичку, перемешивалась с погружением в детали и нюансы.
Литература по данной тематике также не до конца решает проблему, т.к. изложенный материал довольно объемен, обобщен на различные случаи и не дает новичку однозначной информации.
В какой-то момент принял решение забыть всё, что читал и начинать творить, помню, как в детстве всё начиналось с банки 3-х литровой и двух "печальных" гуппи..

Итак что было сделано:
Был склеен аквариум приблизительно такой
[attachment=213869:1.png]

Куплен СРК 8кг и "сделана скульптура" на которую ушло ~5-6кг.
[attachment=213870:2.png]

Далее немного дебатов и скульптура претерпела изменений, стала менее громоздкой
[attachment=213871:3.png]

Далее грунт, тоже немного разговоров, особая благодарность Старичёк-Моховичёк, был выбран грунт
[attachment=213872:4.png]

Также была приобретена,
Помпа течения: wave maker HWM 2000
Тесты для воды: Tetra Marine Test 5 in 1
Соль: Tetra Marine SeaSalt
Солемер : Aqua Medic Salimeter
[attachment=213873:5.png]

Фильтр : SunSun HBL-601 II
[attachment=213882:6.png]
Тоже претерпел небольших доработок, дело в том, что при покупке в описании было указано с насадкой для сбора плёнки, на самом деле её там не оказалось, после засола через неделю ужасно начала раздражать плёнка на поверхности воды, пришлось с другого фильтра снять насадку и вклеить в этот... Результат превзошёл ожидания!!

Освещение : LED (в разработке)
Cool White - CREE Xlamp XP-E R3 - 6шт.
Royal Blue - CREE Xlamp XP-E - 6шт.
Blue - CREE Xlamp XP-E
Ultra Voilet - No Name 420-430nm
RGB - No Name

Контроллер : на базе ARDUINO (в разработке)

Запуск 15.10.2013
Arowana, cuca1250, DIESEL, Peterbold, richmond, Vallacrim, Старичёк-Моховичёк, ~~DANILA~~,

Перейти в начало страницы RSS Текстовая версия Сейчас: 26.4.2024, 23:44