Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Alimentador de animais de estimação fácil de construir

Componentes e suprimentos

Arduino Nano R3
Melhor usar um Arduino Nano se quiser usar uma caixa compacta
× 1
Adafruit Real Time Clock
× 1
Servo de rotação contínua
× 1
Distribuidor de cereais
× 1
Sensor Hall UNIPOLAR
× 1
Ímãs de haste, medidor de 3 mm, comprimento de 5 mm
× 6
Adafruit RGB Backlight LCD - 16x2
× 1
mochila lcd i2c
× 1
Botão de pressão do apem IP67 momentâneo
× 1
Botões pequenos momentâneos
× 1
LED (genérico)
× 6
Caixa Hammond Multi ABS com flange
× 1

Aplicativos e serviços online

Gerador de caracteres LCD

Sobre este projeto









Atualização 06/09/2018


Meus dois comedouros para animais de estimação estão funcionando perfeitamente nos últimos 7 meses. Cuidamos de nossos animais de estimação durante o dia, é claro, mas agora eles se alimentam em horários regulares. Muito feliz com o sistema!





Por que outro comedouro para animais de estimação?


Minha versão de um alimentador de animais de estimação é baseada em um microcontrolador Arduino. Os materiais usados ​​são relativamente baratos e acho que é fácil de construir!

Claro que existem muitas versões, mas não consegui encontrar um projeto completo, pronto para construir com os recursos que eu precisava, então comecei do zero.

Estes são os recursos:
  • * Porções precisas * entregues a cada vez! (usando um sensor Hall)
  • Duas refeições ao dia
  • * Relógio em tempo real extremamente * preciso (somente com chip DS3231 genuíno)
  • Você pode cancelar uma alimentação futura individualmente para ambos os temporizadores com display e indicador LED. O cancelamento é redefinido automaticamente após o tempo definido.
  • Função de alimentação manual (uma porção por pressionamento de botão)
  • Porções ajustáveis ​​para cada um dos dois tempos de alimentação (1-9 porções)
  • Visão geral de todos os parâmetros definidos na tela principal
  • Sistema de menu fácil de navegar
  • Indicação de LED se a alimentação foi bem-sucedida
  • Temporizador de luz de fundo do LCD (desligado após 30 segundos, ligado ao pressionar qualquer botão)
  • A hora e outras configurações são armazenadas com segurança na memória (EEPROM)





VÍDEOS de demonstração:


para o vídeo clique AQUI

vídeo de explicação mais detalhada:clique AQUI

o Pet Feeder em ação em câmera lenta! Clique aqui





Foto:





Peças necessárias:

  • 1 dispensador de cereais (barato no Ebay)
  • alguma (sucata) de madeira para construir o suporte do dispensador de cereais
  • 1x Arduino Uno
  • 1x I2C DS3231 (extremamente preciso) ou relógio em tempo real DS1307
  • 1x display LCD de 16 caracteres / 2 linhas
  • 1 mochila I2C para a tela LCD
  • 1x Servo de rotação contínua (compre um bom!)
  • 1 sensor Honeywell SS443R Unipolar Hall
  • Fonte de alimentação externa 1x 12Volts / 1 Amp (verruga de parede)
  • 7 botões de pressão - momentâneo
  • 6x LED (2x VERMELHO, 3x VERDE, 1 AMARELO)
  • 2x resistor 1KΩ (para o led vermelho)
  • 4x resistor 560Ω (para os leds verde e amarelo)
  • 1x invólucro para eletrônicos
  • plugue de alimentação fêmea e conectores para conectar o servo externo e o sensor hall
  • muitos e muitos HOT GLUE.

É melhor usar uma tensão mais alta para o servo, se possível. Mais poder! Meu servo HSR-2645CRH pode levar 7,4 Volts, portanto, se você também quiser fazer isso, você precisa de:
  • Perf board
  • Regulador de tensão variável LM317T
  • 3 resistores para definir a tensão de saída (1KΩ, 150kΩ e 4K7)
  • 2 capacitores polarizados (220µF, 10µF)
  • dissipador de calor não necessário, o servo irá girar 1-2 segundos por dia;)

Online você pode encontrar muitas calculadoras LM317.





O contêiner de ração para animais de estimação


Os mais baratos e fáceis de usar são os distribuidores de cereais que você pode encontrar em muitas lojas e no Ebay. Comprei um distribuidor duplo de cereais no Ebay por 15 euros, incluindo remessa (do Reino Unido para a Holanda)

O desafio era fazer um suporte para o comedouro e procurar na internet não me ajudou muito, então dei uma olhada no meu galpão e encontrei alguns pedaços lindos de madeira de cedro.

A madeira que segura o distribuidor de cereais de plástico tem 3 cm de espessura, por isso não balança! Você precisa ter certeza de que o orifício (minha base de alimentação é de 86 mm) está apertado, então meça antes de perfurar! Melhor fazer um orifício menor e modelá-lo um pouco do que um orifício muito grande.

Olhe para as fotos para ter uma ideia de por que e como elas se encaixam.





O servo e o acessório para a roda de pás do distribuidor


Certifique-se de comprar um bom servo. Primeiro comprei um servo MG996R que modifiquei para rotação contínua, mas foi um desperdício de dinheiro ... Depois comprei um servo de qualidade, no meu caso o Servo HSR-2645CRH

TEM QUE SER um modelo de rotação contínua !! Não tente modificar um servo normal como eu fiz. O desempenho não foi bom o suficiente e, ao parar, não foi imediato.

vídeo do ensaio do servo:clique AQUI

A conexão Servo para a roda de pás do distribuidor

Então agora ficava a pergunta:como conectar o servo à roda de pás do alimentador? A princípio pareceu a parte mais difícil do projeto, mas na verdade foi muito simples.

Peguei um pedaço de Policarbonato de 5mm e com uma serra trasteira cortei um disco redondo de cerca de 6 cm. No centro fiz um furo de 8 mm (a espessura do eixo de alimentação. Este eixo de plástico é removível da roda de pás)

No exterior faço 6 furos de 3 mm, espessura dos ímanes. Eles são usados ​​para fornecer feedback ao Arduino sobre a posição da roda de venda do alimentador.

Como a roda de pás tinha 6 pás de borracha, usei 6 imãs e divido-os ao redor da borda do disco de policarbonato. 360 graus divididos por 6 são 60 graus. Os ímãs da haste se encaixam perfeitamente.

O sensor Hall detectará cada um dos 6 ímãs para que possamos usar essa informação para posicionar e parar com precisão a roda de pás. A variável de tempo de atraso de parada do servo é usada para adicionar um atraso após alimentação, antes de parar o servo. Portanto, com esse atraso, você pode ajustar a posição exata da roda de pás. Isso é importante porque se a posição de 'parar' estiver errada, o feed não sairá completamente da roda de pás. Além disso, a posição do sensor Hall pode ser diferente no seu caso. Ajustar o tempo variável de atraso da parada do servo resolverá isso.

Agora podemos colar o eixo da roda de pás no disco de policarbonato.

A buzina servo redonda branca é aparafusada no disco de policarbonato com 3 parafusos M3. use algumas porcas extras como espaçadores e não aperte demais!

Agora o servo faz parte do conjunto do alimentador para que possamos colocá-lo no suporte de madeira e medir a altura que o pedaço de madeira deve ter sob o servo.





O sensor Hall


O sensor Hall que usei é do tipo UNIPOLAR. Ele dará uma saída BAIXA se um ímã estiver próximo e NÃO precisa da polaridade reversa do ímã para redefinir a saída para ALTO novamente. Portanto, use um sensor Hall Unipolar, muito mais fácil.

!!! O sensor Hall precisa de um resistor pull up de 10KΩ.

Eu instalei um resistor SMD 0805 bem em cima do sensor Hall, mas você pode fazer do seu jeito. Não se esqueça desse resistor!

Então peguei uma caneta esferográfica velha e usei o plástico como suporte para o sensor.





A caixa de eletrônicos


Usei uma caixa de ABS Hammond com flange. 120 x 65 x 40 mm

para as conexões externas usei conectores soquete fêmea de precisão, não os chineses baratos. Eu uso muito isso em todos os meus projetos. Nada pior do que conexões ruins causando falhas (difíceis de encontrar).

Para tornar a programação do Arduino mais fácil, tenho uma conexão FTDI externa:





O painel frontal


Tentei fazer um painel frontal barato e bonito de várias maneiras ...

Primeiro usei o Mod Podge para colar uma impressão a laser de papel na frente da caixa e cobri-la com mais Mod Podge. -> FALHA

Depois experimentei um verniz transparente, à base de dispersão de acrilato de poliuretano. Muito durável e forte quando seco. Colei muito bem o papel na caixa e o envernizamento da parte superior da impressão do painel frontal ficou muito bom, MAS não iria aderir às partes do toner da impressora a laser da impressão. -> FALHA

Depois disso, tirei a impressão a laser do painel frontal e laminei apenas a parte superior com laminação de pcv. Acabamento muito bonito, protegendo a frente e levantando lindamente as cores. Então, novamente, colei o papel laminado na caixa com o verniz. Minha ideia era que o verniz iria permear o papel tornando-o resistente à água. Mas, como usei papel grosso que não funcionou e o deixei úmido para testar a resistência à água, o papel enrolou para fora da caixa. -> FALHA PARCIALMENTE, a ser investigada posteriormente.

Outra tentativa:comprei papel alumínio especial, feito para impressão a laser. 2,25 euros por folha. O resultado foi ótimo, mas eu queria proteger o toner com uma película especial transparente. Não deu certo porque não consegui me livrar das imperfeições da foto 1:

Em seguida, outra tentativa de proteger com o verniz incolor, Fez o alu foil muito alto brilho! MAS ... de novo, o verniz não iria aderir ao toner, então desisti do verniz permanentemente ...

FINALMENTE ... usei a impressão em alumínio sem proteção ... Ela mostrará estampas vinger quando manuseada com frequência (veja embaixo do botão VOLTAR da foto no topo desta página, abrigando a ração de frango) então não é ideal, mas ainda assim é bom Para mim chega.

Aparentemente, mais fotos não são permitidas ...

Isso é tudo pessoal ... tem divertido!

Código

  • Pet Feed-O-Matic v 1.1 - 20-02-2018
Pet Feed-O-Matic v 1.1 - 20-02-2018 Arduino
v 1.1:pressionar os botões Cancel1 ou 2 irá mostrar uma explicação
 // c ++ stuff ... // # include  // # line 1 // # line 1 "/ Users / Erik / Documents / PlatformIO / Projects / 180202-151127-uno / src / Pet_Feeder_1_1_ENG.cpp "/ * _ _ / \ | | (_) / \ _ __ __ | | _ _ _ _ __ ___ / / \ \ | '__ / _` | | | | | '_ \ / _ \ / ____ \ | | | (_ | | | _ | | | | | | (_) | / _ / \ _ \ _ | \ __, _ | \ __, _ | _ | _ | | _ | \ ___ / _____ _ ______ _ | __ \ | | | ____ | | | | | __) | __ | | _ | | __ ___ ___ __ | | ___ _ __ | ___ / _ \ __ | | __ / _ \ / _ \ / _` | / _ \ '__ | | | | __ / | _ | | | __ / __ / (_ | | __ / | | _ | \ ___ | \ __ | | _ | \ ___ | \ ___ | \ __, _ | \ ___ | _ | Erik de Ruiter -------- -------------------------------------------------- ------------------- O que fazer:- alimentação remota? - atraso de parada do alimentador como item editável do menu última alteração:dinsdag 20 de fevereiro de 2018 - 17:20:28 CARACTERÍSTICAS:- * Porções precisas * de cada vez! (Usando um sensor Hall) - Dois tempos de alimentação, uma vez por dia - * Extremamente * Relógio em tempo real preciso (somente com chip DS3231 genuíno) - Cancele a alimentação futura individualmente para ambos os temporizadores com display e indicador LED . Reinicializado automaticamente após o tempo ter passado. - Função de alimentação manual (uma porção por pressionamento de botão) - Porções ajustáveis ​​para cada um dos dois tempos de alimentação (1-9 porções) - Visão geral de todos os parâmetros definidos na tela principal - Menu fácil de navegar sistema - Indicação de LED se a alimentação foi bem-sucedida - Temporizador de luz de fundo do LCD (desligado após 30 segundos, ligado ao pressionar qualquer botão) - Backup no caso de falha do sensor Hall - LED do sensor Hass piscará até meia-noite se o sensor Hall falhou - O tempo e outras configurações são armazenados com segurança em WEBSITES EEPROM:Site do gerador de caracteres LCD HD44780 para fazer seus próprios símbolos lcd https://omerk.github.io/lcdchargen/ Esboço do Arduino Gerador de comentários com letras grandes http://patorjk.com / software / taag / # p =display &c =c% 2B% 2B &f =Big &t =Revisões de comentários:zondag 28 januari 2018 - 20:17:10 * ////////////////// //////////////////////////////////////////////////////// /////////////// VARIABLES ALTERÁVEIS PELO USUÁRIO //////////////////////////////////// //////////////////////////////////////////////////////// usado para a função de backup de falha do sensor Hall.// o intervalo de tempo deve ser um pouco maior que 60 graus // volta do alimentador (uma porção) #define HALL_SENSOR_BACKUP_VALUE 300 // atraso antes de parar o servo do alimentador após a alimentação. Desta forma, você pode // deixar a roda giratória parar na posição certa # definir FEEDER_STOP_DELAY 100 // luz de fundo lcd ligada após pressionar um botão # definir LCD_BACKLIGHT_ON_TIME 30000 // sair do menu sem salvar após um intervalo de tempo definido aqui em ms # definir MENU_TIMEOUT_VALUE 7000 //////////////////////////////////////////////////// ////////////////////////////////////// https:// github.com/fdebrabander/Arduino-LiquidCrystal-I2C- library # include  // https:// github.com/JChristensen/Button#include  // http:// github.com/JChristensen/DS3232RTC#include  // http:// www.arduino.cc/playground/Code/Time#include  // http:// arduino.cc/en/Reference/Wire (incluído com Arduino IDE) #include  #include  // CONEXÕES://// LCD (módulo I2C):// SCL - A5 // SDA - A4 // VCC // GND // pino do sensor hal de interrupção # define HALL_SENSOR_PIN 3 # define BUTTON_BACK_PIN 4 # define BUTTON_UP_PIN 5 # define BUTTON_DOWN_PIN 6 # define BUTTON_SELECT_PIN 7 # define BUTTON_CANCEL1_PI N 8 # define BUTTON_CANCEL2_PIN 9 # define BUTTON_MANUAL_PIN 10 # define LED_CANCEL1_PIN A0 # define LED_CANCEL2_PIN A1 # define LED_SUCCESS1_PIN A2 # define LED_SUCCESS2_PIN A3 // saída do servo do alimentador Pino # define SERVO_OUTPUT_PIN 12 // Entrada do sensor Hall 13 // LED_PHALL_ define endereço (16x2) 0x27 ou 0x3FLiquidCrystal_I2C lcd (0x3F, 16, 2); // define as configurações da biblioteca de botões // Um ​​tempo de debounce de 20 milissegundos geralmente funciona bem // para botões táteis. # Define DEBOUNCE_MS 20 // ms necessário antes de repetir em pressionamento longo # define REPEAT_FIRST 1000 // intervalo de repetição para pressionamento longo # define REPEAT_INCR 200 // Para manter as coisas simples, usamos o resistor pullup interno do Arduino. # define PULLUP true # define INVERT true // Declara o buttonsButton buttonSelect (BUTTON_SELECT_PIN, PULLUP , INVERT, DEBOUNCE_MS); Button buttonUp (BUTTON_UP_PIN, PULLUP, INVERT, DEBOUNCE_MS); Button buttondown (BUTTON_DOWN_PIN, PULLUP, INVERT, DEBOUNCE_MS); Button buttonBack (BUTTON_BACK_PIN, PULLUP, INVERT, DEBOUNCE); Botão buttonCancel1 (BUTTON_CANCEL1_PIN, PULLUP, INVERT, DEBOUNCE_MS); Botão buttonCancel2 (BUTTON_CANCEL2_PIN, PULLUP, INVERT, DEBOUNCE_MS); Botão buttonManual (BUTTON_MANUAL_PIN, PULLUP, INVERT, DEBOUNCE_MS); count (inicializado para garantir que seja diferente quando // o esboço começar) int lastCount =-1; // Um ​​tempo variável que é usado para conduzir as repetições para pressionamentos longos rpt =REPEAT_FIRST; // usado para o menu time-outunsigned long timeoutValue =0; // cancelamento manual dos tempos de alimentação variáveisboolean manualCancelFeed1 =false; boolean manualCancelFeed2 =false; // Feed manual optionboolean manualFeed =false; // Quantidade de feed (em porções) int feedAmount1 =1; int feedAmount2 =1; bool feederSuccess =false; // feeder porçõesint porções =0; int voltas =0; // inserir actionsenum {btnSELECT, btnUP, btnDOWN, btnBACK, btnCANCEL1, btnCANCEL2, btnMANUAL, trigTIMEOUT}; // Estados da máquina de estados finitos (FSM) enum STATES {MAIN, MENU_EDIT _FEEDTIME1, MENU_EDIT_FEEDTIME2, MENU_EDIT_FEEDAMOUNT, MENU_EDIT_TIME, MENU_EDIT_DATE, MENU_EDIT_SETTINGS, EDIT_FEED_TIME1_HOUR, EDIT_FEED_TIME1_MINUTE, EDIT_FEED_TIME1_ON_OFF, EDIT_FEED_TIME2_HOUR, EDIT_FEED_TIME2_MINUTE, EDIT_FEED_TIME2_ON_OFF, EDIT_FEED_AMOUNT1, EDIT_FEED_AMOUNT2, EDIT_HOUR, EDIT_MINUTE, EDIT_DAY, EDIT_MONTH, EDIT_YEAR, EDIT_SERVO_STOP_DELAY, EDIT_SERVO_BACKUP_DELAY,}; // Mantém o estado atual do estado do sistemaSTATES; int8_t userInput; int8_t trigger; int Segundo; int Minuto; int Hora; int Dia; int Mês; int Ano; int8_t DoW; String day_of_week; endereço char não assinado, data; int testt =0; int feed_time1_hour; int feed_time1_minute; bool feed_time1_active =false; bool alarm1Activated =false; int feed_time2_hour; int feed_time2_minute; bool feed_time2_active =false; bool alarm2Activated =false; // usado para a função de piscar ao editar valoresuint32_t blink_interval_interval =500cill_till; 0; boolean blink_state =false; // usado para o função de piscar ao editar valoresuint32_t spinningWheel_interval =170; uint32_t spinningWheel_previousMillis =0; uint32_t spinningWheel_currentMillis =0; int spinningWheelSymbol =0; // usado para a função de backup de falha de sensor Hall // o intervalo de tempo deve ser um pouco maior que uma volta de 60 graus // do alimentador (uma parte) .uint32_t hallSensorBackup_interval =HALL_SENSOR_BACKUP_VALUE; uint32_t hallSensorBackup_currentMillis =0; booleano hallSensorFail =false; // usado para o lcd backlight timeruint32_t lcdBacklight_intervalo_temporal_total_interval; lcdBacklight_interval; // Definir símbolos personalizados para o display de LCD byte bell_symbol_Char [8] ={B00100, B01110, B01110, B01110, B11111, B00100, B00000, B00000}; byte inverted_one_Char [8] ={0b11111, 0b11011, 0b10011, 0b1101111, 0b11011, 0b11011, 0b11011 , 0b10001, 0b11111}; byte inverted_two_Char [8] ={0b11111, 0b11011, 0b10101, 0b11101, 0b11011, 0b10111, 0b10001, 0b11111}; por te arrow_up_Char [8] ={0b00100, 0b01110, 0b11111, 0b01110, 0b01110, 0b01110, 0b01110, 0b00000}; byte arrow_down_Char [8] ={0b00000, 0b01110, 0b01110, 0b01110, 0b01110, inverted_Charted_Charted 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, inverted_Charted_Charte [8]. [8] ={0b11111, 0b10001, 0b10101, 0b10001, 0b10111, 0b10111, 0b11111, 0b00000}; byte barra invertida_Char [8] ={0b00000, 0b10000, 0b01000, 0b00100Dash, 0b000b00010, 0b00001 ] ={0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000}; volátil booleano hallSensorActivated =false; // Interromper 1void HallSensorIsr () {hallSensorActivated =true; // liga o sensor Hall LED digitalWrite (LED_HALL_SENSOR_PIN, HIGH);} // Essas linhas são necessárias para tornar este esboço um arquivo C ++.// Eu o uso porque edito o código com o editor de texto Atom // e o add PlatformIO -onvoid HallSensorIsr (); void setup (); void loop (); void change_states (); void check_inputs (); void transição (disparador interno); void check_alarm (); void check_manual_feed (); void display_menu_option_set_feedtime2 (); void display_menu_option_set_feed_amount (); void display_menu_option_set_time (); void display_menu_option_set_date (); void midnight_reset (); void display_time (); void displayFeedingAmouts (); void display_menu_option_set_date (); void midnight_reset (); void display_time (); void displayFeedingAmouts (); void display_menu_option_set_date (); void midnight_reset (); void display_time (); void displayFeedingAmouts (); void displayFeeding_time (); void set_feeding1_time (); void set_feeding2_time (); void get_time (); void get_date (); void write_time (); void write_date (); void write_feeding_time1 (); void write_feeding_time2 (); void write_time (); void write_date (); void write_feeding_time1 (); void write_feeding_time2 (void write_feedam); void write_feedam (); void get_feed_time1 (); void get_feed_time2 (); void check_RTC (); byte decToBcd (byte val); byte bcdToDec (byte val); void lead_zero (dígitos inteiros); void blinkFunction (); void displaySpinningWheel (); void startFeederServo (); void stopFeederServo (); void activateFeeder (int porções); void check_LcdBacklight (); void lcd_backlight_ON (); void ledsAndLcdDisplayStartup (); void hallSensorCheck (); # linha 355 // ************************** ************************************************** ** // SETUPvoid ​​setup () {// ativa a tela lcd lcd.begin (); // liga a luz de fundo do lcd e inicia o cronômetro de desligamento da luz de fundo lcd_backlight_ON (); // inicia I2C Wire.begin (); // entrada do sensor Hall para detectar a rotação do alimentador / verificação da quantidade de alimentação pinMode (HALL_SENSOR_PIN, INPUT_PULLUP); pinMode (LED_HALL_SENSOR_PIN, OUTPUT); pinMode (SERVO_OUTPUT_PIN, OUTPUT); pinMode (LED_CANCEL1_PIN, OUTPUT); pinMode (LED_CANCEL2_PIN, OUTPUT); pinMode (LED_SUCCESS1_PIN, OUTPUT); pinMode (LED_SUCCESS2_PIN, OUTPUT); // define o estado padrão dos LEDs para OFF digitalWrite (LED_CANCEL1_PIN, LOW); digitalWrite (LED_CANCEL2_PIN, LOW); digitalWrite (LED_SUCCESS1_PIN, LOW); digitalWrite (LED_SUCCESS2_PIN, LOW); digitalWrite (LED_HALL_SENSOR_PIN, LOW); lcd.createChar (0, thickDash_Char); lcd.createChar (1, bell_symbol_Char); lcd.createChar (2, barra invertida_Char); lcd.createChar (3, inverted_p_Char); lcd.createChar (4, inverted_one_Char); lcd.createChar (5, inverted_two_Char); lcd.createChar (6, arrow_up_Char); lcd.createChar (7, arrow_down_Char); // define o servo do alimentador para o estado padrão OFF stopFeederServo (); Wire.begin (); // definir RTC como o Syncprovider setSyncProvider (RTC.get); // tempo em segundos de ressincronização com RTC setSyncInterval (60); // Desabilita a onda quadrada padrão do pino SQW. RTC.squareWave (SQWAVE_NONE); // Anexar uma interrupção no sensor Hall (quando a transferência torna-se BAIXA) // sempre que gira 60 graus do eixo do alimentador, o sensor Hall // deve gerar uma interrupção attachInterrupt (INT1, HallSensorIsr, FALLING); // teste de exibição ledsAndLcdDisplayStartup (); // Estado inicial do estado FSM =MAIN; // lê o valor do alarme armazenado na memória do Arduino get_feed_time1 (); get_feed_time2 ();} // Fim da CONFIGURAÇÃO // *************************************** **************************************** // LOOPvoid ​​loop () {// alterar estados de FSM change_states (); // verifica as entradas (botões) check_inputs (); // verifique se o alarme foi chamado check_alarm (); // check if manual feed was requsted check_manual_feed(); // at midnight, reset some variables midnight_reset(); // check connection RTC check_RTC(); // Check the Hall sensor function hallSensorCheck(); // check if lcd backlight must be turned off check_LcdBacklight();}// End of LOOP// ******************************************************************************// ******************************************************************************// ******************************************************************************// ******************************************************************************//******************************************************************************// Finite State Machinevoid change_states(){ // states switch (state) { //--------------------------------------- case MAIN:display_time(); displayFeedingAmouts(); displayFeedingTimes(); pausa; //--------------------------------------- case MENU_EDIT_FEEDTIME1:display_menu_option_set_feedtime1(); pausa; //--------------------------------------- case MENU_EDIT_FEEDTIME2:display_menu_option_set_feedtime2(); pausa; //--------------------------------------- case MENU_EDIT_FEEDAMOUNT:display_menu_option_set_feed_amount(); pausa; //--------------------------------------- case MENU_EDIT_TIME:display_menu_option_set_time(); pausa; //--------------------------------------- case MENU_EDIT_DATE:display_menu_option_set_date(); pausa; //--------------------------------------- case EDIT_FEED_TIME1_HOUR:set_feeding1_time(); pausa; //--------------------------------------- case EDIT_FEED_TIME1_MINUTE:set_feeding1_time(); pausa; //--------------------------------------- case EDIT_FEED_TIME1_ON_OFF:set_feeding1_time(); pausa; //--------------------------------------- case EDIT_FEED_TIME2_HOUR:set_feeding2_time(); pausa; //--------------------------------------- case EDIT_FEED_TIME2_MINUTE:set_feeding2_time(); pausa; //--------------------------------------- case EDIT_FEED_TIME2_ON_OFF:set_feeding2_time(); pausa; //--------------------------------------- case EDIT_FEED_AMOUNT1:set_feedAmount(); pausa; //--------------------------------------- case EDIT_FEED_AMOUNT2:set_feedAmount(); pausa; //--------------------------------------- case EDIT_HOUR:set_time(); pausa; //--------------------------------------- case EDIT_MINUTE:set_time(); pausa; //--------------------------------------- case EDIT_DAY:set_date(); pausa; //--------------------------------------- case EDIT_MONTH:set_date(); pausa; //--------------------------------------- case EDIT_YEAR:set_date(); pausa; //--------------------------------------- }}//******************************************************************************// Check INPUTSvoid check_inputs(){ // first check if timeout has occurred if ( millis() - timeoutValue> MENU_TIMEOUT_VALUE ) { userInput =trigTIMEOUT; transition(userInput); } // check state of buttons buttonSelect.read(); buttonUp.read(); buttonDown.read(); buttonBack.read(); buttonManual.read(); buttonCancel1.read(); buttonCancel2.read(); // check manual cancel Feed1 button switch (buttonCancel1.wasPressed()) { case 1:// invert variable value (true to false and vise versa) manualCancelFeed1 =!manualCancelFeed1; //turn on lcd backlight manually lcd_backlight_ON(); // message when Cancel1 button is pressed if (manualCancelFeed1 ==1) { lcd.clear(); lcd.setCursor (0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #1"); lcd.setCursor(0, 1); lcd.print("cancelled once "); atraso (2000); lcd.clear(); } else if (manualCancelFeed1 ==0) { lcd.clear(); lcd.setCursor (0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #1"); lcd.setCursor(0, 1); lcd.print("canceling undone"); atraso (2000); lcd.clear(); } pausa; } // check manual cancel Feed2 button switch (buttonCancel2.wasPressed()) { case 1:// invert variable value (true to false and vise versa) manualCancelFeed2 =!manualCancelFeed2; //turn on lcd backlight manually lcd_backlight_ON(); // message when Cancel1 button is pressed if (manualCancelFeed2 ==1) { lcd.clear(); lcd.setCursor (0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #2"); lcd.setCursor(0, 1); lcd.print("cancelled once "); atraso (2000); lcd.clear(); } else if (manualCancelFeed2 ==0) { lcd.clear(); lcd.setCursor (0, 0); // 0123456789012345 - LCD screen character counter lcd.print("Upcoming Feed #2"); lcd.setCursor(0, 1); lcd.print("canceling undone"); atraso (2000); lcd.clear(); } pausa; } // check manual Feed button switch (buttonManual.wasPressed()) { case 1:manualFeed =true; //turn on lcd backlight manually lcd_backlight_ON(); pausa; } // check MENU/SELECT button switch (buttonSelect.wasPressed()) { case 1:userInput =btnSELECT; //turn on lcd backlight manually lcd_backlight_ON(); transition(userInput); pausa; } // check UP button switch (buttonUp.wasPressed()) { case 1:userInput =btnUP; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); pausa; } // check long press UP button switch (buttonUp.wasReleased()) { case 1:long_press_button =false; rpt =REPEAT_FIRST; pausa; } switch (buttonUp.pressedFor(rpt)) { case 1:// increment the long press interval rpt +=REPEAT_INCR; long_press_button =true; userInput =btnUP; transition(userInput); pausa; } // check DOWN button switch (buttonDown.wasPressed()) { case 1:userInput =btnDOWN; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); pausa; } // check long press DOWN button switch (buttonDown.wasReleased()) { case 1:long_press_button =false; rpt =REPEAT_FIRST; pausa; } switch (buttonDown.pressedFor(rpt)) { case 1:// increment the long press interval rpt +=REPEAT_INCR; long_press_button =true; userInput =btnDOWN; transition(userInput); pausa; } // check btnBACK button switch (buttonBack.wasPressed()) { case 1:userInput =btnBACK; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); pausa; }}//******************************************************************************// Check for state transition triggervoid transition(int trigger){ switch (state) { //--------------------------------------- case MAIN:// set time-out timr timeoutValue =millis(); if (trigger ==btnSELECT) { lcd.clear(); state =MENU_EDIT_FEEDTIME1; } else if (trigger ==btnBACK) { //lcd.clear(); //state =ALARM1_AND_2_TIME; } pausa; //--------------------------------------- case MENU_EDIT_FEEDTIME1:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { //no action, this is the first menu } else if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_FEEDTIME2; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_FEED_TIME1_HOUR; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } pausa; //--------------------------------------- case MENU_EDIT_FEEDTIME2:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_FEEDTIME1; } else if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_FEEDAMOUNT; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_FEED_TIME2_HOUR; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } pausa; //--------------------------------------- case MENU_EDIT_FEEDAMOUNT:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_FEEDTIME2; } else if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_TIME; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_FEED_AMOUNT1; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } pausa; //--------------------------------------- case MENU_EDIT_TIME:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_FEEDTIME2; } if (trigger ==btnDOWN) { lcd.clear(); state =MENU_EDIT_DATE; } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_HOUR; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } pausa; //--------------------------------------- case MENU_EDIT_DATE:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers if (trigger ==btnUP) { lcd.clear(); state =MENU_EDIT_TIME; } else if (trigger ==btnDOWN) { //no action, end of menu items! } if (trigger ==btnSELECT) { lcd.clear(); state =EDIT_DAY; } if (trigger ==btnBACK) { lcd.clear(); state =MAIN; } pausa; //--------------------------------------- case EDIT_FEED_TIME1_HOUR:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); state =MAIN; } // Now check for button triggers...This file has been truncated, please download it to see its full contents.

Esquemas

Arduino based Pet Feeder I used Arduino IDE 1.8.2. BE CAREFUL NOT TO HAVE TWO VERSIONS OF THE SAME LIBRARIES IN YOUR LIBRARIES FOLDER!! arduino_pet_feeder_final_eng_v1_0-ino_hex_libraries_dsoo0HscCr.zip

Processo de manufatura

  1. Alimentos para animais de estimação
  2. Console de edição DIY Photoshop usando Arduino Nano RP 2040
  3. Arduino Spybot
  4. Flores - Arduino Nano, CrazyCircuits, DFRobot
  5. Jogo Arduino Nano Tetris em Matriz 16x8 caseira
  6. Arduino Tamagotchi Clone - Animal de estimação digital
  7. Arduino Nano:Controle 2 motores de passo com joystick
  8. Alimentador de animais de estimação com controle remoto
  9. Contador Geiger portátil com Arduino Nano
  10. TFT Shield para Arduino Nano - Iniciar