Для всех любителей рыбок, представляем устройство способное помочь Вам в заботе о морских обитателях. Самодельная автоматическая кормушка не затратит много хлопот в ее установке, а так же не придется тратиться на дорогие кормушки. Самодельность заключается в том, чтобы небольшой цилиндр закрепить на ось сервопривода. Например пластиковый стакан, в котором необходимо проделать дырки под Ваш корм.
Описание работы:
Для начала работы подключите питание к Arduino. На дисплее Вы увидите время в верхнем ряду. В среднем ряду - 4 квадрата внутри которых в зависимости от вашей платы Arduino, появятся либо прочерки либо цифры. 4 квадрата - это возможность 4 раза задать время кормления рыбок. При наступлении этого времени, произойдет кормление рыбок. Нижний ряд - это количество поворотов сервопривода. Для настройки устройства, нажмите любую кнопку. Начнет мигать значение часов в верхнем ряду. Для регулирования параметра "Часы" нажимайте кнопки: синюю или зеленую. При нажатии синей кнопки значение часов будет уменьшаться, при нажатии зеленой кнопки значение часов будет увеличиваться. Для перехода к настройкам следующего параметра, необходимо подождать 3 секунды. По истечению трех секунд параметр "Часы" перестанет мигать, и начнет мигать параметры "Минуты". Для регулирования минут, нажимайте так же синюю либо зеленую кнопку для уменьшения, либо увеличения минут. И для перехода к следующему параметру так же необходимо подождать три секунды и так далее. Время кормления рыбок задается только часами, следовательно в квадратах для задания времени кормления рыбок, в каждом из квадратов задается диапазон от 0 до 23 и прочерк, если вы хотите отключить одну из позиции. Последний ряд регулируется в диапазоне от 1 до 10. То есть при повороте сервопривода, будет поворачиваться стакан на 180 градусов, создаст небольшую тряску, в виде быстрого поворота стакана на небольшие углы и вернется в исходное положение. Количество поворотов стакана на небольшие углы и регулирует нижний ряд на дисплее. Таким образом происходит регулирование порций для рыбок. При нажатии кнопок, горят светодиоды внутри кнопок. При наступлении времени кормления рыбок светодиоды в кнопках будут тоже индицировать. Попеременно мигать.
Нам понадобится:
- Arduino Uno х 1шт.
- Trema Set Shield х 1шт.
- Trema OLED-дисплей 128x64 х 1шт.
- Trema-модуль кнопка со светодиодом, синяя х 1шт.
- Trema-модуль кнопка со светодиодом, зеленая х 1шт.
- Trema-модуль часы реального времени, RTC х 1шт.
- Штыревой соединитель х 1шт.
- Сервопривод х 1шт.
Для реализации проекта нам необходимо установить следующие библиотеки:
- iarduino_OLED - графическая библиотека для работы с Trema OLED дисплеями.
- Библиотека iarduino_RTC для работы с Trema-модуль часами реального времени, RTC.
- Библиотека Servo для работы с сервоприводами (библиотека входит в стандартный набор Arduino IDE).
- Библиотека EEPROM - для работы с энергонезависимой памятью EEPROM (библиотека входит в стандартный набор Arduino IDE).
О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.
Схема сборки:
- Устанавливаем Trema Set Shield в Arduino Uno.
- Устанавливаем Trema OLED-дисплей 128x64 в 3 посадочную площадку, в верхнюю I2C колодку.

- Устанавливаем Trema-модуль часы реального времени, RTC в 5 посадочную площадку, в верхнюю I2C колодку.

- Устанавливаем Trema-модуль синюю кнопку со светодиодом в 4 посадочную площадку.

- Устанавливаем Trema-модуль зеленую кнопку со светодиодом в 6 посадочную площадку.

- Устанавливаем Сервопривод в 1 посадочную площадку, воспользуясь Штыревым соединителем.

- Полученный результат представлен на рисунке ниже.

- На ось сервопривода закрепить стакан с дырками и закрыть стакан крышкой, как показано на рисунке ниже.

В Верхней части стакана необходимо сделать отверстия, чтобы при повороте сервопривода на 180 градусов, корм высыпался через отверстия. Стакан можно использовать любой для Вашего удобства в зависимости от количества корма. Хоть пластиковый из под сметаны с готовой крышкой, хоть стакан для лекарств из аптеки.
Код программы:
#include <EEPROM.h> // Подключаем библиотеку EEPROM.
//
#include <Servo.h> // Подключаем библиотеку Servo.
Servo servo; // Объявляем объект для работы с сервоприводом.
//
#include <Wire.h> // Подключаем библиотеку для работы с аппаратной шиной I2C, до подключения библиотек iarduino_RTC и iarduino_OLED.
#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 const uint8_t MediumFont[]; // Подключаем шрифт MediumFontRus.
extern const 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) выполняются следующие действия:
- Подключаем стандартную библиотеку EEPROM.h для работы с памятью EEPROM.
- Подключаем библиотеку Servo, для работы с Сервоприводом.
- Объявляем объект servo.
- Подключаем библиотеку iarduino_RTC для работы с Trema-модуль часами реального времени, RTC.
- Объявляем объект time для модуля на базе чипа DS3231.
- Подключаем библиотеку iarduino_4LED для работы с Trema-модуль Четырехразрядным LED индикатором.
- Объявляем объект dispLED, с указанием выводов дисплея.
- Подключаем шрифты
- Объявляем функции, переменный и константы задействованные в скетче.
В коде 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 градусов, затем крутит сервопривод на небольшой угол в зависимости от количества тряски и возвращает сервопривод в исходное положение.
Ссылки:
- Библиотека iarduino_OLED;
- Библиотека iarduino_RTC.
- Wiki - Установка библиотек в Arduino IDE;
- Wiki - OLED экран 128×64 / 0,96”;
- Wiki - описание, подключение Trema-модуль кнопки со светодиодом и ее управление.
- Wiki - описание, подключение Trema-модуль часов реального времени, RTC и их управление.

Обсуждение