Futterautomat
Autoren: Katrin Schöne, Maike Lütkewitte
Betreuer:
→ zurück zur Übersicht: WS 20/21: Angewandte Elektrotechnik (BSE)
Einleitung
Die Studierenden des Masterstudiengangs "Business and Systems Engineering" sollen im Rahmen des Praktikums "Angewandte Elektrotechnik" ein Projekt bearbeiten. Das Projekt beinhaltet folgende Ziele:
- Auslesen von Sensordaten
- Verarbeiten der Daten mithilfe eines Mikrocontrollers
- Ansteuerung eines oder mehrerer Aktoren
Als Anwendungsfall für dieses Projekt wird ein Futterautomat für Katzen entwickelt. Dieser soll jedem Tiere eine individuell festgelegte Futtermenge zur Verfügung stellen. Somit kann auch bei Abwesenheit des Besitzers eine regelmäßige Fütterung der Tiere sichergestellt werden.
Anforderungen
Der Futterautomat soll die folgenden Anforderungen erfüllen:
- Erkennung der unmittelbaren Anwesenheit des Tiers am Futterautomaten sowie Unterscheidung mehrere Tiere voneinander
- Ausgeben der richtigen Futtermenge
- Erkennung und Anzeigen des Füllstands des Futterspeichers
- Schutz vor Überfüllung der Futterschale
- Anpassung der Futtereinstellungen (Menge und Häufigkeit) für jedes Tier
Funktionaler Systementwurf/Technischer Systementwurf
Komponentenspezifikation
Pos. | Anz. | Bezeichnung | Artikel/Link | Im Starterbaukasten enthalten (x) |
---|---|---|---|---|
1 | 1 | Arduino UNO R3 | x | |
2 | 1 | Grove 125 KHz RFID Reader | RFID-Reader | |
3 | 3 | RFID Chip mit 125 kHz Transponder | RFID-Chip | |
4 | 2 | TRCT5000 IR Modul | IR Sensor | |
5 | 1 | Servomotor | x | |
6 | 1 | LCD-Display | x | |
7 | 1 | LED rot | x | |
8 | 1 | LED grün | x | |
9 | 3 | Taster (Schließer) | x | |
10 | 3 | Widerstand 1 kΩ | x | |
11 | 2 | Widerstand 330 Ω | x |
Zusätzlich wird ein Kunststoffgehäuse erstellt.
Umsetzung (HW/SW)
Hardware
Die Hardware besteht aus verschiedenen elektrischen sowie mechanischen Komponenten. Eine Stückliste der elektrischen Bauteile ist unter Komponentenspezifikation zu finden. Im Folgenden soll kurz näher auf die verwendeten Sensoren eingegangen werden.
RFID-Sensor
Die verschiedenen Tiere sollen mittels RFID-Chip am Halsband erkannt und unterschieden werden. Dazu wird ein RFID-Reader am Futternapf benötigt. Für den Anwendungsfall werden RFID-Reader und Transponder mit einer Frequenz von 125 kHz gewählt. Der Grove - 125KHz RFID Reader hat einen maximalen Leseabstand von 7 cm[1]. Durch die Verwendung dieses Readers soll gewährleistet werden, dass eine Futterausgabe erfolgen kann, wenn das Tier nahe genug an den Napf herantritt. Eine direkte Berührung ist nicht erforderlich.
Infrarotsensoren
Zur Füllstandserkennung für den Futterbehälter und den Futternapf wird das KY-033 Linienfolger Modul verwendet. Dieses nutz den IR-Sensor TCRT5000 und gibt via Analogausgang eine Spannung aus. Der im Datenblatt[2] gegebene Arbeitsbereich liegt zwischen 0,2 mm und 15 mm. Unter der Annahme, dass das Futter im zu überwachenden Behältnis gleichmäßig verteilt ist, reicht bei einem in der Wand verbauten Sensormodul eine geringe Reichweite von einigen mm aus, um zu detektieren, ob Futter vorhanden oder nicht vorhanden ist.
Schaltplan
Aufbau auf Steckbrett
Aufbau auf Lochrasterplatine
Um einen möglichst platzsparenden und sicheren Einbau der elektrischen Komponenten in den Futterautomaten zu ermöglichen, wird eine Lochrasterplatine verwendet. Auf dieser Lochrasterplatine werden die Widerstände und Schraubklemmen zur Verbindung mit dem Arduino UNO und den extern gelegenen Bauteilen verschaltet. Der Arduino UNO wird an jeder Seite mit einer Schraubklemmleiste versehen. Diese bietet die Möglichkeit einer deutlich stabileren mechanischen Fixierung der Leitungen im Vergleich zu den Steckbuchsen des Arduino UNO. Die elektrischen Komponenten, wie diverse Aktoren und Sensoren werden an den entsprechenden Stellen im Futterautomat verbaut. Durch Lötverbindungen werden sie mit Leitungen verbunden, welche dann an die Klemmen des Arduino UNO bzw. der Lochrasterplatine angeschlossen werden können.
3D-Modell
Der Futterautomat besteht insgesamt sechs Komponenten. Im Folgendem werden diese im Einzelnen beschrieben. Zu Anfang des Projektes wurden 3D-Modelle auf Basis von ersten theoretischen Überlegungen erstellt. Nach dem Testen der gedruckten Komponenten wurde für einige Komponenten eine überarbeitete Version konstruiert, um diese mechanisch zu verbessern. Für die Erstellung der 3D-Modelle wurde Autodesk Fusion 360 verwendet.
- Technikbehälter
Der Technikbehälter dient zur Aufbewahrung der elektrischen Komponenten. Er hat eine Grundfläche von 140mm x 60mm, eine Höhe von 220mm und eine Wandstärke von 2mm. Auf der Vorderseite werden Aussparungen für den Bildschirm, die drei Taster und die beiden LEDs gelassen. An der Seite befindet sich ein kreisrundes Loch für die Kabel. Damit der Füllstand des Futterbehälters erfasst werden kann, ist auf der Rückseite eine rechteckige Aussparung mit den Maßen 11mm x 5,7mm eingefügt. Damit in Zukunft ein Deckel ergänzt werden kann, existieren auf der oberen Kante zwei Ösen zum Öffnen und Schließen des Deckels.
- Futterbehälter
Der Futterbehälter hat eine Grundfläche von 190mm x 60mm, eine Höhe von 220mm und eine Wandstärke von 2mm. Er wird hinter neben dem Technikbehälter angebracht und hat die Funktion das Futter aufzubewahren. An der oberen Kante befinden sich ebenfalls zwei Ösen, um zukünftig einen Deckel anzubringen. Auf einer Seite befindet sich die gleiche rechteckige Aussparung für den IR-Sensor, wie beim Technikgehäuse, zur Füllstandserfassung. Die Unterseite ist leicht abgeschrägt, damit das Futter nachrutschen kann. Zwischen Grundfläche und Futteröffnung befindet sich ein Abstand von 32,311mm. Der Winkel beträgt 7,305°. Die Futteröffnung ist ein ebener Kreis mit Radius 38,118mm, der sich in der Mitte des Behälters befindet und zu einem Drittel geöffnet ist. Durch diese Öffnung kann später das Futter rutschen.
Verbesserung:
Der Winkel der Schräge ist nicht groß genug gewählt, aufgrund dessen rutscht das Futter nicht nach. Zudem ist der Futterbehälter überdimensioniert. Deswegen wird die Breite auf die Hälfte reduziert. Bei der neuen Version ist eine Seite gerade, sodass der IR-Sensor für die Füllstandserkennung platziert werden kann. Aus diesem Grund befindet sich die Futteröffnung nicht mehr zentral unter dem Futterbehälter, sondern an der geraden Seitenfläche. Außerdem wird der Abstand zwischen Öffnung und Grundfläche auf 117,348mm und der Winkel der Abschrägung auf 62,342° erhöht. Zusätzlich wird aus dem Drittel-Kreis der Öffnung ein Rechteck mit den Maßen 29,5mm x 51,5mm.
- Rutsche
Die Rutsche hat die Funktion, dass das Futter vom Futterbehälter in den Futternapf gelangen kann. Sie hat eine Länge von 160,942mm und eine Maximalhöhe von 92,174mm. Die Rutschfläche ist 36mm breit. An den Seiten befinden sich Erhebungen, die verhindern sollen, dass das Futter zu den Seiten hinausläuft. Die beiden vorderen Stützen sind nicht miteinander verbunden, damit der IR-Sensor zur Füllstandserkennung des Futternapfes ggf. an dieser Stelle verbaut werden kann.
Verbesserung:
Die Seitenabgrenzungen wurden an der Futteraustrittsstelle manuell mithilfe von Pappstücken provisorisch erhöht. Dadurch wird ein Überlaufen des Futters minimiert.
- Stützen
Aufgrund der Höhenlage der Rutsche müssen sich die Behälter ca. 100mm über den Boden befinden. Deshalb werden die Behälter von Stützen getragen. In der Konstruktion werden sowohl Eckstützen als auch Seitenstützen kreiert. Jedoch werden nur die Eckstützen gedruckt, weil diese bereits genügend Stabilität bieten. Die Stützen haben eine Höhe von 150mm. Auf der Höhe von 107,5mm befindet sich eine kleine Plattform mit der Grundfläche 21,416mm x 25mm und einer Dicke von 1,5mm. Diese Plattform dient als Ablagefläche für den Technikbehälter. Aufgrund der Trichterform am unteren Ende des Futterbehälters ist an diesen Eckstützen die Plattform nur 2mm lang. Somit kann der Behälter nicht in Schieflage geraten.
- Futternapf
Der Futternapf hat einen Radius von 75mm und eine Randhöhe von 40mm. Die innere Futterfläche ist leicht abgeschrägt. Somit soll das Futter weiter ins Innere rutschen. An einer Seite befindet sich eine Aussparung für den IR-Sensor auf der Höhe von 27,021mm.
- Futterverschluss
Der Verschluss hat einen Radius von 38,118mm und entspricht dem Futteröffnungsradius. Es wird eine Fläche von 141° bedeckt, somit ist diese circa 20° größer als die Futteröffnung.
Verbesserung:
Aufgrund des Gewichtskraft des Futters verbiegt sich der Verschluss, sodass trotz verschlossener Abdeckung Futter auf die Rutsche fällt. Aus diesem Grund wird ein überarbeiteter Kreis mit einem Radius von 44mm erstellt. Der Kreis erhält eine Aussparung von 120°. Damit bildet der neue Entwurf nahezu das Gegenstück zur ursprünglichen Konstruktion.
Wenn die einzelnen Komponenten zusammengefügt werden, entsteht der folgende Futterbehälter.
Software
Die Software wird in der Entwicklungsumgebung Arduino IDE in der Programmiersprache C++ geschrieben. Die Software ist in zwei Bereiche zu unterteilen: Die Software für das LCD Display und die Eingabe über die Buttons wird zunächst getrennt von der Software zur Steuerung des Hauptprogramms betrachtet.
Includes
Zunächst werden die Bibliotheken eingebunden, die für die Ansteuerung des LCD Displays und des Motors sowie das Auslesen des RFID Readers benötigt werden. Weitere Informationen zu diesen Bibliotheken sind hier zu finden:
LiquidCrystal_I2C
Wire
Servo
SoftwareSerial
Zudem wird die selbstgeschriebene Klasse Katze verwendet.
Die Klasse Katze
Die Klasse Katze enthält alle notwendigen Attribute und Methoden, die im Zusammenhang mit der Funktionsweise des Futterautomaten erforderlich sind.
Hauptprogramm
- Programmablaufplan
Das Arduino Programm besteht aus einer Setup-Funktion, welche einmalig zu Beginn aufgerufen wird, und einer Loop-Funktion, welche im Anschluss an die Setup-Funktion dauerhaft wiederholt wird.
- Setup
void setup() { Serial.begin(9600); SoftSerial.begin(9600); //Setup Motor motor.attach(PinDigitalMotor); motor.write(0); delay(100); //Setup IOs pinConfiguration(); fuellstandLEDSetup(); //Speichern der Katzen in Array katzenListe[0] = mimi; katzenListe[1] = miezie; katzenListe[2] = luna; //Setup LCD lcd.init(); lcd.backlight(); Serial.println("Setup abgeschlossen."); }
- Loop
In der Loop wird zunächst die Anzeige auf dem LCD Display erzeugt. Nähere Informationen zum Display folgen in einem späteren Abschnitt. Im Anschluss wird der Status des Futterbehälters geprüft. Nach der Abfrage geht der Futterautomat in den „Normalbetrieb“.
void loop() { Page_Start(); Page_1(); Page_1_1(); Page_1_2(); Page_2(); Page_2_1(); Page_2_2(); Page_3(); Page_3_1(); Page_3_2(); if (abfrageFuellstandFutterbehaelter() == true) { if (statusFuellstandFutterbehaelter == false) { setFuellstandVoll(); } Normalbetrieb(); Serial.println("Futter voll"); } else { if (statusFuellstandFutterbehaelter == true) { setFuellstandLeer(); } Serial.println("Futter leer"); } delay(200); }
Im Normalbetrieb wird zunächst darauf gewartet, dass über den RFID-Reader Daten empfangen werden. Ist dies der Fall, findet das Auslesen und Auswerten der Daten mithilfe der Funktion auslesenRFID statt. Diese Funktion liefert einen Zeiger auf die mittels RFID Nummer erkannte Katze. Ist die Nummer unbekannt oder mehrdeutig wird ein Nullpointer zurückgegeben. Dieser Fall wird im weiteren Programmverlauf abgefangen. Zum Auslesen der RFID-Nr. wird die unter Grove - 125KHz RFID Reader gegebene Implementierung verwendet.
Katze* auslesenRFID() { Serial.println("Auslesen startet"); unsigned char buffer[64]; int count = 0; if (SoftSerial.available() > 0) { while(SoftSerial.available()) { buffer[count++] = SoftSerial.read(); if(count == 64)break; } Serial.write(buffer, count); // Katze herausfinden int anzahlKorrekt = 0; int indexKorrekt = 0; if (count == 14) { bool nummernVgl[anzahlKatzen];//bool Array mit so vielen Feldern wie Katzen for (int k = 0; k < anzahlKatzen; k++) { nummernVgl[k] = true; } for (int i=0; i < (count-1); i++) { for (int k = 0; k < anzahlKatzen; k++) { unsigned char test[14]; katzenListe[k].getRfidNr().toCharArray(test, 14); if (test[i] != buffer[i]) { nummernVgl[k] = false; } } } for (int k = 0; k < anzahlKatzen; k++) { if (nummernVgl[k] == true) { anzahlKorrekt ++; indexKorrekt = k; } } } count = 0; if(anzahlKorrekt == 1) { return &katzenListe[indexKorrekt]; } else { return nullptr; } } }
Sofern kein Nullpointer zurückgegeben wird, muss geprüft werden, ob für das erkannte Tier eine Futterausgabe erfolgen soll. Die Häufigkeit der Futterausgabe ist über Mindestzeitabstände definiert, die zwischen zwei Ausgaben eingehalten werden müssen. Mögliche Zeitzeitabstände sind 1h, 2h, 6h, 12h und 24h. Diese sind in der Klasse Katze definiert. Jede Katze besitzt eine Integer Variable Häufigkeit, welcher einer der fünf möglichen Zahlenwerte hinterlegt ist.
Zudem besitzt jede Katze eine Variable, welche den Zeitpunkt der letzten Fütterung in ms (Zeit relativ zum Start des Programmstarts) anzeigt. Anhand dieser Zeit und der festgelegten Häufigkeit kann der Zeitpunkt der nächstmöglichen Fütterung in ms berechnet werden. Durch einen Vergleich mit dem aktuellen Zeitpunkt, welcher durch die Funktion millis() ermittelt werden kann, wird geprüft, ob eine Futterausgabe erfolgen soll oder nicht.
Die Zeitwerte in ms werden in unsigned long Variablen gespeichert. Der maximal mögliche Wert dieser Variable beträgt 4.294.967.295 ms. Demnach findet alle 4,97 Tage ein Überlauf statt und das Zählen beginnt erneut bei 0. Um die Reaktion auf diesen Überlauf zu definieren, werden die möglichen Stellungen aus aktuellem Zeitpunkt, letztem Fütterungszeitpunkt und mindestens zu erreichendem neuem Fütterungszeitpunkt ausgewertet.
Vergleich der Zeitpunkte | Schlussfolgerung bzgl. Futterausgabe |
---|---|
Letzte Fütterung <= Nächstmögliche Fütterung < Aktueller Zeitpunkt | Futterausgabe |
Letzte Fütterung < Aktueller Zeitpunkt < Nächstmögliche Fütterung | Keine Futterausgabe |
Nächstmögliche Fütterung < Letzte Fütterung < Aktueller Zeitpunkt | Keine Futterausgabe |
Nächstmögliche Fütterung < Aktueller Zeitpunkt < Letzte Fütterung | Futterausgabe |
Aktueller Zeitpunkt < Nächstmögliche Fütterung < Letzte Fütterung | Keine Futterausgabe |
Aktueller Zeitpunkt < Letzte Fütterung < Nächstmögliche Fütterung | Futterausgabe |
if (hungrigeKatze != nullptr) { Serial.print("Katze erkannt: "); Serial.println(hungrigeKatze->getKatzenname()); // Hier Überprüfung einfügen, ob das Tier Futter haben soll unsigned long minMillisFuetterungOk; if (hungrigeKatze->getLetzteFuetterung() == 0) { minMillisFuetterungOk = 0; } else { minMillisFuetterungOk = hungrigeKatze->getLetzteFuetterung() + ((unsigned long)hungrigeKatze->getHaeufigkeit() * (unsigned long)60 * (unsigned long)60 * (unsigned long)1000); } if (((hungrigeKatze->getLetzteFuetterung() <= minMillisFuetterungOk) && (minMillisFuetterungOk < millis())) || ((minMillisFuetterungOk < millis()) && (millis() < hungrigeKatze->getLetzteFuetterung())) || ((millis() < hungrigeKatze->getLetzteFuetterung()) && (hungrigeKatze->getLetzteFuetterung() < minMillisFuetterungOk))) { Serial.println("Katze hungrig"); if (abfrageFuellstandFutternapf() == false) { //Wert der Futtermenge übergeben futterausgabe(hungrigeKatze->getMenge()); hungrigeKatze->setLetzteFuetterung(millis()); Serial.println("Fütterung"); } } else { Serial.println("Katze satt"); } }
Ist die minimale Wartezeit zwischen den Futterausgaben überschritten und ist der Futternapf nicht voll, so erfolgt die Futterausgabe. Dazu wird der Motor um 90° gedreht. Abhängig von der auszugebenden Futtermenge verweilt er eine bestimmte Zeit in dieser Position. Dann dreht er in die Ausgangsposition zurück. Der entsprechende Programmcode ist Servo Write entnommen.
void futterausgabe(int Menge) { motor.write(90); int delaytime = Menge*200 ; delay(delaytime); // Delay ist abhängig von gewünschter Futtermenge motor.write(0); delay(100); }
Komponententest
Ergebnis
Zusammenfassung
Lessons Learned
Projektunterlagen
Projektplan
Projektdurchführung
YouTube Video
Weblinks
Literatur
→ zurück zur Übersicht: WS 20/21: Angewandte Elektrotechnik (BSE)