Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

projektewise20:cocktailroboter2public:start


Projektdokumentation


Themenbeschreibung

Wir haben einen Cocktailroboter entworfen, dieser soll drei Cocktails mischen können. Die Auswahl der Cocktails soll über einen Bildschirm erfolgen, welcher sich an der Vorderseite des Roboters befindet. Die Cocktails sind durch drei Buttons auswählbar. Durch Auswahl eines Cocktails per Touch werden auf der Rückseite die Ventile für eine bestimmte Zeit geöffnet und anschließend wieder geschlossen, dadurch werden die Zutaten dosiert und man erhält einen fertigen Cocktail. Die Ventile sind an Flaschen befestigt, die auf der Rückseite kopfüber hängen. Durch die Ventile fließt die Flüssigkeit über einen Schlauch in einen Trichter, der sich unter den Flaschen befindet. Dieser Trichter hat ebenfalls einen Schlauch, der die Flüssigkeit nach vorne befördert und in ein Glas fließen lässt.1

Abbildung 1: Skizze

Umsetzung

Unsere Projektarbeit unterteilte sich in die Projektplanung (1), die Programmierung (2), den Bau des Modells sowie die Elektronik (3).

(1) Projektplanung

Wir entwarfen das Modell am Computer und schauten, welche Variante sich am besten umsetzen lässt und am realistischsten ist.

(2) Programmierung

Der Bildschirm, der bereits am Anfang angesprochen wurde, besteht aus dem Display an sich und einem Touchfeld. Rein optisch ist der Unterschied nicht sichtbar, im Programm müssen aber beide „Bauteile“ getrennt voneinander angesprochen werden. Im folgenden Codeausschnitt ist dies verdeutlicht (die Variablen sind die Pins).

Elegoo_TFTLCD* tft = new Elegoo_TFTLCD(A3, A2, A1, A0, A4);
 
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

Die Programmierung erfolgte über Arduino (C++) und sollte es dem Nutzer ermöglichen, per Touch einen voreingestellten Cocktail auszuwählen. Der “Mainbildschirm” ist aus einem Textfeld und den Buttons aufgebaut. 3
Um den Bildschirm zu gestalten, musste immer der Cursor an die entsprechende Koordinate gesetzt, die Textgröße ausgewählt und die Buttons platziert werden. Ein kleiner und simpler Teil ist hier im Codeausschnitt gezeigt:

  tft->setCursor(20, 30);
  tft->setTextSize(2);
  tft->println("Cocktailauswahl");
  tft->setCursor(20, 50);

Die Buttons existieren als vorgefertigte Methoden nicht wirklich und mussten von uns programmiert werden. Zuerst werden sie als Objekte erzeugt und in einem Array gespeichert. Es werden ihnen die Attribute übergeben (Koordinaten, Größe, Farbe, Text).

  buttons[0]->initButton(tft, (tft->width() - BTN_W) / 2,  120, BTN_W, BTN_H, WHITE, BLACK,  WHITE, "CubaLibre", SIZE);
  buttons[1]->initButton(tft, (tft->width() - BTN_W) / 2, 160, BTN_W, BTN_H, WHITE, BLACK, WHITE, "Florida", SIZE);

Dann wird bei jeder Berührung des Displays geprüft, ob diese Koordinate im Button liegt. Dafür wurde ein Objekt „Touchpoint“ erzeugt. Dieses speichert die x- und y-Koordinate. Per if-Abfrage wurde überprüft, ob diese Koordinaten in denen des Buttons liegen. Wenn ja wird „press“ auf true gesetzt. Das hat allerdings noch nicht gereicht, im Anschluss musste getestet werden, welcher der Buttons gedrückt wurde. Dafür wurden in einer if-Schleife alle Buttons durchgegangen und der richtige Button ausgewählt. Wenn dann der richtige Button gedrückt wurde, wurden die in einem Array gespeicherten Zeiten gelesen (Dosierung der Flüssigkeit entspricht zeitgesteuerter Öffnung der Ventile) und somit der Cocktail zusammengestellt.

Hier sieht man nochmal das Array. Jede Zahl ist die Öffnung des jeweiligen Ventils in ms.

int Interactions::cocktailv1[] = {3000, 750, 1500};

Der gesamte Code ist hier nochmal aufgeführt. Er bestand aus drei Dateien. Der normalen .ino-Datei, der .cpp (C++)-Datei und der .h-Datei. In der .h-Datei wurden Variablen angelegt und Methoden definiert, in der .cpp-Datei z.T. programmiert und in der .ino-Datei „ausgeführt“.

Zum Anzeigen hier klicken ⇲

Zum Verstecken hier klicken ⇱

#include "Interactions.h"
#include <Elegoo_TFTLCD.h>
#include <TouchScreen.h>
 
#include <SD.h>
#include <SPI.h>
 
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
 
#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin
#define SD_CS    10  // Chip select line for SD card
 
Elegoo_TFTLCD* tft = new Elegoo_TFTLCD(A3, A2, A1, A0, A4);
 
#define STMPE_CS 8
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
 
void setup() {
 
  Serial.begin(250000);
  tft->begin(0x9341);
  tft->setRotation(2);  
 
  pinMode(Interactions::v1, OUTPUT);
  pinMode(Interactions::v2, OUTPUT);
  pinMode(Interactions::v3, OUTPUT);
 
  Interactions::begin();
  Interactions::mainPage();
 
  Serial.println("Gestartet");
 
}
 
void loop() {
  Interactions::loop();
}
Interactions.ino

Zum Anzeigen hier klicken ⇲

Zum Verstecken hier klicken ⇱

#include "Interactions.h"
#include <TouchScreen.h>
 
#define BTN_W 100
#define BTN_H 20
#define SIZE 1
 
int numVentile = 3;
int Interactions::cocktailv1[] = {3000, 750, 1500};   // Dosierung (Zeit in ms, wie lange jeweiliges Ventil offen ist) ergibt den jeweiligen Cocktail (siehe Arrayname).
int Interactions::cocktailv2[] = {2000, 2000, 4400};
int Interactions::cocktailv3[] = {800, 900, 200};
 
int Interactions::v1 = 31;   // Ventil 1
int Interactions::v2 = 2;   // Ventil 2
int Interactions::v3 = 3;   // Ventil 3
 
bool Interactions::screenChange = false;
 
extern TouchScreen ts;
 
Elegoo_GFX_Button* Interactions::cocktail1 = new Elegoo_GFX_Button();
Elegoo_GFX_Button* Interactions::cocktail2 = new Elegoo_GFX_Button();
Elegoo_GFX_Button* Interactions::cocktail3 = new Elegoo_GFX_Button();
Elegoo_GFX_Button* Interactions::custom = new Elegoo_GFX_Button();
 
Elegoo_GFX_Button* Interactions::buttons[] = {
  cocktail1, cocktail2, cocktail3, custom
};
 
void Interactions::begin() {
  buttons[0]->initButton(tft, (tft->width() - BTN_W) / 2,  120, BTN_W, BTN_H, WHITE, BLACK,  WHITE, "CubaLibre", SIZE);
  buttons[1]->initButton(tft, (tft->width() - BTN_W) / 2, 160, BTN_W, BTN_H, WHITE, BLACK, WHITE, "Florida", SIZE);
  buttons[2]->initButton(tft, (tft->width() - BTN_W) / 2, 200, BTN_W, BTN_H, WHITE, BLACK, WHITE, "Daquiri", SIZE);
  buttons[3]->initButton(tft, (tft->width() - BTN_W) / 2, 280, BTN_W, BTN_H, WHITE, BLACK, WHITE, "Customize", SIZE);
}
 
void Interactions::mainPage() {
  tft->fillScreen(BLACK);
  tft->setTextColor(WHITE);
  tft->setCursor(20, 30);
  tft->setTextSize(2);
  tft->println("Cocktailauswahl");
  tft->setCursor(20, 50);
  tft->setTextSize(1);
  tft->println("Teste einen fertigen Cocktail");
  tft->setCursor(20, 60);
  tft->println("oder erstelle deinen eigenen!");
  tft->setCursor(20, 70);
  for (int i = 0; i < NumButtons; i++) buttons[i]->drawButton();
}
 
void Interactions::customPage() {
  tft->fillScreen(BLACK);
  tft->setTextColor(WHITE);
  tft->setCursor(20, 30);
  tft->setTextSize(2);
  tft->println("Eigene Cocktails");
  tft->setCursor(20, 50);
  tft->setTextSize(1);
  tft->println("Kreiere einen eigenen Cocktail");
  tft->setCursor(20, 60);
  tft->println("oder erstelle deinen eigenen!");
  tft->setCursor(20, 70);
  for (int i = 0; i < NumButtons; i++) buttons[i]->drawButton();
}
 
void Interactions::loop() {
 
  // https://learn.adafruit.com/arduin-o-phone-arduino-powered-diy-cellphone/arduin-o-phone-sketch
  TSPoint p = ts.getPoint();
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
    p.x = map(p.x, TS_MINX, TS_MAXX, tft->width(), 0);
    p.y = (tft->height() - map(p.y, TS_MINY, TS_MAXY, tft->height(), 0));
    // Serial.print("x="); Serial.print(p.x); Serial.print(" y="); Serial.println(p.y);
 
    // Ermitteln, welcher Button gedrückt wurde
    for (int i = 0; i < NumButtons; i++) {
      if (buttons[i]->contains(p.x, p.y)) {
        buttons[i]->press(true);
      } else {
        buttons[i]->press(false);
      }
    }
 
    // Auswerten, welcher Button gedrückt wurde
    for (int i = 0; i < NumButtons; i++) {
      if (buttons[i]->isPressed()) {
        if (buttons[i] == cocktail1) {
          Serial.println("Cocktail 1");
          for(int j = 0; j < numVentile; j++) {
            digitalWrite(30 + j, HIGH);
            delay(cocktailv1[j]);
            Serial.println(cocktailv1[j]);
            digitalWrite(30 + j, LOW); 
          }
        }
        if (buttons[i] == cocktail2) {
          Serial.println("Cocktail 2");
          for(int j = 0; j < numVentile; j++) {
            digitalWrite(30 + j, HIGH);
            delay(cocktailv2[j]);
            Serial.println(cocktailv2[j]);
            digitalWrite(30 + j, LOW); 
          }
        }
        if (buttons[i] == cocktail3) {
          Serial.println("Cocktail 3");
          for(int j = 0; j < numVentile; j++) {
            digitalWrite(30 + j, HIGH);
            delay(cocktailv3[j]);
            Serial.println(cocktailv3[j]);
            digitalWrite(30 + j, LOW); 
          }
        }
        if(buttons[i] == custom) {
          screenChange = true;
        }
      }
    }
  }
}
Interactions.cpp

Zum Anzeigen hier klicken ⇲

Zum Verstecken hier klicken ⇱

#ifndef INTERACTIONS_H
#define INTERACTIONS_H
 
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
 
// Touchscreen
#define MINPRESSURE 10
#define MAXPRESSURE 1000
#define TS_MINX 120
#define TS_MAXX 900
#define TS_MINY 70
#define TS_MAXY 920
 
#define NumButtons 4
 
#include <Arduino.h>
#include <Elegoo_TFTLCD.h> 
 
extern Elegoo_TFTLCD* tft;
 
#define NumMainPageButtons 2
 
class Interactions {
  private:
    static Elegoo_GFX_Button* cocktail1;
    static Elegoo_GFX_Button* cocktail2;
    static Elegoo_GFX_Button* cocktail3;
    static Elegoo_GFX_Button* custom;
    static Elegoo_GFX_Button* buttons[NumButtons]; 
 
  public:
    static void mainPage();
    static void customPage();
    static void begin();
    static void loop();
    static int v1;   // Ventil 1
    static int v2;   // Ventil 2
    static int v3;   // Ventil 3
    static int cocktailv1[];
    static int cocktailv2[];
    static int cocktailv3[];
    static bool screenChange;
};
 
#endif
Interactions.h
Abbildung 2: Code
Abbildung 3: Screen

(3) Bau des Modells + Elektronik

Erst als wir mit der Programmierung fertig waren, machten wir uns aktiv an den Bau, da wir erst sicherstellen wollten, dass das Grundprinzip funktioniert. Am ersten Arbeitstag suchten wir uns die Materialien heraus und fertigten die längliche Grundform an. 4 Dann verstärkten wir die nötigen Stellen mit Kanthölzern, 5 um die Stabilität zu gewährleisten und um bessere Fläche für die Schrauben zu haben. Danach fertigten wir die Seiten sowie die Plattformen für die Ventile und die Flaschenhalterung an. 7 Als das Modell in den Grundzügen fertig war, sprühten wir es rot an, um es optisch aufzuwerten. 6 Der letzte Schritt war dann das Anschließen der Ventile mit den Relais und dem Arduino.8 & 9

MOSFETs (beziehungsweise in unserem Fall Relais) braucht man, da sie Widerstände sind, die durch Spannung gesteuert werden. Sie schützen die Ventile (bzw. Bauteile generell) u.a. vor dem Überhitzen und können elektrische Ströme schalten oder verstärken.

Abbildung 4: Anfänge
Abbildung 5: Gestell
Abbildung 6: Vorderseite
Abbildung 7: Aufbau hinten
Abbildung 8: Ventil
Abbildung 9: Relays
Abbildung 10: Schaltung

Ergebnis

Durch Schwierigkeiten sowohl in der Teamarbeit als auch in der Anpassung unseres Lösungsansatzes kamen wir letztendlich nicht zum eigentlichen Ziel. Jedoch konnten wir die Programmierung für den Display fertig stellen, was der Schwerpunkt unseres Projektes war, genauso wie das Gestell, und wir haben den Automaten auch mit einem Ventil testen können. Anfangs war ja nur ein simpler Knopf geplant. Wir wollten aber ein schönes Menü mit einer Auswahl haben und haben dann ja das Display gewählt. Dieses war wie gesagt Hauptbestandteil unseres Projekts und hat unsere größte Arbeit ausgemacht. Der Erfolg des Projekts hing vom Funktionieren des Displays ab, da wir ohne dieses den Roboter nicht steuern können. Zum Ergebnis hätte nur noch gefehlt, dass der Automat ein bisschen ordentlicher verkleidet wäre und die Kabel versteckt werden, sowie alle Ventile angeschlossen sind. Das Display hat aber perfekt funktioniert und war der anspruchsvollste Teil des Projekts. Daher sind wir darüber froh, dass wir diesen Teil erfolgreich abgeschlossen haben.

Ausblick

Für die Zukunft könnten wir oder andere Gruppen noch ergänzen, dass weitere Flaschen und somit weitere Zutaten angeschlossen werden. Außerdem kann man, was wir schon begonnen hatten, über das Display eigene Cocktails und Dosierungen einstellen. Als letzten Punkt stünde noch die Verschönerung des Gehäuses im Raum. Die rote Farbe, die wir gewählt hatten, ist an sich nicht schlecht, für die Holzstruktur aber eher ungeeignet.

Abbildung 11: Video
Abbildung 12: Video
projektewise20/cocktailroboter2public/start.txt · Zuletzt geändert: 2021/04/23 18:14 von d.golovko