Автоматическая забота о курах [снова умный курятник]
- Войдите на сайт для отправки комментариев
Всем привет. Проект водоснабжения вполне себе живет в первой реализации и ждет своего продолжения. А пока нужда возникла в кормлении кур.
Самая главная часть, механика, в черновом варианте готова и работает. Сперва думал использовать идею одного "товарища по цеху" со шнековой подачей. Но что-то замучался со шнеком, то вал уведёт сваркой, то перо шнека не по выкройке, короче - решил упростить, взял коробку из-под компакт дисков и сервопривод. В инете таких решений валяется куча. И - они работают для небольших объемов корма. Но если заваливать на неделю-две, то вес корма просто выдавит диск-дозатор, или надо думать о каких-то сложных роликах-подпорках. Ну - это все в будущем, а пока - перуанский вариантъ.
Теперь вот код. Набросал первый прикид, есть несколько вопросов к вам, коллеги.
Отслеживание запуска задач (их видится пока 4: выдать корм, налить воды, открыть дверь выгула, закрыть дверь выгула) через прерывание
Создал класс таймера
class Auto_Feeder_timer { public: //я что-то подумал, что пока откажусь от головоломки, что в приват ставить, и что в паблик String timerName; unsigned long start_time; // время включения формат ЧЧММ void (*ptrOnFuniction)(); // указатель на запускаемую функцию, bool haveStartedToday = false; // ставим после запуска, Auto_Feeder_timer (String tName, unsigned long tStart_Time, void f()) { timerName = tName; start_time = tStart_Time;// назначаем время старта ptrOnFuniction = f; // указатель на запускаемую функцию } bool getIsItTime(unsigned long currentTime){ if (currentTime == start_time && !haveStartedToday) // если текущее время равно или больше времени старта { haveStartedToday = true; Serial.println ("we are starting"); ptrOnFuniction(); // запускаем функцию return true; } return false; } };
Теперь прерывание
void setup() { OCR0A = 0xAF; TIMSK0 |= _BV(OCIE0A); setSyncProvider(RTC.get); // получаем время с RTC prevMillis = millis(); }
Прототипы функций и создание экземпляра
// прототипы и укзатели функций void feeder_ON_OFF (); void (*ptrfeederOnOff)() = feeder_ON_OFF; // устанавливаем таймеры Auto_Feeder_timer food_timer("feed", feed_time, ptrfeederOnOff);
Я пока выкидываю куски кода, которые не принципиальны (так что может где-то скобку потерял, но это не вопрос сейчас - в полном коде все компилируется и работает). И вот вопрос.
SIGNAL(TIMER0_COMPA_vect) { if (millis() - prevMillis >= my_delay) { // my_delay по умолчанию я решил ставить в 30 сек. чтобы снизить частоту запуска проверки таймеров prevMillis = millis(); time_t t = now(); if (food_timer.getIsItTime(hour(t)*60UL + minute(t))) {// если возвращается true - значит таймер сработал RecordTimerResult(food_timer.timerName, t); // записываем в лог } if (hour(t) == 00 && minute(t) == 00 && !resetFlag) { // в 00:00 resetFlags(); // сбрасываем флаги выполненных таймеров } } }
У меня была какя-то слегка странная идея, чтобы запускать проверку таймера не часто, например раз в полминуты. Я даже не знаю зачем... И я вижу, что это создает много сложностей. Например, костыль с ResetFlags(). Поскольку условие срабатывает в 00:00, то эта функция обнуления может быть запущена дважды. Чтобы этого не происходило (хотя это и не страшно, но как-то глупо), пришлось устанавливать флаг bool ResetFlag, ставить его true и через минуту ставить false... короче, бред. Видимо, я сейчас переделаю на проверку раз в секунду, буду передавать время в секундах.
Но может быть идея делать проверку раз в пол-минуты хороша собой и стоит того?
В остальном пока вроде все понятно.
А, вот еще. Есть задача, чтобы если в деревне отключат электричество, то после его подачи не произошло "двойного кормления" или сдвига времени кормления. Так что я использую RTC и SD-карточку (сначала думал писать в EEPROM, который на RTC-модуле, но потом плюнул - циклы записи, сколько раз и т.д.).
Сейчас додумываю формат записи флагов, чтобы при включении системы пройтись по ним и проверить, не был ли пропущен запуск какого-либо таймера, пока не было леФтричествА
Не удержался ... После публикации темы получил сообщение:
Тема форума Автоматическая забота о курах [снова умный курятник] был создан.
Сразу вспомнил: "Зарежь мне арбуз, пожалуйста. Да, я говорю по русски, я русский школа скончался"
Я так и не понимаю, почему после публикации топик невозможно отредактировать, а ответы - вот пожалуйста.
Я так и не понимаю, почему после публикации топик невозможно отредактировать, а ответы - вот пожалуйста.
Борьба с пишущими курсачи.
А, вот еще. Есть задача, чтобы если в деревне отключат электричество, то после его подачи не произошло "двойного кормления" или сдвига времени кормления. Так что я использую RTC и SD-карточку (сначала думал писать в EEPROM, который на RTC-модуле, но потом плюнул - циклы записи, сколько раз и т.д.).
Сейчас додумываю формат записи флагов, чтобы при включении системы пройтись по ним и проверить, не был ли пропущен запуск какого-либо таймера, пока не было леФтричествА
Возьмите FRAM и пишите в него без забот. При определенной сноровке можете запаять его на место EEPROM, который, дополнительно приделан к RTC-чипу. Модули с DS3231 зачастую снабжаются епромкой, которая по ногам совпадает с FRAM
Вы сами себе начинаете противоречить, хотите без рюшечек и излишеств и тут же прикручиваете SD карту, которая наличием механических контактов понижает надежность на порядки. При этом уже имеете на плате: родной EEPROM атмеги, 56 энергонезависимых байт в RTC и EEPROM на модуле RTC (если в виде модуля).
Сорок первый предложил решение позволяющее не заботится о количестве перезаписей, в ответ на ваше опасение.
А для обычной епромки давайте посчитаем: курей кормим 2-3, да хоть шесть раз в день. Ресурс внутреннего епрома 100 000 записей. Итого: 100 000/6/31/12 = 44,8 года если писать в одни и те же ячейки. У внешнего - увеличивается на порядок и получается запредельное количество годов. За сорок пять лет, по перуанской методологии, термиты три раза сожрут курей, птичник, девайс и хозяина))).
Лично я столько прожить уже не рассчитываю, а если и проживу, то вряд ли, будучи под сотню лет, смогу заниматься курями.((((
Теперь по теме проекта, нужна проверка, не накосячил ли я где по неопытности.
Вроде бы все работает. Но, может кто опытным взглядом проникнет в суть незаметного и посоветует очевидное? Т.е. правильно ли создаю массив указателей на экземпляры класса и помещаю туда эти самые указатели?
Или есть более элегантный метод?
Нда, вот они грабли :/
Все было красиво - таймеры, прерывания. И добрался до функции запуска сервы, которая спокойно себе сидела внизу, пока я до нее не добрался. И тут - бац: delay...
Никакой delay не происходит, серва не работает. Если загрузить простой скетч (с тем же обвесом из RTC&CD) - конечно все работает. Т.е. дело в использовании delay в функции.
Теперь вот думаю, что же с этим сделать? Как реализовать задержки внутри функции?
Функция-то из обработчика прерывания вызывается, поди.
угу, теперь вот думаю...
как вариант, установить два флага и дальше их в обработчике прерывания проверять и запускать функцию оттуда, а не из функции-таймера, как до этого
и теперь .... ыыыы... ку..., точнее кю
какие костыли... надо будет видимо класс для функции создать, с флагами, которые будут устанавливаться через millis и потом в конце всего поставить флаг haveFinishedToday. Потом раз в сутки в 00:00 все флаги и так сбрасываются...
а вы говорите EEPROM - piece of cake... тут бы основной код бы доделать до пятницы, а мне уезжать...
В обработчике прерывания другие прерывания не выполняются. Delay(), millis(), библиотека servo - все используют прерывания. Делайте выводы.
Мы вас не заставляли связываться с классами и программить на скорость.
либо, чтобы развязаться с обработчиком ... через обработчик устанавливать только флаги, а функции вызывать из loop задействую millis
Вобщем-то, подъем флагов в обработчике - это рекомендованный способ работы с прерываниями.
вас там несколько? ... а ну да, 41...
хотя для правильного ответа на вопрос одного не хватает ;)
Вобщем-то, подъем флагов в обработчике - это рекомендованный способ работы с прерываниями.
вот, наверно 42-й подошел :)
"Во многая знания, многая печали." Либо мне чудится, либо вы сами напридумывали себе проблем. Пока, все что я вижу, пишется спокойно на миллисах и прочих диджиталреад, а вы себе наворотили классов, прерываний, таймеров, про ассемблерные вставки только забыли. ИМХО.
вполне возможно так и вышло
как этот мир еще не самоуничтожился..
хо-хо-хо.... смех безумного профессора...
в классе в вызов функции добавил ссылку на экземпляр класса и изменил соответственно прототипы и указатели
в прерывании проверяем
и сама функция
Вам бы бритвой Оккама побриться...
Выложу-ка скетчик, пока не произошло что-то не предсказуемое :)
Зачем вы вообще классы нагородили - можете объяснить? У вас что, куры из массива timeToFeed[4] не могут покормится?
бу-га-га, сколько умных вокруг... мне вчера некто на этом форуме уже сказал, что с точки зрения компилятора я дурак. а я просто вопрос задал ....
какие вы здесь все милые
классы я нагородил по одной простой причине - я не профессионал, у меня нет берегов :)
мне нравятся классы, я умею их использовать - почему бы и нет?
Да я просто не понимаю - то у вас времени нет, то накрутили с классами так, что не можете разобраться.
В RTC есть аларм - знаете? Вот с массива туда запихивайте время и ждите, пока сработает. Сработал - покрутили сервами, запихали следующее время из массива. Сидите, ждите... До последнего значения дошли - прыгнули на начало. У кур же, надеюсь, нет праздников и кормить их нужно в одно и то же время.
мне нравятся классы, я умею их использовать - почему бы и нет?
У нас уже такой есть - qwone. Хватает одного.
сложность возникла только с millis и прерываниями.
а если серьезно, то да, конечно, можно было, видимо и проще все решить. Но так уж вышло, что я начал с классами, сейчас все переиначивать нет времени (уже ведь работает).
Это, может, смешно прозвучит, но очень прикольное ощущение, когда вот вдруг - ррраз - и массив указателей на экземпляры классов, и это работает :)
мне нравятся классы, я умею их использовать - почему бы и нет?
У нас уже такой есть - qwone. Хватает одного.
Заразный однако.((((
Кстати, про аларм в RTC. Я тут между дел поразмышлял: с ним и EEPROM не нужен. Достаточно найти в массиве с расписанием следующую временнУю точку, значение которой превышает ту, когда RTC дернул за прерывание МК. А если не нашли - установить алармом значение из timeToFeed[0].
Интересный вариант, я когда делал кормушку про использование будильников и не подумал.
А вот и неправда ваша, праздники у них бывают, когда линяют не несуться заразы сколько ни корми. Это постов у них нет.
Это, может, смешно прозвучит, но очень прикольное ощущение, когда вот вдруг - ррраз - и массив указателей на экземпляры классов, и это работает :)
Я сделал проще, в меню можно задавать 3 времени кормления. Этого более чем достаточно для кур. Часы есть, время сравнивается и если куры не кормлены включает кормушку. После выключения кормушки пишем в епром что 1 (2,3) кормление уже было и опционально можно поставить отправку смс. Так что если свет отключат то видно кормили кур или нет.
RTC Library This library allows an enables an Arduino based on SAMD architectures (es. Zero, MKRZero or MKR1000 Board) to control and use the internal RTC (Real Time Clock).
при использовании с Leonardo я получаю
https://www.arduino.cc/en/Tutorial/SimpleRTCAlarm
Этот пример расчитан только на Arduino Zero or MKRZero or MKR1000. Так что, увы, никакие alarm-ы в rtc с моими Leonardo и ds1307 мне не доступны.
Или речь о какой-то другой библиотеке?
...
Собственно, вот ответ:
By looking at DS1307 datasheet it seems that it doesn't support an alarm. Some other RTCs have alarm interrupt output that alerts the controller. I believe that you would have to deal with alarm in the software. You would have to check for alarm condition by comparing the current time with the alarm variable in software.
Так что возвращаемся к нашим граб... клас... бритвам Ока... короче, посмотрим :)
Проблема :)
Мой "наворот с классами" прерасно отрабатывает при включении и ручном изменении времени старта через монитор порта. Но если его оставить на несколько минут, плата наглухо зависает... Риторический вопрос - почему?
Смотрю в сторону
https://platformio.org/lib/show/953/DS1307newAlarms/examples
На DS3231, например, есть алармы: https://github.com/Makuna/Rtc/wiki/RtcDS3231-AlarmOne
На DS1307... сходу только приходит идея читать RTC кажные (60*1000) ms и сравнивать с массивом. Тоже не особо накладно. Костыльно, конечно, выглядит, но это ж 1307. Он еще и идти будет неточно.
то, что не точно, это я уже заметил, но куры простят отклонение в 5-10 минут... да даже в 15.
А про костыли... ну после моих ходуль, да еще и учитывая, что я отключаю питание сервы после выполнения цикла с помощью реле... Костылем больше-костылем мньше.
Попробую запитаться не от USB, а то действительно виснет наглухо. Если не поможет, попробую переписать по-простому... [овации в зале и крики: "наконец-то..." "да, сдрейфил просто..." "эх, мы так и не полетим к звездам..."
Нда... методом исключения выяснил - виснет из-за библиотеки RTC, причем четко через 5 минут...
Я отключил всю перефирию, но все равно через 5 минут плата висла наглухо. Отключил RTC библиотеку, все работает...
И в чем может быть проблема?
Если есть возможность уйти на DS3231 то уходи. Цена вопроса 100р, у меня курятник на ней 8 мес уже работает, ничего не виснет.
А так мало ли, если на макетке все соединения проверь, може где плохой коннект. Да и 5 минут это не плавающая ошибка которая то есть то нет, сделай вывод в сериал времени каждую секунду, будет зависать через 5 минут? Ну тады надо смотреть или другую библиотеку или другой модуль.
Не, врядли. Я отключил весь обвес и просто отключил библиотеку DS1307, весь остальной код остался прежним - и ничего не виснет.
так что я пока пробую другие библиотеки.
даааа.... докатился
Другое дело! Уже по-нашенски, по-ардуински.
Другое дело! Уже по-нашенски, по-ардуински.
Кашу г**м(маслом) не испортишь.
другая библиотека не глючила, но отказывалась работать с моим hi style ...
Пришлось опроститься...
Тут немного отладочных кусков осталось, потом выброшу.
Ну да Конечный автомат используют дураки, настоящие ардуинщики пользуются delay.
ПС:#24 ну это как вариант.
Ну всё, призвали тёмные силы на свою голову... Зачем только классы начали обсуждать.
призрак ходит по европе, классами зовется.
https://habr.com/post/217985/
4 года уже работает. Поток отсекает на ура.
...