Cocktail Mischer

Hallo zusammen,

Ich bin letztens mit meinem ersten Projekt angefangen, einem Cocktail Mischer der per Bluetooth gesteuert wird. Ich habe die ganze Hardware zusammen und auch schon das Programm teilweise geschrieben, jedoch hänge ich immer wieder an 2 Punkten:

  1. Warum ziehen meine Relais nicht an, wie sie sollten?
  2. Kann ich die Werte von Variabeln multiplizieren und als "delay"-Dauer nehmen?

Ich habe mein 8 Relais Modul, den Uno und das BT Modul wie nach Anleitung angeschlossen und ich bekomme auch Signale an den Relais wenn ich ein einfaches 0 oder 1 Signal ansteuere. Der Uno bekommt von der Handy App Signale wie z.B. 3430 für: 3= Longdrink, 4= 400ml, 30=30% Alkohol.

Hier einmal der Teil des Programms:

#define Pumpe1 2

#define Pumpe2 3

#define Pumpe3 4

#define Pumpe4 5

#include <SoftwareSerial.h>  // Einbinden der Bibliothek für Software-UART

int WahreMenge, Dauer1, Dauer2, Menge, Alles;
long Anteil;


void setup() {
  Serial.begin(38400);
  
  Serial.println("AT+NAME=Mischer"); 
  
  pinMode(Pumpe1, OUTPUT);

  pinMode(Pumpe2, OUTPUT);

  pinMode(Pumpe3, OUTPUT);

  pinMode(Pumpe4, OUTPUT);

  digitalWrite (Pumpe1, HIGH);

  digitalWrite (Pumpe2, HIGH);

  digitalWrite (Pumpe3, HIGH);

  digitalWrite (Pumpe4, HIGH);

  delay(1000);

}

void loop() {
  {

    while (Serial.available() > 0) { // Solange etwas empfangen wird, durchlaufe die Schleife
      Alles = Serial.read(); // Speichere das empfangene Zeichen in der Variablen "Alles"

     if (Alles > 3000) {           // Beispiel: 3440       Alles über 3000 = Longdrink
        Menge == (Alles-3000)/100;      //4.4,  da int => 4
        Anteil == ((Alles - 3000) / 100 - Menge);
        WahreMenge = Menge * 100;
        Dauer1 = WahreMenge*Anteil*10;
        Dauer2 = WahreMenge*(1-Anteil)*10;
        digitalWrite (Pumpe1, LOW);
        delay(Dauer1);
        digitalWrite (Pumpe1, HIGH);
        digitalWrite (Pumpe2, LOW);
        delay(Dauer2);
        digitalWrite (Pumpe2, HIGH);
      }
      if (2000 < Alles > 3000) {             // Alles zwischen 2000 und 3000 = Shot
        Menge == (Alles - 2000) / 100;         // Beispiel: 2430   => 4.3 da int: 4
        Anteil == ((Alles - 2000) / 100 - Menge);
        WahreMenge == Menge * 10;
        Dauer1 = WahreMenge*Anteil;
        Dauer2 = WahreMenge*(1-Anteil);        
        digitalWrite (Pumpe1, LOW);
        delay(Dauer1);
        digitalWrite (Pumpe1, HIGH);
        digitalWrite (Pumpe2, LOW);
        delay(WahreMenge*(1-Anteil)*100);
        digitalWrite (Pumpe2, HIGH);
        
      }
      if (1000 < Alles > 107) {    // Zufallsshot Beispiel: 1004 = 40% Alk
        Anteil == (Alles - 1000)/10;
        Dauer1 = 20*Anteil;
        Dauer2 = 20*(1-Anteil);
        digitalWrite (Pumpe1, HIGH);
        delay(Dauer1);
        digitalWrite (Pumpe1, LOW);
        digitalWrite (Pumpe2, HIGH);
        delay(Dauer2);
        digitalWrite (Pumpe2, LOW);

 }
  }
   }
    }

Ich hoffe jemand kann mir helfen, ich weiß nicht mehr was ich noch probieren kann ^.^
Liebe Grüße,
Gundulf

if (2000 < Alles > 3000)

Das solltest du auf jeden Fall nochmal überdenken!

Wenn Alles == 1000
(2000 < Alles > 3000)
(2000 < 1000 > 3000)
(false > 3000)
(false)

Wenn Alles == 5000
(2000 < Alles > 3000)
(2000 < 5000 > 3000)
(true > 3000)
(false)

if (1000 < Alles > 107) {

Das ist kein richtiger Code.

Hier einmal der Teil des Programms:

Das mögen wir gar nicht. Der Fehler ist immer im nicht geteilten Code.

Grüße Uwe

Ok, das waren echt dumme fehler, die ich da gemacht habe.
Das ">" Zeichen in jeder Zeile sollte natürlich ein "<" Zeichen sein. Und die 107 eine 1007.
Nach den Änderungen ziehen jetzt aber die 2 Schütze bei z.B. 3240 an , aber fallen nicht mehr ab.

Gundulf:
Hier einmal der Teil des Programms:

Damit meinte ich, dass ich nur den Teil bis jetzt geschrieben habe. Das hätte ich erklären sollen, tut mir leid.

Hier die geänderte Version.

#define Pumpe1 2

#define Pumpe2 3

#define Pumpe3 4

#define Pumpe4 5

#include <SoftwareSerial.h>  // Einbinden der Bibliothek für Software-UART

int WahreMenge, Dauer1, Dauer2, Menge, Alles;
long Anteil;


void setup() { 
  Serial.begin(38400);
  
  Serial.println("AT+NAME=Mischer"); 
  
  delay(500);
  
  pinMode(Pumpe1, OUTPUT);

  pinMode(Pumpe2, OUTPUT);

  pinMode(Pumpe3, OUTPUT);

  pinMode(Pumpe4, OUTPUT);

  digitalWrite (Pumpe1, HIGH);

  digitalWrite (Pumpe2, HIGH);

  digitalWrite (Pumpe3, HIGH);

  digitalWrite (Pumpe4, HIGH);

  delay(1000); // let relays settle down before running the first time.

}

void loop() {
  {

    while (Serial.available() > 0) { // Solange etwas empfangen wird, durchlaufe die Schleife
      Alles = Serial.read(); // Speichere das empfangene Zeichen in der Variablen "Alles"

     if (Alles > 3000) {           // Beispiel: 3440       Alles über 3000 = Longdrink
        Menge == (Alles-3000)/100;      //4.4,  da int => 4
        Anteil == ((Alles - 3000) / 100 - Menge);    // =0.4
        WahreMenge = Menge * 100;
        Dauer1 = WahreMenge*Anteil*10;
        Dauer2 = WahreMenge*(1-Anteil)*10;
        digitalWrite (Pumpe1, LOW);
        delay(Dauer1);
        digitalWrite (Pumpe1, HIGH);
        digitalWrite (Pumpe2, LOW);
        delay(Dauer2);
        digitalWrite (Pumpe2, HIGH);
      }
      if (2000 < Alles < 3000) {             // Alles zwischen 2000 und 3000 = Shot
        Menge == (Alles - 2000) / 100;         // Beispiel: 2430   => 4.3 da int: 4
        Anteil == ((Alles - 2000) / 100 - Menge);
        WahreMenge == Menge * 10;
        Dauer1 = WahreMenge*Anteil;
        Dauer2 = WahreMenge*(1-Anteil);        
        digitalWrite (Pumpe1, LOW);
        delay(Dauer1);
        digitalWrite (Pumpe1, HIGH);
        digitalWrite (Pumpe2, LOW);
        delay(WahreMenge*(1-Anteil)*100);
        digitalWrite (Pumpe2, HIGH);
        
      }
      if (1000 < Alles < 1007) {    // Zufallsshot Beispiel: 1004 = 40% Alk
        Anteil == (Alles - 1000)/10;
        Dauer1 = 20*Anteil;
        Dauer2 = 20*(1-Anteil);
        digitalWrite (Pumpe1, HIGH);
        delay(Dauer1);
        digitalWrite (Pumpe1, LOW);
        digitalWrite (Pumpe2, HIGH);
        delay(Dauer2);
        digitalWrite (Pumpe2, LOW);

 }
  }
   }
    }

Bitte die Antworten lesen ("Das ist kein richtiger Code" - wie wahr!) und/oder nochmals das Kapitel über 'if' und Bedingungen in der Arduino-Referenz oder in (fast) jedem C- oder C++-Buch lesen. verstehen und dann anwenden.

Gruß Walter

Und lerne erst mal die Arduino-Grundlagen sowie C++, bevor du dich an derartige Projekte ranwagst.
Zu den vorhandenen Vorschlägen auch die Vorgehensweise von SerialRead lesen.
So wie du es willst, geht es nicht. Du findest alles in den Beispielen der IDE.

Ok, danke für all die Hilfe und Tipps. Ich hatte gehofft aus eigenem Herleiten das Programm schreiben zu können aber ohne Grundlagen geht das wahrscheinlich nicht. :slight_smile:

Ich bringe mir dann das Grundlegende bei und Frage wann anders eventuell noch mal nach wenn ich etwas nicht verstehe.

LG

Hallo,

  if (2000 < alles < 3000) 
  {
     ..
  }

geht gar nicht. Warum das wurde oben schon geschrieben.
Das müsste (wenn ich durchschaue was du willst) so aussehen

if ((2000 < alles) && (alles < 3000) )
{
   /* alles ist zwischen hat einen Wert zwischen 2001 (einschliesslich) und 2999 (einschliesslich) */

Ulli

Hier im Forum findest Du deutlich bessere Beispiele als Deines. Da kannst Du auch die Komplexität abschätzen und was auf Deine Lernliste gehört.

In diesem Thema habe ich mal was dazu geschrieben.

Habe mir jetzt einiges über die Funktionsweise von Serial durchgelesen aber ich bin mir nicht sicher ob ich 2 Bytes auf einmal einlesen kann mit z.B.

if (Serial.available() >= 2) {
Alles = Serial.read();

Gundulf:

 }

}
  }
   }

Boh, eine solche Folge schließender Klammern zu sehen, ist fast schon Folterei. Wahrscheinlich wächst mir jetzt ein Pickel, der genau zwischen Fahrradsattel und Sitzhöcker (ein Teil des Beckenknochens) platziert ist. Benutze wenigstens Strg-T, bevor Du Code postest!

Gruß

Gregor

ich bin mir nicht sicher ob ich 2 Bytes auf einmal einlesen kann

Nein, nicht mit einem einzelnen read() - Aufruf.

gregorss:
Benutze wenigstens Strg-T, bevor Du Code postest!

Solche Tricks findet man leider nicht so schnell selber raus, aber ich werde ab jetzt drauf achten sauberer zu formatieren.

Also muss ich mehrfach einlesen um eine 2-Byte große Zahl zu erfassen? (denn das meinte ich vorher, ich muss mich echt deutlicher ausdrücken, Entschuldigung).
Und reicht dann eine einfache Zeitverzögerung in meiner App um die Signale voneinander zu trennen um währenddessen die Variable aus dem Buffer zu ziehen?

Gundulf:
Solche Tricks findet man leider nicht so schnell selber raus, aber ich werde ab jetzt drauf achten sauberer zu formatieren.

Tu das unbedingt. Besonders, wenn Du beim Programmieren noch neu bist und ab und zu Fehlersuche betreiben musst. Wenn man sich die Arbeit durch „schönen Code“ erleichtert, ist das gerade bei der Fehlersuche Gold wert.

Gruß

Gregor

Gundulf:
Also muss ich mehrfach einlesen um eine 2-Byte große Zahl zu erfassen? (denn das meinte ich vorher, ich muss mich echt deutlicher ausdrücken, Entschuldigung).

Suche Dir eine passende Funktion von Serial heraus, da gibt es auch welche für mehrere Bytes.

int Alles = Serial.read();  // Alles enthält nun eine Zahl zwischen -1 und 255, aber nie eine 3000

Normalerweise ist es einfacher und üblich, über Serial Texte statt Binärdaten zu übertragen.

Der Uno bekommt von der Handy App Signale wie z.B. 3430 für: 3= Longdrink, 4= 400ml, 30=30% Alkohol.

Bekommt er den Text "3430" oder die zwei Bytes {0x66, 0x0D} oder 0d66, was der Zahl 3430 entspricht?
Bekommt er zusätzlich zum Text "3430" auch noch ein Zeilenende übertragen ?
(Dann musst du nicht warten, bis kein Zeichen mehr gekommen ist, musst das Zeilenende aber auch weglesen. Das sind dann 5 oder 6 Zeichen)
Oder sendet die App immer genau 4 Zeichen und dann sehr lange nichts?

Ich hatte jetzt vor 2 Bytes für die Zahl zu übertragen. Und es sind immer 4-stellige Ziffern. Ich könnte mir auch eine Übersetzung von Buchstaben zu Zahlen erstellen wenn das einfacher ist.
Mit atoi könnte ich dann Buchstabe für Buchstabe bzw. Zahl für Zahl auswerten oder? Die Zerlegung habe ich mir noch nicht angelesen weil ich dachte dass ich sie nicht brauche :smiley:

Es wäre sinnvoll, wenn Du die gestellten Fragen beantwortest. Dann könnte Dir gezielter geholfen werden.

Gruß Tommy

Entschuldigung, ich verstehe noch nicht alle Fragen und worauf ihr genau damit abziehlt, ich dachte ich hätte geantwortet.
Der arduino bekommt 0d66 für die Zahl "3430" übertragen und kein Zeilenende. Und ich übertrage immer 4stellige Zahlen und danach kommt eine Pause von min 10 Sekunden (Hier wollte ich ein Timeout nutzen)
Noch mal Danke für die echt schnelle und gute Hilfe :slight_smile:

Da solltest Du dann das höherwertige Byte zuerst senden.
Beim Empfang setzt Du das in einen unsigned int und verschiebst es 8 Bitpositionewn nach links. Dann addierst Du das 2. Byte und Du hast Deine Zahl.
Pseudocode:

unsigned int zahl;
byte c = Serial.read();
zahl = c;
zahl = zahl <<8;
c = Serial.read();
zahl += c;

Gruß Tommy