Проект 8. Автоматическая кормушка для рыбок

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

Описание работы:

Для начала работы подключите питание к Arduino. На дисплее Вы увидите время в верхнем ряду. В среднем ряду - 4 квадрата внутри которых в зависимости от вашей платы Arduino, появятся либо прочерки либо цифры. 4 квадрата - это возможность 4 раза задать время кормления рыбок. При наступлении этого времени, произойдет кормление рыбок. Нижний ряд - это количество поворотов сервопривода. Для настройки устройства, нажмите любую кнопку. Начнет мигать значение часов в верхнем ряду. Для регулирования параметра "Часы" нажимайте кнопки: синюю или зеленую. При нажатии синей кнопки значение часов будет уменьшаться, при нажатии зеленой кнопки значение часов будет увеличиваться. Для перехода к настройкам следующего параметра, необходимо подождать 3 секунды. По истечению трех секунд параметр "Часы" перестанет мигать, и начнет мигать параметры "Минуты". Для регулирования минут, нажимайте так же синюю либо зеленую кнопку для уменьшения, либо увеличения минут. И для перехода к следующему параметру так же необходимо подождать три секунды и так далее. Время кормления рыбок задается только часами, следовательно в квадратах для задания времени кормления рыбок, в каждом из квадратов задается диапазон от 0 до 23 и прочерк, если вы хотите отключить одну из позиции. Последний ряд регулируется в диапазоне от 1 до 10. То есть при повороте сервопривода, будет поворачиваться стакан на 180 градусов, создаст небольшую тряску, в виде быстрого поворота стакана на небольшие углы и вернется в исходное положение. Количество поворотов стакана на небольшие углы и регулирует нижний ряд на дисплее. Таким образом происходит регулирование порций для рыбок. При нажатии кнопок, горят светодиоды внутри кнопок. При наступлении времени кормления рыбок светодиоды в кнопках будут тоже индицировать. Попеременно мигать.

Нам понадобится:

Для реализации проекта нам необходимо установить следующие библиотеки:

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Схема сборки:

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

Код программы:

#include <EEPROM.h>                                                                                           // Подключаем библиотеку EEPROM.
                                                                                                              //
#include <Servo.h>                                                                                            // Подключаем библиотеку Servo.
Servo servo;                                                                                                  // Объявляем объект для работы с сервоприводом.
                                                                                                              //
#include <iarduino_RTC.h>                                                                                     // Подключаем библиотеку.
iarduino_RTC time(RTC_DS3231);                                                                                // Объявляем объект time для модуля на базе чипа DS3231.
                                                                                                              //
#include <iarduino_OLED.h>                                                                                    // Подключаем библиотеку iarduino_OLED.
iarduino_OLED myOLED(0x3C);                                                                                   // Объявляем объект myOLED, указывая адрес дисплея на шине I2C: 0x3C.
extern uint8_t MediumFont[];                                                                                  // Подключаем шрифт MediumFontRus.
extern uint8_t SmallFont[];                                                                                   // Подключаем шрифт MediumFontRus.
                                                                                                              //
const uint8_t pinLedBlue = A2;                                                                                // Создаем массив констант с № входов к которым подключены светодиоды.
const uint8_t pinLedGreen = 5;                                                                                // Создаем массив констант с № входов к которым подключены светодиоды.
                                                                                                              //
const uint8_t pinKeyBlue = 2;                                                                                 // Создаем массив констант с № входов к которым подключены кнопки.
const uint8_t pinKeyGreen = A3;                                                                               // Создаем массив констант с № входов к которым подключены кнопки.
                                                                                                              //
const uint8_t pinServo = 6;                                                                                   // Определяем № вывода к которому подключён сервопривод.
                                                                                                              //
const uint8_t deg = 30;                                                                                       // Угол отклонения кормушки.
const uint16_t del = 400;                                                                                     // Задержка между отклонениями кормушки.
                                                                                                              //
int menu;                                                                                                     // Переменная события. 
int minut;                                                                                                    // Переменная минут.
int hour;                                                                                                     // Переменная часов.
int minutPrev;                                                                                                // Переменная предыдущих минут.
int i;                                                                                                        // Переменная количества счета.
int k;                                                                                                        // Переменная количества счета.
                                                                                                              //
long prevMicros;                                                                                              // Предыдущая переменная значений счетчика.
long prevMicros2;                                                                                             // Вторая предыдущая переменная значений счетчика.
bool counter;                                                                                                 // Переменная события разрешает/запрещает событие каждые пол секунды.
                                                                                                              //
long microsBlue;                                                                                              // Предыдущее значений счетчика для синей кнопки.
long microsGreen;                                                                                             // Предыдущее значений счетчика для зеленой кнопки.
                                                                                                              //
int serv = 10;                                                                                                // Переменная уровня тряски.
                                                                                                              //
int times;                                                                                                    // Переменная времени выхода из подпрограммы.
int prevTimes;                                                                                                // Переменная предыдущего значения времени выхода из под программы.
                                                                                                              //
int A = 20;                                                                                                   // Начальная Y-координата центрального ряда.
int mTmAlarm[5];                                                                                              // Массив значений времени, когда кормить рыбок.
uint8_t mCrdTmAlarm[5] = {37,A,A+24,A+24*2,A+24*3};                                                           // Массив координат центрального ряда.
                                                                                                              //
int O = 10;                                                                                                   // Начальная Y-координата нижнего ряда.
const int massOscill[11] = {50,O,O+11,O+11*2,O+11*3,O+11*4,O+11*5,O+11*6,O+11*7,O+11*8,O+11*9};               // Массив координат нижнего ряда.
                                                                                                              //
void Return();                                                                                                // Функция переход из одного события в другое.
void Check();                                                                                                 // Функция проверки диапазонов.
void ChangeTime();                                                                                            // Функция изменения параметров. Увеличение/уменьшение.
void Alert();                                                                                                 // Функция тряски кормушки для рыбок.
                                                                                                              //
void ShowTime();                                                                                              // Функция вывода на экран времени.
void ShowHour();                                                                                              // Функция вывода на экран часов.
void ShowMinut();                                                                                             // Функция вывода на экран минут.
void ShowSec();                                                                                               // Функция вывода на экран секунда.
void ShowAlarm();                                                                                             // Функция вывода на экран времени кормить рыбок.
void ShowServo();                                                                                             // Функция вывода на экран количества тряски кормушки для рыбок.
                                                                                                              //
void setup()                                                                                                  //
{                                                                                                             //
  pinMode(pinLedBlue,OUTPUT);                                                                                 // Переводим выводы pinLedBlue в режим выхода.
  digitalWrite(pinLedBlue,LOW);                                                                               // Выключаем светодиоды.
  pinMode(pinKeyBlue,INPUT);                                                                                  // Переводим выводы pinKeyBlue в режим входа.
                                                                                                              //
  pinMode(pinLedGreen,OUTPUT);                                                                                // Переводим выводы pinLedGreen в режим выхода.
  digitalWrite(pinLedGreen,LOW);                                                                              // Выключаем светодиоды.
  pinMode(pinKeyGreen,INPUT);                                                                                 // Переводим выводы pinKeyGreen в режим входа.
                                                                                                              //
  servo.attach(pinServo);                                                                                     // Присоединяем сервопривод к выводу pinServo.
                                                                                                              //
  myOLED.begin();                                                                                             // Инициируем работу с дисплеем.
  myOLED.autoUpdate(false);                                                                                   // Запрещаем автоматический вывод данных.
  time.begin();                                                                                               // Инициируем RTC модуль.
                                                                                                              //
  menu = 1;                                                                                                   // Разрешаем переход к событию 1.
  servo.write(0);                                                                                             // Устанавливаем сервопривод в 0 градусов.
                                                                                                              //
  for(int i = 1; i <= 4; i++)                                                                                 // В цикле считываем время кормления рыбок из памяти EEPROM.
  {                                                                                                           //
    mTmAlarm[i] = EEPROM.read(i);                                                                             // Считываем время кормления рыбок из памяти EEPROM.
    if (mTmAlarm[i] > 23 || mTmAlarm[i] < 0) {mTmAlarm[i] = 24;}                                              // Если значение не в диапазоне от 0 до 23, то присваиваем значение 24.
  }                                                                                                           //
  serv = EEPROM.read(5);                                                                                      // Считываем количество тряски из памяти EEPROM.
  if (serv > 10 || serv < 1) {serv = 9;}                                                                      // Проверяем на диапазон от 1 до 10, если нет то присваиваем значение 9. 
}                                                                                                             //
                                                                                                              //
void loop()                                                                                                   //
{                                                                                                             //
  if (micros() - microsBlue > 500000) {digitalWrite(pinLedBlue,LOW);}                                         // Каждые пол секунды мигаем значением часов.
  if (micros() - microsGreen > 500000){digitalWrite(pinLedGreen,LOW);}                                        // Каждые пол секунды мигаем значением часов.
                                                                                                              //
  switch(menu)                                                                                                // Выбор события.
  {                                                                                                           //
    case 1:                                                                                                   // Событие 1.
                                                                                                              // Прорисовываем двоеточия между часами и минутами.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем двоеточием.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawLine(65, 9,  65, 11, 0);                                                                   // Гасим линию.
        myOLED.drawLine(65, 16, 65, 18, 0);                                                                   // Гасим линию.
        myOLED.drawLine(64, 10, 66, 10, 0);                                                                   // Гасим линию.
        myOLED.drawLine(64, 17, 66, 17, 0);                                                                   // Гасим линию.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        myOLED.drawLine(65, 9,  65, 11, 1);                                                                   // Прорисовываем линию.
        myOLED.drawLine(65, 16, 65, 18, 1);                                                                   // Прорисовываем линию.
        myOLED.drawLine(64, 10, 66, 10, 1);                                                                   // Прорисовываем линию.
        myOLED.drawLine(64, 17, 66, 17, 1);                                                                   // Прорисовываем линию.
      }                                                                                                       //
    }                                                                                                         //
                                                                                                              //
    myOLED.setFont(MediumFont);                                                                               // Указываем шрифт Medium который требуется использовать для вывода цифр и текста.
    time.gettime();                                                                                           // Читаем время, обновляя значения всех переменных.  
    hour  = time.Hours;                                                                                       // Сохраняем значение часов.
    minut = time.minutes;                                                                                     // Сохраняем значение минут.
    ShowTime();                                                                                               // Функция вывода на экран времени.
                                                                                                              //
    for(int i = 1; i <= 4; i++)                                                                               // В цикле проверяем совпадение текущего времени и времени кормления рыбок.
    {if(mTmAlarm[i] == hour && minut == 0 && time.seconds == 0){Alert();}}                                    // Если время кормления рыбок совпадает с текущем временем, то переходим к функции тряски кормушки.
                                                                                                              //
    myOLED.setFont(SmallFont);                                                                                // Указываем шрифт Small который требуется использовать для вывода цифр и текста.
    for(int i = 1; i <= 4; i++)                                                                               // В цикле формируем центральный ряд параметров.
    {                                                                                                         //
      if (mTmAlarm[i]>=0 && mTmAlarm[i]<10)                                                                   // Если количество времени от 0 до 9.
      {                                                                                                       //
        myOLED.print(F("0"), mCrdTmAlarm[i], mCrdTmAlarm[0]);                                                 // Добавляем спереди ноль, выводя его на дисплей.
        myOLED.print(mTmAlarm[i], mCrdTmAlarm[i]+6, mCrdTmAlarm[0]);                                          // Выводим переменную значения времени кормления рыбок.
      }                                                                                                       //
      else{myOLED.print(mTmAlarm[i], mCrdTmAlarm[i], mCrdTmAlarm[0]);}                                        // Иначе выводим переменную значения времени кормления рыбок без нуля.
      myOLED.drawRect(mCrdTmAlarm[i]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[i]+14, mCrdTmAlarm[0]+2, false, 1);    // Выводим на экран рамки для значений времени кормления рыбок.
    }                                                                                                         //
                                                                                                              //
    for(int i = 1; i <= 4; i++)                                                                               // В цикле сравниваем переменные времени кормления рыбок с числом 24 и 0.
    {                                                                                                         //
      if (mTmAlarm[i] == 24 || mTmAlarm[i] == -1)                                                             // Если переменные времени кормления рыбок равны 24 или 0, то ставим прочерк.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[i]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[i]+13, mCrdTmAlarm[0]+1, true, 0);    // Гасим квадрат.
        myOLED.drawLine(23+24*(i-1), 33, 29+24*(i-1), 33, 1);                                                 // Прорисовываем линию.
      }                                                                                                       //
    }                                                                                                         //
                                                                                                              //
    myOLED.drawRect(O-3, massOscill[0]-3, O+109, massOscill[0]+7, false, 1);                                  // Выводим рамку нижнего ряда.
    for(int i = 1; i <= serv; i++)                                                                            // В цикле формируем уровень тряски кормушки.
    {                                                                                                         //
      myOLED.drawRect(massOscill[i], massOscill[0], massOscill[i]+7, massOscill[0]+4, true, 1);               // Выводим уровень тряски кормушки в виде прямоугольников.
    }                                                                                                         //
                                                                                                              //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    if(digitalRead(pinKeyBlue)) {digitalWrite(pinLedBlue,HIGH);  microsBlue = micros();}                      // Если нажата синяя кнопка, то включаем ее светодиод, считываем значения счетчика.
    if(digitalRead(pinKeyGreen)){digitalWrite(pinLedGreen,HIGH); microsGreen = micros();}                     // Если нажата зеленая кнопка, то включаем ее светодиод, считываем значения счетчика.
    if(digitalRead(pinKeyBlue) || digitalRead(pinKeyGreen)) {menu = 2;}                                       // Если нажата кнопка, то разрешаем переход к событию 2, сбрасываем секунды.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 2:                                                                                                   // Событие 2.
    delay(200);                                                                                               // Задержка 200 мс.
    menu = 3;                                                                                                 // Разрешаем переход к событию 3.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 3:                                                                                                   // Событие 2.
    myOLED.setFont(MediumFont);                                                                               // Указываем шрифт Medium который требуется использовать для вывода цифр и текста.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем значением часов.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(39,5,60,20, true, 0);                                                                 // Гасим значение на индикаторе.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        ShowTime();                                                                                           // Выводим на экран значения часов.
      }                                                                                                       //
    }                                                                                                         //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    time.settime(-1, -1, hour);                                                                               // Присваиваем значение часов датчику реального времени.
    times = hour;                                                                                             // Присваиваем значение часов переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 4:                                                                                                   // Событие 3.
    ShowHour();                                                                                               // Выводим на экран значения часов.
    myOLED.setFont(MediumFont);                                                                               // Указываем шрифт Medium который требуется использовать для вывода цифр и текста.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем значением минут.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(67,5,92,20, true, 0);                                                                 // Гасим значение на индикаторе.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        ShowMinut();                                                                                          // Выводим на экран значения минут.
      }                                                                                                       //
    }                                                                                                         //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    time.settime(0, minut, -1);                                                                               // Присваиваем значение минут датчику реального времени.
    times = minut;                                                                                            // Присваиваем значение минут переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 5:                                                                                                   // Событие 5.
    ShowMinut();                                                                                              // Выводим на экран значения минут.
    menu = 6;                                                                                                 // Разрешаем переход к событию 6.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 6:                                                                                                   // Событие 6.
    myOLED.setFont(SmallFont);                                                                                // Указываем шрифт Small который требуется использовать для вывода цифр и текста.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем рамкой первого значения времени кормления рыбок.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[1]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[1]+14, mCrdTmAlarm[0]+2, false, 1);  // Выводим рамку первого значения времени кормления рыбок на индикатор.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[1]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[1]+14, mCrdTmAlarm[0]+2, false, 0);  // Гасим румку первого значения времени кормления рыбок на индикаторе.
      }                                                                                                       //
    }                                                                                                         //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    times = mTmAlarm[1];                                                                                      // Присваиваем первое значение времени кормления рыбок переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    if(menu != 6){EEPROM.write(1, mTmAlarm[1]);}                                                              // Если изменилась переменная события, то записываем в память EEPROM время первого кормления рыбок.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 7:                                                                                                   //
    myOLED.drawRect(mCrdTmAlarm[1]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[1]+14, mCrdTmAlarm[0]+2, false, 1);      // Выводим румку первого значения времени кормления рыбок на индикатор.
    myOLED.setFont(SmallFont);                                                                                // Указываем шрифт Small который требуется использовать для вывода цифр и текста.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем рамкой второго значения времени кормления рыбок.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[2]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[2]+14, mCrdTmAlarm[0]+2, false, 1);  // Выводим румку второго значения времени кормления рыбок на индикатор.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[2]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[2]+14, mCrdTmAlarm[0]+2, false, 0);  // Гасим румку второго значения времени кормления рыбок на индикаторе.
      }                                                                                                       //
    }                                                                                                         //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    times = mTmAlarm[2];                                                                                      // Присваиваем второе значение времени кормления рыбок переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    if(menu != 7){EEPROM.write(2, mTmAlarm[2]);}                                                              // Если изменилась переменная события, то записываем в память EEPROM время второго кормления рыбок.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 8:                                                                                                   // Событие 8.
    myOLED.drawRect(mCrdTmAlarm[2]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[2]+14, mCrdTmAlarm[0]+2, false, 1);      // Выводим румку второго значения времени кормления рыбок на индикатор.
    myOLED.setFont(SmallFont);                                                                                // Указываем шрифт Small который требуется использовать для вывода цифр и текста.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем рамкой третьего значения времени кормления рыбок.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[3]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[3]+14, mCrdTmAlarm[0]+2, false, 1);  // Выводим румку третьего значения времени кормления рыбок на индикатор.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[3]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[3]+14, mCrdTmAlarm[0]+2, false, 0);  // Гасим румку третьего значения времени кормления рыбок на индикаторе.
      }                                                                                                       //
    }                                                                                                         //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    times = mTmAlarm[3];                                                                                      // Присваиваем третье значение времени кормления рыбок переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    if(menu != 8){EEPROM.write(3, mTmAlarm[3]);}                                                              // Если изменилась переменная события, то записываем в память EEPROM время третьего кормления рыбок.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 9:                                                                                                   // Событие 9.
    myOLED.drawRect(mCrdTmAlarm[3]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[3]+14, mCrdTmAlarm[0]+2, false, 1);      // Выводим румку третьего значения времени кормления рыбок на индикатор.
    myOLED.setFont(SmallFont);                                                                                // Указываем шрифт Small который требуется использовать для вывода цифр и текста.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем рамкой четвертого значения времени кормления рыбок.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[4]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[4]+14, mCrdTmAlarm[0]+2, false, 1);  // Выводим румку четвертого значения времени кормления рыбок на индикатор.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        myOLED.drawRect(mCrdTmAlarm[4]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[4]+14, mCrdTmAlarm[0]+2, false, 0);  // Гасим румку четвертого значения времени кормления рыбок на индикаторе.
      }                                                                                                       //
    }                                                                                                         //
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    times = mTmAlarm[4];                                                                                      // Присваиваем четвертое значение времени кормления рыбок переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    if(menu != 9){EEPROM.write(4, mTmAlarm[4]);}                                                              // Если изменилась переменная события, то записываем в память EEPROM время четвертого кормления рыбок.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 10:                                                                                                  // Событие 10.
    myOLED.drawRect(mCrdTmAlarm[4]-2, mCrdTmAlarm[0]-10, mCrdTmAlarm[4]+14, mCrdTmAlarm[0]+2, false, 1);      // Выводим рамку четвертого значения времени кормления рыбок на индикатор.
    menu = 11;                                                                                                // Разрешаем переход к событию 11.
    break;                                                                                                    // Выходим из оператора case.
                                                                                                              //
    case 11:                                                                                                  // Событие 11.
    if (micros() - prevMicros > 500000)                                                                       // Каждые пол секунды мигаем рамкой уровня тряски кормушки.
    {                                                                                                         //
      prevMicros = micros();                                                                                  // Сохраняем предыдущее значение таймера.
      counter=!counter;                                                                                       // Изменяем переменную события вывода значений на индикатор.
      if (!counter)                                                                                           // Если переменная события false.
      {                                                                                                       //
        myOLED.drawRect(O-3, massOscill[0]-3, O+109, massOscill[0]+7, false, 1);                              // Выводим рамку уровня тряски кормушки.
      }                                                                                                       //
      else                                                                                                    // Если переменная события true.
      {                                                                                                       //
        myOLED.drawRect(O-3, massOscill[0]-3, O+109, massOscill[0]+7, false, 0);                              // Гасим рамку уровня тряски кормушки.
      }                                                                                                       //
    }                                                                                                         //
    ChangeTime();                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
    ShowServo();                                                                                              // Функция вывода на экран количества тряски кормушки для рыбок.
    times = serv;                                                                                             // Присваиваем значение уровня тряски кормушки переменной времени выхода из подпрограммы.
    Return();                                                                                                 // Функция переход из одного события в другое.
    myOLED.update();                                                                                          // Обновляем информацию на дисплее.
    if(menu != 11){EEPROM.write(5, serv);}                                                                    // Если изменилась переменная события, то записываем в память EEPROM количество тряски.
    break;                                                                                                    // Выходим из оператора case.
  }                                                                                                           //
}                                                                                                             //
                                                                                                              //
void Return()                                                                                                 // Функция переход из одного события в другое.
{                                                                                                             //
  if (prevTimes == times)                                                                                     // Если нынешнее значение времени равно предыдущему значению.
  {                                                                                                           //
    if (micros() - prevMicros2 > 100000)                                                                      // Каждые 100 мс увеличиваем переменную счета.
    {                                                                                                         //
      prevMicros2 = micros();                                                                                 // Сохраняем предыдущее значение таймера.
      k++;                                                                                                    // Увеличиваем переменную счета.
    }                                                                                                         //
  }                                                                                                           //
  else {k = 0;}                                                                                               // Иначе обнуляем переменную счета.
  if (k > 30)                                                                                                 // Если переменная счета больше 30.
  {                                                                                                           //
    menu++; k = 0; prevTimes = 0;                                                                             // Увеличиваем переменную события. Сбрасываем переменную предыдущего значения времени выхода из подпрограммы.
    if (menu == 12){menu = 1;}                                                                                // Если событие равно 12, то разрешаем переход к событию 1.
  }                                                                                                           //
  prevTimes = times;                                                                                          // Сохраняем текущее значение времени выхода из подпрограммы.
}                                                                                                             //
                                                                                                              //
void Check()                                                                                                  // Функция проверки диапазонов.
{                                                                                                             //
  if (minut > 59){minut = 0; }                                                                                // Если минуты больше 59, то обнуляем минуты.
  if (minut < 0) {minut = 59;}                                                                                // Если минуты меньше 00, то устанавливаем 59 минут.
  if (hour > 23) {hour = 0; }                                                                                 // Если часы больше 23, то обнуляем часы.
  if (hour < 0)  {hour = 23;}                                                                                 // Если часы меньше 00, то устанавливаем 23 часа.
                                                                                                              //
  if (mTmAlarm[1] > 24){mTmAlarm[1] = 0; }                                                                    // Если переменная первого значения времени кормления рыбок больше 23, то обнуляем переменную.
  if (mTmAlarm[1] < -1){mTmAlarm[1] = 23;}                                                                    // Если переменная первого значения времени кормления рыбок меньше 00, присваиваем ей 23.
  if (mTmAlarm[2] > 24){mTmAlarm[2] = 0; }                                                                    // Если переменная второго значения времени кормления рыбок больше 23, то обнуляем переменную.
  if (mTmAlarm[2] < -1){mTmAlarm[2] = 23;}                                                                    // Если переменная второго значения времени кормления рыбок меньше 00, присваиваем ей 23.
  if (mTmAlarm[3] > 24){mTmAlarm[3] = 0; }                                                                    // Если переменная третьего значения времени кормления рыбок больше 23, то обнуляем переменную.
  if (mTmAlarm[3] < -1){mTmAlarm[3] = 23;}                                                                    // Если переменная третьего значения времени кормления рыбок меньше 00, присваиваем ей 23.
  if (mTmAlarm[4] > 24){mTmAlarm[4] = 0; }                                                                    // Если переменная четвертого значения времени кормления рыбок больше 23, то обнуляем переменную.
  if (mTmAlarm[4] < -1){mTmAlarm[4] = 23;}                                                                    // Если переменная четвертого значения времени кормления рыбок меньше 00, присваиваем ей 23.
                                                                                                              //
  if (serv > 10) {serv = 10;}                                                                                 // Если переменная уровня тряски кормушки больше 10, присваиваем ей 10.
  if (serv < 1)  {serv = 1;}                                                                                  // Если переменная уровня тряски кормушки меньше 1, присваиваем ей 1.
}                                                                                                             //
                                                                                                              //
void ChangeTime()                                                                                             // Функция изменения параметров. Увеличение/уменьшение.
{                                                                                                             //
  if(digitalRead(pinKeyBlue))                                                                                 // Проверка нажатия синей кнопки.
  {                                                                                                           //
    if(digitalRead(pinKeyBlue)) {digitalWrite(pinLedBlue,HIGH);  microsBlue = micros();}                      // Если нажата синяя кнопка, то включаем ее светодиод, считываем значения счетчика.
    while(digitalRead(pinKeyBlue))                                                                            // Цикл слежения нажатой синей кнопки.
    {                                                                                                         //
      delay(10);                                                                                              // Ждём пока мы её не отпустим.
      if(i<100){i++;}                                                                                         // Если переменная счета меньше 100, то увеличиваем переменную счета.
      else                                                                                                    // Если переменная счета больше 100.
      {                                                                                                       //
        delay(50);                                                                                            // Задержка 50 мс.
        if(menu==3) {hour--;        Check(); ShowHour();  myOLED.update();}                                   // Если Событие 3, то уменьшаем часы, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
        if(menu==4) {minut--;       Check(); ShowMinut(); myOLED.update();}                                   // Если Событие 4, то уменьшаем минуты, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
                                                                                                              //
        if(menu==6) {mTmAlarm[1]--; Check(); ShowAlarm();                                                     // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[1] == 24 || mTmAlarm[1] == -1)                                                         // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[1]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[1]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(23, 33, 29, 33, 1);                                                               // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
        if(menu==7) {mTmAlarm[2]--; Check(); ShowAlarm();                                                     // Если Событие 7, то увеличиваем переменную второго значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[2] == 24 || mTmAlarm[2] == -1)                                                         // Если переменная второго значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[2]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[2]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(47, 33, 53, 33, 1);                                                               // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
        if(menu==8) {mTmAlarm[3]--; Check(); ShowAlarm();                                                     // Если Событие 8, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[3] == 24 || mTmAlarm[3] == -1)                                                         // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[3]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[3]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(71, 33, 77, 33, 1);                                                               // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
        if(menu==9) {mTmAlarm[4]--; Check(); ShowAlarm();                                                     // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[4] == 24 || mTmAlarm[4] == -1)                                                         // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[4]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[4]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(95, 33, 101, 33, 1);                                                              // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
                                                                                                              //
        if(menu==11){serv--;        Check(); ShowServo(); myOLED.update();}                                   // Если Событие 11, то уменьшаем переменную уровня тряски кормушки, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
      }                                                                                                       //
    }                                                                                                         //
    if (i < 70)                                                                                               // Если переменная счета меньше 70.
    {                                                                                                         //
      if(menu==3) {hour--;        Check(); ShowHour();  myOLED.update();}                                     // Если Событие 3, то уменьшаем часы, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
      if(menu==4) {minut--;       Check(); ShowMinut(); myOLED.update();}                                     // Если Событие 4, то уменьшаем минуты, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
                                                                                                              //
      if(menu==6) {mTmAlarm[1]--; Check(); ShowAlarm();                                                       // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[1] == 24 || mTmAlarm[1] == -1)                                                           // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[1]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[1]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(23, 33, 29, 33, 1);                                                                 // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
      if(menu==7) {mTmAlarm[2]--; Check(); ShowAlarm();                                                       // Если Событие 7, то увеличиваем переменную второго значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[2] == 24 || mTmAlarm[2] == -1)                                                           // Если переменная второго значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[2]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[2]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(47, 33, 53, 33, 1);                                                                 // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
      if(menu==8) {mTmAlarm[3]--; Check(); ShowAlarm();                                                       // Если Событие 8, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[3] == 24 || mTmAlarm[3] == -1)                                                           // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[3]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[3]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(71, 33, 77, 33, 1);                                                                 // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
      if(menu==9) {mTmAlarm[4]--; Check(); ShowAlarm();                                                       // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[4] == 24 || mTmAlarm[4] == -1)                                                           // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[4]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[4]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(95, 33, 101, 33, 1);                                                                // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
                                                                                                              //
      if(menu==11){serv--;        Check(); ShowServo(); myOLED.update();}                                     // Если Событие 11, то уменьшаем переменную уровня тряски кормушки, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
    }                                                                                                         //
    i = 0;                                                                                                    // Обнуляем переменную счета.
  }                                                                                                           //
                                                                                                              //
  if(digitalRead(pinKeyGreen))                                                                                // Проверка нажатия зеленой кнопки.
  {                                                                                                           //
    if(digitalRead(pinKeyGreen)){digitalWrite(pinLedGreen,HIGH); microsGreen = micros();}                     // Если нажата зеленая кнопка, то включаем ее светодиод, считываем значения счетчика.
    while(digitalRead(pinKeyGreen))                                                                           // Цикл слежения нажатой зеленой кнопки.
    {                                                                                                         //
      delay(10);                                                                                              // Ждём пока мы её не отпустим.
      if(i<100){i++;}                                                                                         // Если переменная счета меньше 100, то увеличиваем переменную счета.
      else                                                                                                    // Если переменная счета больше 100.
      {                                                                                                       //
        delay(50);                                                                                            // Задержка 50 мс.
        if(menu==3) {hour++;        Check(); ShowHour();  myOLED.update();}                                   // Если Событие 3, то увеличиваем часы, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
        if(menu==4) {minut++;       Check(); ShowMinut(); myOLED.update();}                                   // Если Событие 4, то увеличиваем минуты, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
                                                                                                              //
        if(menu==6) {mTmAlarm[1]++; Check(); ShowAlarm();                                                     // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[1] == 24 || mTmAlarm[1] == -1)                                                         // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[1]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[1]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(23, 33, 29, 33, 1);                                                               // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
        if(menu==7) {mTmAlarm[2]++; Check(); ShowAlarm();                                                     // Если Событие 7, то увеличиваем переменную второго значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[2] == 24 || mTmAlarm[2] == -1)                                                         // Если переменная второго значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[2]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[2]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(47, 33, 53, 33, 1);                                                               // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
        if(menu==8) {mTmAlarm[3]++; Check(); ShowAlarm();                                                     // Если Событие 8, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[3] == 24 || mTmAlarm[3] == -1)                                                         // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[3]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[3]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(71, 33, 77, 33, 1);                                                               // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
        if(menu==9) {mTmAlarm[4]++; Check(); ShowAlarm();                                                     // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
          if (mTmAlarm[4] == 24 || mTmAlarm[4] == -1)                                                         // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
          {                                                                                                   //
            myOLED.drawRect(mCrdTmAlarm[4]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[4]+13, mCrdTmAlarm[0]+1, true, 0);// Гасим квадрат.
            myOLED.drawLine(95, 33, 101, 33, 1);                                                              // Прорисовываем линию.
          }                                                                                                   //
          myOLED.update();}                                                                                   // Обновляем информацию на дисплее.
                                                                                                              //
        if(menu==11){serv++;        Check(); ShowServo(); myOLED.update();}                                   // Если Событие 11, то увеличиваем переменную уровня тряски кормушки, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
      }                                                                                                       //
    }                                                                                                         //
    if (i < 70)                                                                                               // Если переменная счета меньше 70.
    {                                                                                                         //
      if(menu==3) {hour++;        Check(); ShowHour();  myOLED.update();}                                     // Если Событие 3, то увеличиваем часы, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
      if(menu==4) {minut++;       Check(); ShowMinut(); myOLED.update();}                                     // Если Событие 4, то увеличиваем минуты, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
                                                                                                              //
      if(menu==6) {mTmAlarm[1]++; Check(); ShowAlarm();                                                       // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[1] == 24 || mTmAlarm[1] == -1)                                                           // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[1]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[1]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(23, 33, 29, 33, 1);                                                                 // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
      if(menu==7) {mTmAlarm[2]++; Check(); ShowAlarm();                                                       // Если Событие 7, то увеличиваем переменную второго значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[2] == 24 || mTmAlarm[2] == -1)                                                           // Если переменная второго значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[2]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[2]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(47, 33, 53, 33, 1);                                                                 // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
      if(menu==8) {mTmAlarm[3]++; Check(); ShowAlarm();                                                       // Если Событие 8, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[3] == 24 || mTmAlarm[3] == -1)                                                           // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[3]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[3]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(71, 33, 77, 33, 1);                                                                 // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
      if(menu==9) {mTmAlarm[4]++; Check(); ShowAlarm();                                                       // Если Событие 6, то увеличиваем переменную первого значения времени кормления рыбок, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение.
        if (mTmAlarm[4] == 24 || mTmAlarm[4] == -1)                                                           // Если переменная первого значения времени кормления рыбок равна 24 или 0, то ставим прочерк.
        {                                                                                                     //
          myOLED.drawRect(mCrdTmAlarm[4]-1, mCrdTmAlarm[0]-9, mCrdTmAlarm[4]+13, mCrdTmAlarm[0]+1, true, 0);  // Гасим квадрат.
          myOLED.drawLine(95, 33, 101, 33, 1);                                                                // Прорисовываем линию.
        }                                                                                                     //
        myOLED.update();}                                                                                     // Обновляем информацию на дисплее.
                                                                                                              //
      if(menu==11){serv++;        Check(); ShowServo(); myOLED.update();}                                     // Если Событие 11, то увеличиваем переменную уровня тряски кормушки, проверяем переменную на выход за пределы диапазона, выводим на дисплей значение, обновляем информацию на дисплее.
    }                                                                                                         //
    i = 0;                                                                                                    // Обнуляем переменную счета.
  }                                                                                                           //
}                                                                                                             //
                                                                                                              //
void ShowServo()                                                                                              // Функция вывода на экран количества тряски кормушки для рыбок.
{                                                                                                             //
  for(int i = serv; i <= 10; i++)                                                                             // В цикле формируем пустые ячейки уровня тряски.
  {myOLED.drawRect(massOscill[i], massOscill[0], massOscill[i]+7, massOscill[0]+4, true, 0);}                 // Гасим ячейки уровня тряски.
                                                                                                              //
  for(int i = 1; i <= serv; i++)                                                                              // В цикле формируем ячейки уровня тряски.
  {myOLED.drawRect(massOscill[i], massOscill[0], massOscill[i]+7, massOscill[0]+4, true, 1);}                 // Выводим ячейки уровня тряски.
}                                                                                                             //
                                                                                                              //
void ShowAlarm()                                                                                              // Функция вывода на экран времени кормить рыбок.
{                                                                                                             //
  if (mTmAlarm[menu-5]>=0 && mTmAlarm[menu-5]<10)                                                             // Если количество времени от 0 до 9.
  {                                                                                                           //
    myOLED.print(F("0"), mCrdTmAlarm[menu-5], mCrdTmAlarm[0]);                                                // Добавляем спереди ноль, выводя его на дисплей.
    myOLED.print(mTmAlarm[menu-5], mCrdTmAlarm[menu-5]+6, mCrdTmAlarm[0]);                                    // Выводим переменную значения времени кормления рыбок.
  }                                                                                                           //
  else{myOLED.print(mTmAlarm[menu-5], mCrdTmAlarm[menu-5], mCrdTmAlarm[0]);}                                  // Иначе выводим переменную значения времени кормления рыбок без нуля.
}                                                                                                             //
                                                                                                              //
void ShowHour()                                                                                               // Функция показа часов.
{                                                                                                             //
  if (hour>=0 && hour<10)                                                                                     // Если количество часов от 0 до 9.
  {                                                                                                           //
    myOLED.print(F("0"), 38, 20);                                                                             // Добавляем спереди ноль, выводя его на дисплей.
    myOLED.print(hour,   50, 20);                                                                             // Выводим часы.
  }                                                                                                           //
  else{myOLED.print(hour, 38, 20);}                                                                           // Иначе выводим часы без нуля.
}                                                                                                             //
                                                                                                              //
void ShowMinut()                                                                                              // Функция показа минут.
{                                                                                                             //
  if (minut>=0 && minut<10)                                                                                   // Если количество минут от 0 до 9.
  {                                                                                                           //
    myOLED.print(F("0"), 69, 20);                                                                             // Добавляем спереди ноль, выводя его на дисплей.
    myOLED.print(minut,  81, 20);                                                                             // Выводим минуты.
  }                                                                                                           //
  else{myOLED.print(minut, 69, 20);}                                                                          // Иначе выводим минуты без нуля.
}                                                                                                             //
                                                                                                              //
void ShowTime()                                                                                               // Функция показа всего времени.
{                                                                                                             //
  if (hour>=0 && hour<10)                                                                                     // Если количество часов от 0 до 9.
  {                                                                                                           //
    myOLED.print(F("0"), 38, 20);                                                                             // Добавляем спереди ноль, выводя его на дисплей.
    myOLED.print(hour,   50, 20);                                                                             // Выводим часы.
  }                                                                                                           //
  else{myOLED.print(hour, 38, 20);}                                                                           // Иначе выводим часы без нуля.
                                                                                                              //
  if (minut>=0 && minut<10)                                                                                   // Если количество минут от 0 до 9.
  {                                                                                                           //
    myOLED.print(F("0"), 69, 20);                                                                             // Добавляем спереди ноль, выводя его на дисплей.
    myOLED.print(minut,  81, 20);                                                                             // Выводим минуты.
  }                                                                                                           //
  else{myOLED.print(minut, 69, 20);}                                                                          // Иначе выводим минуты без нуля.
}                                                                                                             //
                                                                                                              //
void Alert()                                                                                                  // Функция тряски кормушки для рыбок.
{                                                                                                             //
  servo.write(180);                                                                                           // Устанавливаем сервопривод на 180 градусов.
  delay(del);                                                                                                 // Задержка.
  for(int i = 1; i <= serv; i++)                                                                              // Повторяем столько раз сколько задан уровень тряски. От 1 до 10.
  {                                                                                                           //
    digitalWrite(pinLedBlue,HIGH);                                                                            // Включаем синей светодиод.
    servo.write(180 - deg);                                                                                   // Устанавливаем сервопривод на заданный угол.
    delay(del);                                                                                               // Задержка.
    digitalWrite(pinLedBlue,LOW);                                                                             // Выключаем синей светодиод.
                                                                                                              //
    digitalWrite(pinLedGreen,HIGH);                                                                           // Включаем зеленый светодиод.
    servo.write(180);                                                                                         // Устанавливаем сервопривод на 180 градусов.
    delay(del);                                                                                               // Задержка.
    digitalWrite(pinLedGreen,LOW);                                                                            // Выключаем зеленый светодиод.
  }                                                                                                           //
  servo.write(0);                                                                                             // Устанавливаем сервопривод в 0 градусов.
}                                                                                                             //

Особенности:

Для удобства в программе предусмотрены константы для регулирования угла отклонения сервопривода "deg" и задержки между тряской стакана "del". Регулируются в начале скетча. По умолчанию угол отклонения равен 30 градусов, а задержка 400 мс. Прежде чем полноценно использовать устройство поэкспериментируйте с этими значениями, чтобы настроить оптимальную подачу корма Вашим рыбкам.

Алгоритм работы:

В начале скетча (до кода seup) выполняются следующие действия:

В коде setup выполняются следующие действия:

  • Переводим выводы pinKeyGreen для зеленой кнопки и pinKeyRed для красной кнопки в режим выхода.
  • Переводим выводы pinKeyGreen для зеленой кнопки и pinKeyBlue для cbytq кнопки в режим входа, а выводы pinLedGreen и pinLedBlue для светодиодов кнопок в режим выхода.
  • Гасим все светодиоды.
  • Присоединяем сервопривод к выводу pinServo.
  • Инициируем OLED дисплей и запрещаем автоматический вывод данных.
  • Инициируем RTC модуль.
  • Выбираем событие 1. Устанавливаем сервопривод в 0 градусов. Считываем из памяти EEPROM значение времени кормления рыбок и количество тряски.

В коде loop выполняются следующие действия:

  • Через каждые пол секунды, после нажатие кнопки, выключаем светодиод.
  • Событие 1.
  • Каждые пол секунды мигаем двоеточием между часами и минутами.
  • Считываем время, выводим его на дисплей.
  • Сравниваем текущее время и время кормления рыбок. При совпадении запускаем сервопривод с помощью функции "Alert()".
  • Выводим на дисплей центральный ряд параметров времени кормления рыбок.
  • Выводим на дисплей нижний ряд параметра количества тряски стакана.
  • Ожидаем нажатие одной из кнопок. При нажатии разрешаем переход к событию 2 и включаем светодиод нажатой клавиши.
  • Событие 2.
  • Задержка для подавления дребезга кнопки и разрешаем переход к событию 3.
  • Событие 3.
  • Каждые пол секунды мигаем параметром "Часы". С помощью функции "ChangeTime()" изменяем значение параметра. Устанавливаем значение в датчик реального времени и разрешаем переход к следующему событию с помощью функции "Return()".
  • Событие 4.
  • Каждые пол секунды мигаем параметром "Минуты". С помощью функции "ChangeTime()" изменяем значение параметра. Устанавливаем значение в датчик реального времени и разрешаем переход к следующему событию с помощью функции "Return()". Настройка секунд происходит в этом событии автоматически, как только перестают мигать минуты, то есть прошло 3 секунды, при переходе к следующему событию, секунды устанавливаются в ноль.
  • Событие 5. Выводим минуты на дисплей. и разрешаем переход к событию 6.
  • Событие 6 - 9. Каждые пол секунды мигаем рамкой параметра "Время кормления рыбок" в зависимости от события. В событии 6 настраиваем первый параметр, в событии 7 настраиваем второй параметр, в событии 8 настраиваем третий параметр, в событии 9 настраиваем 4 параметр. С помощью функции "ChangeTime()" изменяем значение параметров, а так же возможность установить прочерк, что соответствует отключению времени кормления рыбок. Разрешаем переход к следующему событию с помощью функции "Return()" и сохраняем значение в память EEPROM.
  • Событие 10.
  • Отрисовываем рамку последнего параметра центрального ряда и разрешаем переход к событию 11.
  • Событие 11.
  • Кадые пол секунды мигаем рамкой нижнего ряда. С помощью функции "ChangeTime()" изменяем значение параметра. Выводим на дисплей полученный результат. Разрешаем переход к следующему событию с помощью функции "Return()" и сохраняем значение в память EEPROM.
  • Функция "Return()". В ней отслеживаем изменение параметров. Если изменялись параметры обнуляем счетчик. Если не изменялись, то ждем три секунды и разрешаем переход к следующему событию. Если события закончились, то разрешаем переход к событию 1.
  • Функция "ChangeTime()". В ней при разовом нажатии или удержании синей кнопки уменьшается параметр в зависимости от события. При разовом нажатии или удержании зеленой кнопки увеличивается параметр в зависимости от события.
  • Функции "Check()" проверяет параметр на выход из диапазона. Если выходит, то присваиваем противоположное значение.
  • Функции "ShowServo()", "ShowAlarm()", "ShowHour()", "ShowMinut()", "ShowTime()" выводят на дисплей параметры.
  • Функция "Alert()" поворачивает сервопривод на 180 градусов, затем крутит сервопривод на небольшой угол в зависимости от количества тряски и возвращает сервопривод в исходное положение.

Ссылки:

Обсуждение