Go Down

Topic: HILFE !!! Cocktailmaschine mit Arduino Uno (Read 10015 times) previous topic - next topic

agmue

Cocktailautomat mit manuellem Modus einschließlich Lern- und Speicherfunktion, gute Idee :)

Zwei für sich selbst und je einen für Papa und Mama, damit jeder etwas abbekommt.
Glückspils, das würde mir auch gefallen!

Das Grogrezept kenne ich von der Wasserkante. Nach einem schönen Strandspaziergang erst in die Sauna und dann einen Grog, das mag ich. Und auf einem Bein kann man nicht stehen, nach mehreren solchen Sprüchen nur noch auf vier.

Die Caipririnha Variante kommt mit bekannt vor, dürfte erfrischend sein :)
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

sth77

- Ein bis zwei unbehandelte Limetten vierteln
- und mit einigen Teelöffen braunem Rohrzucker in einem Longdrink-Glas zerstoßen
- reichlich Eiswürfel dazugeben
- und mit Schweppes Ginger-Ale auffüllen
- umrühren, fertig
Ah, noch ein Ipanema-Genießer!
Mein verwaister Arduino-Blog: http://www.sth77.de/ - letzter Eintrag: Diamex-ISP in der irgendwann mal aktuellen Arduino-IDE 1.6.4

agmue

#32
Nov 05, 2016, 02:31 pm Last Edit: Nov 05, 2016, 02:56 pm by agmue
mal ne Frage am Rande: Wenn ich die arrays für so ein Rezept auf einer SD- Karte speichern will- wie lese ich die am besten aus (bzw. wie muss ich sie speichern) damit die Zuordnung korrekt ist?
Da Du ja gerne anderen hilfst, möchte ich eine ausführliche Antwort auf diese Frage nachliefern.

Ausgangspunkt ist eine Tabellenkalkulation (OpenOfficeCalc), in der ich die Cocktailnamen und die Mengen in cl speichere:



Als Export entsteht die Datei Rezepte.csv, die man so natürlich auch mittels Texteditor erstellen könnte (die Zeiten sind Phantasie):
Mai Tai,0,6,7,8,8,6
Long Island Iced Tea,7,0,0,0,0,0
Apple Crumple,2,0,5,0,2,0
White Basil,2,0,4,6,0,0
Casual Friday,2,0,0,0,0,6
Caipirinha,2,4,0,0,0,0
Sex on the Beach,0,7,3,3,0,0
Sun Downer,3,1,1,0,0,5

Die dem PC entnommene SD-Karte wird nun in den SD-Kartenhalter des Arduino gesteckt. Der Arduino liest die SD-Karte aus und speichert den Inhalt in zwei Feldern für die Rezepte. Das eine Feld enthält die Cocktailnamen, das andere die Mengen.

Der Sketch enthält eine Menge Testausgaben für den seriellen Monitor, die im Produktionsbetrieb entfallen können. Außerdem schreibe ich die Rezepte auf ein Grafikdisplay. Weitere Funktionen wie das Weiterblättern oder die Auswahl eines Cocktails habe ich nicht impementiert. Der Sketch ist eine Mischung von Beispielsketchen:

Code: [Select]
// Getestet mit Mega2560

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library
#define LCD_CS 31 // Chip Select
#define LCD_CD A15 // Command/Data
#define LCD_WR A14 // LCD Write
#define LCD_RD 30 // LCD Read
#define LCD_RESET 0 // direkt mit Arduinos Resetpin verbunden

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

#include <SPI.h>
#include <SdFat.h>
#define error(s) sd.errorHalt(F(s))  // store error strings in flash to save RAM
ArduinoOutStream cout(Serial);       // create Serial stream

const uint8_t chipSelect = SS;      // SD chip select pin
SdFat sd;                           // file system object
char fileName[] = "Rezepte.csv";

const byte Anzahl_Rezepte = 10;       // anzahl Rezepte
const byte Anzahl_Zutaten = 6;       // anzahl zutaten
const byte Anzahl_Buchstaben = 25;   // Max. Anzahl Buchstaben ja Rezeptnamen

unsigned int RezeptZeiten[Anzahl_Rezepte][Anzahl_Zutaten];
char RezeptNamen[Anzahl_Rezepte][Anzahl_Buchstaben];
bool leseRezepte = true, zeigeRezepte = true;

// read and print CSV test file
void readFile() {
  cout << F("\nSD-Karte einlesen Anfang") << endl;
  unsigned int z[Anzahl_Zutaten]; // eine Zeile mit Zutaten (vorübergehend)
  char text[Anzahl_Buchstaben];   // Cocktailname (vorübergehend)
  const char FeldTrenner = ',';   // Trennzeichen zwischen den Feldelemeneten
  byte Rezept = 0, Zutat = 0;     // Indexvariablen
  byte j;

  // open input file
  ifstream sdin(fileName);

  // check for open error
  if (!sdin.is_open()) error("open");

  // read until input fails
  while (1) {
    // Get text field.
    sdin.get(text, sizeof(text), FeldTrenner);

    if (sdin.fail()) break;      // Assume EOF if fail.

    // Hole Zeiten für Zutaten
    for (j = 0; j < Anzahl_Zutaten; j++) {
      char t;
      sdin >> t >> z[j];
      if (t != FeldTrenner) {
        error("fehlerhafter Feldtrenner");
      }
    }
    sdin.skipWhite();       // Skip CR/LF.

    if (sdin.fail()) error("bad input");

    cout << text;
    for (j = 0; j < Anzahl_Zutaten; j++) {
      RezeptZeiten[Rezept][j] = z[j];
      cout << FeldTrenner << z[j];
    }
    cout << endl;
    for (j = 0; j < Anzahl_Buchstaben - 1; j++) {
      RezeptNamen[Rezept][j] = text[j];
      RezeptNamen[Rezept][j + 1] = '\0';
    }
    if (Rezept < Anzahl_Rezepte) {
      Rezept++;
    } else {
      error("zu viele Rezepte");
      break;
    }
  }

  if (!sdin.eof()) error("readFile");  // Error in an input line if file is not at EOF.
  cout << F("\nSD-Karte eingelesen und gespeichert") << endl;

  cout << F("\nAusgabe des Rezeptfeldes") << endl;
  for (Rezept = 0; Rezept < Anzahl_Rezepte; Rezept++) {
    cout << RezeptNamen[Rezept];
    for (j = 0; j < Anzahl_Zutaten; j++) {
      cout << '\t';
      cout << RezeptZeiten[Rezept][j];
    }
    cout << endl;
  }
  cout << F("\nSD-Karte einlesen Ende") << endl;
}

void tftAnzeige() {
  tft.fillScreen(0x03E0);
  tft.setTextColor(0xFFFF);
  tft.setTextSize(2);
  tft.print(" ");
  tft.setTextSize(4);
  tft.println("Cocktails");
  tft.setTextSize(2);
  tft.println();
  for (byte Rezept = 0; Rezept < Anzahl_Rezepte; Rezept++) {
    if (Rezept + 1 < 10)tft.print(" ");
    tft.print(Rezept + 1);
    tft.print(" ");
    tft.println(RezeptNamen[Rezept]);
    tft.setTextSize(1);
    tft.println();
    tft.setTextSize(2);
  }
}

void setup() {
  Serial.begin(9600);
  cout << F("Programmanfang\n");

  tft.reset();
  uint16_t identifier = 0x9341;
  cout << F("Using 0x9341 LCD driver!") << endl;
  tft.begin(identifier);
  tft.invert();  // funktioniert nur mit der Bibliotheksanpassung
  tft.setRotation(2);

  if (!sd.begin()) {
    sd.initErrorHalt();
  }
  cout << F("\nInitialisierung beendet") << endl;
}

void loop() {
  if (leseRezepte) {
    leseRezepte = false;
    readFile();
  }
  if (zeigeRezepte) {
    zeigeRezepte = false;
    tftAnzeige();
  }
}


Testausgaben:
Programmanfang
Using 0x9341 LCD driver!

Initialisierung beendet

SD-Karte einlesen Anfang
Mai Tai,0,6,7,8,8,6
Long Island Iced Tea,7,0,0,0,0,0
Apple Crumple,2,0,5,0,2,0
White Basil,2,0,4,6,0,0
Casual Friday,2,0,0,0,0,6
Caipirinha,2,4,0,0,0,0
Sex on the Beach,0,7,3,3,0,0
Sun Downer,3,1,1,0,0,5

SD-Karte eingelesen und gespeichert

Ausgabe des Rezeptfeldes
Mai Tai 0 6 7 8 8 6
Long Island Iced Tea 7 0 0 0 0 0
Apple Crumple 2 0 5 0 2 0
White Basil 2 0 4 6 0 0
Casual Friday 2 0 0 0 0 6
Caipirinha 2 4 0 0 0 0
Sex on the Beach 0 7 3 3 0 0
Sun Downer 3 1 1 0 0 5
 0 0 0 0 0 0
 0 0 0 0 0 0

SD-Karte einlesen Ende


Auf dem Grafikdisplay sieht die Anzeige dann so aus:



Also Anklicken und Prost :)
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

MaHa76

Hey, danke schön.... da setz ich mich die Tage mal hin und befasse mich damit... warte schon ne gute Woche  auf das SD- shield was ich per Express bestellt habe...

agmue

Bei mir sitzt die SD-Karte unter der Grafik, drum habe ich dann gleich was draufgeschrieben.

Und bei Fragen natürlich fragen, ich bin etwas sparsam mit den Kommentaren ;)
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

qualidat

#35
Nov 05, 2016, 08:06 pm Last Edit: Nov 05, 2016, 08:07 pm by qualidat
Ich würde die Steuerung der Hardware und das Mixen der Drinks in der Software deutlicher trennen.

Die Rezepte sollten m.E. nicht im Code fest verdrahtet werden - das ist "Kinderkacke". Dazu würde ich mir eine Art Kommandocode (zugehörige Taste, Bezeichnung, Pumpen und Mengen in Liste) ausdenken. Sowas in der Art:

"1,Hulahula, 4,2,30,3,20,4,10,5,30" soll heissen Drink-Tatste 1, Anzeige "Hulahula", es folgen 4 Komponenten, Flasche 2 - 30 Umdrehungen, Flasche 3 - 20 Undrehungen ... usw.

Während der Entwicklungszeit kann man diese ja als Zeichenkette im Flash mit F("...") ablegen, später würde ich das z.B. von einer SD-Karte laden wollen.

Peristaltikpumpen würde ich nicht nach Zeit steuern, sondern nach Anzahl der Umdrehungen - notfalls mit einem entsprechenden Geber ausstatten.

MaHa76

Wo ich das so sehe kommt mir eine Idee bei welchem Projekt ich das nachträglich noch rein bringen werde... Bei der Lampensteuerung meiner Eltern haben ich viele Werte die Zeiten, Farben und Helligkeiten vorgeben.... Anpassen kann man da ein bißchen was mit einer Fernbedienung... aber etliche Werte eigentlich nur über die Programmierung.... Wenn meine Eltern das über eine SD- Karte machen könnten, wo man einfach ein paar Zahlen am Rechner ändert, würde das einiges an Vorteilen bringen...

Da setz ich mich mal als erstes ran...

Da muss ich aber mal noch an die SPI- Grundlagen ran... ich habe dann TFT, DS3232, NRF24 und SD am SPI (Mega) hängen.... beißt sich das irgendwann?

agmue

Da muss ich aber mal noch an die SPI- Grundlagen ran... ich habe dann TFT, DS3232, NRF24 und SD am SPI (Mega) hängen.... beißt sich das irgendwann?
DS3232 an SPI, nicht doch I2C?

Die Mitglieder, die an einem Bus teilhaben, müssen sich unterscheiden. Bei I2C wird das über Adressen der Slaves gemacht, bei SPI mittels ChipSelect (CS) Leitung.

Beim Sketch in #32 (Mega2560) liegt CS der Grafik auf 31, CS der SD-Karte an SS, was 53 entspricht. Problematisch wird es, wenn an SPI was dranhängt, was kein CS kennt, beispielsweise LED-Streifen (APA102).
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

MaHa76

Achja... hast recht, die DS3232 hängt am I2C, der Rest am SPI... Ich warte mal is das SD Shield da ist und löte es mal nach bestem Wissen und Gewissen mit dran und schau mal was mit einem Beispielsketch passiert... :-) Ich meld mich wenn es so weit ist. :-)

agmue

Wenn meine Eltern das über eine SD- Karte machen könnten, wo man einfach ein paar Zahlen am Rechner ändert, würde das einiges an Vorteilen bringen...
Anregung: Wenn SD-Karte vorhanden, dann nimm die vermeindlich neuen Werte und speichere sie im EEPROM. Wenn keine SD-Karte vorhanden, arbeite mit den Werten im EEPROM.

Die Idee habe ich aus einem anderen Thema geklaut  :)
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

MaHa76


Dualpower

Hi,
sorry steht auch für dein TFT
  tft.invert();  // funktioniert nur mit der Bibliotheksanpassung

hat sich erledigt.

Aber wo bekomme ich die SdFat Bibliothek her
Arduino Mega 2560

agmue

Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

tsfdb

Hallo Leute,
mich gibts immernoch :-) Im Ausgangspost habe ich eine Cocktailmaschine geplant und später auch so gebaut. Diese funktioniert bis heute wunderbar :-)

Jetzt einige Jahre später möchte ich das gute Stück erweitern.
mit: - einem Arduino 'MEGA
     - 2,8 Zoll Touch Display
     - 8 anstelle von 6 Pumpen (8 Grundzutaten statt 6)

Bis jetzt habe ich 12 Buttons erstellt für 12 mögliche Cocktails, dies ist der Homescreen.
Wenn man auf einen Button drückt sollte eine "neue" Seite aufgehen, auf welcher ein kleines BMP vom ausgewählten Cocktail erscheint sowie 2 Buttons (Start und Home).
Beim betätigen von "Start" beginnt dann die Zubereitung. Beim betätigen von Home kehrt man auf den Homescreen zurück.

Leider Hänge ich jetzt total fest und komme nicht mehr weiter.
Ich stelle mal den Code für die Buttons rein und würde mich über Hilfe freuen.
Das "alte" Programm für die Zubereitung kann ich ja dann mehr oder weniger übernehmen.



volvodani

Wenn du jetzt einige Jahre später erweitern willlst und auch mit Bildchen arbeiten dann würde ich dir auch mittlerweilse zu den NEXTION Displays raten dann hast du nix mit Bildchen auf dem Ardu zu tun.
"Nur" noch Steuerbist hin und herscheiben evtl auch ein paar Textchen. So mal als kleinen Tip
Gruß
DerDani
"Komm wir essen Opa!" - Satzzeichen retten Leben!

Go Up