Motorsteuerung

Hi alle zusammen,

ich moechte eine Motorsteurrung realisieren. Hier mein Anliegen:

Ein Motor treibt mehrere Zahnraeder an. An einem Zahnrad ist ein Magnet angebracht. Der Motor soll nur so lange laufen das dieses Zahnrad mit dem Magneten genau eine Undrehung macht.
Der Taster wird einmal betaetigt, Mosfet bekommt ein Signal, Motor laeuft und dieser Vorgang wir von dem Hallsensor unterbrochen, sobald der Magnet daran vorbei geht.
Der Vorgang soll immer von dem Magneten unterbrochen werden egal ob der Taster dauerhaft gedrueckt ist oder waehrend dem Vorgang mehrmals betaetigt wird. Sprich fuer einen neuen Zyklus muss der Taster immer erneut gedrueckt werden.

Das Hauptproblem welches ich habe. Ich schaffe es einfach nicht das der Taster immer erneut fuer einen neuen Zyklus gedrueckt werden muss. Ein weiters Problem ist auch, wenn der Taster durchgehend gedrueckt ist wird der Vorgang nur kurz unterbrochen bzw. der Motor haelt nur kurz an und laeuft dann weiter.

In dem Code funktioniert es nur bedingt, indem der Motor erst startet wenn der Schalter wieder los gelassen wird. Allerdings waere mein Wunsch das der Motor schon bei Betaetigung startet.

Ich benutze ein Adafruit Trinket.

Gruss Michael

const int buttonPin = 0;
const int MagnetPin = 2;
const int MosfetPin = 4;

int myStatus = 1; //diese Variable entspricht der Schrittnummer
 
void setup(){
pinMode(buttonPin, INPUT);
pinMode(MagnetPin, INPUT);
pinMode(MosfetPin, OUTPUT);
;}
 
void loop(){
     if ((digitalRead(buttonPin)==HIGH) && (myStatus==1)){
         myStatus=2;}
     if ((digitalRead(buttonPin)==LOW) && (myStatus==2)){
         myStatus=3;}
     if ((digitalRead(MagnetPin)==LOW) && (myStatus==3)){
         myStatus=1;}
}
switch (myStatus){
   case 1: // stopp
        digitalWrite(MosfetPin,LOW);
        break;
   case 2: // auch stopp
        digitalWrite(MosfetPin,LOW);
        break;
   case 3: // vorwärts
        digitalWrite(MosfetPin,HIGH);
        break;
}
delay(20);
}

Deine Loop() endet in Zeile 21 mit der Klammer.

die Switch-Anweisung wird nie ausgeführt.

Das zweite Thema: "Der Vorgang soll immer von dem Magneten unterbrochen werden egal ob der Taster dauerhaft gedrueckt ist oder waehrend dem Vorgang mehrmals betaetigt wird. Sprich fuer einen neuen Zyklus muss der Taster immer erneut gedrueckt werden."
Dafür musst du einen Pinwechsel erkennen. Es reicht also nicht nur auf den aktuelle Status abzufragen: "if ((digitalRead(buttonPin)==HIGH)", sondern du musst dir den letzten Zustand des Tasters merken und nur bei (der gewünschten) Änderung ein Flag setzen. Zm Beispiel so:

  nowbutton = digitalRead(buttonPin);
 if (lastbutton == HIGH && nowbutton == LOW) buttonchange = true;
 else                                        buttonchange = false;
 lastbutton = nowbutton;

 if (buttonchange) {  //Motoran...};

Alles klar danke fuer die schnelle Antwort ich werde mal versuchen das umzusetzen. Das mit der KLammer war ein Versehen danke fuer den Hinweis.

So ich bin jetzte auf eine Loesung gekommen koennt ihr vielleicht kurz rueber schauen ob das so gehen wuerde.

Gruss Michael

const int buttonPin = 0;
const int MagnetPin = 2;
const int MosfetPin = 4;

int myStatus = 1; //diese Variable entspricht der Schrittnummer
int nowbutton;
int lastbutton;
int magnet;

void setup(){
pinMode(buttonPin, INPUT);
pinMode(MagnetPin, INPUT);
pinMode(MosfetPin, OUTPUT);
;}
 
void loop()
{
  nowbutton = digitalRead(buttonPin);
  magnet = digitalRead(MagnetPin);

  if (lastbutton == LOW && nowbutton == HIGH)
  {
    myStatus=3;
    lastbutton == nowbutten;
  }

  if (magnet == HIGH)
  {
    myStatus=1;
  }

  if (myStatus=1 && nowbutton == LOW)
  {
    lastbutton == nowbutton;
  }
  switch (myStatus)
        {
          case 1: // stopp
            digitalWrite(MosfetPin,LOW);
          break;
 
          case 3: // vorwärts
            digitalWrite(MosfetPin,HIGH);
          break;
        }
delay(20);
}

Pins 0 und 1 sind die serielle Schnittstelle. Da sollte man nichts anschließen

Du bringst mehrmals = und == durcheinander

michi243:
So ich bin jetzte auf eine Loesung gekommen koennt ihr vielleicht kurz rueber schauen ob das so gehen wuerde.

Hast du es denn schonmal probiert??

Der Code, den du gepostet hast, ist ja nicht mal compilierfähig!

Bevor du hier nachfragst, könntest du schonmal prüfen, ob der Code überhaupt läuft.

Wie sind denn Taster Magnetschalter angeschlossen? Stimmt das mit dem HIGH und LOW so?

Du machst die Logik irgendwie zweimal. Zum einen hast du eine Statemachine, die den Motorzustand regelt, zum anderen hast du bei den Tasterabfragen nochmal logische Verknüpfungen zum Setzen der Zustände.

Das ist einfacher, wenn du in der Statemachine nur die jeweils relevante Bedingung abfragst.

Am besten, du malst die die Statemachine mal auf:
Zwischenablage01.jpg
Deine hat 2 Zustände: Motor An und Motor aus.
Und die Bedingungen zum wechsel sind auch eindeutig: In Motor AN wartest du auf den Magneten, in Motor AUS auf den Taster.

Das vereinfacht den Code deutlich.
Aber eines kommt noch dazu: Wenn du bei erreichen des Magneten sofort in AUS springst, ist der Magnetschalter wahrscheinlich noch an. Bei nächsten Start führt das noch anliegende Signal des Magnetschalters dazu, dass der Motor sofort wieder stoppt. Als musst du auch beim Magnetschalter eine Flankenerkennung einführen.

Das könnte dann so aussehen:

const int buttonPin = 3;
const int MagnetPin = 2;
const int MosfetPin = 4;



int motorStatus = AUS;                               // Variable für Zustand der Statemachine
const byte AUS = 0;                                    // mögliche Zustände der Statemachine
const byte AN = 1;

boolean nowbutton;                                    // aktuell gelesener Tasterzustand
boolean lastbutton;                                     // letzter gelesener Tasterzustand
boolean buttonpressed;                               // true: Taster wurde gedrückt

boolean nowMagnet;                                   // gleiches für Magneteingang
boolean lastMagnet;
boolean Magnetreached;


void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(MagnetPin, INPUT);
  pinMode(MosfetPin, OUTPUT);
}

void loop()
{
  // Flankenerkennung des Tasters
  nowbutton = digitalRead(buttonPin);
  if (lastbutton == LOW && nowbutton == HIGH) {             // steigende Flanke Taster wurde gedrückt
    buttonpressed = true;
  } else {
    buttonpressed = false;
  }
  lastbutton = nowbutton;


  // Flankenerkennung des Magneten
  nowMagnet = digitalRead(MagnetPin);
  if (lastMagnet == LOW && nowMagnet == HIGH) {             // steigende Flanke bei Erreichen des Magneten
    Magnetreached = true;
  } else {
    Magnetreached = false;
  }
  lastMagnet = nowMagnet;


  switch (motorStatus) {
    case AUS: // stopp
      digitalWrite(MosfetPin, LOW);
      if (buttonpressed) motorStatus = AN;               // Wenn Taster gedrückt wurde, Zustand wechseln.
    break;

    case AN: // vorwärts
      digitalWrite(MosfetPin, HIGH);
      if (Magnetreached) motorStatus = AUS;                     // Wenn Magnet erreicht wurde, Zustand wechseln.
    break;
  }
}

Was du noch beachten musst: Die Logik der Schalter. Je nach dem, wie die Schalter angeschlossen sind, kann sich die Bedeutung von HIGH und LOW umkehren. Ist es ein Schalter nach Masse mit Pullup, bedeutet HIGH offen und LOW gedrückt. Ist es Schalter nach +5V mit pulldown, ist es umgekehrt.

Vielen Dank fuer deine Muehe trotzdem hab ich mehrere Fragen dazu. Ich haette mein Programm natuerlich vorher pruefen sollen. Leider kann ich es erst am Donnerstag testen, da mein Trinket abgeraucht ist :roll_eyes: .

Vorher wurde gesagt das ich 1 und 0 nicht benutzen darf. Beim Trinket sind doch von 0 bis 4 alles Digitale In und Outs.

Ich habe noch ein Verstaendnisproblem bei den Flankenerkennungen und bei "const byte".

Flankenerkennung:

Das Adafruit wiederholt den Loop oder das Programm ja steandig. Ich versteh nicht ganz wann genau der "lastbutton" wieder den Wert "Low" bekommt. Oder bekommt der "lastbutton" immer dann ein "low" sobald ich den Button wieder loslasse? Sprich ueber diese Bedingung regelst du, dass man den Schalter nicht dauerhaft gedrueckt halten kann.

In der If Bedingung vom "motorStatus" pruefst du dann zusaetzlich noch, das der Taster nur dann eine Wirkung hat wenn der Motor steht. Das selbe machst du ja auch beim Magneten.
Allerdings braucht man glaube ich beim Magneten keine Flankenerkennung, da der Motor nach dem Stopp immer etwas nach dreht und somit den Magnet wieder frei gibt.

const byte:
Ich komme mit den Variablen "const byte" nicht ganz zurecht und beim pruefen wird dort ein Fehler angezeigt. Ich habe das mal so veraendert wie es fuer mich einfacher klingt. Im Prinzip muesste es nach meiner Aenderung gleich sein wie von dir.

Ich Bedanke mich nochmals fuer deine Muehe.

Gruss Michael

const int buttonPin = 3;
const int MagnetPin = 2;
const int MosfetPin = 4;



int motorStatus = 0;                               // Variable für Zustand der Statemachine
//const byte AUS = 0;                                    // mögliche Zustände der Statemachine
//const byte AN = 1;

boolean nowbutton;                                    // aktuell gelesener Tasterzustand
boolean lastbutton;                                     // letzter gelesener Tasterzustand
boolean buttonpressed;                               // true: Taster wurde gedrückt

boolean nowMagnet;                                   // gleiches für Magneteingang
boolean lastMagnet;
boolean Magnetreached;


void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(MagnetPin, INPUT);
  pinMode(MosfetPin, OUTPUT);
}

void loop()
{
  // Flankenerkennung des Tasters
  nowbutton = digitalRead(buttonPin);
  if (lastbutton == LOW && nowbutton == HIGH) {             // steigende Flanke Taster wurde gedrückt
    buttonpressed = true;
  } else {
    buttonpressed = false;
  }
  lastbutton = nowbutton;


  // Flankenerkennung des Magneten
  nowMagnet = digitalRead(MagnetPin);
  if (lastMagnet == LOW && nowMagnet == HIGH) {             // steigende Flanke bei Erreichen des Magneten
    Magnetreached = true;
  } else {
    Magnetreached = false;
  }
  lastMagnet = nowMagnet;


  switch (motorStatus) {
    case 0: // stopp
      digitalWrite(MosfetPin, LOW);
      if (buttonpressed) motorStatus = 1;               // Wenn Taster gedrückt wurde, Zustand wechseln.
    break;

    case 1: // vorwärts
      digitalWrite(MosfetPin, HIGH);
      if (Magnetreached) motorStatus = 0;                     // Wenn Magnet erreicht wurde, Zustand wechseln.
    break;
  }
}

Vorher wurde gesagt das ich 1 und 0 nicht benutzen darf. Beim Trinket sind doch von 0 bis 4 alles Digitale In und Outs

Sorry, den Satz hatte ich überlesen :frowning:

Das mit 0/1 gilt für die Standard Arduinos wie UNO und Mega

michi243:
Vielen Dank fuer deine Muehe trotzdem hab ich mehrere Fragen dazu. Ich haette mein Programm natuerlich vorher pruefen sollen. Leider kann ich es erst am Donnerstag testen, da mein Trinket abgeraucht ist :roll_eyes: .

Vorher wurde gesagt das ich 1 und 0 nicht benutzen darf. Beim Trinket sind doch von 0 bis 4 alles Digitale In und Outs.

muss ich passen, trinket kenn ich nicht

michi243:
Ich habe noch ein Verstaendnisproblem bei den Flankenerkennungen und bei "const byte".

Das funktioniert auch so, wie du es machst.
die Deklaration "const byte AN = 1;" bewirkt nur, dass ich unten in der Statemachine anstelle "case 1:" schreiben kann "case AN:". Das macht bei größeren Statemachines die Sache übersichtlicher.

michi243:
Flankenerkennung:

Das Adafruit wiederholt den Loop oder das Programm ja steandig. Ich versteh nicht ganz wann genau der "lastbutton" wieder den Wert "Low" bekommt. Oder bekommt der "lastbutton" immer dann ein "low" sobald ich den Button wieder loslasse? Sprich ueber diese Bedingung regelst du, dass man den Schalter nicht dauerhaft gedrueckt halten kann.

Über die Flankenerkennung wird die Variable "buttonpressed" genau für einen loopdurchlauf auf true gesetzt, wenn der Taster gedrückt wurde. Und genau dann, wenn buttonpressed true ist, wechselt der State.

Loop Taster nowbutton lastbutton buttonpressed
1 offen LOW LOW false
2 offen LOW LOW false
3 geschl. HIGH LOW TRUE
4 geschl. HIGH HIGH false
5 geschl. HIGH HIGH false
6 offen LOW HIGH false
7 offen LOW LOW false

michi243:
In der If Bedingung vom "motorStatus" pruefst du dann zusaetzlich noch, das der Taster nur dann eine Wirkung hat wenn der Motor steht. Das selbe machst du ja auch beim Magneten.
Allerdings braucht man glaube ich beim Magneten keine Flankenerkennung, da der Motor nach dem Stopp immer etwas nach dreht und somit den Magnet wieder frei gibt.

Wenn das sicher und immer so ist, kannst du das auch weglassen. Aber besser ist es.

michi243:
const byte:
Ich komme mit den Variablen "const byte" nicht ganz zurecht und beim pruefen wird dort ein Fehler angezeigt. Ich habe das mal so veraendert wie es fuer mich einfacher klingt. Im Prinzip muesste es nach meiner Aenderung gleich sein wie von dir.

Es sollte so auch funktionieren, aber ich verstehe nicht, warum da ein Fehler angezeigt wird. Welche IDE Version hast du?

michi243:
Ich Bedanke mich nochmals fuer deine Muehe.

Gerne

guntherb:
aber ich verstehe nicht, warum da ein Fehler angezeigt wird. Welche IDE Version hast du?

Gefunden!
Ich hatte noch die 1.6.7. Mit der 1.6.10 gibt es Fehlermeldung.
Ist auch logisch. Weil "AUS" verwendet wird, bevor es deklariert wird.

int motorStatus = AUS;                               // Variable für Zustand der Statemachine
const byte AUS = 0;                                    // mögliche Zustände der Statemachine
const byte AN = 1;

Wenn man die Reihenfolge ändert, gehts:

const byte AUS = 0;                                    // mögliche Zustände der Statemachine
const byte AN = 1;
int motorStatus = AUS;                               // Variable für Zustand der Statemachine

Aber es dient sowieso nur der besseren Lesbarkeit des Codes.

So hab den Code endlich ausprobieren koennen. Hat allerdings erst richtig funktioniert als ich die Flankenerkennung vom Magnet komplett entfernt habe.

Ich habe noch eine weitere Frage: Ist es moeglich die Zykluszeit also den Loop zu verkuerzen ?
Den ich kann den Taster erst wieder betaetigen wenn der Loop 3 mal durchgelaufen ist. So hast du es mir erklaert oder liegt die lange Wartezeit zwischen Stop und erneutem Anlaufen an etwas anderem ?

Mein Kristallkugel sagt:
Du hast die Pulldown an den Tastern vergessen.

Hab ich dran daran kann es nicht liegen. Ich denke nur der Loop wird bei so einem kurzem Programm doch so schnell durch sein, dass ich doch eigentlich vom Motorstillstand bis zum erneuten anlaufen keine Verzoegerung haben duerfte.

So nun funktioniert alles wie es soll :slight_smile: . Danke nochmal an alle die geholfen haben. Gunther hatte wohl doch recht, ohne Flankenerkennung vom Magnet gings halt nicht :wink: . Ich mach das vollstaendige Programm unten nochmal rein, wenn es mal jemanden interessiert. Thread kann geschlossen werden.

Gruss Michael

const int buttonPin = 0;
const int MagnetPin = 2;
const int MosfetPin = 4;
const int LedPin    = 1;


int motorStatus = 0;                               // Variable für Zustand der Statemachine

boolean nowbutton;                                    // aktuell gelesener Tasterzustand
boolean lastbutton;                                     // letzter gelesener Tasterzustand
boolean buttonpressed;                               // true: Taster wurde gedrückt

boolean nowMagnet;                                   // gleiches für Magneteingang
boolean lastMagnet;
boolean Magnetreached;


void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(MagnetPin, INPUT);
  pinMode(MosfetPin, OUTPUT);
}

void loop()
{
  // Flankenerkennung des Tasters
  nowbutton = digitalRead(buttonPin);
  if (lastbutton == LOW && nowbutton == HIGH) {             // steigende Flanke Taster wurde gedrückt
  digitalWrite(MosfetPin, HIGH);
   digitalWrite(LedPin, HIGH);
  }
  lastbutton = nowbutton;


  // Flankenerkennung des Magneten
  nowMagnet = digitalRead(MagnetPin);
  if (lastMagnet == LOW && nowMagnet == HIGH) {             // steigende Flanke bei Erreichen des Magneten
  digitalWrite(MosfetPin, LOW);
  digitalWrite(LedPin, LOW);
  delay (30);
  }
  lastMagnet = nowMagnet;
 
}