Ausgänge gleichzeitig einschalten und unabhängig voneinander ausschalten

Hallo zusammen,
habe dank agmue jetzt alles soweit das die Dosierung funktioniert auch das Display ist eingebunden und gibt den entsprechenden Text aus, ob das so in der Art und Weise gut ist? was denkt Ihr den.

Als nächstes möchte ich gerne einen Zähler einbauen, der die Gesammtanzahl der aufgerufen Rezepte zählt und Speichert aber auch für jedes Rezept.

Die Werte sollen auch nach dem Ein und Ausschalten gepeichert bleiben, erst nach einem Gewolltem Reset alles auf Null setzt.

Ich habe das "DS3231 Real Time Clock" Modul aus dem Aruino Set, kann ich das dafür verwenden?

Wie baue ich das überhaupt auf?

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x3F                          // <<----- Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

const int Anzahl_Rezepte = 9;  // anzahl Rezepte
const int Anzahl_Zutaten = 12;  // anzahl zutaten
const int Anzahl_Buchstaben = 16; // zwei zeilen Display  
const int Anzahl_Buchstaben = 20; // vier zeilen Display

//Cocktailnamen
const char Cocktail[Anzahl_Rezepte][Anzahl_Buchstaben]  = {
{"Long Island Ice."},{"Pina Colada"},{"Gin Tonic"},
{"Cuba Libre"},{"Cuban Ice Tea"},{"Zombie"},
{"Averna"},{"Touch Down"},{"frei"}
};

const unsigned long Rezept[Anzahl_Rezepte][Anzahl_Zutaten]  = {
  { 0   , 3000, 3500, 4000, 4000, 3000,    0,    0,    0,    0,    0,4000},           // Long Island Ice Tea
  { 1000, 1000, 1000, 1000, 1000, 1000, 500, 1000, 2000, 2000, 2000, 4000},           // Pina Colade
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Gin Tonic (John Tinnic)
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Cuba Libre (Setfan)
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Cuban Ice Tea 
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Zombie
  { 3000, 2000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Averna
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Touch Down
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}           // frei 
};


// Taster
const int Taster[Anzahl_Rezepte] = {A0, A1, A2, A3, A4, A5,A6, A7, A8};

// Ventile
// neu mit PMW  --> const int Ventil[Anzahl_Zutaten] = {2, 3, 4, 5, 6, 7, 22, 23, 24, 25, 26, 27};
const int Ventil[Anzahl_Zutaten] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};


boolean Dosierungaktiv = false;
unsigned long StartZeit;
int Rezept_Nr;
// neu mit PMW
//bool PumpenVentilZustand[Anzahl_Zutaten] = {false, false, false, false, false, false, false, false, false, false, false, false};
//byte pwmwert[] = {210, 60, 70, 255, 100, 50};
//

void setup() {
  Serial.begin(9600);
  lcd.begin (16,2); //  <<----- LCD 16x2
  //lcd.begin (20,4); //  <<----- LCD 20x4
    for (int i = 0; i < Anzahl_Rezepte; i++) {
    pinMode(Taster[i], INPUT);
    digitalWrite(Taster[i], HIGH);
  }
  for (int i = 0; i < Anzahl_Zutaten; i++) {
    pinMode(Ventil[i], OUTPUT);
  }
  Start();
  //
  for (int i = 0; i < Anzahl_Zutaten; i++) digitalWrite(Ventil[i], LOW);
  //
}

void loop() {
  if (!Dosierungaktiv) {                                       // Wenn keine Dosierung, dann Taster abfragen
    for (int i = 0; i < Anzahl_Rezepte; i++) {
      if (analogRead(Taster[i]) < 512) {                     // Wenn Taster gedrückt wurden,
        Rezept_Nr = i;                                        // Ausgewähltes Rezept merken,
        StartZeit = millis();                                 //    Zeit merken,
        Serial.print("\nRezept_Nr: "); Serial.print(Rezept_Nr);
        //Start(i); 
        lcd.clear();
        lcd.setCursor (0,0); 
        lcd.print(Cocktail[i]);     
        lcd.setCursor (0,1); 
        lcd.print("wird Zubereitet");
        for (int z = 0; z <= Anzahl_Zutaten; z++) {           //    Dosierung Ventil i starten
          digitalWrite(Ventil[z], HIGH);
        }
        Dosierungaktiv = true;                                 //    und Status setzen.
      }
    }
  } else {                                                     // Solange Dosierung aktiv
    for (int i = 0; i < Anzahl_Zutaten; i++) {                 // für jede Zutat abfragen,
      unsigned long currentMillis = millis();
      if ( currentMillis - StartZeit > Rezept[Rezept_Nr][i]) {      // ob die Dosierzeit abgelaufen ist
        digitalWrite(Ventil[i], LOW);
      }
    }
    boolean DosierungAus = true;
    for (int i = 0; i < Anzahl_Zutaten; i++)  {           // Wenn alle Ventile abgeschalten sind
      DosierungAus = DosierungAus && !digitalRead(Ventil[i]);
    }
    if (DosierungAus) {
      Dosierungaktiv = false;                  // Status zurücksetzen
      Rezeptwael();
    }
  }
} // end loop()a

void Rezeptwael(){
   lcd.clear();  
   delay (1000);
   lcd.setCursor (1,0);
   lcd.print("Bitte Cocktail");
     lcd.setCursor (4,1);
  lcd.print("waehlen");}
    
  void Start(){
  // Hintergrundbeleuchtung
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(LOW);
  delay (2000) ;
  lcd.setBacklight(HIGH);
  lcd.home ();
  lcd.clear();
  lcd.setCursor (5,0);
  lcd.print("A B C");
  lcd.setCursor (1,1);
  lcd.print("Modell: xxx");
  delay (3000) ;
  lcd.setCursor (1,1);
  lcd.print("wird gestertet");
   delay (4000) ;  
Rezeptwael();
}

  void Start(int &Cocktail){

    }

Hallo,
hat keiner eine Idee wie ich das mit dem Zähler machen könte?

Ist das mit der textausgabe ok, oder sollte das aus euerer sicht Optimiert werden?

Zu deinem Zähler:
Du nimmst eine Zählvariable für jedes Rezept und zählst immer +1 wenn ein Rezept verwendet wird.
Das musst du aber auch im EEProm speichern. Dazu auch einen Wert für das Rezept.
Beim Start wird beides wieder ausgelesen und angezeigt. Entsprechend für alle Rezepte.

könnte der Zähler so aussehen, kann im momnet leider nicht Testen

//Zähler
int Zaehler[Anzahl_Rezepte][Count] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
...
  } else {                                                     // Solange Dosierung aktiv
    for (int i = 0; i < Anzahl_Zutaten; i++) {                 // für jede Zutat abfragen,
      unsigned long currentMillis = millis();
      if ( currentMillis - StartZeit > Rezept[Rezept_Nr][i]) {      // ob die Dosierzeit abgelaufen ist
        digitalWrite(Ventil[i], LOW);
// Zählen
        Count = Zaehler[i]
        Zaehler[i] = Count++;
      }

nur wie schreibe ich das in einen EEProm und vorallem in welchen, könnte das auch mit dem "DS3231 Real Time Clock" funktionieren, oder sogar direkt im Arduino Mega?

Das wichtigste hast du vergessen: Die meisten Variablen.

Und die einzige Variable die du zeigst,Zaehler ist falsch.

Rezept scheint ein zweidimensionales Array zu sein, Zähler eindimensional.

Willst du bei jedem Cocktail alle möglichen, auch nicht benutzten, Zutaten eins hochzählen? (Warum?)
Oder willst du einen Verbrauchszähler je Zutat haben?

dann wäre sowas passender:

long Zaehler[Anzahl_Zutaten] ;

...
      if ( currentMillis - StartZeit > Rezept[Rezept_Nr][i]) {      
         // die Dosierzeit ist abgelaufen
         if (digitalRead(Ventil[i] == HIGH) { 
            // damit nur einmal gezählt wird 
            digitalWrite(Ventil[i], LOW);
            Zaehler[i] += Rezept[Rezept_Nr][i]);
         }
     }

OK, zweidimensionaler Zutatenzähler auf dieser Basis geht auch:

long Zaehler[Anzahl_Rezepte][Anzahl_Zutaten] ;

...
      if ( currentMillis - StartZeit > Rezept[Rezept_Nr][i]) {      
         // die Dosierzeit ist abgelaufen
         if (digitalRead(Ventil[i] == HIGH) { 
            // damit nur einmal gezählt wird 
            digitalWrite(Ventil[i], LOW);
            Zaehler[Rezept_Nr][i] += Rezept[Rezept_Nr][i]);
         }
     }

Hi michael_x,
habe es jetzt so angepasst und funktioniert.

//Zähler
long Zaehler[Anzahl_Rezepte];

...
        Dosierungaktiv = true;                                 //    und Status setzen.
        Zaehler[i] = Zaehler[i]+ 1;
        Serial.print("\n"); Serial.print(Cocktail[i]); Serial.print(": ");  Serial.print(Zaehler[i]);
...
Gesammt =   Zaehler[0]+Zaehler[1]+Zaehler[2]+Zaehler[3]+Zaehler[4]+Zaehler[5]+Zaehler[6]+Zaehler[7]+Zaehler[8]+Zaehler[9];
Serial.print("\nGesammt: "); Serial.print(Gesammt);

und wie jetzt in ein EEProm oder in das Clock Modul "DS3231"

In den EEPROM mit der EEPROM - Library
In der RAM der Uhr mit I2C (Wire.h)

Da du nun nur die Anzahl Cocktails zählst, reicht evtl. sogar zum ersten Test ein byte je Cocktail (0.255)
Das vereinfacht die Handhabung. Besonders bei I2C.

Ansonsten musst du die Größe eines Zähler-Elements berücksichtigen.

EEPROM Beispiel:

unsigned int Zaehler[Anzahl_Rezepte]; // reicht für 65535 Cocktails je Rezept
const byte ELEN=sizeof(Zaehler[0]);  // Länge eines Elements
...

        Dosierungaktiv = true;                                 //    und Status setzen.
        Zaehler[i] = Zaehler[i]+ 1;
        EEPROM.put(i*ELEN, Zaehler[i]); // put berücksichtigt die Größe von Zaehler[i], aber die Ziel-Adresse muss stimmen

Beim zugehörigenEEPROM.get(i*ELEN, Zaehler[ i ] ) ;musst du berücksichtigen, dass ein leerer EEPROM mit 0xFF beschrieben ist. (Einfach erstmal einen "auf's Haus", danach steht der Zähler auf 0)

michael_x:
In der RAM der Uhr mit I2C (Wire.h)

Entschuldige, wenn ich Dir widersprechen muß, aber DS3231 hat kein RAM, nur EEPROM nebendran. Das Ding, was falsch geht, hat RAM.

Dualpower:
und wie jetzt in ein EEProm oder in das Clock Modul "DS3231"

Für DS3231 habe ich mal etwas gesucht und probiert und kann Dir zwei Funktionen anbieten:

void i2c_eeprom_writeByte(int deviceaddress, unsigned int eeaddress, byte data)
{
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
  delay(10);
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
{
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress, 1);
  if (Wire.available()) rdata = Wire.read();
  return rdata;
};

Die I2C-Adresse unterscheidet sich von der der Uhr und ist bei mir 0x57.

Entschuldige, wenn ich Dir widersprechen muß, aber DS3231 hat kein RAM, nur EEPROM nebendran. Das Ding, was falsch geht, hat RAM.

Ja, musst du, danke. Eine DS3232 (hatte ich fälschlich im Kopf) hätte 236 Byte extra RAM und wäre genau, aber davon war hier nicht die Rede.
Die 56 Byte des "Dings was falsch geht" (DS1307) sind etwas knapp und die steht hier auch nicht zur Debatte.

Wenn man den überflüssigen EEPROM auf dem DS3231-Modul benutzen möchte, muss man zusätzlich zu deinen Anregungen, @agmue, noch an das Schreiben/Lesen größerer Variablen als bytes denken. Geht auch, man könnte sich sogar die Arduino EEPROM.h als Anregung nehmen.
Aber der Arduino EEPROM wird auch nicht übermässig viel verwendet und ist besser unterstützt.

Hallo,
danke konnet ersrt jetzt euer Tipps lesen, habe es getestet wie -agmue- gepostet hat, habe auch im DS3231 die Adresse 0x57 für die Clock und 0x68 beschreibe ich, allerdings weis ich nicht wie ich das mit meinen Cocktails und den Gesammt zähler schreibe.

wenn ich folgendes Probiere schreibt und liest das Prog aber ich kannst nicht als ges. umsetzen.

all = i2c_eeprom_read_byte(I2C_ADDR3, 0x12);
---
i2c_eeprom_writeByte(I2C_ADDR3, 0x12, all);

michael_x:
Wenn man den überflüssigen EEPROM auf dem DS3231-Modul benutzen möchte, muss man zusätzlich zu deinen Anregungen, @agmue, noch an das Schreiben/Lesen größerer Variablen als bytes denken.

Bitte sei gütig mit mir, ich habe das allererste Mal was in ein EEPROM geschrieben :slight_smile:

Und erst durch ein anderes Thema dieser Tage habe ich über den I2C-Scanner bemerkt, daß da eine Adresse zuviel auf dem Bus war. Es handelte sich um das EEPROM :-[ Das habe ich ausprobiert und konnte mein neu erworbenes Wissen hier anbringen. Manchmal paßt es :slight_smile:

Dualpower:
... habe auch im DS3231 die Adresse 0x57 für die Clock und 0x68 beschreibe ich, allerdings weis ich nicht wie ich das mit meinen Cocktails und den Gesammtzähler schreibe.

Welche Variablen Deines Programmes möchtest Du denn sichern und überschreiten die Werte die magische Grenze von 255?

Ein aktueller Stand Deines Programmes wäre dazu hilfreich.

Hallo,
ich möchtedie Zaehler Variable für das jeweilige Rezept speichern

unsigned int Zaehler[Anzahl_Rezepte];

Die Gesammtzahl aller zubereiteten Cocktails (Rezepte) möchte ich am Display ausgeben.

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <EEPROM.h>

#define I2C_ADDR    0x27                          // 20x4 Display
#define I2C_ADDR2    0x3F                          // 16 x 2 Display
#define I2C_ADDR3    0x68                          // RTC EEProm

#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

#define eep 0x20


LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
LiquidCrystal_I2C  lcd2(I2C_ADDR2,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

const int Anzahl_Rezepte = 10;  // anzahl Rezepte
const int Anzahl_Zutaten = 12;  // anzahl zutaten
const int Anzahl_Buchstaben = 20;
int Gesammt;

//Cocktailnamen
const char Cocktail[Anzahl_Rezepte][Anzahl_Buchstaben]  = {
{"Long Island Ice Tea"},{"    Pina Colada"},{"    Gin Tonic"},
{"   Cuba Libre"},{"   Cuban Ice Tea"},{"       Zombie"},
{"       Averna"},{"     Touch Down"},{"     Margarita"},{"fre"}
};

const unsigned long Rezept[Anzahl_Rezepte][Anzahl_Zutaten]  = {
  { 0   , 3000, 3500, 4000, 4000, 3000,   0,  200,  200,  200,    0, 4000},           // Long Island Ice Tea
  { 1000, 1000, 1000, 1000, 1000, 1000, 500, 1000, 2000, 2000, 2000, 4000},           // Pina Colade
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Gin Tonic (John Tinnic)
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Cuba Libre (Setfan)
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Cuban Ice Tea 
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Zombie
  { 3500, 1000,    0,    0,    0,    0,    0,    0,  500,  500,    0,    0},          // Averna
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Touch Down
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // frei 9
  { 3000,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}           // frei 10
};

//Zähler
unsigned int Zaehler[Anzahl_Rezepte]; // reicht für 65535 Cocktails je Rezept

// Taster
const int Taster[Anzahl_Rezepte] = {A0, A1, A2, A3, A4, A5,A6, A7, A8, A9};

// Ventile
// neu mit PMW  --> const int Ventil[Anzahl_Zutaten] = {2, 3, 4, 5, 6, 7, 22, 23, 24, 25, 26, 27};
const int Ventil[Anzahl_Zutaten] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

boolean Dosierungaktiv = false;
unsigned long StartZeit;
int Rezept_Nr;
// neu mit PMW
//bool PumpenVentilZustand[Anzahl_Zutaten] = {false, false, false, false, false, false, false, false, false, false, false, false};
//byte pwmwert[] = {210, 60, 70, 255, 100, 50};
//

void setup() {
  Serial.begin(9600);
  lcd.begin (20,4); //  <<----- LCD 20x4
  lcd2.begin (16,2); //  <<----- LCD 20x4
    for (int i = 0; i < Anzahl_Rezepte; i++) {  
    pinMode(Taster[i], INPUT);
    digitalWrite(Taster[i], HIGH);
  }
  for (int i = 0; i < Anzahl_Zutaten; i++) {
    pinMode(Ventil[i], OUTPUT);
  }
  Start();
  //
  for (int i = 0; i < Anzahl_Zutaten; i++) digitalWrite(Ventil[i], LOW);
  //
}

void loop() {
  if (!Dosierungaktiv) {                                       // Wenn keine Dosierung, dann Taster abfragen
    for (int i = 0; i < Anzahl_Rezepte; i++) {
        if (analogRead(Taster[i]) < 512) {                     // Wenn Taster gedrückt wurden,
        Rezept_Nr = i;                                      // Ausgewähltes Rezept merken,
        StartZeit = millis();                                 //    Zeit merken,
        //Serial.print("\nRezept_Nr: "); Serial.print(Rezept_Nr);
        //Start(i); 
        lcd.clear();
        lcd.setCursor (0,0); 
        lcd.print(Cocktail[i]);  
        lcd.setCursor (4,2); 
        lcd.print("Bisher "); lcd.print(Zaehler[i]); lcd.write(" mal");   
        lcd.setCursor (5,3); 
        lcd.print("Zubereitet ");
        for (int z = 0; z <= Anzahl_Zutaten; z++) {           //    Dosierung Ventil i starten
        digitalWrite(Ventil[z], HIGH);
        }
        Dosierungaktiv = true;                                 //    und Status setzen.
        Zaehler[i] = Zaehler[i]+ 1;
        //Serial.print("\n"); Serial.print(Cocktail[i]); Serial.print(": ");  Serial.print(Zaehler[i]);
      }
    }
  } else {                                                     // Solange Dosierung aktiv
    for (int i = 0; i < Anzahl_Zutaten; i++) {                 // für jede Zutat abfragen,
      unsigned long currentMillis = millis();
      if ( currentMillis - StartZeit > Rezept[Rezept_Nr][i]) {      // ob die Dosierzeit abgelaufen ist
        digitalWrite(Ventil[i], LOW);
      }
    }
    boolean DosierungAus = true;
    for (int i = 0; i < Anzahl_Zutaten; i++)  {           // Wenn alle Ventile abgeschalten sind
      DosierungAus = DosierungAus && !digitalRead(Ventil[i]);
    }
    if (DosierungAus) {
      Dosierungaktiv = false;                  // Status zurücksetzen
      Rezeptwael();
    }   
  }
} // end loop()a

void Rezeptwael(){
   lcd.clear();  
   delay (1000);
   lcd.setCursor (3,0);
   lcd.print("Bitte Cocktail");
   lcd.setCursor (7,1);
   lcd.print("w\341hlen");
   Gesammt = Zaehler[0]+Zaehler[1]+Zaehler[2]+Zaehler[3]+Zaehler[4]+Zaehler[5]+Zaehler[6]+Zaehler[7]+Zaehler[8]+Zaehler[9];
        Serial.print("\nGesammt: "); Serial.print(Gesammt);  
        lcd.setCursor (0,3);
        lcd.print("Gesammtz\341hler: "); lcd.print(Gesammt);  
        lcd2.setCursor (0,2);
        lcd2.print("Z\341hler: "); lcd2.print(Gesammt); 
    }
  void Start(){
  // Hintergrundbeleuchtung
  lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
  lcd.setBacklight(LOW);
  lcd.setBacklight(HIGH);
  lcd.home ();
  lcd.clear();
   
Rezeptwael();
}

void i2c_eeprom_writeByte(int deviceaddress, unsigned int eeaddress, byte data)
{
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
  delay(10);
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
{
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress, 1);
  if (Wire.available()) rdata = Wire.read();
  return rdata;
};

agmue:
Bitte sei gütig mit mir, ich habe das allererste Mal was in ein EEPROM geschrieben :slight_smile:

Und erst durch ein anderes Thema dieser Tage habe ich über den I2C-Scanner bemerkt, daß da eine Adresse zuviel auf dem Bus war. Es handelte sich um das EEPROM :-[ Das habe ich ausprobiert und konnte mein neu erworbenes Wissen hier anbringen. Manchmal paßt es :slight_smile:
Welche Variablen Deines Programmes möchtest Du denn sichern und überschreiten die Werte die magische Grenze von 255?

Ein aktueller Stand Deines Programmes wäre dazu hilfreich.

michael_x:
Geht auch, man könnte sich sogar die Arduino EEPROM.h als Anregung nehmen.

Gute Idee. Sowas wie EEPROM.put(eeAddress, f); könnte passen. Nur finde ich die zugehörige cpp-Datei nicht :frowning:

Ein uint16_t kann man in zwei Bytes aufteilen, aber dann erst MSByte oder LSByte schreiben? Da würde ich mich gerne an die üblichen Spielregeln halten.

Ich hoffe, wir bekommen die Reihenfolge noch geklärt, hatte da auf Hilfe gehofft. Nun definiere ich vorübergehend MSByte zuerst.

Der folgende Sketch liest während setup den EEPROM-Speicher und speichert den Inhalt in dem Feld Zaehler. Innerhalb von loop wird der Inhalt von allen Elementen von des Feldes Zaehler inkrementiert und im EEPROM mittels Update gespeichert. Wenn man den Sketch neu startet, geht es von vorne los.

Der unbenutzte EEPROM-Speicher steht auf 65535 (0xFFFF), weshalb er mit 0 initialisiert werden muß (oder einen aufs Haus mit allen Zutaten :o ). Oder die Zähler sollen zurückgesetzt werden. Dafür müssen alle Elemente des Feldes Zaehler auf 0 gesetzt werden und dann die Funktion i2c_eeprom_updateUIntArray() ausgeführt werden. Alle Ausgaben an den seriellen Monitor dienen nur der Veranschaulichung und können weggelassen werden.

#include <Wire.h>
#define I2C_EEPROM_ADRESSE 0x57
#define EEPROM_SPEICHER_ADR 0x00
const uint16_t Anzahl_Rezepte = 10;  // anzahl Rezepte
uint16_t Zaehler[Anzahl_Rezepte] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool oneshot = true;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Serial.println("Programmanfang");
  Serial.print("Zaehlerfeld vor dem Lesen: \t");
  for (uint16_t j = 0; j < (sizeof(Zaehler) / sizeof(Zaehler[0])); j++) {
    Serial.print(Zaehler[j]);
    Serial.print(" ");
  }
  Serial.println();
  bool zaehlerzuruecksetzen = false;  // auf true zum Loeschen, auch zur Speicherinitialisierung auf 0
  if (zaehlerzuruecksetzen) {
    i2c_eeprom_updateUIntArray(I2C_EEPROM_ADRESSE, EEPROM_SPEICHER_ADR, Zaehler, sizeof(Zaehler) / sizeof(Zaehler[0]));  // Zaehler zuruecksetzen
  } else {
    i2c_eeprom_readUIntArray(I2C_EEPROM_ADRESSE, EEPROM_SPEICHER_ADR, Zaehler, sizeof(Zaehler) / sizeof(Zaehler[0]));
  }
  Serial.print("Zaehlerfeld nach dem Lesen: \t");
  for (uint16_t j = 0; j < (sizeof(Zaehler) / sizeof(Zaehler[0])); j++) {
    Serial.print(Zaehler[j]);
    Serial.print(" ");
  }
  Serial.println();
}

void loop() {
  if (oneshot) {
    for (uint16_t j = 0; j < (sizeof(Zaehler) / sizeof(Zaehler[0])); j++) {
      Zaehler[j]++;
    }
    Serial.print("Zaehlerfeld +1:            \t");
    for (uint16_t j = 0; j < (sizeof(Zaehler) / sizeof(Zaehler[0])); j++) {
      Serial.print(Zaehler[j]);
      Serial.print(" ");
    }
    Serial.println();
    i2c_eeprom_updateUIntArray(I2C_EEPROM_ADRESSE, EEPROM_SPEICHER_ADR, Zaehler, sizeof(Zaehler) / sizeof(Zaehler[0]));
    oneshot = false;
  }
}

void i2c_eeprom_updateUIntArray(int16_t deviceaddress, uint16_t eeaddress, uint16_t *ptr, uint16_t anzahlElemente) {
  uint16_t buf[anzahlElemente];
  i2c_eeprom_readUIntArray(deviceaddress, eeaddress, buf, sizeof(buf) / sizeof(buf[0]));
  uint16_t eadr=eeaddress;
  for (uint16_t j = 0; j < anzahlElemente; j++) {
    if ((ptr[j] >> 8) != (buf[j] >> 8)) {
      Wire.beginTransmission(deviceaddress);
      Wire.write((int)(eadr >> 8)); // MSB
      Wire.write((int)(eadr & 0xFF)); // LSB
      Wire.write(ptr[j] >> 8);
      Wire.endTransmission();
      delay(10);
    }
    eadr++;
    if ((ptr[j] & 0xFF) != (buf[j] & 0xFF)) {
      Wire.beginTransmission(deviceaddress);
      Wire.write((int)(eadr >> 8)); // MSB
      Wire.write((int)(eadr & 0xFF)); // LSB
      Wire.write(ptr[j] & 0xFF);
      Wire.endTransmission();
      delay(10);
    }
    eadr++;
  }
}

void i2c_eeprom_readUIntArray(int16_t deviceaddress, uint16_t eeaddress, uint16_t *ptr, uint16_t anzahlElemente) {
  uint16_t data = 0xFF;
  delay(2);
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress, anzahlElemente << 1);
  for (uint16_t j = 0; j < anzahlElemente; j++) {
    delay(5);
    data = Wire.read() << 8;
    delay(5);
    data = data | Wire.read();
    ptr[j] = data;
  }
}

Ausgabe nach dem fünften Lauf:

Programmanfang
Zaehlerfeld vor dem Lesen:  0 0 0 0 0 0 0 0 0 0 
Zaehlerfeld nach dem Lesen: 4 4 4 4 4 4 4 4 4 4 
Zaehlerfeld +1:             5 5 5 5 5 5 5 5 5 5

Prost! :slight_smile:

Perfekt, danke funktioniert wunderbar!

@agmu, Prost!

Hallo,
so mein SD Karten Modul ist eingetroffen.
@agmue, Du hattes die Idee die Rezepte auf die SD Karte zu schreiben und dort anzupassen, hast du sowas ähnliches schonmal gemacht, wie gehe ich das an?

Was ich auch gerne möchte ist die Auswertung der Cocktails also den mengenzähler nach einem Reset auf Die SD Karte zu schreiben,
Beispiel;
"29 x Pinacolada"
"222 x Averna" usw

Dualpower:
@agmue, Du hattes die Idee die Rezepte auf die SD Karte zu schreiben und dort anzupassen, hast du sowas ähnliches schonmal gemacht, wie gehe ich das an?

Ja, Cocktailmaschine mit Arduino Uno.

Hallo zusammen,
hat einer von Euch eine Idee wie ich die Menge der Cocktails in "ml" Steuern könnte,
bisher läuft die steuereung in millis, leider sind die Mengen der einzelnen Pumpen und Ventile unterschiedlich wegen der Schlauchlängen und der Ventile selbst und leider nicht linear.
So das ich die einzelnen Ventile/Punpen Kalibriert werden.

Habt Ihr eine Idee?

//Cocktailnamen
const char Cocktail[Anzahl_Rezepte][Anzahl_Buchstaben]  = {
{"    Pina Colada"},{"     Touch Down"},{"    John Tinic"},
{"Cuba Libre -Setfan-"},{"      Zombie"},{"     nicht belegt"},
{"     nicht belegt"},{"     nicht belegt"},{"     nicht belegt"},{"     nicht belegt"}
};

//   1     2     3     4      5     6    7     x8      9    10    11    12            1-6 Ventile 7-12 Pumpen
const unsigned long Rezept[Anzahl_Rezepte][Anzahl_Zutaten]  = {
  { 2700,    0,   0,    0,     0,    0,    0,    0,    0, 3000, 2700,    0},           // Pina Colade
  {    0, 3300, 5300,    0, 1800,    0,    0,    0, 4300,    0,    0,    0},           // Touch DownAverna
  {    0,    0,    0, 4200,    0,    0,    0,    0,    0,    0,    0, 6100},          // Gin Tonic 
  {    0, 6500,    0,    0,    0,    0, 5500,    0,    0,    0,    0,    0},          // Cuba Libre (Setfan) 
  { 2700, 2700,    0,    0, 3600, 3000,    0, 1400, 1400, 1800,    0,    0},          // Zombie
  {    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Margarita
  {    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // Long Island Ice Tea
  {    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // 
  {    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0},          // 
  {    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0}           // 
};[s][/s]

Da must Du bei allen mit der Originalflüssigkeit messen, wieviel in einer bestimmten Zeit (z.B. 1 Sekunde) fließt. Dann kannst Du Dir einen Umrechnungsfaktor ermitteln.

Das ist aber auch nur eine Näherung, da z.B. aus einer vollen Flasche der Ablauf anders ist, als aus einer fast leeren.

Gruß Tommy

OT:

Wenn man nix trinken will bestellt man sich ein Long Island Ice Tea... :smiley:

Sorry musste sein.
Gruß
DerDani :smiley: