Counter und Schrittmotor

Hallo zusammen ich bin immer noch an meinem Projekt mit der Uhr.
Hier die Aufgabe:

Ein Pulsgeber (Quarzuhr) gibt dem Arduino Impulse, nach einer bestimmten Impulszahl (hier im Beispielsketch sind es 5) Schaltet der Arduino 2 Schrittmotoren.
Ich hab das ganze mal mit untenstehendem Sketch soweit hinbekommen. Das Problem ist jedoch, dass die Impulse während die Schrittmotoren ihre Bewegungen ausführen, weiterzählen sollte. In diesem Beispiel stopt der Zählvorgang und geht nach Vollendung der Schrittmotorenbewegung wieder in Ausgangslage.
Hat jemand eine Idee wie ich dad ändern könnte?

#include <Stepper.h>

int button1 = A4; //button pin, connect to ground to move servo
bool press1 ;
bool oldpress1 = false;
bool sweep1state = false;


int switchPin = A4;              // switch is connected to pin A4
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;          // how many times the button has been pressed

int stepCount = 0;

const int stepsPerRevolution = 4;  // change this to fit the number of steps per revolution
// for your motor

// initialize the stepper library on pins 5 through 8 and 9 through12:
Stepper myStepper(stepsPerRevolution, 5, 6, 7, 8);
Stepper myStepper2(stepsPerRevolution, 9, 10, 11, 12);

void setup() {

  digitalWrite(A4, HIGH);


  pinMode(switchPin, INPUT);    // Set the switch pin as input
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state

  myStepper.setSpeed(1500);
  myStepper2.setSpeed(1500);

  
  #define STEPS 48

}

void loop() {
  val = digitalRead(switchPin);        // read input value and store it in val
  if (val != buttonState) {            // the button state has changed!
    if (val == LOW) {                  // check if the button is pressed
      buttonPresses++;                 // increment the buttonPresses variable
      Serial.print("Button has been pressed ");
      Serial.print(buttonPresses);
      Serial.println(" times");


      if (buttonPresses >= 5)
      
      {
        myStepper2.step(-340);      // Kelle wird herunter geklappt
        myStepper.step(340);        // Kelle bewegt sich um 30 Grad
       
        myStepper2.step(340);       // Neue Kelle wird hochgedrückt
      
        digitalWrite(5, LOW);       // Nimmt den Schrittmotor vom Strom
        digitalWrite(6, LOW);
        digitalWrite(7, LOW);
        digitalWrite(8, LOW);
        Serial.println(" off");
        
        
        {
          buttonPresses = 0;
          oldpress1 = press1; 

        }
      }
    }

  }
         buttonState = val;                 // save the new state in our variable

}

Nimm Accelstepper oder die MoBaTools anstelle von Stepper.

Gruß Tommy

Die lösen das Problem? Der Sketch war etwas ein Gebastel und ich habs erst nach langem rumprobieren soweit bekommen mit der Stepper-Bibliothek. Mit den neuen angegebenen Bibliotheken müsste ich allerdings ganz von vorne anfangen.

Draht:
Mit den neuen angegebenen Bibliotheken müsste ich allerdings ganz von vorne anfangen.

Das ist ein normaler Vorgang in der Softwareentwicklung. Ja, die blockieren nicht.

Gruß Tommy

Draht:
Das Problem ist jedoch, dass die Impulse während die Schrittmotoren ihre Bewegungen ausführen, weiterzählen sollte.

Das Problem der stepper.h ist, dass sie während der Bewegung des Schrittmotors blockiert. Du kannst Dann also nichts anderes machen bis die Bewegung beendet ist. Das ist bei den von Tommy vorgeschlagenen Libs nicht so. Da läuft dein Sketch während der Schrittmotorbewegung weiter.

@ Tommy56 und MicroBahner Danke euch. Dann wird mir wohl oder übel nix anderes übrig bleiben und verschwinde in die Klausur. Mal sehen, ob ich das hin bekomme :o

Nimm die MoBaTools, da ist der Autor hier im Forum, wenn Du Fragen hast. :wink:

Gruß Tommy

Tommy56:
Nimm die MoBaTools, da ist der Autor hier im Forum, wenn Du Fragen hast. :wink:

Gruß Tommy

Danke für den Tip! :wink:

Ich hab jetzt mal folgenden Experimentier-Sketch im Versuchsaufbau um Mobatools kennen zu lernen.
Nun versuche ich mit dem Schrittmotor einen 360 grad drehung hinzubekommen, sodass er wieder zurück am Ausgangsort ist. Irgend wie scheint er aber immer das Ziel um ein paar Grade oder Steps zu überschiessen. Was mag da wohl nicht stimmen?

[code]/*  Demo zum Anschluß eines unipolaren Stepmotors 28BYJ-48
    mit Verwendung einer Beschleunigungsrampe
    Dieses Beispiel läuft nicht auf ESP8266
        Danke an 'agmue' vom arduino.cc Forum für dieses Beispiel
*/
/* Demo for connecting a unipolar stepper motor 28BYJ-48 with use of an acceleration ramp
   This example does not run on ESP8266
*/
#include <MobaTools.h>
const int FULLROT1 = 400;
MoToStepper Step1(FULLROT1);          // HALFSTEP ist default



int button1 = 4; //button pin, connect to ground to move servo
bool press1 ;
bool oldpress1 = false;
bool sweep1state = false;

int switchPin = 4;              // switch is connected to pin 4
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;

int stepCount = 0;


void setup() {

  pinMode(button1, INPUT_PULLUP);

  Step1.attach( 0, 1, 2, 3 ); // Anschluß an digitalen Ausgängen; Treiber IN1,IN2,IN3,IN4
  //Step1.attach( SPI_1 );        // alternativ über SPI
  Step1.setSpeed(600);        // = 24 U/Min


}

void loop()

{


  press1 = digitalRead(button1);  // check button1
  if (press1 == LOW && oldpress1 == HIGH) // test if button has been pressed
  {
    sweep1state = HIGH;         // if yes
  }
  if (sweep1state == HIGH)

  {

    Step1.doSteps(4096);

    sweep1state = LOW;

  }
    oldpress1 = press1;
}

[/code]

Bei diesen kleinen Steppern gibt es verschiedene Varianten ( die nicht als solche gekennzeichent sind ) und bei denen die Getriebeübersetzung nicht unbedingt genau 1:64 ist. Manchmal sind es nur 1:63,irgendwas . Wenn Du nun exakt 4096 Steps machst, ist das in dem Fall immer etwas mehr als eine Umdrehung, und das addiert sich mit jeder weiteren Umdrehung.
Wenn Du wirklich wissen willst, ob die Software die Zahl der Steps richtig ausgibt, musst Du erst z.B. 4096 Steps vorwärts, und dann wieder 4096 Steps zurück machen. Vielleicht auch mal mit unterschiedlichen Zahlen hin und her, aber so, dass die Gesamtsumme am Ende wieder 0 ergibt. Dann hebt sich dieser Fehler wieder auf, und Du musst genau am Ausgangspunkt ankommen ( evtl. um das Getriebespiel versetzt, aber das addiert sich nicht, wenn Du das mehrfach hin- und her machst. )
Oder Du brauchst einen Stepper, von dem Du wirklich exakt weist, wieviel Steps/Umdrehung der macht.

@MicroBahner

Vielen Dank für Die Antwort. Dann werde ich mal etwas probieren.

Komme leider auf kein Ergebnis. Habe verschiedene Steps eingestellt und bei mehreren umdrehungen in die gleiche Richtung (das ist das was ich am Schluss brauche) geht er manchmal vor ist wieder genau und dann hintennach. Irgendwie willkürlich!

Ein paar Dinge fallen mir bei deinem Sketch auf:

    • Du nutzt die Pins 0 und 1. Das sind bei UNO Nano und Mega die Pins zur Kommunikation mit dem PC, die sollte man micht nutzen ( Ich weis nicht, welchen Arduino Du verwendest ).
  1. Du entprellst deinen Taster nicht. Damit wird das doSteps u.U. in kurzer Folge mehrfach aufgerufen. Da doSteps immer ab dem Punkt gilt, an dem sich der Stepper gerade befindet, und dann vom ersten Aufruf vielleicht schon einpaar Steps ausgeführt wurden, ist das ungenau.

  2. Du sagst den MobaTools beim Einrichten, dass der Stepper nur 400 Steps / Umdrehung braucht.

Noch ein Hinweis: Auf dem Treiberplatinchen für den kleinen Stepper sind ja LED's, die das Ansteuermuster für den Stepper visualisieren. Im Fullstep sind das 4 verschiedene Muster, im Halfstep 8. Bei einer vollen Umdrehung ( im Fullstep 2048 Schritte, im Halfstep 4096 ) muss am Ende der Bewegung immer wieder das gleiche Muster zu sehen sein, da die Zahl der Schritte ein vielfaches von 4 bzw. 8 ist.
Und bedenke, dass der Aufruf von doSteps() nicht blockierend ist. Dein Sketch läuft danach sofort weiter ( noch bevor der erste Step an den Motor ausgegeben wird ). Deshalb musst Du unbedingt den Taster entprellen! Dein sweep1state bringt da gar nichts und ist eigentlich vollkommen nutzlos.

Vielen Dank MicroBahner für die vielen Inputs. Es scheint, da hab ich ja noch etwas Stoff mit dem ich mich befassen Muss :wink:

MicroBahner du hattest recht! Das mit den Verschiebungen hatte wirklich mit den unentprellten Schalter zu tun. Da ich, jedoch am Schluss die Sache mit einem Counter auslösen werde, sollte das dann nicht das Problem sein.

Dann kann's ja jetzt weitergehen :wink:
Und immer dran denken: die MobaTools Methoden kehren alle immer sofort zurück, die blockieren nicht. Die eigentliche Ansteuerung des Steppers geschieht im Hintergrund per Interrupt. Da muss man manchmal etwas umdenken 8).

Im Moment sieht mein Sketch so aus:

#include <MobaTools.h>


int button1 = 4; //button pin, connect to ground to move servo

int switchPin = 4;              // switch is connected to pin 4
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;          // how many times the button has been pressed

int stepCount = 0;

const int FULLROT1 = 4096;
MoToStepper Step1(FULLROT1);           // HALFSTEP ist default



const byte stPn[] = { 5, 6, 7, 8 }; // bei bipolarem Stepper (4-Draht) über ein H-Brücke müssen
// gegebenenfalls die inneren Pins vertauscht werden
// ( oder entsprechend verdrahten )
// Spule 1: 1. und 3. Pin
// Spule 2: 2. und 4. Pin

void setup() {
  Step1.attach( 5, 6, 7, 8 );
  Step1.setSpeed(50);

  pinMode(button1, INPUT_PULLUP);
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state

  digitalWrite(4, HIGH); //enable pullups to make pin high
  pinMode(LED_BUILTIN, OUTPUT);


}

void loop() {

  val = digitalRead(switchPin);      // read input value and store it in val
  if (val != buttonState) {          // the button state has changed!
    if (val == LOW) {                // check if the button is pressed
      buttonPresses++;               // increment the buttonPresses variable
      Serial.print("Button has been pressed ");
      Serial.print(buttonPresses);
      Serial.println(" times");
      delay(500);


    

      if (buttonPresses >= 5)
      {

        Step1.write(45);

        {

          if (buttonPresses >= 6)
            buttonPresses = 0;

        }
      }
    }

  }
  buttonState = val;


}

Bei 6 ButtonPresses dreht der Schrittmotor um 30 Grad und der Counter beginnt nach 6 buttonPresses wieder bei Null. Beim 2. und weiteren Durchgängen führt der Schrittmotor die 30 Grad-Bewegung aber nicht mehr aus. Was mach ich da falsch?

Ok hab die Lösung für dieses Problem. Statt Step1.write() musste ich step1.doSteps() nehmen. Weiter gehts!

Also hier ist mein Sketch wie ich mir das in etwa vorgestellt habe.

/******************************************************************
   Demo zum Anschluß eines unipolaren Stepmotors 28BYJ-48 ( über SPI )
  und eines Standard bipolaren Steppers über 4 Pins und eine H-Brücke.
  Dieses Beispiel läuft nicht auf ESP8266!

  Der Schrittmotor kann wahlweise direkt über 4 frei wählbare Pins, oder über die SPI-
  Schnittstelle und Schieberegister angeschlossen werden.
  SPI belegt beim UNO oder nano die Pins 10(SS),11(MOSI) und 13(SCK)
  Pin 12 (MISO) wird zwar nicht genutzt, aber von der HW belegt
*/
/*******************************************************************
  Demo for connecting a unipolar stepper motor 28BYJ-48 ( via SPI ) and a standard bipolar stepper
  via 4 pins and a H-bridge.  This example does not run on ESP8266!

  The stepper motor can be connected either directly via 4 freely selectable pins, or via the SPI
  interface and shift register (see circuit diagram in documentation).
  SPI occupies the pins 10(SS), 11(MOSI) and 13(SCK) of the UNO or nano.
  Pin 12 (MISO) is not used, but is occupied by the hardware
  In this example Step1 is connected directly while Step2 is connected via SPI.

  Translated with www.DeepL.com/Translator (free version)
*/
#include <MobaTools.h>


int button1 = 4; //button pin, connect to ground to move servo

int switchPin = 4;              // switch is connected to pin 4
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;          // how many times the button has been pressed

int stepCount = 0;

const int FULLROT1 = 4096;
MoToStepper Step1(FULLROT1); 
MoToStepper Step2(FULLROT1);   // HALFSTEP ist default



void setup() {

  pinMode(button1, INPUT_PULLUP);

   
  Step1.attach( 5, 6, 7, 8 );
  Step1.setSpeed(50);

  Step2.attach( 9, 10, 11, 12 );
  Step2.setSpeed(50);

  pinMode(button1, INPUT_PULLUP);
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state

  digitalWrite(4, HIGH); //enable pullups to make pin high
  pinMode(LED_BUILTIN, OUTPUT);


}

void loop() {

  val = digitalRead(switchPin);      // read input value and store it in val
  if (val != buttonState) {          // the button state has changed!
    if (val == LOW) {                // check if the button is pressed
      buttonPresses++;               // increment the buttonPresses variable
      Serial.print("Button has been pressed ");
      Serial.print(buttonPresses);
      Serial.println(" times");
      delay(500);

      if (buttonPresses >= 60)
      {

        Step1.doSteps(512); 
        delay(2000);
        Step2.doSteps(512);
        delay(2000);
        Step2.doSteps(-512);
        delay(2000);
        Step1.detach();
        Step2.detach();
        
        buttonPresses = 0;
      
          }
        
      }
    }

  buttonState = val;