Homemade Electronics
Блог о моём хобби — электронике. В основном посвящён устройствам на микроконтроллерах, например Arduino, домашней автоматизации. и другим простым электронным устройствам. Заходите!
вторник, 15 декабря 2015 г.
Автоматическая кормушка для аквариумных рыб под управлением Arduino
Лень — двигатель прогресса, как всем известно. А склероз — двигатель автоматизации. Я вот, к примеру, часто забываю покормить рыбок в аквариуме. И освещение им забываю включить, и воздушный компрессор. А аквариум мне всё же нравится. Так что, выхода нет: придётся делать автоматизацию аквариума. А так как готовые решения по вменяемой цене на эту тему отсутствуют — сделаю всё своими руками.
Собственно, автоматический контроллер для аквариума я сконструировал уже с год назад. Он у меня включает — отключает в нужное время свет, периодически — фильтр, и за температурой следит. В деталях опишу конструкцию в следующем посте. А сейчас покажу, как я сделал для своего самодельного контроллера аквариума ещё одну приблуду — автоматичесую кормушку для рыб.
Перед тем, как придумывать что-то новое я, конечно, поковырялся в интернете в поиске готовых конструкций. Но они меня не устроили прежде всего тем, что не обеспечивают сколь-либо точного дозирования корма. В большинстве случаев корм просто высыпается через отверстие в контейнере на протяжении какого-то времени. Поменяется тип корма, или просто он чуть слежится под действием влаги — и уже будет высыпаться другое количество. Более навороченные конструкции сложно сделать своими руками — часто нужен 3D-притнер. Второе, что мне хотелось видеть — чтобы аквариум был сверху накрыт крышкой или покровным стеклом. А те варианты, что я видел, не особо удобны для встраивания в крышку.
Моя автоматическая кормушка для рыб будет приводиться в движение популярным шаговым двигателем 28BYJ-48. Двигатель куплен на Алиэкспрессе, в комплекте идёт плата драйвера на базе микросхемы ULN2003. Управляющие сигналы на драйвер будет подавать (пока, для тестовых целей) Arduino, информация о времени будет считываться с модуля часов реального времени DS1307.
Итак, я сделал механическую часть кормушки из старого куска оргстекла толщиной 5 мм.
1. Нарезал куски нужного размера:
10×50 мм — 6 штук
15×105 мм — 2 штуки
50×100 мм — 1 штука
и последний большой кусок оргстекла — по размерам моего аквариума. Он будет использован в качестве покровного стекла, а через отверстие в нём будет подаваться корм для рыбок.
2. Кусочки 10×50 мм сложил «бутербродом» по три и склеил. Клей для оргстекла — дихлорэтан с растворённым в нём примерно 2% того же оргстекла. Получилось два брусочка 10x50x15 мм.
Боковые стороны брусочков шкурим на наждачке, положенной на ровную твёрдую поверхность, пока не станут идеально ровными.
Покровное стекло снизу обклеил алюминиевой фольгой (для отражения света лампы), а сверху — самоклейкой (как бы, для красоты).
Нууу, собсно, с механикой вроде всё. Переходим к электронике.
Соединяем Arduino с модулями драйвера шагового двигателя и часов реального времени:
Вывод Arduino | К чему присоединяем |
D11 | IN1 драйвера ШД |
D10 | IN2 |
D9 | IN3 |
D8 | IN4 |
ANALOG IN5 | SCL модуля DS1307 |
ANALOG IN4 | SDA модуля DS1307 |
+5V | +5V модуля DS1307 |
GND | GND обоих модулей |
Питание +5В на драйвер ШД лучше подавать от отдельного источника. Но на крайний случай можно попытаться и от Arduino — хотя опасно, может сгореть или перезагружаться.
Шаговый двигатель присоединяем к разъёму на драйвере, обозначенному буквами ABCD.
Заливаем в Arduino скетч:
#include
#include «RTClib.h»
#define IN1 11
#define IN2 10
#define IN3 9
#define IN4 8
RTC_DS1307 RTC;
int Steps = 0;
unsigned long last_time;
unsigned long currentMillis ;
unsigned long steps_left;
long time;
uint8_t feedingHour = 12;
uint8_t feedingMinute = 30;
uint8_t feedingHour2 = 12;
uint8_t feedingMinute2 = 54;
void setup() <
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
Wire.begin();
RTC.begin();
if (! RTC.isrunning()) <
Serial.println(«RTC is NOT running!»);
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
>
>
void loop()
<
DateTime now = RTC.now();
if(now.hour()==feedingHour && now.minute()==feedingMinute) <
rotate(false, 25.0); //move FROM motor
delay(1000);
rotate(true, 30.0); //move TO motor
delay(1000);
rotate(false, 5.0); //move FROM motor
>
if(now.hour()==feedingHour2 && now.minute()==feedingMinute2) <
rotate(true, 25.0); //move TO motor
delay(2000);
rotate(false, 30.0); //move FROM motor
delay(1000);
rotate(true, 5.0); //move TO motor
>
delay(1000);
>
//——————————————
void rotate (boolean dir, float mm) < steps_left=(unsigned long)64.0*64.0*mm;
while(steps_left>0) <
currentMillis = micros();
if(currentMillis-last_time>=1000) <
switch(Steps) <
case 0:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
case 1:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
break;
case 2:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 3:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 4:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 5:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 6:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 7:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
default:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
>
if(dir==true) < Steps++;>
if(dir==false) < Steps--; >
if(Steps>7)
if(Steps
time=time+micros()-last_time;
last_time=micros();
steps_left—;
>
>
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
Steps=0;
>
Особо задерживаться на ней не буду — там чуть переделанный пример из стандартной библиотеки для DS1307 и управление ШД, взятое с сайта instructables.com и чуть переделанное. Arduino в основном цикле сравнивает текущее время с тем, которое задано в переменных feedingMinute и feedingHour , и при совпадении вращает шаговый двигатель — сначала подавая деталь №1 под отверстие в контейнере с пищей, затем перемещая её к отверстию в покровном стекле. За один такой цикл в аквариум высыпается около 1 см3 корма. Если нужно больше — можно задать любое нужное количество повторений. В два контейнера можно насыпать разные корма — и в разное время рыбы будут получать разную пищу.
Единственный минус — двигатель с редуктором, вращается очень медленно. Один цикл кормления занимает больше минуты.
Как работает эта автоматическая кормушка для рыб, и процесс её сборки можно посмотреть на видео:
А по этой ссылке можно скачать PDF файл с «выкройками» оргстекла для контейнеров.
Источник
Проект 8. Автоматическая кормушка для рыбок
Для всех любителей рыбок, представляем устройство способное помочь Вам в заботе о морских обитателях. Самодельная автоматическая кормушка не затратит много хлопот в ее установке, а так же не придется тратиться на дорогие кормушки. Самодельность заключается в том, чтобы небольшой цилиндр закрепить на ось сервопривода. Например пластиковый стакан, в котором необходимо проделать дырки под Ваш корм.
Описание работы:
Для начала работы подключите питание к Arduino. На дисплее Вы увидите время в верхнем ряду. В среднем ряду — 4 квадрата внутри которых в зависимости от вашей платы Arduino, появятся либо прочерки либо цифры. 4 квадрата — это возможность 4 раза задать время кормления рыбок. При наступлении этого времени, произойдет кормление рыбок. Нижний ряд — это количество поворотов сервопривода. Для настройки устройства, нажмите любую кнопку. Начнет мигать значение часов в верхнем ряду. Для регулирования параметра «Часы» нажимайте кнопки: синюю или зеленую. При нажатии синей кнопки значение часов будет уменьшаться, при нажатии зеленой кнопки значение часов будет увеличиваться. Для перехода к настройкам следующего параметра, необходимо подождать 3 секунды. По истечению трех секунд параметр «Часы» перестанет мигать, и начнет мигать параметры «Минуты». Для регулирования минут, нажимайте так же синюю либо зеленую кнопку для уменьшения, либо увеличения минут. И для перехода к следующему параметру так же необходимо подождать три секунды и так далее. Время кормления рыбок задается только часами, следовательно в квадратах для задания времени кормления рыбок, в каждом из квадратов задается диапазон от 0 до 23 и прочерк, если вы хотите отключить одну из позиции. Последний ряд регулируется в диапазоне от 1 до 10. То есть при повороте сервопривода, будет поворачиваться стакан на 180 градусов, создаст небольшую тряску, в виде быстрого поворота стакана на небольшие углы и вернется в исходное положение. Количество поворотов стакана на небольшие углы и регулирует нижний ряд на дисплее. Таким образом происходит регулирование порций для рыбок. При нажатии кнопок, горят светодиоды внутри кнопок. При наступлении времени кормления рыбок светодиоды в кнопках будут тоже индицировать. Попеременно мигать.
Нам понадобится:
- Arduino Uno х 1шт.
- Trema Set Shield х 1шт.
- Trema OLED-дисплей 128×64 х 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-дисплей 128×64 в 3 посадочную площадку, в верхнюю I2C колодку.
- Устанавливаем Trema-модуль часы реального времени, RTC в 5 посадочную площадку, в верхнюю I2C колодку.
- Устанавливаем Trema-модуль синюю кнопку со светодиодом в 4 посадочную площадку.
- Устанавливаем Trema-модуль зеленую кнопку со светодиодом в 6 посадочную площадку.
- Устанавливаем Сервопривод в 1 посадочную площадку, воспользуясь Штыревым соединителем.
- Полученный результат представлен на рисунке ниже.
- На ось сервопривода закрепить стакан с дырками и закрыть стакан крышкой, как показано на рисунке ниже.
В Верхней части стакана необходимо сделать отверстия, чтобы при повороте сервопривода на 180 градусов, корм высыпался через отверстия. Стакан можно использовать любой для Вашего удобства в зависимости от количества корма. Хоть пластиковый из под сметаны с готовой крышкой, хоть стакан для лекарств из аптеки.
Код программы:
Особенности:
Для удобства в программе предусмотрены константы для регулирования угла отклонения сервопривода «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 градусов, затем крутит сервопривод на небольшой угол в зависимости от количества тряски и возвращает сервопривод в исходное положение.
Источник