HILFE !!! Cocktailmaschine mit Arduino Uno

Hallo, ich bin gerade dabei eine Cocktailmaschine zu bauen,
leider fehlt es mir noch an den nötigen Programmierkenntnissen :frowning:
Deshalb wollte ich fragen ob mir bitte jemand beim Sketch helfen könnte.
Ich habe 6 Pumpen und 6 Taster, dabei steht jeder der 6 Taster für einen anderen Cocktail
Z.b.
Taster 1 = Mai Tai
das bedeutet:
Pumpe 1 für 30 Sek 20ml
Pumpe 2 für 15 Sek 20ml
Pumpe 4 für 15 Sek 20ml
Pumpe 5 für 15 Sek 20ml
Pumpe 6 für 60 Sek 80ml
= 160ml
Alle Pumpen sollten gleichzeit an sein, für die beschriebene Zeit.

Taster 2 = Golden Girl

Pumpe 3 = 30 Sek
Pumpe 4 = 30 Sek
Pumpe 6 = 60 Sek
= 160ml

usw.

Ich habe 6 verschiedene Getränke, für jede Flasche eine Pumpe.

Ich benötige:

  • 6 Eingänge für die Taster
  • 6 Ausgänge für die Pumpen
    Wenn ich wahlweise Taster 1 bis 6 betätige, müssten verschiedene Ausgänge für eine gewisse Zeit auf high gesetzt werden,
    nach Ablauf dieser Zeit wieder auf Lo

Wie gesagt mir fehlt es leider an der Programmierung und ich würde mich rießig freuen wenn mir jemand helfen könnte.

Hier sieht man mein Projekt:

Danke
Viele Grüße
Thomas

Sind die Pumpen schon vorhanden?
Was für eine Spannungsversorgung benötigen die?

Du könntest das so machen, dass Du die Pumpen z.B. mit einem Relais schaltest.
Ein Relais ist bekannt?
Das Relais wird einfach mit einem Ausgang des Arduinos angesteuert.

Den Schaltzustand eines Tasters kannst Du ja einfach am Arduino abfragen.

Gleichzeitig solltest Du noch ein "Sicherheitsfeature" einstellen:
Nach dem Drücken von einem der Knöpfe muss die gesamte Anlage, für die Dauer des Abfüllvorgangs, für weitere Eingangssignale gesperrt sein. Sonst drückt jemand "Cocktail A", die Anlage startet, er drückt noch mal und die Anlage startet erneut -> Glas läuft über.

Einfacher wäre definitiv eine Schwerkraft-Befüllung.
Also Flaschen verkehrt herum (Öffnung nach unten) in eine Halterung.
Der Flaschenverschluss hat dann einen Anschluss für einen Schlauch. Der schlauch geht einfach in ein Ventil, welches Du mit dem Arduino schaltest.
So sparst Du Dir die ganzen Pumpen und eventuell auch die Relais.
Außerdem sieht das ja ganz geil aus, wenn der Flaschenhals in einer "Kiste" verschwindet und aus der Kiste kommt dann der fertige Cocktail raus.
Gleichzeitig sieht man, wie sich die Flasche langsam leert und man könnte die sogar noch beleuchten. Könnte nen schickes Ding werden.

Hi,
also die Pumpen sind Vorhanden (Peristaltikpumpen) mit 24V Spannungsversorgung.
Das ganze schalte ich über Schalttransitoren und das funktioniert auch schon soweit prima.
Mir gehts lediglich um die Programmierung, ich habe zwar die nötigen Elektronischen-Kentnisse
da ich Elektroniker bin. Aber ich habe halt leider noch nie was programmiert.

Ja Das Programm sollte bei z.B. Cocktail A durchlaufen und erst dann sollte wieder eine
erneute Eingabe möglich sein.

Danke

Software technisch habe ich genau das hier erklärt:
http://forum.arduino.cc/index.php?topic=183896.msg1364127#msg1364127

Ist aber nicht getestet, also versuche es selbst zu verstehen

Also das Dir das jemand programmiert, wird glaub ich nicht klappen :stuck_out_tongue:

Aber helfen wird man Dir sicher!

Funktionieren wird das Ganze auf jeden Fall. Relais schalten und Taster auswerten kann der Arduino mit links.

Am Besten kaufst Du Dir einfach einen Arduino und legst los. Das ist nicht besonders schwer zu lernen.
Es gibt viele Beispiele dazu. Einige in der Arduino-Software und einige auch hier: http://arduino.cc/en/Tutorial/HomePage

Auch ohne Vorkenntnisse, hast Du das Programm ruckzuck in ein paar Stunden zusammen.

ich hab schon einen arduino uno r3 hier.
Ich erwarte ja nicht das mir dass einer komplett programmiert,
aber vielleicht kann man mir ein Beispiel für einen Ablauf (1 Cocktail) geben
Den rest erarbeite ich mir dann schon zusammen.
Danke schonmal
Viele Grüße Thomas

maeckes:
Also das Dir das jemand programmiert, wird glaub ich nicht klappen :stuck_out_tongue:

Dann kennst Du aber noch nicht die "erweiterten Beispielprogramme" die User 'jurs' hier im Forum von Zeit zu Zeit postet.

Zum Beispiel auch für eine Ablaufsteuerung:

// Ventilsteuerung Cocktails by 'jurs' for German Arduino Forum

#define SPRITARTEN 6
#define COCKTAILARTEN 6

#define EIN LOW
#define AUS HIGH

int startPins[COCKTAILARTEN]={2,3,4,5,6,7};
int pumpenPins[SPRITARTEN]={8,9,10,11,12,13};

int MaiTai[SPRITARTEN]={30,15,0,15,15,60};
int GoldenGirl[SPRITARTEN]={0,0,30,30,0,60};

void setup() 
{
  int i;
  Serial.begin(9600); // Serielle Schnittstelle mit 9600 Baud starten
  Serial.println("Ventilsteuerung gestartet");
  for (i=0;i<COCKTAILARTEN;i++) pinMode(startPins[i],INPUT_PULLUP);
  for (i=0;i<SPRITARTEN;i++)
  {
    digitalWrite(pumpenPins[i], AUS);
    pinMode(pumpenPins[i],OUTPUT);
  }
}  

void ablaufSteuerung(char* name, int* pumpzeit)
{
  long laufzeit[SPRITARTEN];
  long maxlaufzeit=0;
  // Pumpzeit von Sekunden in Millisekunden umrechnen und Gesamtdauer feststellen
  for (int i=0;i<SPRITARTEN;i++)
  {
    laufzeit[i]=1000L*pumpzeit[i];// Sekunden in Millisekunden umrechnen
    if (laufzeit[i]>maxlaufzeit) maxlaufzeit=laufzeit[i];
  }
  Serial.print("Gesamtdauer zum Mixen von ");Serial.print(name);
  Serial.print(" = ");Serial.print(maxlaufzeit/1000);Serial.println(" Sekunden");
  Serial.println("Millis\tPumpe\tEIN/AUS");
  delay(100); // Zum Senden der vorherigen Serial-Ausgaben
  unsigned long startTime=millis();
  do
  {
    for (int i=0;i<SPRITARTEN;i++)
    {
      if (millis()-startTime<laufzeit[i]) 
      {
        if (digitalRead(pumpenPins[i])!=EIN)
        {
          digitalWrite(pumpenPins[i],EIN);
          Serial.print(millis()-startTime);Serial.print("\t");Serial.print(i);Serial.println("\tEIN"); 
        }
      }
      else
      {
        if (digitalRead(pumpenPins[i])!=AUS)
        {
          digitalWrite(pumpenPins[i],AUS);
          Serial.print(millis()-startTime);Serial.print("\t");Serial.print(i);Serial.println("\tAUS"); 
        }
      }
    }
    if (millis()-startTime>maxlaufzeit) break;
  } while(1);
  Serial.println("fertig!\r\n");
}

void loop() {
  if (digitalRead(startPins[0])==LOW) 
    ablaufSteuerung("Mai Tai",MaiTai);
  else if (digitalRead(startPins[1])==LOW) 
    ablaufSteuerung("Golden Girl",GoldenGirl);
}

Annahmen über die Hardware:

  1. Die Button-Pins seien ohne Pulldown-Widerstände angeschlossen, im Setup werden die internen PullUps aktiviert. So kann man die Simulation auf Serial starten, indem man als "Tastendruck" einfach einen Draht zwischen GND und Pin-2, Pin-3 etc. dranhält, um einen Tastendruck zu simulieren.

  2. Die Relais seien "Active LOW" schaltend, also schalten auf LOW. Kann man natürlich im Quellcode leicht ändern, indem die Definitionen für EIN und AUS vertauscht werden.

Wie immer ist bei solchen Dingen die Wahl einer geeigneten Datenstruktur entscheidend. Ich habe mich einfach dazu entschlossen, für jeden Cocktail die Pumpzeiten jeder Pumpe in ein Array zu packen:

int MaiTai[SPRITARTEN]={30,15,0,15,15,60};
int GoldenGirl[SPRITARTEN]={0,0,30,30,0,60};

Wenn eine Pumpe bei einem Cocktail nicht gefeuert werden soll, ist die Zeit für diese Pumpe eben 0.

Viel Spaß beim Saufen!

vielen vielen Dank jurs !!!! :smiley:
Das freut mich echt sehr :slight_smile:

Als taster in der maschine benutze ich diese hier

Zum schalten der Pumpen nehme ich einen IRLZ34N und keine Relais,
das sollte aber auch gehen.

Die Ausgänge sind jetz von anfang an auf high, wie kann ich das genau vertauschen?
also wenn die unde jene pumpe aktiviert wird auf high setzten. oder soll ich mir doch lieber eine 8 fach Ralaiskarte holen
da wäre ja diese variante richtig herum oder?

danke

tsfdb:
Als taster in der maschine benutze ich diese hier
http://www.ebay.de/itm/Lamptron-Vandalismustaster-16mm-Silverline-blue-/310858926436?pt=DE_Computer_Sonstige&hash=item4860a2c964

Wenn Du Elektroniker bist, kennst Du Dich mit der Hardwareschaltung und ob externe Pull-Widerstände eingebaut werden sollten sicher besser aus als ich.

Ich verfahre da nach der Faustformel:
Wenn es zwischen Arduino und Button nur maximal 25cm Zentimeter Leitungslänge sind, reichen die internen PullUps des Atmega-Controllers. Bei längeren Leitungen zu den Buttons sind externe Pull-Widerstände notwendig, um Störungen zu vermeiden. Man will ja nicht, dass wenn jemand im Raum den Staubsauger anschaltet, plötzlich die Maschine eventuell einen Cocktail mixt, ohne dass der Button gedrückt wurde.

Der Sketch wie gepostet verwendet die internen PullUp-Widerstände des Atmega-Controllers, so dass extern nur die Schalter angeschlossen werden müssen. Verwendest Du wegen langer Leitungen zusätzliche externe PullUps, kann das Programm unverändert bleiben. Und verwendest Du externe PullDown-Widerstände, muß im Sketch nur der pinMode von INPUTT_PULLUP auf INPUT gesetzt werden und in der loop auf HIGH statt auf LOW der Mixvorgang gestartet werden.

tsfdb:
Zum schalten der Pumpen nehme ich einen IRLZ34N und keine Relais,
das sollte aber auch gehen.

Der Sketch wie gepostet ist für "Active LOW" schaltende Relais. Wenn Deine Pumpen stattdessen auf HIGH loslaufen und auf LOW stoppen, brauchst Du nur die Logik-Definitionen für EIN und AUS im Sketch vertauschen.

ok danke, ich habe jetzt mal den sketch um einen Cocktail erweitert
stimmt das so?

// Ventilsteuerung Cocktails by 'jurs' for German Arduino Forum

#define SPRITARTEN 6
#define COCKTAILARTEN 6

#define EIN LOW
#define AUS HIGH

int startPins[COCKTAILARTEN]={2,3,4,5,6,7};
int pumpenPins[SPRITARTEN]={8,9,10,11,12,13};

int MaiTai[SPRITARTEN]={30,15,0,15,15,60};
int GoldenGirl[SPRITARTEN]={0,0,30,30,0,60};
int Caipi[SPRITARTEN]={0,0,45,0,15,0};

void setup()
{
int i;
Serial.begin(9600); // Serielle Schnittstelle mit 9600 Baud starten
Serial.println("Ventilsteuerung gestartet");
for (i=0;i<COCKTAILARTEN;i++) pinMode(startPins*,INPUT_PULLUP);*

  • for (i=0;i<SPRITARTEN;i++)*
  • {*
    _ digitalWrite(pumpenPins*, AUS);_
    _ pinMode(pumpenPins,OUTPUT);
    }
    } _
    _void ablaufSteuerung(char name, int* pumpzeit)
    {
    * long laufzeit[SPRITARTEN];
    long maxlaufzeit=0;
    // Pumpzeit von Sekunden in Millisekunden umrechnen und Gesamtdauer feststellen*
    * for (int i=0;i<SPRITARTEN;i++)
    {
    laufzeit=1000Lpumpzeit*;// Sekunden in Millisekunden umrechnen*

    if (laufzeit>maxlaufzeit) maxlaufzeit=laufzeit*;
    }
    Serial.print("Gesamtdauer zum Mixen von ");Serial.print(name);
    Serial.print(" = ");Serial.print(maxlaufzeit/1000);Serial.println(" Sekunden");
    Serial.println("Millis\tPumpe\tEIN/AUS");
    delay(100); // Zum Senden der vorherigen Serial-Ausgaben*

    * unsigned long startTime=millis();
    do*

    * {
    for (int i=0;i<SPRITARTEN;i++)
    {
    if (millis()-startTime<laufzeit)
    {
    if (digitalRead(pumpenPins)!=EIN)
    {
    digitalWrite(pumpenPins,EIN);
    Serial.print(millis()-startTime);Serial.print("\t");Serial.print(i);Serial.println("\tEIN");
    }
    }
    else*

    * {
    if (digitalRead(pumpenPins)!=AUS)
    {
    digitalWrite(pumpenPins,AUS);
    Serial.print(millis()-startTime);Serial.print("\t");Serial.print(i);Serial.println("\tAUS");
    }
    }
    }
    if (millis()-startTime>maxlaufzeit) break;
    } while(1);
    Serial.println("fertig!\r\n");
    }
    void loop() {
    if (digitalRead(startPins[0])==LOW)
    ablaufSteuerung("Mai Tai",MaiTai);
    else if (digitalRead(startPins[1])==LOW)
    ablaufSteuerung("Golden Girl",GoldenGirl);
    else if (digitalRead(startPins[2])==LOW)
    ablaufSteuerung("Caipi",Caipi);
    }*_

tsfdb:
stimmt das so?

Abgesehen davon, dass hier im Forum Code-Tags um geposteten Code herum gehören, die Du vergessen hast: Ja, genau so wird das Programm um weitere Cocktails erweitert, bis zu 6 Stück maximal.

Falls mehr als 6 Cocktails gemixt werden sollen, müßte das startPins-Array um weitere Pins erweitert werden.

Falls mehr als 6 Pumpen verwendet werden sollen, müßte das pumpenPins-Array um weitere Pins erweitert werden, und auch die Cocktail-Definitionen um weitere Zeitangaben für die weiteren Pumpen.

Testen kannst Du den Sketch ganz simpel mit einem Arduino-Board und einem Stückchen Draht:
Den Draht an GND anschließen und dann je nachdem mit einem der Pins 2 bis 7 kurz verbinden, zwecks Simulation eines gedrückten Buttons und um den Ablauf zu starten. Welche Aktionen ausgeführt werden, wird dann jeweils im seriellen Monitor angezeigt. Als Hilfe beim Debuggen der Software.

Beim Peristaltikprinzip weißt du doch extakt, wieviel ml/cl pro Umdrehung gefördert werden und wielange eine Umdrehung benötigt. Oder sind es gar welche mit Schrittmotoren? Diese Werte musst du dann nur noch auf die Mengen im Rezept anwenden...

Ja das stimmt schon, allerdings hab ich mich für die Zeit entschieden, da es nicht so genau sein muss und ich das
vorher einfach versucht habe, wieviel ml in wieviel Sekunden gepumpt werden.

Alledering bräuchte ich noch einen 7 Taster, der einfach alle Pumpen anschaltet so lange ich auf dem Taster bin.
Diese funktion würde ich erstens zum reinigen benutzen und zweitens um am anfang so lange die Pumpen zu betätigen,
bis der Sprit auch vorne im Schlauch ist :slight_smile:
Geht den das noch?
Danke

tsfdb:
Alledering bräuchte ich noch einen 7 Taster, der einfach alle Pumpen anschaltet so lange ich auf dem Taster bin.
Diese funktion würde ich erstens zum reinigen benutzen und zweitens um am anfang so lange die Pumpen zu betätigen,
bis der Sprit auch vorne im Schlauch ist :slight_smile:
Geht den das noch?

Ja. Selbst wenn Du Pin-0/1 für Serial-Debug frei läßt und die übrigen digitalen Pins für 6 Schalter und 6 Pumpen benutzt, bleiben Dir ja immer noch 6 Analog-Pins übrig, die noch frei sind.

Du kannst alle Analog-Pins (A0..A5) auch als Digital-Pins nutzen!

Und wenn Dir diese 6 zusätzlichen freien Pins nicht reichen, könnte man noch mehr freischaufeln, indem man die Taster nicht an (echte oder nur so verwendete) Digital-Pins anschließt, sondern z.B. immer 5 bis 6 Taster an einem einzigen Analog-Pin. An einem Analog-Pin kann man nämlich mit nur wenig Zusatzbeschaltung (ein paar Widerstände als Widerstandsnetzwerk mit Tastern) und spezieller Programmierung pro Pin viel mehr als einen Taster auswerten.

D.h. um Tastendrücke an 10 Tastern festzustellen, würdest Du nur A0, A1 und einige Widerstände benötigen. Einziger Nachteil dabei wäre, dass dabei nur einzeln gedrückte Tasten zuverlässig erkannt werden können, also nicht zeitgleiche Mehrfach-Tastendrücke.

Ich würd die Pumpen über ein Schieberegister und transistoren ansteuern. Und die Buttons multiplexen oder in ein Widerstandsgrab umbasteln...

Hallo,
dann könnte ich rein theoretisch sogar noch ein LCD an die "analogen Eingange" anschließen,
wenn ich sie als digitale festlege oder? Aber das wäre nur schnick schnack und ist nicht soooo wichtig.

Aber das mit dem 7ten Taster brauche ich, also muss ich einen anaolen port zum digitalen machen, aber wie mach ich dann, das alle pumpen an sind solange ich den taster gedrückt halte?
Danke

tsfdb:
dann könnte ich rein theoretisch sogar noch ein LCD an die "analogen Eingange" anschließen,
wenn ich sie als digitale festlege oder? Aber das wäre nur schnick schnack und ist nicht soooo wichtig.

Für ein "nacktes" LCD-Display wird es von den Leitungen her dann doch etwas knapp, aber Du kannst problemlos ein I2C-LCD-Display verwenden, bei dem eine kleine I2C-Backpack Platine auf dem LCD-Dafür sorgt, dass Du es mit nur zwei Datenleitungen am Arduino anschließen kannst. Am Arduino würden nur die Anschlüsse A4 und A5 benötigt.

tsfdb:
Aber das mit dem 7ten Taster brauche ich, also muss ich einen anaolen port zum digitalen machen, aber wie mach ich dann, das alle pumpen an sind solange ich den taster gedrückt halte?

Am einfachsten wäre es, einen Cocktail mit dem Namen "Reinigen" in das Programm einzubauen, der z.B. so definiert ist:

int Reinigen[SPRITARTEN]={30,30,30,30,30,30};

Dann würde ein Druck auf die Reinigen-Taste zu einem 30-Sekunden Lauf aller sechs Pumpen führen. Den man bei Bedarf beliebig wiederholen kann, so wie auch alle Cocktails beliebig oft gemixt werden können. Du brauchst dann nur die Zahl der Cocktails auf 7 setzen und einen zusätzlichen Pin in das startPins-Array eintragen:

#define COCKTAILARTEN 7
...
int startPins[COCKTAILARTEN]={2,3,4,5,6,7,A0};

Und diesen "Cocktail" dann von der loop aus zum Mixen starten wie alle anderen auch.
Den Reinigen-Button aber am Gerät vielleicht etwas versteckt anbringen, damit man ihn nicht aus Versehen drücken kann: Denn aufgrund der von mir verwendeten Programmlogik läßt sich ein einmal gestarteter Mixvorgang nicht mehr abbrechen, es sei denn, durch Drücken von "Reset".

Du kannst aber auch eine spezielle reinigen-Funktion für das Programm programmieren. Das von mir gepostete Beispielprogramm ist da durchaus erweiterungsfähig: Ob LCD oder zusätzliche Funktionen, das kann man alles dranstricken.

ok vielen dank,
ich habe gerade gesehen, es gibt eine kleine Zusatzpletine für mein blaues LCD, wo dann auch nur noch 2 Datenleitungen benötigt werden. Mal schauen ob ich es noch rein baue, einerseits sieht es schon cool aus, aber andererseits bringts ja auch nicht wirklich viel, ausser das der Cocktailname dann auf dem LCD steht.

Mit dem reinigen als "7 coktail" hatte ich auch schon gedacht, alledering wäre es mir am liebsten, wenn die pumpen an sind, solange ich auf dem taster bin (also der Taster geschlossen ist). Aber das wird wohl nicht so leicht gehen oder?

Vielen Dank für eure super nette Hilfe :slight_smile:

Du kannst z.B. eine Variable "boolean reinigen" anlegen. Wenn der Taster das erste mal gedrückt wird, setzt du diese auf true. Dann machst du sowas in der Art (Pseudo code):

void loop()
{
     if(Taster gedrückt)
           reinigen = true;

      if(reinigen == true)
      {
           while(Taster gedrückt)
           {
                Pumpen an
           }
           reinigen = false;
      }
}

Dabei auch immer daran denken die Taster korrekt zu entprellen.

Geht vielleicht auch nur mit der while-Schleife ohne die Status Variable!

Das kann man natürlich auch nicht-blockierend schreiben, aber das ist hier glaube ich nicht nötig :slight_smile:

tsfdb:
ich habe gerade gesehen, es gibt eine kleine Zusatzpletine für mein blaues LCD, wo dann auch nur noch 2 Datenleitungen benötigt werden. Mal schauen ob ich es noch rein baue, einerseits sieht es schon cool aus, aber andererseits bringts ja auch nicht wirklich viel, ausser das der Cocktailname dann auf dem LCD steht.

Ja, die kleinen I2C Backpack-Platinen gibt es einzeln zu kaufen, zum nachträglichen Anlöten an ein LCD-Display. Softwaretechnisch sind die allerdings nicht alle zu jeder I2C-LCD-Library kompatibel, so dass Du bei der Ansteuerung unter Umständen erstmal verschiedene Libraries mit verschiedenen Belegungen durchprobieren müßtest, bis Du die passende Ansteuerung gefunden hast. Das kann sehr einfach sein. Oder knifflig werden.

tsfdb:
Mit dem reinigen als "7 coktail" hatte ich auch schon gedacht, alledering wäre es mir am liebsten, wenn die pumpen an sind, solange ich auf dem taster bin (also der Taster geschlossen ist). Aber das wird wohl nicht so leicht gehen oder?

Mit einem Button eine Funktion ein und aus zu schalten, ist eine super einfache Angelegenheit. Noch einfacher geht kaum etwas. Schwieriger wäre eher eine Logik der Art zu programmieren:

  • einmal drücken ==> Einschalten
  • nochmal drücken ==> Ausschalten
  • aber spätestens nach 30 Sekunden automatisch ausschalten, falls man das manuelle Ausschalten vergißt

Vielleicht nimmst Du den Sketch erstmal so in Betrieb wie er ist. Und überlegst, was Du sonst noch benötigst. Und fängst vielleicht mal an, ein bisschen programmieren zu lernen. Zum Beispiel mit einem Button die Board LED an Pin-13 ein und aus zu schalten. Damit Du irgendwann einen fremden Sketch auch selbst ändern und erweitern kannst.

Falls Du noch einen "Not-Aus" Schalter benötigst, so kannst Du diesen übrigens einfach an Reset anschließen und brauchst dafür überhaupt keine Programmierung: Wenn Reset gedrückt wird, startet der Controller automatisch neu und setzt alles auf aus. Für den Fall, dass Du ein Not-Aus haben möchtest, etwa wenn jemand den Startknopf zum Mixen eines Cocktails drückt, ohne dass ein Glas unter der Maschine steht. Man könnte natürlich auch einen Sensor anbringen, so dass der Mischvorgang nicht direkt beim Drücken des Startknopfes startet, sondern erst dann, wenn der Sensor auch signalisiert, dass ein Glas zum Befüllen dort steht, wo es stehen sollte.