Schrittmotor Steuerung mit LCD Menü

Guten Tag ich habe ein kleines Projekt woran ich jetzt schon eine weile Sitze es ist ein Barmixer mit LCD Menü auswahl.
Ich habe ein Ardunio Mega mit Adafruit motor shield drauf.
Nun habe ich ein kleines Problem. Die Menüführung klappt aber sobald ich die Motordatei mit in den Code nehme funktioniert weder das Menü noch der
Motor richtig. Ich habe die befürtung das Irgendwo ein Signal an das Motorshiel gegeben wird ohne das ich das merke.
Vielleicht kann mir irgendjemand helfen warum der Motor anfängt zu laufen obwohl keine Taste von mir gedrückt wurde.

Hier mal der Code:

#include <LiquidCrystal.h>
#include <AFMotor.h>  <------- Motor sequenz


//AF_Stepper motor1(200, 1);  <------- Motor sequenz  



#define RS 32
#define E  33
#define D4 34
#define D5 35
#define D6 36
#define D7 37
#define COLS 16
#define ROWS 2
LiquidCrystal lcd(RS, E, D4, D5, D6, D7);


int Led1 = 28; 
int Taster1 = 27;                    // Taster1 - wird an Pin 8 initialisiert
int TasterStatus;

// Symbolische Konstanten für die Getränke
enum {KEINS, COLA, RUM, WASSER, WEIN, WEINBRAND, WHISKEY};
// LCD-Namen für die Getränke
char getraenkenamen[][10]={"Nichts","Cola", "Rum", "Wasser", "Wein", "Weinbrand", "Whiskey"};

// Symbolische Konstanten für die Mengen
enum {NICHTS, CL2, CL4};
// LCD-Namen für die Mengen
char mengennamen[][4]={"---","2CL", "4CL"};

// Symbolische Konstanten für die Buttons
enum {GETRAENKEWAHL, MENGENWAHL, FREIERBUTTON, START};
// I/O-Pins für die Buttons
byte buttons[]={24, 25, 26, 27};
byte buttontype= INPUT_PULLUP;  // may be INPUT or INPUT_PULLUP


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
pinMode(Led1, OUTPUT); 
pinMode(Taster1, INPUT); 

// motor1.setSpeed(30);  // 10 rpm   <------- Motor sequenz
 

  lcd.begin(16,2);
  for (int i=0;i<4;i++)
  {
    pinMode(buttons[i],buttontype);
  }
  lcdWelcome();
}

void lcdWelcome()
{
  lcd.clear();
  lcd.print("Willkommen"); 
  lcd.setCursor(0,1);
  lcd.print("Ihre Auswahl?");
}

int getButton()
{
  static boolean oldStatus[]={false,false,false,false};
  boolean newStatus;
  int i;
  for (i=0;i<4;i++)
  {
    newStatus=digitalRead(buttons[i]);
    if (buttontype==INPUT_PULLUP) newStatus=!newStatus;
    if (newStatus==HIGH &&  oldStatus[i]==false)
    {
      oldStatus[i]=true;
      delay(5);
      return i;
    }  
    else if (newStatus==LOW && oldStatus[i]==true)
     oldStatus[i]=false;
  }
  return -1;
}

void doMenu(byte &getraenk, byte &menge)
{
  int button=getButton();
  if (button<0) return;
  switch (button)
  {
  case GETRAENKEWAHL: getraenk++;
                      if (getraenk>WHISKEY) getraenk=KEINS;
                      break;
  case MENGENWAHL:    menge++;
                      if (menge>CL4) menge=NICHTS; 
                      break;
  case START: if (getraenk!=KEINS && menge !=NICHTS)
              {
                doCocktail(getraenk,menge);
                return;  
              }
              else return;
  }                    
  lcd.clear();
  lcd.print(getraenkenamen[getraenk]);
  lcd.setCursor(0,1);
  lcd.print(mengennamen[menge]);
}

void doCocktail(byte getraenk, byte menge)
{ 
  char linebuf[17];
  lcd.clear();
  lcd.print(getraenkenamen[getraenk]);
  lcd.setCursor(0,1);
  lcd.print("mixen...");
  delay(5000);
  lcd.setCursor(0,1);
  lcd.print("Fertig!  ");
  delay(5000);
  lcdWelcome();
}

void loop() {
  // put your main code here, to run repeatedly: 
  static byte getraenk, menge;
  doMenu(getraenk, menge);
  
  Serial.println(getraenk);
  
   TasterStatus = digitalRead(Taster1);
   
  if(Taster1 == HIGH && getraenk == 2)
  
//  motor1.step(50, FORWARD, DOUBLE);  <------- Motor sequenz
 delay(1000);

//motor1.step(50, BACKWARD, DOUBLE);      <------- Motor sequenz
delay(1000);

Dortmunder85:
delay(1000);

Für interaktive Programme ist jedes "delay()" (= Blockieren des Programms für eine bestimmte Zeit) innerhalb der loop ein absolutes No-Go!

Wo Du das Programm für eine Weile zum Mixen Deiner Getränke blockieren kannst habe ich Dir in den Menücode reingeschrieben, es handelt sich um die Funktion:
void doCocktail(byte getraenk, byte menge)

In genau dieser Funktion mußt Du Deine Motoren und Ventile und was weiß ich steuern. Und da darfst Du dann auch delay() verwenden, allerdings sind dann sämtliche Menüeingaben blockiert, solange bis die doCocktai-Funktion wieder beendet ist. Diese Funktion wird immer dann abgearbeitet, wenn im Menü ein Getränk und eine Menge gewählt wurden und danach der Startknopf gedrückt wird.

OK klappt leider immer noch nicht!
Der Motor läuft nur in eine Richtung obwohl ich FRONT und BACKWARD eingegeben habe
Mir ist übrigens aufgefallen das gleich beim rüber laden auf den Arduino die LCD anzeige Cola mixen Anzeigt und danach fertig und erst danach
das Willkommen Ihre Auswahl.
kann es sein das gleich zu Anfang die doCocktail Schleife einmal abgearbeitet wird??

void doCocktail(byte getraenk, byte menge)
{ 
  
  TasterStatus = digitalRead(Taster1);


   TasterStatus = digitalRead(Taster1);
   if(Taster1 == HIGH )
  
 //motor1.step(50, FORWARD, DOUBLE);
 delay(1000);

motor1.step(50, BACKWARD, DOUBLE);
delay(1000);
  
  
  char linebuf[17];
  lcd.clear();
  lcd.print(getraenkenamen[getraenk]);
  lcd.setCursor(0,1);
  lcd.print("mixen...");
  delay(5000);
  lcd.setCursor(0,1);
  lcd.print("Fertig!  ");
  delay(5000);
  lcdWelcome();
}

Dortmunder85:
OK klappt leider immer noch nicht!
Der Motor läuft nur in eine Richtung obwohl ich FRONT und BACKWARD eingegeben habe

Die erste Zeile mit "motor1.step" ist eine Kommentarzeile, sie ist auskommentiert und wird demzufolge weder vom Compiler in Programmcode übersetzt noch wird die auskommentierte Zeile ausgeführt:

//motor1.step(50, FORWARD, DOUBLE);
...
motor1.step(50, BACKWARD, DOUBLE);

Nur für die Zeile mit BACKWARD wird ausführbarer Programmcode erzeugt.

ja das Auskomentieren habe ich absichtlich gemacht da ich sehen wollte warum der Schrittmotor nur in eine Richtung läuft obwohl ich

motor1.step(50, FORWARD, DOUBLE);
...
motor1.step(50, BACKWARD, DOUBLE);

keine Ahnung warum.

Hier nochmal der Code:
Ich habe alles so eingefügt wie von Ihnen Gesagt.
Aber der Motor läuft nur in eine Richtung

void doCocktail(byte getraenk, byte menge)
{ 
  
        TasterStatus = digitalRead(Taster1);
            if(TasterStatus == HIGH && getraenk == 3 )
 
 motor1.step(100, FORWARD, DOUBLE);
 delay(1000);
motor1.step(100, BACKWARD, DOUBLE);
delay(1000);
  
  char linebuf[17];
  lcd.clear();
  lcd.print(getraenkenamen[getraenk]);
  lcd.setCursor(0,1);
  lcd.print("mixen...");
  delay(5000);
  lcd.setCursor(0,1);
  lcd.print("Fertig!  ");
  delay(5000);
  lcdWelcome();
}

Dortmunder85:
TasterStatus = digitalRead(Taster1);
if(TasterStatus == HIGH && getraenk == 3 )

motor1.step(100, FORWARD, DOUBLE);
delay(1000);
motor1.step(100, BACKWARD, DOUBLE);
delay(1000);

Was soll die Tasterabfrage an dieser Stelle?
Alle Tasten, die das Getränk und die Menge wählen und diese Funktion starten, wurden vorher gedrückt und ausgewertet?

Jetzt hast Du programmiert, dass FORWARD nur ausgeführt wird, wenn eine bestimmte Bedingung erfüllt ist:

if(TasterStatus == HIGH && getraenk == 3 )
motor1.step(100, FORWARD, DOUBLE);

Nur dann wird FORWARD ausgeführt.

Aber BACKWARD wird immer ausgeführt.

So what?

Ein Programm macht immer das, was Du programmierst.

Normalerweise ist es so programmiert wenn Taste1 bei mir im Code also Pin 27 gedrückt wird und Getränke Nummmer 3
dann wird der Motor 100 Schritte vorwärts dann 1 sekunde warten und danach 100 Schritte zurück.
Das sagt der Code momentan aus
Ich mache nochmal eine Tastenabfrage weil ich nicht genaus weis wo die Taste Start abgelegt ist. Eigentlich dachte ich es reicht wenn ich

if(buttons[3] == HIGH && getraenk == 3 ) also buttons eintrage die 3 für die 4. Taste wie in deinem Code auch beschrieben.
Momentan ist einfach das Problem egal in welche loop schleife ich versuche mein Motor zu integrieren er läuft nicht so wie ich es haben will.
Unter welcher variablen ist den der Startbutton ??

Dortmunder85:
Normalerweise ist es so programmiert wenn Taste1 bei mir im Code also Pin 27 gedrückt wird und Getränke Nummmer 3
dann wird der Motor 100 Schritte vorwärts dann 1 sekunde warten und danach 100 Schritte zurück.
Das sagt der Code momentan aus.

Es ist mir alles unbegreiflich. Wenn der Mixvorgang und die Funktion doCocktail schon gestartet ist nochmal den Start-Button abfragen, ich verstehe es nicht.

Ich glaube nicht mal, dass das mit PullUp- oder PullDown-Widerständen in Deiner Schaltung richtig verdrahtet und im Programm passend dazu programmiert ist.

Wenn Du nämlich auf einen gedrückten Taster testen möchtest mit:
buttons[3] == HIGH
und andererseits steht im Quelltext die Initialisierung für die Verwendung der internen PullUps:
byte buttontype= INPUT_PULLUP; // may be INPUT or INPUT_PULLUP
dann ist das schon mal ein Widerspruch an sich.

Ein und derselbe Button kann entweder nur mit dem internen PullUp-Widerstand verwendet (pinMode INPUT_PULLUP) werden und ist im gedrückten Zustand LOW, oder er wird mit einem externen PullDown-Widerstand verwendet (pinMode INPUT) und ist im gedrückten Zustand HIGH. Beides gleichzeitig im selben Programm mit demselben Button geht nicht.

Was die Funktion betrifft, vielleicht wolltest Du sowas:

void doCocktail(byte getraenk, byte menge)
{ 
  char linebuf[17];
  lcd.clear();
  lcd.print(getraenkenamen[getraenk]);
  lcd.setCursor(0,1);
  lcd.print("mixen...");
  if(getraenk == WASSER )
  {
    motor1.step(100, FORWARD, DOUBLE);
    delay(1000);
    motor1.step(100, BACKWARD, DOUBLE);
    delay(1000);
  }
  else
  { // das Mixen aller anderen Getränke wird nur durch ein delay simuliert
    delay(5000);
  }
  lcd.setCursor(0,1);
  lcd.print("Fertig!  ");
  delay(5000);
  lcdWelcome();
}

so also habe ausserhalb der Schaltung auch Pull up Widerstände verbaut.
Ich habe jetzt mal deine Version nochmal rein kopiert. Jetzt hat es geklappt!!!
Dank dir Jurs.
Eine Frage hätte ich da noch nur zum verständnis. wenn ich den den Code rüber lade zum Arduino oder algemein den Arduino an mache dann kommt als erstes Cola mixen... und 5 sekunden später Cola Fertig
Und erst danach kommt Willkommen Ihre Auswahl.
Kann es sein das die doCocktail Schleife am Anfang einmal ausgeführt wird ohne ein Grund.

Dortmunder85:
Und erst danach kommt Willkommen Ihre Auswahl.
Kann es sein das die doCocktail Schleife am Anfang einmal ausgeführt wird ohne ein Grund.

Wie gesagt, ich bin mir nicht sicher, dass Du überhaupt den Unterschied zwischen PullUp und PullDown Widerständen an den Buttons kennst und wie sich damit die Logik bei der Abfrage der Taster verändert.

Siehst Du diese Zeile im Programm:
byte buttontype= INPUT_PULLUP; // may be INPUT or INPUT_PULLUP
So mit INPUT_PULLUP ist es richtig, wenn die Schaltung so ausgeführt ist, dass

  • die Buttons direkt (ohne Widerstand) angeschlossen sind, es wird der interne PullUp verwendet
  • die Buttons mit externem PullUp-Widerstand angeschlossen sind

Wenn Du stattdessen PullDown-Widerstände an die Buttons angeschlossen hast, muss die Zeile geändert werden auf:
byte buttontype= INPUT; // may be INPUT or INPUT_PULLUP

Wie ist es damit? Fängt er dann auch gleich mit dem Mixen von Cola an?

Unterschied zwischen Pull up und Pull down Widerstand kenne ich XD.
Jup jetzt hat es geklappt. Sorry das ich mich etwas zu blöd anstelle.
Hab noch so meine Probleme bei der Programmierung alles zu erkennen.

Ich Danke dir auf jedenfall für deine Hilfe weiß garnicht wie man sich bedanken kann.
DANKE,DANKE,DANKE

Dortmunder85:
Ich Danke dir auf jedenfall für deine Hilfe weiß garnicht wie man sich bedanken kann.

Nichts leichter als das! Ein Cocktail aus deiner Maschine und während der Abfüllung eine Laufschrift auf dem LCD: "jurs ist der Beste!" :wink: