Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektewise20:cocktailroboter1public:start

Projektdokumentation Cocktail'o'mat

Projektbeschreibung

Der Cocktail'o'mat ist ein Automat der verschiedene Cocktails mischt und serviert. Der Benutzer kann sich ein Cocktail über eine Menüsteuerung auswählen, welchen der Cocktail'o'mat dann ohne weiteres zutun des Benutzers serviert. Dazu muss der Automat die einzelnen Bestandteile eines Drinks zusammenfügen, mischen und in ein Glas füllen können. Die Zutaten aus denen der Automat einen Drink mischen kann sind Flüssigkeiten, Zucker und Eis. Diese Zutaten sollten das mischen der meistens Drinks ermöglichen. Das Menü wird auf einem 16×2 LCD Bildschirm angezeigt und mit Knöpfen bedient.

Abbildung 1: Cocktail'o'mat mit einzelnen Systemgruppen



Methoden/Umsetzung:

Der Automat besteht im wesentlichen aus zwei Baugruppen, wobei in jeder Baugruppe drei Subsysteme verbaut sind. Die obere Baugruppe besteht aus dem Deckel des Automaten und der Kiste, welche die Flaschen hält. In dieser Baugruppe sind die Ventilsteuerung, der Zuckerspender und die Bedienung verbaut. Die untere Baugruppe ist der Rahmen und hat den Eisspender, den Mischbecher und den Kippmechanismus zum Befüllen eines Glases verbaut. Mithilfe eines Kistenverschlusses ist es optimal durchführbar diese Baugruppen zu trennen, um leere Flaschen auszutauschen.

Abbildung 2: Kistenverschluss

Unsere Mindestanforderungen an den Automaten waren, dass er mehrere verschiedene Flüssigkeiten in ein Gefäß füllen kann und das dem Benutzer mindestens zwei Drinks zur Auswahl stehen.

Was unser Roboter können sollte:

  • Zucker und Eis hinzufügen
  • Den Drink mixen
  • Drink-Auswahl per LCD und Drehregler

Einzelne Abschnitte zur Beschreibung von Details der einzelnen Systembestandteile


▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

1. Ventil Steuerung

Die Ventile sind mit Silikonschlauch an einem Belüftungsdeckel montiert. Wenn keine Spannung auf dem Ventil ist, bleibt es geschlossen und der Flüssigkeitsbehälter dicht. Das Arduino regelt über Mosfets die Ventile, so können die sechs Ventile individuell geschaltet werden. Silikonschlauch ist auch verwendet um die Flüssigkeiten in den Shaker-Becher zu leiten, ein Flaschenhals dient als Befestigung der Schläuche.

Abbildung 3: Ventil Aufbau

Für die Ventilsteuerung haben wir eine Funktion namens Ventil() geschrieben. Unsere ursprüngliche Idee war eine Ventil-Funktion zu schreiben, bei welcher man mithilfe eines Parameters das zu öffnende Ventil auswählen kann. Da wir auch den Anspruch hatten, dass sich mehrere oder alle Ventile gleichzeitig öffnen lassen mussten wir die Ventil()-Funktion so programmieren, das jedes geöffnete Ventil einen eigenen Timer hat. Das kann man umsetzen indem man Pointer definiert. Pointer sind eine Variable die für eine andere Variable, Funktion oder Klasse einsteht, also ich schreibe in mein Programm den Pointer, aber wenn das Programm von dem Arduino ausgeführt wird, dann wird die Variable, Funktion oder Klasse ausgeführt, auf welche der Pointer zeigt. Wir haben es auch geschafft alles so zu programmieren, das der Code ohne Fehler kompiliert, aber leider funktioniert die Timer-Bibliothek welche wir benutzten anscheinend nicht richtig mit einem Pointer oder einem Pointer-Array und somit hat auch der Code nicht funktioniert. Da wir keine Fehlermeldungen hatten um nach Lösungen zu suchen haben wir den einfacheren Weg gewählt und für jedes Ventil eine eigene Funktion geschrieben. So konnten die verschiedenen Timer-Namen direkt in den Code schreiben und konnten auf Pointer verzichten. Das war aber leider auch nicht die einzige Hürde die uns diese Timer-Bibliothek bereitet hat, denn wenn ein Timer abläuft, dann wird TimerName.justFinished einmal auf True gesetzt. Allerdings funktioniert diese .justFinished Funktion nur in loop(), womit man für jede Funktion die einen Timer benutzt etwas Code in loop() schreiben muss um die Funktion die die Funktion ausführt entweder zu beenden oder man muss die Funktion so schreiben, dass man sie bei Ablauf des Timers nochmal mit ähnlichen Parametern aufruft und sie ihre Funktion weiter ausführen kann. Beide Optionen sind unserer Meinung nach relativ unschön, aber wir haben keinen besseren Weg gefunden und wir haben beide Optionen für verschiedene Funktionen benutzt. Bei der Ventil Funktion haben wir uns dazu entschieden die Funktion mit veränderten Parametern nochmals aufzurufen, da wir denn Code der Funktionen möglichst an einer Stelle im Sketch sammeln wollten.

Ventil Funktion:
void Ventil1(int ms, bool schliessen) {
    if (schliessen == false) {
      VentilDelay1.start(ms);
      digitalWrite(2, HIGH);
      Ventiloffen[1] = true;
      //schliessen = true;
    }
    if (schliessen == true) {
      digitalWrite(2, LOW);
      Ventiloffen[1] = false;
      Serial.print("Ventil1 ");Serial.println(" zu");
    }
  }
Der Interrupt nach ablauf des Timers:
if (VentilDelay1.justFinished()) {                    // Da die Pointer nicht funktioniert haben haben wir für jedes Ventil eine eigene if-funktion bei ablauf des Timers benutzt.
    Serial.println("Timer1 Abgelaufen");
    Ventil1(0, true); // Der zweite parameter sorgt dafür das das Ventil wieder geschlossen wird.
    //Ventiloffen[i] = false;
    //Serial.print("i: "); Serial.println(i);
  }

Die Version mit einem Pointer-Array ist in dem Zip-Archiv bei den alten Versionen


▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

2. Zuckerspender

Der Zucker wird separat von den Flüssigkeiten mithilfe eines Flaschenhalses in den Shaker befördert. Dieser befindet sich genau über dem Shaker, so dass der Zucker optimal in diesen fällt. Eine Mühle die durch einen Elektromotor angetrieben wird, dosiert die Menge.

Da der Motor von dem Zuckerspender 9V Spannung benötigt gibt die Zuckerspender-Funktion Zucker() ein PWM-Signal auf Pin 6 aus, welches die Spannung am Motor von 12V auf 9V senkt. Wenn der Zuckerspender-Timer abläuft wird Pin 6 wieder auf LOW gesetzt.

Abbildung 4: Zuckerspender


▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

3. Bedienung

Die Bedienung des Automaten erfolgt über vier Taster und ein LCD-Display. Ursprünglich wollten wir ein Menü programmieren in dem sich alle Parameter verändern und einstellen lassen, aber uns hat es nicht gefallen, dass man mehrere Knopfdrücke braucht um den Mischvorgang auszulösen. Deswegen haben wir uns entschieden die Rezepte direkt auf die Tasten zu legen. Das bedeutet das der Automat sofort anfängt ein Drink zuzubereiten, wenn man eine Taste drückt. Zusätzlich wollten wir trotzdem noch ein Menü programmieren, welches sich öffnet wenn man eine der Tasten gedrückt hält. In dem Menü hätte man dann die Zusammenstellung des Rezeptes, von der Taste die man gedrückt hat, verändern können. Leider hatten wir am Ende keine Zeit mehr um dieses Menü zu implementieren. Die Tasten selbst funktionieren genau wie die Tasten auf einem LCD-Keypad-Shield, sie sind alle über Wiederstände an Pin A6 angeschlossen und wenn eine Taste gedrückt wird liegt an Pin A6 eine bestimmte Spannung an. Diese Spannung wird vom Arduino gemessen und mithilfe von getButton() der richtigen, gedrückten, Taste zugeordnet. Jeder Taste ist in loop() ein Rezept zugeordnet, welches diese auslöst und in welchem gespeichert ist wie die verschiedenen Funktionen ausgeführt werden müssen um den richtigen Drink zu mischen. Die Rezepte haben wir als Funktion umgesetzt, damit loop() übersichtlich bleibt und da man auf diesem Weg einfach die Datei mit den Rezepten austauschen kann ohne an dem Code etwas zu verändern.

Die Tasten Funktion:
#define BUTTON_RIGHT_ANALOG_VALUE   60
#define BUTTON_UP_ANALOG_VALUE      250
#define BUTTON_DOWN_ANALOG_VALUE    485
#define BUTTON_LEFT_ANALOG_VALUE    650
unsigned long buttonSampleTime = 0;
int getButton () {
  if (millis() - buttonSampleTime >= 20) {
    buttonSampleTime = millis();
 
    int button = analogRead(BUTTON_PIN);
    //Serial.print("button :");Serial.println(button);
    if (button < BUTTON_RIGHT_ANALOG_VALUE) return 0;
    if (button < BUTTON_UP_ANALOG_VALUE)    return 1;
    if (button < BUTTON_DOWN_ANALOG_VALUE)  return 2;
    if (button < BUTTON_LEFT_ANALOG_VALUE)  return 3;
    if (button > BUTTON_LEFT_ANALOG_VALUE)  return 4;
 
  }
}
Das Starten der Rezepte in loop():
btn = getButton();
  if (btn == 0) {                     //Diese if-funktionen starten die Rezept funktion nachdem die dazugehörige Taste gedrückt wurde.
    if (Rezeptlauft[0] == false) {
      Rezept1();
      lcd.clear();
      lcd.print("Mixe Rezept1");
      //Serial.println(Rezeptlauft[0]);
    }
  }
Abbildung 5: Bedienelement


▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

4. Mischen

Für die Funktion des Mischens haben wir ursprünglich überlegt, ob wir den ganzen Behälter schütteln können oder ob wir uns eine möglichkeit ausdenken um die Zutaten zu verrühren. Glücklicherweise hatte Johannes die Idee einen Selbstrührenden Trinkbecher zu benutzen. Da dieser ein fertiges Produkt ist mussten wir uns keine komplizierte Konstruktion ausdenken die den Shaker abdichtet, waren Motor und Rühraufsatz schon im Becher befestigt und der Becher lässt sich einfach zerlegen und in der Spülmaschine waschen.

Abbildung 6: Shaker-Becher

Verschiedene Flüssigkeiten werden mit Hilfe der Ventilsteuerung, durch Schläuche aus den Behältnissen, in den Mixer dosiert. Der Mixer verfügt über einen Elektromotor auf den ein Rührelement angebracht ist. Nach dem die gewünschten Flüssigkeiten eingefüllt sind, wird der Elektromotor aktiviert und die Flüssigkeiten werden durchrührt und ordentlich gemixt.

Abbildung 7: Shaker-Becher Waschen und Mixen

Der Code für den Mixer funktioniert genau so wie der Code für den Zuckerspender, mit dem Unterschied, dass das PWM-Signal auf Pin 11 ausgegeben wird und das die Spannung auf 3V gesenkt wird. Sowohl die Mixer-Funktion Mixer() als auch Zucker() und alle anderen Funktionen des Cocktailomaten schreiben während sie ablaufen eine Variable auf HIGH, um zu verhindern, dass die Funktion nochmal ausgeführt werden kann während sie bereits läuft. Des weiteren schreiben alle Funktionen die eine Funktion des Cocktailomaten steuern eine zweite Funktion HIGH, wenn sie ihre Aufgabe erfüllt haben. Diese Variablen sorgen dafür, dass die Rezepte warten können bis eine Funktion fertig ist bevor die nächste ausgeführt wird.


▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

5. Kippen

Der Shaker-Becher ist in einem MDF Rahmen befestigt, welcher mit einem Servo verbunden ist, der fest in einem Gestell sitzt. Auf der anderen Seite wird der Rahmen durch eine Maschinenschraube, als Achse, beweglich gestützt. Wenn der Shaker fertig gemischt hat, wird der Servo aktiviert und der Shaker Becher in eine Richtung gekippt. Nun läuft das gemischte Getränk in eine dafür gemachte Aussparung, in dem das Glass steht.

Abbildung 8: Shaker-Becher kippmechanismus

Da .justFinished nur in loop() funktioniert haben wir zuerst beinahe die gesamte Funktion nach loop() verschoben, aber jetzt wird Shakerleeren() jedes mal wenn der Timer ShaServDelay() gestartet und somit konnten wir den Code in der Funktion lassen.

Die Shakerleeren()-Funktion starte zuerst den Timer und bewegt dann den Servo jedes mal wenn der Timer abläuft einen Schritt weiter, bis der Shaker in seiner ausguss-Position ist.
In dieser Position wartet die Funktion ein paar Zyklen und bewegt sich dann Schritt für Schritt wieder zurück in die Ausgangsposition. Shakerleeren() hat nur einen Parameter, welcher die länge von dem Timer vorgibt. Damit kann also die Geschwindigkeit des ganzen Vorganges verändert werden.


▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀

6. Eis

Das Eis wird ebenfalls über eine Rampe („Magazin“) angeordnet. Über einen Servo wird je ein Eiswürfel angeschoben, wodurch er in den Behälter rutscht.

Die Eis-Funktion kontrolliert einen Servo, welcher pro Eiswürfel einmal den Weg freigibt. Damit die richtige Anzahl an Eiswürfel ausgegeben wird zählt die Funktion mit wie viele Eiswürfel sie bereits Ausgegeben hat und beendet sich sobald die gewünschte Anzahl an Eiswürfeln erreicht ist.

Abbildung 9: Eisspender mit Rampe und PET Behältnis


Technische Daten, Bauteile, Pins, etc.

Bauteil Quantität Preis
Ventile 6 9,69€
Shaker 1 9,99€
Salzmühle für Zucker 1 11,99€
Rampe für Eis 1 11,69€
leerer 11er Kasten 1 -
großer Servomotor 1 1,05€
kleiner Servomotor 1 0,99€
Kistenverschluss 2 2,25€
Plastik Schlauch 1 3,38€
1L PET Flaschen 7 0,55€
MDF 1 -
Holz-Dübel 7 1,80€
CA-Kleber 1 2,99€
Lack 2 4,95€
O-Ringe 6 10,99€
Metall Strohhalm 6 6,98€
40x40mm Holz 1 -
kleiner Metallwinkel 2 0,25€
100 Ohm Wiederstand 8 *
1000 Ohm Wiederstand 8 *
Dioden 8 *
Mosfet 8 -
Breadboard 1 *
Arduino Nano 1 1,79€
16x2 LCD Bildschirm 1 1,27€
Knöpfe 4 *
Kabel 1 -
2.54 mm Pin female 57 *
2.54 mm Pin male 27 *
(Elektronik Set) 1 *17,99€
Gummipropfen 6 -
Abbildung 10: Schaltplan der Hauptplatine
Pin Funktion
D2-D5,D7-D8 Ventile 1-6
D6 Zucker Spender
D9 Kipp-Servo
D10 Eis-Servo
D11 Mixermotor
A4 LCD SDA
A5 LCD SCL
A6 Taster-Knöpfe
GND 12V GND
Vin 12V Plus

Ergebnis und Diskussion

Der Cocktail'o'mat ist fertig gebaut, aber nicht fertig optimiert und es gibt noch einige Möglichkeiten die Programmierung zu erweitern. Wir haben alle wichtigen Funktionen verbaut und funktional Programmiert, aber wir hatten nicht die Zeit um alle Timings so zu schreiben, dass alle Abläufe schön flüssig sind und wir hatten leider auch nicht mehr genug Zeit um wirklich alle Funktionen zu schreiben die der Automat können sollte. Die offensichtlichsten Punkte an denen der Automat verbessert werden könnte sind zum einen das fehlende Menü welches Kurz in dem Abschnitt über die Bedienung beschrieben wird und die fehlende Füllstands-Kontrolle.

Abbildung 11: Löcher müssen fein vorgebohrt werden und reißen trotzdem. Ganz rechts zu erkennen, Lack zieht ungleichmäßig ein.

Fazit und Ausblick


Für ca. 80€ ist es möglich sein eigenen DIY Cocktailautomaten zu bauen. Unser Arbeitsprozess ging zügig voran, es gab hin und wieder Schwierigkeiten, welche aber durch intensive Diskussionen gelöst werden konnten. So haben die Holz und Löt-arbeiten ziemlich spaß gemacht und waren schnell fertig, wohingegen das Programmieren länger dauerte. Oft hatten wir auch Glückliche Zufälle, z.B. dass die Bierkiste genau unser Maß hat und wir so direkt eine Lösung als Flaschenhalterung fanden; Oder dinge rumliegen hatten die wir für den Bau verwenden konnten.

Code und Rohdaten

projektewise20/cocktailroboter1public/start.txt · Zuletzt geändert: 2021/04/07 19:31 von d.golovko