вторник, 15 декабря 2015 г.

Автоматическая кормушка для аквариумных рыб под управлением Arduino

Лень - двигатель прогресса, как всем известно. А склероз - двигатель автоматизации. Я вот, к примеру, часто забываю покормить рыбок в аквариуме. И освещение им забываю включить, и воздушный компрессор. А аквариум мне всё же нравится. Так что, выхода нет: придётся делать автоматизацию аквариума. А так как готовые решения по вменяемой цене на эту тему отсутствуют - сделаю всё своими руками.
Собственно, автоматический контроллер для аквариума я сконструировал уже с год назад. Он у меня включает - отключает в нужное время свет, периодически - фильтр, и за температурой следит. В деталях опишу конструкцию в следующем посте. А сейчас покажу, как я сделал для своего самодельного контроллера аквариума ещё одну приблуду - автоматичесую кормушку для рыб.

Перед тем, как придумывать что-то новое я, конечно, поковырялся в интернете в поиске готовых конструкций. Но они меня не устроили прежде всего тем, что не обеспечивают сколь-либо точного дозирования корма. В большинстве случаев корм просто высыпается через отверстие в контейнере на протяжении какого-то времени. Поменяется тип корма, или просто он чуть слежится под действием влаги - и уже будет высыпаться другое количество. Более навороченные конструкции сложно сделать своими руками - часто нужен 3D-притнер. Второе, что мне хотелось видеть - чтобы аквариум был сверху накрыт крышкой или покровным стеклом. А те варианты, что я видел, не особо удобны для встраивания в крышку.
Моя автоматическая кормушка для рыб будет приводиться в движение популярным шаговым двигателем 28BYJ-48. Двигатель куплен на Алиэкспрессе, в комплекте идёт плата драйвера на базе микросхемы ULN2003. Управляющие сигналы на драйвер будет подавать (пока, для тестовых целей) Arduino, информация о времени будет считываться с модуля часов реального времени DS1307.

Итак, я сделал механическую часть кормушки из старого куска оргстекла толщиной 5 мм.
1. Нарезал куски нужного размера:
10x50 мм  -  6 штук
15x105 мм - 2 штуки
50x100 мм - 1 штука
и последний большой кусок оргстекла - по размерам моего аквариума. Он будет использован в качестве покровного стекла, а через отверстие в нём будет подаваться корм для рыбок.


2. Кусочки 10x50 мм сложил "бутербродом" по три и склеил. Клей для оргстекла - дихлорэтан с растворённым в нём примерно 2% того же оргстекла. Получилось два брусочка 10x50x15 мм.
Боковые стороны брусочков шкурим на наждачке, положенной на ровную твёрдую поверхность, пока не станут идеально ровными.

3. К этим брусочкам на боковые стороны клеим кусочки оргстекла 15x105 мм. При этом между внутренними торцами брусочков оставляем промежуток 5 мм. В итоге получаем брусок 20x105x15 мм с прямоугольным отверстием в центре. Тем же способом шлифуем грани этого бруска - они должны быть плоскими и максимально параллельными.
4. Берём мебельный уголок 25x15 см. Одно из его отверстий рассверливаем сверлом на 7 мм. С обеих сторон термоклеем прикрепляем гайки M6. Для соосности гайки накручиваем на болт.
5. В боковой грани бруска сверлим отверстие под саморез и прикручиваем  мебельный уголок из пункта 4. Деталь №1 готова!
6. Размечаем на кусочке оргстекла 50x100 мм (деталь №2) два прямоугольных отверстия 10х20 мм, через которые будет поступать корм. Расстояние между отверстиями - 30 мм.

7. По краям будущих прямоугольных отверстий засверливаемся сверлом на 8 мм, а затем с помощью лобзика выпиливаем по разметке. Дорабатываем напильником до нужной формы.
8. Отступая от углов детали №2 примерно 6-7 мм, сверлим отверстия диаметром 4 мм под шурупы. Деталь №2 готова!
9. Деталь №2 кладём на будущее покровное стекло, размечаем ответные отверстия для шурупов, и место отверстия для корма (8-10 мм) - точно посредине между прямоугольными отверстиями детали №2. Сверлим.
10. Отпиливаем кусок строительной шпильки М6 длиной 17 см. Она будет использваться в качестве ходового винта.
11. Делаем муфту для соединения вала шагового двигателя со шпилькой. Я взял алюминиевую трубку диаметром 8 мм (внутренний диаметр 6 мм - как раз входит шпилька). Отрезаем 1.5 см трубки. на расстоянии от каждого из её концов сверлим отверстия сверлом на 2.5 мм. В этих отверстиях нарезаем резьбу на 3 мм. Я просто с усилием вкрутил туда шурупы: алюминий мягкий, резьба нарезается легко.
12. Делаем крепление для шагового двигателя.Я взял кусочек фанеры 4 мм размерами 60х35 мм. На расстоянии 6 мм от нижнего края сверлим отверстие для вала диаметром 10 мм, вставляем двигатель, и просверливаем отверстия для крепления "ушек", прикручиваем шурупами 3х10мм. Фанерку крепим к покровному стеклу с помощью ещё одного мебельного уголка.
Шпильку вкручиваем в гайки на детали№1 до средины.

Деталь №2 крепим к покровному стеклу с помощью 4х шурупов М4, так, чтобы между ними размещалась деталь №1. Важно, чтобы деталь №1 перемещалась по оси без заметного трения - но при этом не было щелей между ней и деталью №2!
Муфту надеваем на вал двигателя и шпильку, фиксируем шурупами 3х6 мм.
Возле конца шпильки сверлим отверстие в покровном стекле, закрепляем там шуруп, который не будет давать шпильке уходить в сторону при вращении двигателя.

Осталось дело за контейнерами для корма. Я их склеил из кусочков тонкого оргстекла от коробки от компакт-диска. PDF-файл с "выкройками" можно скачать по ссылке внизу.
Покровное стекло снизу обклеил алюминиевой фольгой (для отражения света лампы), а сверху - самоклейкой (как бы, для красоты).

Нууу, собсно, с механикой вроде всё. Переходим к электронике.

Соединяем 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 <Wire.h>
#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){Steps=0;}
if(Steps<0){Steps=7; }

  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 файл с "выкройками" оргстекла для контейнеров.



Комментариев нет :

Отправить комментарий