Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Einfach zu bauender Futterautomat für Haustiere

Komponenten und Verbrauchsmaterialien

Arduino Nano R3
Verwenden Sie am besten einen Arduino Nano, wenn Sie ein kompaktes Gehäuse verwenden möchten
× 1
Adafruit Echtzeituhr
× 1
Continuous Rotation Servo
× 1
Müslispender
× 1
Hallsensor UNIPOLAR
× 1
Stabmagnete 3 mm Durchmesser, 5 mm Länge
× 6
Adafruit RGB-Hintergrundbeleuchtung LCD - 16x2
× 1
lcd i2c Rucksack
× 1
Apem-Taster kurzzeitig IP67
× 1
Kleine Druckknöpfe kurzzeitig
× 1
LED (generisch)
× 6
Hammond Multi ABS Gehäuse mit Flansch
× 1

Apps und Onlinedienste

LCD-Zeichengenerator

Über dieses Projekt

Update 06.09.2018

Meine beiden Futterautomaten funktionieren seit 7 Monaten einwandfrei. Wir kümmern uns natürlich tagsüber um unsere Haustiere, aber sie bekommen jetzt zu regelmäßigen Zeiten ihr Futter. Sehr zufrieden mit dem System!

Warum noch ein Tierfutterautomat?

Meine Version eines Tierfutterautomaten basiert auf einem Arduino-Mikrocontroller. Die verwendeten Materialien sind relativ günstig und ich finde es ist einfach zu bauen!

Natürlich gibt es viele Versionen, aber ich konnte kein vollständiges Projekt finden, das bereit war, mit den Funktionen zu bauen, die ich brauchte, also habe ich bei Null angefangen.

Dies sind die Funktionen:

  • *Genaue Portionen* werden jedes Mal geliefert! (durch Verwendung eines Hallsensors)
  • Zwei Fütterungen am Tag
  • *Extrem* genaue Echtzeituhr (Nur mit echtem DS3231-Chip)
  • Sie können eine anstehende Fütterung individuell für beide Timer mit Display und LED-Anzeige abbrechen. Das Abbrechen wird nach Ablauf der eingestellten Zeit automatisch zurückgesetzt.
  • Manuelle Zufuhrfunktion (eine Portion pro Tastendruck)
  • Anpassbare Portionen für jede der beiden Fütterungszeiten (1-9 Portionen)
  • Übersicht aller eingestellten Parameter im Hauptbildschirm
  • Einfaches Menüsystem
  • LED-Anzeige, wenn die Fütterung erfolgreich war
  • Timer für die LCD-Hintergrundbeleuchtung (aus nach 30 Sek., an mit jedem Tastendruck)
  • Zeit und andere Einstellungen werden sicher im Speicher (EEPROM) gespeichert

Demonstrations-VIDEOs:

für Video HIER klicken

ausführlicheres Erklärvideo:HIER klicken

der Pet Feeder in Zeitlupe! HIER klicken

Fotos:

Benötigte Teile:

  • 1x Müslispender (günstig bei Ebay)
  • etwas (Schrott-)Holz, um die Halterung für den Müslispender zu bauen
  • 1x Arduino Uno
  • 1x I2C DS3231 (extrem genau) oder DS1307 Echtzeituhr
  • 1x LCD-Display 16 Zeichen / 2 Zeilen
  • 1x I2C-Rucksack für das LCD-Display
  • 1x setzt Rotationsservo fort (kaufe einen guten!)
  • 1x Honeywell SS443R Unipolarer Hallsensor
  • 1x 12Volt/1 Ampere externes Netzteil (Wandwarze)
  • 7x Druckknöpfe - Momentan
  • 6x LED (2x ROT, 3x GRÜN, 1x GELB)
  • 2x Widerstand 1KΩ (für die roten LEDs)
  • 4x Widerstand 560Ω (für die grünen und gelben LEDs)
  • 1x Gehäuse für die Elektronik
  • Netzsteckerbuchse und Anschlüsse zum Anschluss des externen Servos und des Hallsensors
  • viel, viel HEISSER KLEBER.

Am besten ist es, wenn möglich eine höhere Spannung für das Servo zu verwenden. Mehr Macht! Mein HSR-2645CRH Servo kann 7,4 Volt aufnehmen. Wenn Sie dies auch tun möchten, benötigen Sie:

  • Perfboard
  • LM317T Variabler Spannungsregler
  • 3 Widerstände zum Einstellen der Ausgangsspannung (1KΩ, 150kΩ und 4K7)
  • 2 polarisierte Kondensatoren (220µF, 10µF)
  • Kühlkörper nicht erforderlich, das Servo dreht sich jeden Tag 1-2 Sekunden lang;)

Online finden Sie viele LM317-Rechner.

Der Futterbehälter für Haustiere

Am günstigsten und am einfachsten zu bedienen sind die Müslispender, die Sie in vielen Geschäften und bei Ebay finden. Ich habe bei Ebay einen Doppel-Müslispender für 15 Euro inklusive Versand gekauft (Großbritannien in die Niederlande)

Die Herausforderung bestand darin, ein Reittier für den Feeder zu bauen und das Stöbern im Internet half mir nicht viel, also schaute ich mich in meinem Schuppen um und fand einige schöne Stücke aus Zedernholz.

Das Holz, das den Müslispender aus Kunststoff hält, ist 3 cm dick, damit kein Wackeln! Sie müssen sicher sein, dass das Loch (meine Feeder-Basis ist 86 mm) fest ist, also messen Sie vor dem Bohren! Besser ein kleineres Loch bohren und etwas formen als ein zu großes Loch.

Schauen Sie sich die Fotos an, um eine Vorstellung davon zu bekommen, warum und wie es zusammenpasst.

Der Servo und die Befestigung am Schaufelrad des Spenders

Achten Sie darauf, ein gutes Servo zu kaufen. Zuerst kaufte ich ein MG996R-Servo, das ich für eine kontinuierliche Rotation modifiziert hatte, aber das war Geldverschwendung...

Es MUSS ein kontinuierliches Rotationsmodell SEIN!! Versuchen Sie nicht, ein normales Servo so zu modifizieren, wie ich es getan habe. Es funktionierte nicht annähernd gut genug und beim Stoppen war es nicht sofort.

Video vom Servoversuch:HIER klicken

Die Servoverbindung zum Spenderschaufelrad

Nun war also die Frage:Wie verbinde ich das Servo mit dem Feeder-Schaufelrad? Es schien zunächst der schwierigste Teil des Projekts, aber in Wirklichkeit war es sehr einfach.

Ich nahm ein Stück 5mm Polycarbonat und schnitt mit einer Laubsäge eine runde Scheibe von ca. 6 cm aus. In der Mitte habe ich ein Loch von 8 mm gebohrt (die Dicke der Feederachse. Diese Kunststoffachse ist vom Schaufelrad abnehmbar)

An der Außenseite bohre ich 6 Löcher von 3 mm, die Dicke der Magnete. Diese werden verwendet, um dem Arduino Feedback über die Position des Feeder-Peddle-Rads zu geben.

Da das Schaufelrad 6 Gummipaddel hatte, habe ich 6 Magnete verwendet und sie um den Rand der Polycarbonatscheibe verteilt. 360 Grad geteilt durch 6 ergibt 60 Grad. Die Stabmagnete passen genau hinein.

Der Hallsensor erkennt jeden der 6 Magnete, sodass wir diese Informationen verwenden können, um das Schaufelrad präzise zu positionieren und zu stoppen. Die Variable für die Verzögerungszeit des Servostopps wird verwendet, um eine Verzögerung nach hinzuzufügen Füttern, vor dem Aufhören die Servos. Mit dieser Verzögerung können Sie also die genaue Position des Schaufelrads optimieren. Dies ist wichtig, da bei einer falschen 'Stopp'-Position das Futter das Schaufelrad nicht vollständig verlässt. Auch die Position des Hallsensors kann in Ihrem Fall unterschiedlich sein. Das Optimieren der variablen Zeit der Servostoppverzögerung wird dieses Problem lösen.

Jetzt können wir die Schaufelradachse in die Polycarbonatscheibe kleben.

Das weiße runde Servohorn wird mit 3 M3-Schrauben auf der Polycarbonatscheibe verschraubt. Verwenden Sie einige zusätzliche Muttern als Abstandshalter und ziehen Sie sie nicht zu fest an!

Jetzt ist das Servo Teil der Feeder-Baugruppe, so dass wir es in die Holzhalterung einsetzen und messen können, wie hoch das Holzstück unter dem Servo sein muss.

Der Hallsensor

Der von mir verwendete Hallsensor ist vom Typ UNIPOLAR. Es gibt einen LOW-Ausgang, wenn sich ein Magnet in der Nähe befindet und NICHT die umgekehrte Polarität des Magneten benötigt, um den Ausgang wieder auf HIGH zurückzusetzen. Verwenden Sie also einen unipolaren Hallsensor, viel einfacher.

!!! Der Hallsensor benötigt einen 10KΩ Pullup-Widerstand.

Ich habe einen 0805-SMD-Widerstand direkt über dem Hallsensor angebracht, aber Sie können es auf Ihre Weise tun. Vergiss diesen Widerstand nicht!

Dann habe ich einen alten Kugelschreiber genommen und den Kunststoff als Halterung für den Sensor verwendet.

Das Elektronikgehäuse

Ich habe ein Hammond ABS-Gehäuse mit Flansch verwendet. 120 x 65 x 40 mm

für die externen Anschlüsse habe ich weibliche Präzisionsbuchsen verwendet, nicht die billigen chinesischen. Diese verwende ich sehr oft in all meinen Projekten. Nichts ist schlimmer als schlechte Verbindungen, die (schwer zu findende) Fehler verursachen.

Um die Programmierung des Arduino zu erleichtern, habe ich eine externe FTDI-Verbindung:

Die Frontplatte

Ich habe viel versucht, um eine billige und gut aussehende Frontplatte herzustellen...

Zuerst habe ich mit Mod Podge einen Papierlaserdruck auf die Vorderseite des Gehäuses geklebt und mit weiteren Mod Podge beklebt. --> FEHLER

Dann habe ich es mit einem Klarlack auf Basis einer Polyurethan-Acrylat-Dispersion versucht. Sehr haltbar und stark im getrockneten Zustand. Ich habe das Papier sehr gut auf das Gehäuse geklebt und die Oberseite des Frontplattendrucks lackiert sah sehr gut aus ABER es würde nicht an den Laserdrucker-Tonerteilen des Drucks haften. --> FEHLER

Danach habe ich den Laserdruck der Frontplatte genommen und nur die Oberseite mit Laminier-PCV laminiert. sehr schönes Finish, schützt die Front und hebt die Farben schön an. Dann habe ich das laminierte Papier wieder mit dem Lack auf das Gehäuse geklebt. Meine Idee war, dass der Lack das Papier durchdringt und es wasserabweisend macht. Aber weil ich dickes Papier verwendet habe, das nicht funktionierte und es nass machte, um die Wasserbeständigkeit zu testen, rollte sich das Papier vom Gehäuse ab. --> TEILWEISE FEHL, wird weiter untersucht.

Ein weiterer Versuch:Ich habe spezielle Alufolie gekauft, gemacht für den Laserdruck. 2,25 Euro pro Blatt. Das Ergebnis war super, aber ich wollte den Toner mit einer speziellen Klarsichtfolie schützen. Das war kein Erfolg, da ich die Unvollkommenheiten, wie auf Foto 1 zu sehen, nicht loswerden konnte:

Dann noch ein Versuch mit dem Klarlack zu schützen, dadurch wurde die Alufolie sehr hochglänzend! ABER... auch hier würde der Lack nicht auf dem Toner haften, also habe ich den Lack endgültig aufgegeben...

ENDLICH... Ich habe den Foliendruck ohne Schutz verwendet... Er wird bei häufigem Hantieren Fingerabdrücke zeigen (siehe unter dem ZURÜCK-Button des Fotos oben auf dieser Seite, Unterbringung im Hühnerfutter) also nicht ideal, aber immer noch gut genug für mich.

Mehr Fotos sind anscheinend nicht erlaubt, also...

Das ist alles Leute... haben Spaß!

Code

  • Tierfutter-O-Matic v 1.1 - 20.02.2018
Haustierfutter-O-Matic v 1.1 - 20-02-2018Arduino
v 1.1:Wenn Sie die Tasten Cancel1 oder 2 drücken, wird eine Erklärung angezeigt
// 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 -------- -------------------------------------------------- ------------------- Zu tun:- Fernfütterung? - Feeder-Stoppverzögerung als bearbeitbares Menüelement Letzte Änderung:dinsdag 20 februari 2018 - 17:20:28 FEATURES:- *Genaue Portionen* jedes Mal!(durch Verwendung eines Hall-Sensors) - Zwei Fütterungszeiten, einmal täglich - *Extrem* genaue Echtzeituhr (Nur mit echtem DS3231-Chip) - bevorstehende Fütterung einzeln abbrechen für beide Timer mit Display und LED-Anzeige - Automatisches Zurücksetzen nach Ablauf der Zeit - Manuelle Fütterungsfunktion (eine Portion pro Tastendruck) - Einstellbare Portionen für jede der beiden Fütterungszeiten (1-9 Portionen) - Übersicht aller eingestellten Parameter im Hauptbildschirm - Einfache Menüführung - LED-Anzeige, wenn die Fütterung erfolgreich war - LCD-Hintergrundbeleuchtungs-Timer (aus nach 30 Sek., ein bei jedem Tastendruck) - Backup bei Ausfall des Hall-Sensors - Hass-Sensor-LED blinkt bis Mitternacht, wenn der Hall-Sensor ist fehlgeschlagen - Zeit und andere Einstellungen werden sicher in EEPROM WEBSITES gespeichert:LCD HD44780 Zeichengenerator-Website zum Erstellen eigener LCD-Symbole https://omerk.github.io/lcdchargen/ Arduino-Skizze Großbuchstaben-Kommentargenerator http://patorjk.com /software/taag/#p=display&c=c%2B%2B&f=Big&t=Kommentar Revisionen:zondag 28 januari 2018 - 20:17:10 *////////////////// //////////////////////////////////////////////// /////////////// BENUTZER ÄNDERBARE VARIABLEN /////////////////////////////// //////////////////////////////////////////////// wird für die Hall-Sensor-Fail-Backup-Funktion verwendet. // die Intervallzeit sollte etwas größer als eine 60 Grad sein // Umdrehung des Feeders (eine Portion) #define HALL_SENSOR_BACKUP_VALUE 300 // Verzögerung vor dem Stoppen des Feeder-Servos nach dem Zuführen. Auf diese Weise können Sie // das rotierende Peddle-Rad an der richtigen Position stoppen#define FEEDER_STOP_DELAY 100 // LCD-Hintergrundbeleuchtung auf Zeit nach Tastendruck definieren#define LCD_BACKLIGHT_ON_TIME 30000 // Verlassen des Menüs ohne Speichern nach einer hier in ms eingestellten Zeit#define 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 (in Arduino IDE enthalten)#include  #include // CONNECTIONS://// LCD (I2C-Modul):// SCL - A5// SDA - A4// VCC// GND// Interrupt Hal Sensor Pin#define HALL_SENSOR_PIN 3#define BUTTON_BACK_PIN 4#BUTTON_UP_PIN definieren 5#BUTTON_DOWN_PIN definieren 6#BUTTON_SELECT_PIN definieren 7#BUTTON_CANCEL1_PI definieren 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// Feeder Eingang Servoausgang Pin__#define_Sensor (16x2) 0x27 oder 0x3FLiquidCrystal_I2C lcd(0x3F, 16, 2)); // Einstellungen für die Tastenbibliothek definieren // Eine Entprellzeit von 20 Millisekunden funktioniert normalerweise gut // für taktile Tastenschalter. #define DEBOUNCE_MS 20 // ms erforderlich, bevor wiederholt wird langes Drücken#define REPEAT_FIRST 1000// Wiederholungsintervall für langes Drücken#define REPEAT_INCR 200// Der Einfachheit halber verwenden wir den internen Pullup-Widerstand des Arduino.#define PULLUP true#define INVERT true// Deklarieren Sie die TastenButton 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_MS); Button buttonCancel1 (BUTTON_CANCEL1_PIN, PULLUP, INVERT, DEBOUNCE_MS);Button buttonCancel2 (BUTTON_CANCEL2_PIN, PULLUP, INVERT, DEBOUNCE_MS);Button buttonManual (BUTTON_MANUAL_PIN, PULLUP, INVERT, DEBOUNCE_MS); count (initialisiert, um sicherzustellen, dass es anders ist, wenn // die Skizze beginnt)int lastCount =-1;// Eine variable Zeit, die verwendet wird, um die Wiederholungen für langes Drücken zu steuernunsigned long rpt =REPEAT_FIRST; // verwendet für das Menü time-outunsigned long timeoutValue =0;// Fütterung manuell abbrechen Zeiten variablesboolean manualCancelFeed1 =false;boolean manualCancelFeed2 =false;// Manuelle Fütterungsoptionboolean manualFeed =false;// Futtermenge (in Portionen)int feedAmount1 =1;int feedAmount2 =1;bool feederSuccess =false;// Feeder-Portionenint-Portionen =0;int Turns =0;// input actionsenum {btnSELECT, btnUP, btnDOWN, btnBACK, btnCANCEL1, btnCANCEL2, btnMANUAL, trigTIMEOUT};// Zustände der Finite State Machine (FSM)enum STATES { HAUPT, 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,}; // enthält den aktuellen Zustand of the systemSTATES state;int8_t userInput;int8_t trigger;int Second;int Minute;int Hour;int Day;int Month;int Year;int8_t DoW;String day_of_week;unsigned char address, 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;// verwendet für die Blinkfunktion beim Bearbeiten von Wertenuint32_t blink_interval =500;uint32_t =0;currentintMillis 0;boolean blink_state =false; // verwendet für die Blinkfunktion beim Editieren von Wertenuint32_t SpinningWheel_interval =170;uint32_t SpinningWheel_vorherigerMillis =0;uint32_t SpinningWheel_currentMillis =0;int SpinningWheelSymbol =0;// verwendet für die Hallsensor Fail Backup Funktion// die Intervallzeit sollte etwas größer als ein 60 Grad sein// turn des Feeders (eine Portion).uint32_t hallSensorBackup_interval =HALL_SENSOR_BACKUP_VALUE;uint32_t hallSensorBackup_currentMillis =0;boolean hallSensorFail =false;// verwendet für die LCD-Hintergrundbeleuchtung timeruint32_t lcdBacklight_interval =LCD_BACKLIGHT_ON_currentM;cilliint32_ole =;cilliint32_ole =;cilliint32_ole =; // Definiere benutzerdefinierte Symbole für das LCD-Displaybyte bell_symbol_Char[8] ={ B00100, B01110, B01110, B01110, B11111, B00100, B00000, B00000};byte inverted_one_Char[8] ={ 0b11111, 0b11011, 0b10011, 0b11011, 0b11011, 0b11011 , 0b10001, 0b11111};Byte inverted_two_Char[8] ={ 0b11111, 0b11011, 0b10101, 0b11101, 0b11011, 0b10111, 0b10001, 0b11111};by te arrow_up_Char[8] ={ 0b00100, 0b01110, 0b11111, 0b01110, 0b01110, 0b01110, 0b01110, 0b00000};byte arrow_down_Char[8] ={ 0b00000, 0b01110, 0b01110, 0b01110, 0b01110, 0b11111 0b011001110,Byte invert [8] ={ 0b11111, 0b10001, 0b10101, 0b10001, 0b10111, 0b10111, 0b11111, 0b00000};Byte Backslash_Char[8] ={ 0b00000, 0b10000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00000, 0b00000_Char};8 .Dash ] ={ 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000};volatile boolean hallSensorActivated =false; // Interrupt 1void HallSensorIsr() { hallSensorActivated =true; // Hall-Sensor-LED einschalten digitalWrite(LED_HALL_SENSOR_PIN, HIGH);} // Diese Zeilen werden benötigt, um diese Skizze zu einer C++-Datei zu machen. // Ich verwende sie, weil ich den Code mit dem Atom // Texteditor und dem PlatformIO-Add bearbeite -onvoid HallSensorIsr();void setup();void loop();void change_states();void check_inputs();void Transition(int trigger);void check_alarm();void check_manual_feed();void display_menu_option_set_feedtime1();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 Mitternacht_reset();void display_time();void displayFeedingAmouts();void displayFeedingTimes();void set_feedAmount();void set_date(); ();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_feedamount();void get_feedamount ();void get_feed_time1();void get_feed_time2();void check_RTC();byte decToBcd(bytewert);byte bcdToDec(bytewert);void führende_null(int digits);void blinkFunction();void displaySpinningWheel();void startFeederServo();void stopFeederServo();void activateFeeder(int portion);void check_LcdBacklight();void lcd_backlight_ON();void ledsAndLcdDisplayStartup();void hallSensorCheck();#line 355// ************************** ************************************************* **// SETUPvoid ​​setup () { // aktiviere den lcd-Bildschirm lcd.begin (); // LCD-Hintergrundbeleuchtung einschalten und Hintergrundbeleuchtungs-Aus-Timer starten lcd_backlight_ON (); // I2C Wire.begin() starten; // Hall-Sensor-Eingang zur Erkennung der Drehung des Feeders / Feed-Mengen-Ausgang check pinMode (HALL_SENSOR_PIN, INPUT_PULLUP); pinMode (LED_HALL_SENSOR_PIN, AUSGANG); pinMode (SERVO_OUTPUT_PIN, OUTPUT); pinMode (LED_CANCEL1_PIN, AUSGANG); pinMode (LED_CANCEL2_PIN, AUSGANG); pinMode (LED_SUCCESS1_PIN, AUSGANG); pinMode (LED_SUCCESS2_PIN, AUSGANG); // Standardzustand der LEDs auf OFF setzen 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, dickDash_Char); lcd.createChar(1, bell_symbol_Char); lcd.createChar(2, Backslash_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); // Feeder-Servo in den Standardzustand setzen OFF stopFeederServo (); Wire.begin(); // RTC als Syncprovider einstellen setSyncProvider(RTC.get); // Zeit in Sekunden der Neusynchronisierung mit RTC setSyncInterval(60); // Deaktivieren Sie die Standard-Rechteckwelle des SQW-Pins. RTC.squareWave(SQWAVE_NONE); // Bringen Sie einen Interrupt am Hall-Sensor an (wenn der Eingang LOW wird) // Jede 60-Grad-Drehung der Feeder-Welle sollte der Hall-Sensor // einen Interrupt erzeugen. attachInterrupt (INT1, HallSensorIsr, FALLING); // Anzeigetest ledsAndLcdDisplayStartup (); // Anfangszustand des FSM-Zustands =MAIN; // den gespeicherten Alarmwert aus dem Arduino-Speicher lesen get_feed_time1(); get_feed_time2();}// SETUP beenden// **************************************** ************************************** // LOOPvoid ​​loop () { // Zustände ändern von FSM change_states(); // Eingaben prüfen (Schaltflächen) check_inputs(); // prüfen, ob der Alarm aufgerufen wurde check_alarm(); // prüfen, ob manueller Feed angefordert wurde check_manual_feed(); // um Mitternacht einige Variablen zurücksetzen Mitternacht_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(); brechen; //--------------------------------------- case MENU_EDIT_FEEDTIME1:display_menu_option_set_feedtime1(); brechen; //--------------------------------------- case MENU_EDIT_FEEDTIME2:display_menu_option_set_feedtime2(); brechen; //--------------------------------------- case MENU_EDIT_FEEDAMOUNT:display_menu_option_set_feed_amount(); brechen; //--------------------------------------- case MENU_EDIT_TIME:display_menu_option_set_time(); brechen; //--------------------------------------- case MENU_EDIT_DATE:display_menu_option_set_date(); brechen; //--------------------------------------- case EDIT_FEED_TIME1_HOUR:set_feeding1_time(); brechen; //--------------------------------------- case EDIT_FEED_TIME1_MINUTE:set_feeding1_time(); brechen; //--------------------------------------- case EDIT_FEED_TIME1_ON_OFF:set_feeding1_time(); brechen; //--------------------------------------- case EDIT_FEED_TIME2_HOUR:set_feeding2_time(); brechen; //--------------------------------------- case EDIT_FEED_TIME2_MINUTE:set_feeding2_time(); brechen; //--------------------------------------- case EDIT_FEED_TIME2_ON_OFF:set_feeding2_time(); brechen; //--------------------------------------- case EDIT_FEED_AMOUNT1:set_feedAmount(); brechen; //--------------------------------------- case EDIT_FEED_AMOUNT2:set_feedAmount(); brechen; //--------------------------------------- case EDIT_HOUR:set_time(); brechen; //--------------------------------------- case EDIT_MINUTE:set_time(); brechen; //--------------------------------------- case EDIT_DAY:set_date(); brechen; //--------------------------------------- case EDIT_MONTH:set_date(); brechen; //--------------------------------------- case EDIT_YEAR:set_date(); brechen; //--------------------------------------- }}//******************************************************************************// 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 "); Verzögerung (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"); Verzögerung (2000); lcd.clear(); } brechen; } // 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 "); Verzögerung (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"); Verzögerung (2000); lcd.clear(); } brechen; } // check manual Feed button switch (buttonManual.wasPressed()) { case 1:manualFeed =true; //turn on lcd backlight manually lcd_backlight_ON(); brechen; } // check MENU/SELECT button switch (buttonSelect.wasPressed()) { case 1:userInput =btnSELECT; //turn on lcd backlight manually lcd_backlight_ON(); transition(userInput); brechen; } // check UP button switch (buttonUp.wasPressed()) { case 1:userInput =btnUP; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); brechen; } // check long press UP button switch (buttonUp.wasReleased()) { case 1:long_press_button =false; rpt =REPEAT_FIRST; brechen; } switch (buttonUp.pressedFor(rpt)) { case 1:// increment the long press interval rpt +=REPEAT_INCR; long_press_button =true; userInput =btnUP; transition(userInput); brechen; } // check DOWN button switch (buttonDown.wasPressed()) { case 1:userInput =btnDOWN; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); brechen; } // check long press DOWN button switch (buttonDown.wasReleased()) { case 1:long_press_button =false; rpt =REPEAT_FIRST; brechen; } switch (buttonDown.pressedFor(rpt)) { case 1:// increment the long press interval rpt +=REPEAT_INCR; long_press_button =true; userInput =btnDOWN; transition(userInput); brechen; } // check btnBACK button switch (buttonBack.wasPressed()) { case 1:userInput =btnBACK; transition(userInput); //turn on lcd backlight manually lcd_backlight_ON(); brechen; }}//******************************************************************************// 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; } brechen; //--------------------------------------- case MENU_EDIT_FEEDTIME1:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); Zustand =HAUPT; } // 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(); Zustand =HAUPT; } brechen; //--------------------------------------- case MENU_EDIT_FEEDTIME2:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); Zustand =HAUPT; } // 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(); Zustand =HAUPT; } brechen; //--------------------------------------- case MENU_EDIT_FEEDAMOUNT:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); Zustand =HAUPT; } // 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(); Zustand =HAUPT; } brechen; //--------------------------------------- case MENU_EDIT_TIME:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); Zustand =HAUPT; } // 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(); Zustand =HAUPT; } brechen; //--------------------------------------- case MENU_EDIT_DATE:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); Zustand =HAUPT; } // 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(); Zustand =HAUPT; } brechen; //--------------------------------------- case EDIT_FEED_TIME1_HOUR:// set time-out timer timeoutValue =millis(); // check for time-out 'button' trigger if (trigger ==trigTIMEOUT) { lcd.clear(); Zustand =HAUPT; } // Now check for button triggers...This file has been truncated, please download it to see its full contents.

Schaltpläne

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

Herstellungsprozess

  1. Haustierfutter
  2. DIY Photoshop-Bearbeitungskonsole mit Arduino Nano RP 2040
  3. Arduino Spybot
  4. Blumen - Arduino Nano, CrazyCircuits, DFRobot
  5. Arduino Nano Tetris-Spiel auf hausgemachter 16x8-Matrix
  6. Arduino Tamagotchi Klon - Digitales Haustier
  7. Arduino Nano:Steuerung von 2 Schrittmotoren mit Joystick
  8. Ferngesteuerter Futterautomat für Haustiere
  9. Handheld-Geigerzähler mit Arduino Nano
  10. TFT-Shield für Arduino Nano - Start