Контроллер для аквариума без Arduino

image

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

Предполагалось, что рыбок нужно кормить два раза в сутки — в 7 и 16 часов. Раз нужно знать время, надо делать часы, в итоге я применил модуль RTC DS1302. Корм нужно как-то сыпать определенными дозами, тут я выбрал униполярный шаговый двигатель и сборку Дарлингтона ULN2003, чтобы его крутить. Для управления пришлось подключить дисплей и клавиатуру. Позже захотелось реализовать и термостат, для чего был куплен датчик DS18B20. Для экономии пинов я влепил еще сдвиговый регистр 74HC595N через который подключил LCD дисплей.

Я немного слукавил, применив в названии топика слова «без arduino», на самом деле, как раз на ней я и собрал пробный макет.



Таким образом я оттестировал базовый функционал программы

листинг
#include <Stepper.h>
#include <EEPROM.h>
#include <MenuSystem.h>
#include <LiquidCrystal595.h>
#include <DS1302.h>
#include <OneWire.h>

#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24UL)
#define DAYS_PER_WEEK (7UL)
#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK)
#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL)
#define SECS_YR_2000 (946684800UL) // the time at the start of y2k
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts

// Инициализация пинов часов
DS1302 rtc(2, 3, 4);

//датчик температуры
OneWire ds(5);

//Инициализация пинов экрана
LiquidCrystal595 lcd(6,7,8);

//пины шагового двигателя
const int Step1Pin = 9;
const int Step2Pin = 10;
const int Step3Pin = 11;
const int Step4Pin = 12;

Stepper motor(100, Step1Pin, Step2Pin, Step3Pin, Step4Pin);

int key=0;
int show_time=1;
int CurS=0; //текущий настраиваемый параметр (час/мин/сек)
long timestamp;
long timestamp_eeprom;
char k;
int ArrT[3]; //time
int ArrD[3]; //date
Time t;
int counter1 = 100;
int counter2 = 1;
int counter3 = 300;
int counter4 = 30; //счетчик выключения подсветки
int temp1=0;
int ttemp=0;
byte thermostat=0;
byte i;
byte data[12];
byte present = 0;
float celsius = 0;

//menu
MenuSystem ms;
Menu mm("------Menu------");
MenuItem mm_mi1(«Feed Now»);
MenuItem mm_mi2(«Time Setup»);
MenuItem mm_mi3(«Date Setup»);
MenuItem mm_mi4(«Thermostat Setup»);

void setup()
{
//кнопки
pinMode (A0, INPUT);

//шаговик
pinMode(Step1Pin, OUTPUT);
pinMode(Step2Pin, OUTPUT);
pinMode(Step3Pin, OUTPUT);
pinMode(Step4Pin, OUTPUT);
motor.setSpeed(40);

// Запуск часов
rtc.halt(false);
rtc.writeProtect(false);

//читаем установки температуры из EEPROM
int TEMP_EEPROM = 0;
TEMP_EEPROM = EEPROM_int_read(4);
if ((TEMP_EEPROM >= 0) && (TEMP_EEPROM <= 100)){
temp1 = TEMP_EEPROM;
}

// Запуск экрана с указанием количества символов и строк
lcd.setLED2Pin(HIGH);
lcd.begin(16, 2);
lcd.clear();

mm.add_item(&mm_mi1, &feed_now_selected);
mm.add_item(&mm_mi2, &time_setup_selected);
mm.add_item(&mm_mi3, &date_setup_selected);
mm.add_item(&mm_mi4, &thermostat_setup_selected);
// mm.add_menu(&mu1);
// mu1.add_item(&mu1_mi1, &on_item3_selected);
ms.set_root_menu(&mm);
}

void loop(){
//читаем температуру
byte addr[8];
if (ds.search(addr)) {
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1);//1000
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad

for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
celsius = (float)raw / 16.0;
}

if (show_time == 1){
//lcd.clear();
counter2--;
if (counter2==0){
if (counter4>0){
counter4--;
lcd.setLED2Pin(HIGH);
}else{
lcd.setLED2Pin(LOW);
}

counter2=10;
lcd.setCursor(0, 0); // Устанавливаем курсор для печати времени в верхней строчке
lcd.print(rtc.getTimeStr()); // Печатаем время
lcd.setCursor(9,0);

lcd.print(celsius);
lcd.print((char)223); //celsius simvol
// lcd.print(«C»);
lcd.setCursor(3, 1);

//timestamp = getEpochTime(rtc.getTime());
//lcd.print(timestamp);
lcd.print(rtc.getDateStr()); // Печатаем дату
}
}

//проверяем раз в… секунд
counter1--;
if (counter1==0){
counter1=100;

//thermostat
if (temp1>0 && celsius >0){ //если в настройках не 0 и датчик выдает больше 0
if (thermostat == 0){
if (celsius<temp1-1){
thermostat = 1;
lcd.setLED1Pin(LOW); //вкл
}
}else{
if (celsius>temp1+1){
thermostat = 0;
lcd.setLED1Pin(HIGH); //выкл
}
}
}

//feeder
t = rtc.getTime();
int H = t.hour;
if ((H == 0) || (H == 8) || (H == 16)){

timestamp_eeprom=EEPROMReadlong(0);
timestamp = getEpochTime(t);

if (timestamp_eeprom+3600 < timestamp){
lcd.clear();
lcd.setCursor(4,0);
lcd.print(«Feed Now!»);
EEPROMWritelong(0,timestamp);
motor.step(100);
motor_stop();
lcd.clear();
}
}
}

if (keyboard()!=0){
show_time=0;
}

menu();
delay (100); // Пауза и все по новой!
}

void motor_stop(){
digitalWrite(Step1Pin,0);
digitalWrite(Step2Pin,0);
digitalWrite(Step3Pin,0);
digitalWrite(Step4Pin,0);
}

//display menu function
void displayMenu() {
lcd.clear();
lcd.setCursor(0,0);
// Display the menu
Menu const* cp_menu = ms.get_current_menu();

//lcd.print(«Current menu name: „);
lcd.print(cp_menu->get_name());
lcd.setCursor(0,1);
lcd.print(cp_menu->get_selected()->get_name());
delay(100);
}

char keyboard(){
key = analogRead (0);

//debug
//lcd.setCursor(10, 1);
//lcd.print(key);

//Esc/Cancel
if ((key > 350) && (key < 360)){
return 'c';
}
//up
if ((key > 210) && (key < 230)){
return 'u';
}
//right
if ((key > 560) && (key < 590)){
return 'r';
}
//down
if ((key > 510) && (key < 540)){
return 'd';
}
//left
if ((key > 440) && (key < 470)){
return 'l';
}
//Enter
if (key < 20){
return 'e';
}
return 0;
}

void menu(){
k = keyboard();
if (k == 0){
counter3--;
if (counter3 == 0){
counter3 = 300;
k='c';
}
}else{
lcd.setLED2Pin(HIGH);
counter4=30;
}

switch (k){
case 'c':
ms.back();
lcd.clear();
show_time=1;
break;
case 'u':
ms.prev();
displayMenu();
break;

case 'd':
ms.next();
displayMenu();
break;
case 'e':
ms.select();
displayMenu();
break;
}
}

//feed now
void feed_now_selected(MenuItem* p_menu_item)
{
lcd.clear();
lcd.setCursor(4,0);
lcd.print(“Feed Now!»);
motor.step(100);
motor_stop();
lcd.clear();
}

void thermostat_setup_selected(MenuItem* p_menu_item)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«Temperature:»);
ttemp=temp1;
delay(300);
while (k!='c'){
delay(1);
k=keyboard();

if (k=='e'){
temp1=ttemp;
EEPROM_int_write(4,temp1);
k='c'; //выход
}

if (k=='u'){incrTemp();}
if (k=='d'){decrTemp();}
lcd.setCursor(0,1);
lcd.print(ttemp);
lcd.print(" ");
}
}

//функция увеличивает temp1
void incrTemp(){
if (ttemp<30){
ttemp++;
}
delay(200);
}
void decrTemp(){
if (ttemp>0){
ttemp--;
}
delay(200);
}

//Date setup
void date_setup_selected(MenuItem* p_menu_item)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(«Date setup»);
delay (300);
int Flash=0; //или рисуем цифры или пробелы, мерцание выбранного элемента
int FC=0; //счетчик для flash
t = rtc.getTime();
ArrD[0]=t.date;
ArrD[1]=t.mon;
ArrD[2]=t.year;
while (k!='c'){
delay(1);
k=keyboard();
//flash
FC++;
if (FC == 30){
if (Flash == 0){
Flash=1;
}else{
Flash=0;
}
FC=0;
}
if (k!=0){
Flash=1;
}

//end flash
lcd.setCursor(0,1);
flashPrintDate(Flash,0);
lcd.print('.');
flashPrintDate(Flash,1);
lcd.print('.');
flashPrintDate(Flash,2);

if (k=='u'){incrD();}
if (k=='d'){decrD();}

if (k=='r'){
if (CurS <2){
CurS++;
}else{
CurS=0;
}
delay(300);
}
if (k=='l'){
if (CurS>0){
CurS--;
}else{
CurS=2;
}
delay(300);
}
if (k=='e'){
rtc.setDate(ArrD[0],ArrD[1],ArrD[2]); // Дата.
k='c'; //выход
}
}
}

//Time setup
void time_setup_selected(MenuItem* p_menu_item)
{

lcd.clear();
lcd.setCursor(0,0);
lcd.print(«Time setup»);
delay (300);
int Flash=0; //или рисуем цифры или пробелы, мерцание выбранного элемента
int FC=0; //счетчик для flash

t = rtc.getTime();
ArrT[0]=t.hour;
ArrT[1]=t.min;
ArrT[2]=t.sec;

while (k!='c'){
delay(1);
k=keyboard();

//flash
FC++;
if (FC == 30){
if (Flash == 0){
Flash=1;
}else{
Flash=0;
}
FC=0;
}
if (k!=0){
Flash=1;
}
//end flash

lcd.setCursor(0,1);
flashPrint(Flash,0);
lcd.print(':');
flashPrint(Flash,1);
lcd.print(':');
flashPrint(Flash,2);

//меняем значение
if (k=='u'){incr();}
if (k=='d'){decr();}
if (k=='r'){
if (CurS <2){
CurS++;
}else{
CurS=0;
}
delay(300);
}
if (k=='l'){
if (CurS>0){
CurS--;
}else{
CurS=2;
}
delay(300);
}

if (k=='e'){
rtc.setTime(ArrT[0], ArrT[1], ArrT[2]); // Часы, минуты, секунды 24-часовой формат.
k='c'; //выход
}

}
}

//функция выводит чч или мм или cc
void flashPrint(int Flash, int CT){
if ((CurS == CT) && (Flash==0)){
lcd.print(" ");
}else{
if (ArrT[CT]<10){
lcd.print('0');
}
lcd.print(ArrT[CT]);
}
}
//функция выводит день, месяц или год
void flashPrintDate(int Flash, int CT){
if ((CurS == CT) && (Flash==0)){
if (CurS == 2){
lcd.print(" ");
}else{
lcd.print(" ");
}
}else{
if (ArrD[CT]<10){
lcd.print('0');
}
lcd.print(ArrD[CT]);
}
}

//функция увеличивает выбранный элемент на 1
void incr(){
int limit=59;
if (CurS==0){
limit=23;
}

if (ArrT[CurS] < limit){
ArrT[CurS]++;
}else{
ArrT[CurS]=0;
}
delay(200);
}
//функция уменьшает выбранный элемент на 1 для даты
void decr(){
int limit=59;
if (CurS==0){
limit=23;
}
if (ArrT[CurS] > 0){
ArrT[CurS]--;
}else{
ArrT[CurS]=limit;
}
delay(200);
}

//функция увеличивает выбранный элемент на 1 для даты
void incrD(){
int limit=31;
if (CurS==1){
limit=12;
}
if (CurS==2){
limit=5079;
}

if (ArrD[CurS] < limit){
ArrD[CurS]++;
}else{
ArrD[CurS]=1;
}
delay(200);
}
//функция уменьшает выбранный элемент на 1 для даты
void decrD(){
int limit=31;
if (CurS==1){
limit=12;
}
if (CurS==2){
limit=5079;
}
if (ArrD[CurS] > 1){
ArrD[CurS]--;
}else{
ArrD[CurS]=limit;
}
delay(200);
}

//timestamp
uint32_t getEpochTime(Time tm){
int i;
uint32_t seconds;
int year = tm.year — 1970;

// seconds from 1970 till 1 jan 00:00:00 of the given year
seconds= year*(SECS_PER_DAY * 365);
for (i = 0; i < year; i++) {
if (LEAP_YEAR(i)) {
seconds += SECS_PER_DAY; // add extra days for leap years
}
}

// add days for this year, months start from 1
for (i = 1; i < tm.mon; i++) {
if ( (i == 2) && LEAP_YEAR(year)) {
seconds += SECS_PER_DAY * 29;
} else {
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
}
}
seconds+= (tm.date-1) * SECS_PER_DAY;
seconds+= tm.hour * SECS_PER_HOUR;
seconds+= tm.min * SECS_PER_MIN;
seconds+= tm.sec;
return seconds;
}

//eeprom int
void EEPROM_int_write(int p_address, int p_value)
{
byte lowByte = ((p_value >> 0) & 0xFF);
byte highByte = ((p_value >> 8) & 0xFF);

EEPROM.write(p_address, lowByte);
EEPROM.write(p_address + 1, highByte);
}

unsigned int EEPROM_int_read(int p_address)
{
byte lowByte = EEPROM.read(p_address);
byte highByte = EEPROM.read(p_address + 1);
return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

//eeprom long int
void EEPROMWritelong(int address, long value)
{
//Decomposition from a long to 4 bytes by using bitshift.
//One = Most significant -> Four = Least significant byte
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);

//Write the 4 bytes into the eeprom memory.
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}

long EEPROMReadlong(long address)
{
//Read the 4 bytes from the eeprom memory.
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);

//Return the recomposed long by using bitshift.
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}

Я не программист, потому за программу сильно не ругайте, сам знаю, что тут косяк на косяке.


Но Arduino UNO сама по себе большая плата, к тому же ее жалко. Решено было сделать кормушку на чистом Atmega328. В итоге я разработал плату в Sprint-Layout:



В этой версии платы часы DS1302 уже разведены прямо на плате, а так же исправлены мелкие ошибки.

Печатную плату изготовил методом ЛУТ и залудил сплавом Розе


Так же была сделана и плата клавиатуры, ее видно на фото макета.

После чего запаял все детальки:



Никакого интерфейса для программирования у меня не предусмотрено, поэтому все изменения я заливаю на Arduino, а дальше просто переставляю контроллер в панельку на плате.

Корпус нарисовал в OpenSCAD и распечатал на 3D-принтере



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




Так же нарисовал и распечатал корпус для самой кормушки


Внутри этой штуки должен крутится такой вот цилиндр с прорезями:



Клавиатуру и часовой модуль зафиксировал термоклеем:



И собрал все до кучи:



Вот тут можно посмотреть результат работы:



Попробовал, все работает. Отдал прибор отцу на тестирование. Наверняка будут недочеты, когда оттестируем — отпишусь
о результатах и исправлениях.

После того, как все было сделано, нарисовал схему:

Сильно не пинайте первый раз использую Eagle


R1,R2 — 10 кОм, R3 — 3 кОм, резисторы на кнопках по 2.2 кОм, С1,C2 — 20 пФ, электролит C3 — 5мкФ, так же электролит стоит по питанию, где-то на 1000 мкФ. Кварц для микроконтроллера 16 MHz, транзистор любой npn.

По итогу можно прикинуть смету:


1. Микроконтроллер Atmega328 — $1.8;
2. LCD экран 16x2 — $2.3;
3. Термодатчик DS18B20 — $3;
4. Модуль часов RTC DS1302 — $3.5;
5. Пластик ABS для 3d печати 84г. — $2.5
6. Шаговый двигатель, кварц, резисторы, кондеры, текстолит, итп — $1, как бы такого добра хватает.
Итого: ~$14.

Что хотелось бы сделать в будущем


1. Русифицировать интерфейс. Для этого надо разобраться с библиотекой LiquidCrystal595Rus.h;
2. Сделать настройку для регулирования дозы корма;
3. Сделать настройку для выбора времени кормления;
4. Можно управлять светом и компрессором, для этого есть свободные пины и ноги ULN2003;
5. Если моторчик переключить на аналоговые пины, то останется место для подключения модуля Wi-Fi, тем самым его можно связать с OpenHAB, чтобы видеть графики температуры и всегда знать, работает ли прибор, даже находясь за границей.

В заключении хочу добавить, что все исходники залил на github.
Там и платы в layout, и файлы openscad, stl, исходник программы.

На этом всё, спасибо за внимание.
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 73

    0
    На нашего Буншу похож ©

    Хорошая работа! Цитата моя вот к чему. Делаю контроллер для домашней пивоварни. На 2/3 уже готов. Расскажите, пожалуйста, как вы внутри корпуса платы крепили? На герметик? И как экран у вас прикреплен? На фото не совсем понятно.
    Спасибо!
      0
      Ох, жду пост. Сейчас думаю о заказе www.embeddedcontrolconcepts.com/ — выглядит вкусно.
        0
        Уже давно все собирают контроллер управления пивоварни типа Braumeister. Намного доступнее и увлекательнее.
          0
          Походу лег сайтик… Хабрэффект =))))))))) В чем там суть, плата\прошивки\схемы сборки есть?
            0
            Да, так и есть. В контроллере я полностью повторяю функционал контроллера Braumeister. Для моих нужд этого достаточно. Промышленные масштабы пивоварения налаживать не собираюсь :)
            0
            Вот тут человек уже собирал контроллер. Я вдохновился его постом и спустя 100500 лет решил сделать свою пивоварню. Контроллер у меня тоже на Ардуино, реле немного другие и есть AC-DC преобразователь. Процесс сейчас тормозит поставка 2-х канального реле с алиэкспресса :(
              0
              Вместо ожидания двухканального реле можно было бы зайти в любой магазин радиотехники и купить пару реле, транзисторов и диодов. Там обвязка-то примитивная.
              0
              И по поводу embeddedcontrolconcepts.com
              Дороговато нынче будет эта штука. Да и по сути, если не промышленные масштабы, то Ардуино вполне справится с задачей.
                0
                Дороговата с одной стороны, если собирать на тех же PID по 30$ за штуку, получается 90$, эта штука в два раза дороже. Плюс все запрограммировать и т.п. С моим временем выйдет дороже явно. На самом деле хочу конечно 462 версию на вырост.
              0
              Плата клавиатуры и модуля часов зафиксирована термоклеем, а основная плата просто прикручивается саморезом прямо через крышку, не самое лучшее решение кстати.
                0
                Понятно. У вас что хорошо — вы сами напечатали корпус, а я его покупал, поэтому пока приходится городить огород. В дальнейшем я планирую тоже печатать корпуса с отверстиями для крепления плат.
              0
              Боюсь, с механикой дозатора корма будут проблемы. То мало будет сыпать, то много. А иногда будет забиваться.
              Механика ведь дело такое.
                0
                Добавить буфер с вибрацией. Открывается лючок в буфер, кормушка жужжит, чтоб точно буфер заполнился, лючок буфера закрывается, открывается нижний лючок. Можно верхний лючок сделать перемещаемым, тогда и дозировкой управлять можно:)
                  0
                  Лючок заклинит, т.к. ему корм помешает закрыться =).
                    +7
                    Закрывать с вибрацией. В любой непонятной ситуации — вибрируй:)
                      +1
                      А вот это неплохо, может сработать.
                      Главное, чтобы в процессе вибрации не высыпалось слишком много корма. Рыбы от этого дохнут.
                        0
                        Слишком много корма в аквариуме — вибрируй. Рыба не сможет в таких условиях полноценно кормиться.
                          0
                          они дохнут как раз от несъеденного корма, он начинает гнить в воде
                          0
                          Так буфер же для этих целей. А вообще, пришло потом в голову, хотя ниже уже предложили, шнековый механизм. Кофе-машины, собственно, так и дозируют. Но с вибрацией веселей:)
                      +1
                      В магазинных кормушках часто просто вентилятор стоит, который воздухом корм разрыхляет в процессе кормления. Такими кормушками можно легко хлопьями кормить.
                      +1
                      Первое что приходит в голову сделать дозатор наподобие мясорубки, чтоб червяк выталкивал корм, либо второй вариант — горизонтальная трубка с поршнем, шаговик толкает поршень выталкивая корм, но первый вариант кажется лучше
                        0
                        Да, если этим будет управлять мощный двигатель, множество проблем уйдёт.
                          0
                          мощный не обязательно, более чем хватит двигателя 28BYJ-48 со встроенным редуктором, причем этот двигатель работает бесшумно и дает хороший момент, управляется примитивнейшей ULN2003.
                        0
                        Все возможно, пока проверил сыпет неплохо и всегда одинаковая кучка получается, но все покажет время.
                        –23
                        > без arduino

                        Угу. Как же! Прошивка не на сях написана, а на ардуйне-язычке. Так что, врать-то не надо!!!

                        Если дерьмо тщательно присыпать сахарной пудрой, это все равно будет дерьмо, а не торт! Чтобы был торт, надо вообще от дерьма избавиться!
                          +5
                          А чего у вас так подгорело? Может автор имел ввиду аппаратную часть Arduino. Вы бы хоть уточнили или попросили автора поправить. А то зашли в ветку, накинули Г на вентилятор еще и платформу в целом обругали. Терпимие надо быть.
                            +4
                            Товарищ просто не стесняется в выражениях, но в целом прав. Автор от ардуины взял худшее, а именно софт, да еще и сделал желтый заголовок. А в остальном все сделано на достойном уровне.
                            Плюсанул брату-железячнику, но остался недоволен подачей.
                              +8
                              С тем что у ардуины не лучший софт, мало кто не согласиться, но благодаря этому плохому софту, порог вхождения в arduino, значительно ниже. Тем более плохой софт, не оправдывает хамство. Может быть я в чем-то не прав, но для меня это дико.
                                +1
                                Под словами «брат-железячник» я имел ввиду автора статьи, а не комментатора.
                                Eddy_Em — известный тролль, но и статьи писал по делу. Хамство я не одобряю, но в целом он прав.
                              –1
                              Я сказал то, что и хотел сказать!
                              И не собираюсь толеразмом к ущербным страдать! Инвалидов надо инвалидами называть, а не выдумывать всякий толерастический бред!
                              Ардуйня плоха тем, что она создает у хомячков мнение, как будто бы они что-то умеют. И будто бы просто достаточно собрать кубики, потыкать мышкой — и ты уже великий робототехник! А вот хрен!
                              И ладно еще, когда эти обезьяны в своей песочнице колупаются. Но когда они свою ардуйню пытаются запихнуть в производство, а то и вообще лифтом управлять… Это все! Таких надо в психиатрической клинике лечить принудительно, пока они никого не убили!
                              А то как про ту кухарку будет…

                              Кстати, быдлохабра — наглядный пример того, что будет если кухарке дать власть: толпа конформистского школоло набегает на говностатьи, где есть слова «ардуйня», «мастдайка» и прочая ширпотребщина, и плюсуют до потери пульса! А хорошие статьи обычно где-то на задворках остаются, потому что нет там ардуйни и хомячкам вообще ничего не понятно.

                              Кухарку лучше дальше кухни не выпускать. Вот так вот быдлохабра стала кухней для этих кухарок.
                                +3
                                если в вашей тираде заменить ардуино на автомобиль автомат/мыльницу/театралов/etc/etc/etc то
                                будет очень похоже на цитаты
                                1) автолюбителей (которые могли по винтику разобрать и собрать машину) в сторону водителей машин с коробкой автоматом. да и вообще всех просто водителей.
                                2) фотграфов профи (которые в тёмных комнатах корпели над шедеврами)
                                3) в сторону телевиденья
                                4) etc etc

                                очень похоже на стоны лишенных «исключительности» профи
                                их просто колбасит от осознания того что то что раньше они делать только ОНИ
                                теперь может делать домохозяйка (да мягко скажем не оптимально),
                                но зато она решает свои РЕАЛЬНЫЕ проблемы которые иначе не были бы решены вообще никак не решены
                                ибо профи до таких вещей не опускаются…
                            0
                            А как сама кормушка крепится к аквариуму? Ведь одно неловкое движение и она опрокинется.
                            P.S. заказы не принимаете?
                              0
                              Аквариум у отца с большой массивной крышкой, в ней есть люк для кормления, если его открыть, то под ним отверстие, но с бортиками, туда как раз ставится кормушка и падать ей как бы некуда, но можно придумать разные варианты крепления, благо 3D-печать сейчас доступна. Заказы на что имеете ввиду? Все возможно.
                              0
                              Корм очень не любит находиться на открытом воздухе, т.к. очень гигроскопичен. Малого того, что будет слёживаться, так и гадость всякая будет заводиться.

                              В фирменных кормушках (далеко не за 10 баксов), даже специально подводиться воздух от компрессора и есть периодический цикл «встряхивания» корма в бункере.
                                0
                                Интересное решение, а где можно посмотреть на такой девайс?
                                  0
                                  С вентиляцией, но без встряхивания, например, такой.
                                    0
                                    Я правильно понимаю, что воздух поступает от компрессора, который в комплект к этой кормушки не входит? Тогда плюсом этого устройства является лишь отверстие или патрубок для подключения шланга от компрессора? Это не сложно реализовать.
                                      0
                                      Верно. Кстати, про встряхивание, при каждом кормлении барабан делает полный оборот, чтобы забрать в отсек для выброса новую порцию корма, так что «встряхивание» в некором роде тоже происходит.
                                0
                                А кнопочки не дребезжат при нажатии? Обычно стявят конденсатор параллельно, чтобы шум убрать
                                  0
                                  Нет, не дребезжат, там резистор 10кОм на 5в подтягивает, хотя кондер может и стоит поставить, спасибо.
                                    +1
                                    Проект интересный и небольшой.

                                    У вас наверно просто кнопки хорошие поэтому нет шума. Обычно с них сыпется при нажатии. А резистор подтягивающий хорош в статике, когда никто ничего не нажимает.

                                    Кнопка S2 мне не совсем понятна. Если 10к подтягивают на 0, то кнопка на 0 как бы не задействована. Её бы нужно приподнять сопротивлением. Либо делать подтверждение по «ненажатию» в течении 5 секунд.

                                    Кстати код по считыванию результата кнопок я бы чуть чуть подправил. дал бы самые большие интервалы (усреднил ваши):
                                    ЕСЛИ key > 550 ТО «r»
                                    ИНАЧЕ ЕСЛИ key > 490 ТО «d»
                                    ИНАЧЕ ЕСЛИ key > 400 ТО «l»
                                    ИНАЧЕ ЕСЛИ key > 290 ТО «c»
                                    ИНАЧЕ ЕСЛИ key > 50 ТО «u»
                                    ИНАЧЕ «e»

                                    Чтобы не «проскакивать» значения, я бы ещё отслеживал отпуск кнопки. Например вы нажали на кнопку, а программа уже выполнила 3 цикла, то Инкремент значений например будет равен 3.
                                    А чтобы удобно было устанавливать время можно только для функции «дата» устанавливать счётчик инкремента который активируется после допустим 3 секунд удерживания кнопки. То есть программа делает инкремент 1 если кнопка нажата и отпущена в течении 3х секунд. Ежели она нажата и не отпущена в течении 3х секунд, то инкремент увеличивается каждый период П на 5. (К примеру 2 раза в секунду).

                                    У вас не система реального времени, так что ресурсы вы не учитываете. Но если вдруг придётся, то для кнопок можно использовать прерывания. У вас как раз РС0 поддерживает прерывания. То есть как только значение превышает 0,8В, вы обрабатываете кнопки, Если не превышает, то программа их и не опрашивает.
                                      0
                                      Да, ваш алгоритм опроса кнопок более толковый, учту. По поводу кнопки S2 не понял, резистор 10к у меня подтягивает на 1, а не на 0, кнопка S2 коротит вход сразу на землю, кнопка S3 через резистор 2.2к, S4 уже через 4.4 к и т.д.
                                        0
                                        Всё верно, прошу прощения, не так посмотрел.
                                        Обычно земля находится всегда снизу компонента, а + сверху.
                                        0
                                        Можно заюзать debouncer library
                                      0
                                      У меня вот с кнопками сначала тоже беда была, даже вопрос на Тостере задавал. По итогу сам же и нашел решение (там выложил). Резистора вполне хватает.
                                      +1
                                      Просто супер, готовое решение для маленькой фермы, что-б не вставать рано кормить животину.
                                        +4
                                        без Arduino

                                        Вот эту фразу я бы из заголовка убрал, тогда всё бы стало совсем хорошо :)
                                        А то у вас получился заголовок, в котором Arduino звучит как что-то плохое, а в самом девайсе он у вас и используется.
                                          –1
                                          он свою плату сделал, на ардуино он макет устройства делал
                                            +1
                                            От того, что бутлоадер Arduino прошит в контроллер, которой впаян не в «родную» плату, платформа не перестаёт быть Arduino.
                                              0
                                              Дак софт и есть основная часть ардуины! Если бы не было простого и глючного софта, то и не было бы никакой ардуины!
                                          0
                                          Ну когда уже перестанут лепить внешний RTC к микроконтроллеру, у которого и так есть таймер с тактированием от часового кварца?
                                            0
                                            Интересно, а насколько точно можно было бы измерять время своим кварцем? Я подозреваю, что в RTC используют и более точный и стабильный кварц, и схему компенсации температурного дрейфа.
                                              0
                                              Более точный, чем где? В китайских часах стоят кварцы гораздо менее качественные, чем те, которые можно приобрести под свои самоделки, и тем не менее, никто особо их точностью не заморачивается. При использовании в комнатных условиях можно ограничится лишь постоянной поправкой (типа +1,2сек. в месяц), без учета температуры.
                                              +2
                                              Я подумал еще про отключения света. Все-таки RTC-платы включают в себя автономное питание! Вот выключится свет, потом включится, а ардуина не знает, сколько времени.
                                                0
                                                а как решать вопрос временного пропадания питания?
                                                  0
                                                  А тут он как бы решен, имеется батарейка на 3V для питания модуля часов, так что рыбки останутся голодные только если питания не будет целый час с 16:00 до 16:59 к примеру. Программа проверяет только час 8 или 16

                                                  if ((H == 8) || (H == 16)){
                                                  затем проверяет timestamp последнего кормления, который записан EEPROM.

                                                  if (timestamp_eeprom+3600 < timestamp){
                                                  это для того, что бы гарантированно покормить один раз в назначенный час, но не более
                                                  Можно конечно красивей запрограммировать, скажем просто задать интервал кормления в часах и проверять все по тому же timestamp.
                                                    0
                                                    Ой. Вопрос был к KoteSoft
                                                      0
                                                      Ну так можно прилепить такую же 3в батарейку к контроллеру. В простейшем случае через диод Шоттки, параллельно источнику питания. Можно собрать и более энергоэффективную схему например, на аналоговом компараторе микроконтроллера и паре MOSFETов. Отслеживать пропадание питания тем же компаратором и включать подходящий режим энергосбережения микроконтроллера. Вариантов много. У более продвинутых контроллеров есть отдельный вывод для подключения батарейки, там никаких дополнительных элементов не нужно.
                                                        0
                                                        А не подскажете, где почитать на эту тему по-подробнее?
                                                          0
                                                          Вы меня простите, но такого рода темы уже обсуждались не раз
                                                        0
                                                        Если встаёт вопрос по перебою питания, то самое простое и недорогое решение это аппаратно ПО-шное.
                                                        Смотрим на потребление питания Атмеги.
                                                        Используем калькулятор ёмкости в зависимости от тока и напряжения
                                                        Смотрим на цены ионисторов
                                                        Подбираем самый лучший вариант цена/длительность (например 5В номинально, 4В минимально и 15мА: 0,1Ф — 2часа — 80Руб, или 1Ф — 20часов — 160Руб)
                                                        Правим слегка питание. Диод, чтобы не питать всю схему, сопротивление, чтобы убрать потенциал возникающего из-за обратного тока диода.
                                                        Если хотим большей эффективности, то заводим входное напряжение на АЦП (6,5мА всего) и отслеживаем. Ставим только счётчик на работу. При появлении напряжения выходим в обычный режим.
                                                        Если регистр позволяет, то снижаем частоту до минимума.

                                                        Ещё можно загрубить подстветку экрана, а регистр отключать через EN3 после минутного простоя. Включать при изменении состаяния на одной из кнопок.
                                                    0
                                                    Рекомендую для рисования плат и схем — очень удобная и бесплатная тулза
                                                      0
                                                      Ух ты. На каждый день — отличная вещь. Я всё еще Альтиумом пользуюсь. хотя кроме ЛУТа больше ничего не применяю.
                                                      0
                                                      Надо-же! Даже linux не пришлось ставить :)
                                                        0
                                                        Ну как сказать, на ПК то у меня линукс, т.е. OpenSCAD, Arduino IDE я в нем пускаю, только Sprint-layout под виртуалкой.
                                                          0
                                                          Я имел в виду сам девайс :)
                                                          А то сейчас всё чаще наблюдаю: проинсталлим линукс, на него перл и будем этим кормить рыбок.
                                                            0
                                                            Я понял, вообще на сервере у меня linux и OpenHAB, думаю привязать контроллер к нему по wi-fi, тогда получится, что линукс, хоть и не кормит рыбок, но контролирует и оповещает хозяина по email, без линукса никуда сейчас ;)
                                                        0
                                                        круто, предлагаю наладить производство и продажу через Интернет
                                                          0
                                                          Вообще-то мне это уже предложили и я согласился, сейчас делаю опытный образец, с вайфаем, но без экрана и клавиатуры, все на smd компонентах. Пока самая сложная задача это настройка wi-fi без экрана и кнопок, смотрю в сторону WPS и как альтернатива дополнительный USB (HID) интерфейс для первоначальной настройки.
                                                            0
                                                            просто устройство постоянно должно быть wifi точкой доступа. Подключился, настроил, отключился.
                                                              0
                                                              Да, такой вариант я тоже рассматриваю, но боюсь слишком сложно это будет для обычного пользователя.
                                                                0
                                                                Ну вы же управлять устройством со смартфона планируете? Зашел в настройки выбрал wifi сеть устройства и запустил приложение. Мне кажется дешевле bluetouth использовать
                                                          0
                                                          Не только со смартфона, но и браузером через Интернет, так что блютус отпадает, а за идею настройки приложением спасибо!
                                                          Я вижу такой алгоритм:
                                                          При старте проверяем есть ли настройки в EEPROM и предыдущая удачная попытка установки связи, если есть берем настройки и вперед,
                                                          если нет, включаем режим точки доступа и ждем.
                                                          Запускаем приложение, подключаемся к девайсу, как к точке доступа, настраиваем wi-fi, перегружаемся.
                                                          Так же предусмотреть кнопку сброса настроек.

                                                          Only users with full accounts can post comments. Log in, please.