Probleme mit Schrittmotor und Accelstepper-lib

  1. Das ist 1 zu 1 der Code den der Thread-opener gepostet hat. Also gar nicht mein Code.

völliges Missverständnis - wahrscheinlich verursacht durch blitzschnelles "an die Decke gehen" und dann nicht mehr genau lesen.

Also gut man kann es natürlich noch deutlicher ausdrücken:
Jetzt wäre interessant wenn du Links zu den ANDEREN Beispielen in denen WOKWI "versagt" hat posten würdest.

Es ging gar nicht um meine Simulation sondern um deine Aussage

Und die solltest du durch weitere andere Beispiele belegen.
Hast du dann an einem Beispiel gemacht.

Mal wieder so eine allgemein gehaltene Aussage ohne Substanz. Das im Detail zu begründen dazu bist du wohl auch zu bequem!

Nun mal zurück zum Code:
Den habe ich mir beim Erstellen der WOKWI-Simulation nicht im Detail angeschaut.

Da wird setSpeed mit unterschiedlichen Sachen aufgerufen und an einer Stelle ist wohl eine Klammer falsch gesetzt

    myStepper.setSpeed((500 / Direction)) * 4;

mal 4 hinter der letzten Klammer macht keinen Sinn. Das sollte wohl in der Klammer sein.
und hier wird anders berechnet

myStepper.setSpeed(Direction * 4);

klar das da andere Geschwindigkeiten herauskommen.

Und dann habe ich mir die Doku zum WOKWI-"Analog-Joystick angeschaut.
Das ist in der Tat armselig: Der Joystick gibt nur 0 oder 512 oder 1023 aus.
Das ist nicht analog, auch nicht digital man könnte es vielleicht trigital nennen.

So neue WOKWI-Simulation mit Schieberegler Poti. Das kann man per Cursor links/rechts sehr feinfühlig bewegen.

In Sachen genau zu begründen und direkt Details zu nennen gibt es bei dir noch eine Menge Optimierungspotential. Aber dazu bist du wohl auch zu bequem.
Hauptsache schnell draufgehauen.

Wenn dir die Zeit zu schade ist, dann lass eine direkte Antwort einfach gleich sein.

vgs

Hallo Leute
Ich habe inzwischen die gesamte Elektronik definitiv verbaut. Also ein Gehäuse für die Steuerung und von dort ein mehradriges Kabel zum Stepper. Nun funktioniert der Code, bzw. der Atmega328 nicht mehr so wie er sollte. Sobald ich einen Button drücke, stürzt das Programm ab, bzw. hängt sich auf. Hat jemand ne Ahnung weshalb?
Nachfolgend der aktuelle Code:

#include <MobaTools.h>

// Adjust pins, steps and time as needed
const byte stepPin = 3;
const byte dirPin  = 2;
const int stepsPerRev = 400;   // Steps per Revolution ( example with 1/4 microsteps )
const long  targetPos = 1600;         // stepper moves between 0 and targetpos
int enable = 10;
long nextPos;
long Speed;
long Ramp;
long Last = 0;
long SpeedVal = A1;
long RampVal = A0;
long PotVal;
long JoyStick = A2;
long Direction;
long SetZero = 5;
long GoToZero = 6;
long ActualStep;
long SetTarget = 7;
long GoToTarget = 8;
long TargetPosition;



MoToStepper myStepper ( stepsPerRev, STEPDIR );
MoToTimer stepperPause;                    // Pause between stepper moves
bool stepperRunning;

void setup() {
  Serial.begin(9600);
  myStepper.attach( stepPin, dirPin );
  myStepper.setSpeed( 2000 );  // 60 Rev/Min ( if stepsPerRev is set correctly )
  myStepper.setRampLen( 50 );
  stepperRunning = true;
  pinMode(enable, OUTPUT);
  pinMode(PotVal, INPUT);
  pinMode(JoyStick, INPUT);
  pinMode(SetZero, INPUT_PULLUP);
  pinMode(GoToZero, INPUT_PULLUP);
  pinMode(SetTarget, INPUT_PULLUP);
  pinMode(GoToTarget, INPUT_PULLUP);
  pinMode(SpeedVal, INPUT);
  pinMode(RampVal, INPUT);
  digitalWrite(enable, LOW);
  
}

void loop() {
  
Direction = analogRead(JoyStick);         //read value of Joystick
//ActualStep = myStepper.read();            //read the actual step of the motor
Ramp = analogRead(RampVal);
myStepper.setRampLen(Ramp);




if(Direction <= 500) {                    //move the stepper CW infinitively

  Direction = map(Direction, 0, 500, 1024, 0);
  myStepper.setSpeed(Direction*2);
  myStepper.rotate(1);

}
else if(Direction >= 520) {               //move the stepper CCW infinitively

  //Serial.println(Direction*4); 
  myStepper.setSpeed(Direction*2);
  myStepper.rotate(-1);

}
else {
  myStepper.stop();
    }


Speed = (analogRead(SpeedVal)*2);



if(Speed != Last) {
myStepper.setSpeed(Speed);
Last = Speed;
}


if((digitalRead(SetZero)) == LOW) {         //read the button state to setzero
  myStepper.setZero(0);
}

if((digitalRead(SetTarget)) == LOW) {       // read button to set the target position
  TargetPosition = myStepper.read();
}

if((digitalRead(GoToZero)) == LOW) {        //read the go to zero button state
  
  myStepper.write(0);
  myStepper.setSpeed(Speed);
  while(myStepper.moving());
  
    }
  

if((digitalRead(GoToTarget)) == LOW) {           // read the go to target switch
  myStepper.write(TargetPosition);
  myStepper.setSpeed(Speed);
  while(myStepper.moving());
   
  }
}


  // The sketch is not blocked while the stepper is moving nor while it is stopped.
  // Other nonblocking  tasks can be added here

Hat denn genau der gleiche Code vor dem Verkabeln funktioniert?

Stürzt ab / hängt sich auf auf ist eine unpräzise Beschreibung
Setze Serial.println() in den Code um die "Absturzstelle" einzukreisen

Es hat etwas mit dem Speed und der Ramp zu tun. Vor dem Verkabeln hatte ich nicht gross an Speed und Ramp verändert. Jetzt läuft der Code gut. Nur bewegt sich der Stepper manchmal beim Bewegen mit dem Joystick plötzlich viel zu langsam. Dies obwohl ich für den Joystick-Betrieb ja einen eigenen Speed festlege. Irgendwie wird da was vermischt, dass es nicht sollte.

Ja wat denn nu ? stürzt ab oder code läuft gut??

Hier ist eine Code-Version die serial debugging macht.
Setze die baudrate im Serial Monitor auf 115200

Noch was:
Mit der Tastenkombination Strg-T kannst du den code automatisch formatieren lassen
Code-Blöcke werden durch Einrückung dargestellt NICHT durch möglichst viel Leerzeilen

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *



#include <MobaTools.h>

// Adjust pins, steps and time as needed
const byte stepPin = 3;
const byte dirPin  = 2;
const int stepsPerRev = 400;   // Steps per Revolution ( example with 1/4 microsteps )
const long  targetPos = 1600;         // stepper moves between 0 and targetpos
int enable = 10;
long nextPos;
long Speed;
long Ramp;
long Last = 0;
long SpeedVal = A1;
long RampVal = A0;
long PotVal;
long JoyStick = A2;
long Direction;
long SetZero = 5;
long GoToZero = 6;
long ActualStep;
long SetTarget = 7;
long GoToTarget = 8;
long TargetPosition;



MoToStepper myStepper ( stepsPerRev, STEPDIR );
MoToTimer stepperPause;                    // Pause between stepper moves
bool stepperRunning;

void setup() {
  Serial.begin(115200);
  myStepper.attach( stepPin, dirPin );
  myStepper.setSpeed( 2000 );  // 60 Rev/Min ( if stepsPerRev is set correctly )
  myStepper.setRampLen( 50 );
  stepperRunning = true;
  pinMode(enable, OUTPUT);
  pinMode(PotVal, INPUT);
  pinMode(JoyStick, INPUT);
  pinMode(SetZero, INPUT_PULLUP);
  pinMode(GoToZero, INPUT_PULLUP);
  pinMode(SetTarget, INPUT_PULLUP);
  pinMode(GoToTarget, INPUT_PULLUP);
  pinMode(SpeedVal, INPUT);
  pinMode(RampVal, INPUT);
  digitalWrite(enable, LOW);
}

void loop() {

  Direction = analogRead(JoyStick);         //read value of Joystick
  //ActualStep = myStepper.read();            //read the actual step of the motor
  Ramp = analogRead(RampVal);
  dbgc("Ramp ",Ramp );
  
  myStepper.setRampLen(Ramp);

  if (Direction <= 500) {                   //move the stepper CW infinitively
    Direction = map(Direction, 0, 500, 1024, 0);
    myStepper.setSpeed(Direction * 2);
    myStepper.rotate(1);
  }
  else if (Direction >= 520) {              //move the stepper CCW infinitively
    //Serial.println(Direction*4);
    myStepper.setSpeed(Direction * 2);
    myStepper.rotate(-1);
  }
  else {
    myStepper.stop();
  }
  
  dbgc("Dir",Direction);
  Speed = (analogRead(SpeedVal) * 2);
  dbgc("speed",Speed);
  if (Speed != Last) {
    myStepper.setSpeed(Speed);
    Last = Speed;
  }

  if ( (digitalRead(SetZero) ) == LOW) {        //read the button state to setzero
    dbg("01", digitalRead(SetZero) );
    myStepper.setZero(0);
  }

  if ( (digitalRead(SetTarget) ) == LOW) {      // read button to set the target position
    dbg("02", digitalRead(SetTarget) );
    TargetPosition = myStepper.read();
  }

  if ( (digitalRead(GoToZero) ) == LOW) {       //read the go to zero button state
    dbg("03", digitalRead(GoToZero) );
    myStepper.write(0);
    myStepper.setSpeed(Speed);
    while (myStepper.moving() ) {
      dbgi("04 zero moving", myStepper.read(), 1000);
    }
  }

  if ( (digitalRead(GoToTarget) ) == LOW) {          // read the go to target switch
    dbg("05", digitalRead(GoToTarget) );
    myStepper.write(TargetPosition);
    myStepper.setSpeed(Speed);
    while (myStepper.moving() ) {
      dbgi("06 target moving", myStepper.read(), 1000);
    }
  }
}


// The sketch is not blocked while the stepper is moving nor while it is stopped.
// Other nonblocking  tasks can be added here

vgs

Hallo StefanL38
Der Code läuft. Ich hatte vorhin dummerweise etwas zu rasch in die Tasten gegriffen. Ein Phänomen gibt es allerdings noch. Wenn ich den Speed für "GoToZero" und "GoToTarget" runterdrehe, läuft der Stepper im Joystick-Modus plötzlich auch langsamer. Dies obwohl ich für den Joystick-Mode den Speed anhand des Joystick-Potis vorgebe...

Das ist genau das was du programmiert hast.
Du solltest Programmieren lernen. Nicht nur posten.

Jetzt klappere mal alle

myStepper.setSpeed(

Befehle ab und untersuche ob die IMMER ausgefüht werden oder nur wenn bestimmte Bedingungen erfüllt sind

Dein Problem ist, dass Du die Modi im Programm nicht ordentlich unterscheidest. Das geht im loop() munter durcheinander. Du solltest exakt definieren, wann welcher Modus aktiv ist, und dann auch nur diese entsprechenden Programmteile aktiv im loop() durchlaufen.
Sowas nennt sich 'Zustandsautomat' oder 'finite state machine'. Danach kannst Du gern mal googeln. Mit der Programmierttechnik kannst Du viele Probleme lösen - deshalb lohnt es sich, sich damit zu beschäftigen :wink:
Kleiner Tip: die 'switch' Anweisung ist ein perfektes Hilfsmittel um einen einmal defnierten Zustandsautomaten programmtechnisch umzusetzen.

Danke für deinen Input MicroBahner! Ich werde foglich den ganzen Code in einer switch case Strukur neu aufbauen.
In der Zwischenzeit habe ich aber noch ein Phänomen, das ich nicht verstehe. Mein Display printet nämlich komische Werte für "Speed" und "Ramp". Je nach Poti-Stellung geht z.B. "Ramp" über 5000. Dieser Wert ist aber rein mathematisch gar nicht möglich. Der Serial Monitor hingegen gibt mir an diesen Stellen immer die korrekten Werte aus.
Nachfolgend der aktuelle Code:


*/
#include <MobaTools.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeMono9pt7b.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);

// Adjust pins, steps and time as needed
const byte stepPin = 3;
const byte dirPin  = 2;
const int stepsPerRev = 400;   // Steps per Revolution ( example with 1/4 microsteps )
//const long  targetPos = 1600;         // stepper moves between 0 and targetpos
int enable = 10;
long nextPos;
unsigned long Speed;
unsigned long Ramp;
unsigned long Last = 0;
unsigned long LastR = 0;
unsigned long SpeedVal = A1;
unsigned long RampVal = A0;
unsigned long PotVal;
long JoyStick = A2;
long Direction;
long SetZero = 5;
long GoToZero = 6;
long ActualStep;
long SetTarget = 7;
long GoToTarget = 8;
long TargetPosition;

unsigned long currentMillis;
unsigned long startMillis;
const unsigned long period = 1000;



MoToStepper myStepper ( stepsPerRev, STEPDIR );
MoToTimer stepperPause;                    // Pause between stepper moves
bool stepperRunning;

void setup() {
  Serial.begin(9600);
  myStepper.attach( stepPin, dirPin );
  myStepper.setSpeed( 2000 );  // 60 Rev/Min ( if stepsPerRev is set correctly )
  myStepper.setRampLen( 50 );
  stepperRunning = true;
  pinMode(enable, OUTPUT);
  pinMode(PotVal, INPUT);
  pinMode(JoyStick, INPUT);
  pinMode(SetZero, INPUT_PULLUP);
  pinMode(GoToZero, INPUT_PULLUP);
  pinMode(SetTarget, INPUT_PULLUP);
  pinMode(GoToTarget, INPUT_PULLUP);
  pinMode(SpeedVal, INPUT);
  pinMode(RampVal, INPUT);
  digitalWrite(enable, LOW);

  delay(500);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  delay(2000);
  display.clearDisplay();

  //display.setFont(&FreeMono9pt7b);
  display.setTextSize(1.5);
  display.setTextColor(WHITE,BLACK);
  display.setCursor(0, 5);
  // Display static text
  display.println("Current:");
  display.setCursor(70,5);
  display.println("Target:");
  display.setCursor(0,40);
  display.println("Speed:");
  display.setCursor(70,40);
  display.println("Ramp:");
  display.display();

  startMillis = millis();
}

void loop() {

  Direction = analogRead(JoyStick);         //read value of Joystick


  const int SMOOTH_FACTOR1 = 5;
  Ramp = (Ramp - (Ramp >> SMOOTH_FACTOR1)) +((analogRead(RampVal) * 2) >> SMOOTH_FACTOR1);

  if (Ramp != LastR) {
    myStepper.setRampLen(Ramp);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(70, 50);
    display.print(Ramp);
    display.display();
    LastR = Ramp;
  }
  
  
  const int SMOOTH_FACTOR2 = 6;
  Speed = (Speed - (Speed >> SMOOTH_FACTOR2)) +((analogRead(SpeedVal) * 2) >> SMOOTH_FACTOR2);

  if (Speed != Last) {
    
    myStepper.setSpeed(Speed);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 50);
    display.println(Speed);
    display.display();
    Last = Speed;
  }



currentMillis = millis();

if(currentMillis - startMillis >= period) {
  
    
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 20);
    long CurrentStep = myStepper.read();
    display.println(CurrentStep);
    display.setCursor(70, 20);
    display.println(TargetPosition);
    display.display();
    startMillis = currentMillis;
}

  if (Direction <= 500) {                   //move the stepper CW infinitively

    Direction = map(Direction, 0, 500, 1024, 0);
    myStepper.setSpeed(Speed);
    myStepper.rotate(1);

  }
  else if (Direction >= 520) {              //move the stepper CCW infinitively

    myStepper.setSpeed(Speed);
    myStepper.rotate(-1);

  }
  else {
    myStepper.stop();
  }




  if ((digitalRead(SetZero)) == LOW) {        //read the button state to setzero
    myStepper.setZero(0);
  }

  if ((digitalRead(SetTarget)) == LOW) {      // read button to set the target position
    TargetPosition = myStepper.read();
  }

  if ((digitalRead(GoToZero)) == LOW) {       //read the go to zero button state

    myStepper.write(0);
    myStepper.setSpeed(Speed);
    while (myStepper.moving());

  }


  if ((digitalRead(GoToTarget)) == LOW) {          // read the go to target switch
    myStepper.write(TargetPosition);
    myStepper.setSpeed(Speed);
    while (myStepper.moving());

  }

}

Lieber Laurin,

das einzige Serial.print was dein Code in Post # 29 macht ist das hier

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }

das bedeutet: entweder du hast einen anderen Code gepostet.
Oder du beziehst dich auf einen anderen Code.
Es mag sein das du 1000% davon überzeugt bist, dass diese beiden Codes
einmal mit Serial.print und einmal mit display.print sich an dieser Stelle gleich verhalten.

Je mehr Annahmen man macht in der Art

  • "das müsste doch funktionieren"
  • "daran kann es nicht liegen (da habe ich alles gelassen wie es ist)"

desto längr wirst du brauchen den Fehler zu finden.
Also füge deinem code Serial prints hinzu und dann hast du es schwarz auf weiß was da für Werte sind

vgs

Das Problem dürfte auftreten, wenn Du z.B. vormalige 4-stellige Werte mit 3-stelligen überschreibst. Dann bleibt die vierte Stelle das alten Wertes stehen und Du siehst einen gegebenfalls größeren 4-stelligen Wert. Wenn Du z.B. 1000 durch 999 überschreibst, siehst Du 9990. Du musst das Feld vor dem print löschen, oder gegebenenfalls ein( oder mehrere) Leerzeichen anhängen - oder davorstellen ( rechtsbündige Darstellung ). Das geht z.B. mit sprintf rel. einfach.

Du hast speed und ramp als

unsigned long Speed;
unsigned long Ramp;

definiert
bei dieser Rechnung können dann sehr große Werte herauskommen

  Ramp = (Ramp - (Ramp >> SMOOTH_FACTOR1)) + ((analogRead(RampVal) * 2) >>   

  Speed = (Speed - (Speed >> SMOOTH_FACTOR2)) + ((analogRead(SpeedVal) * 2) >> SMOOTH_FACTOR2);

Das hast du bestimmt ohne es gründlich auszutesten ins Programm geschrieben.

Gründlich austesten heißt es für ALLE möglichen Werte durchzutesten.

Und wenn ich schreibe ALLE Werte dann meine ich auch wirklich ALLE Werte auch die die man für "unmöglich" hält.
oder besser ausgedrückt den ganzen Wertebereich abdecken.
Testen was passiert wenn aus welchen Gründen auch immer ramp auf einmal den Wert 400000000 hat

Man braucht dazu keine Schleife die das mit +1 hochzählt. Sondern nur bestimmte Werte
Wert 0, Wert 1000, Wert 10000 Maximalwert eines unsigned long minus 10
2^32 - 1 - 10 = 4294967285

Ada ist im dem fall nicht die beste Lib, mit U8g2 muss man nicht zaubern mit dem löschen, macht das selber, einziges was passieret das die werte bei normalem print "Tanzen" wen von 4 Stellen auf 3 sich ändern.

Ich würde ja gerne auf die U8g2 umstellen, aber mein Display will nicht ;(
Es muss was mit dem Überschreiben zu tun haben. Ich habe die Werte von "Speed" und "Ramp" geprintet. Dort kommen sie wie erwartet an.
Ich konnte aber noch keine Lösung für die korrekte Darstellung finden, bzw. habe mich mit dem constructor von der U8g2 rumgeschlagen

Was für einen micocontroller benutzt du? Poste die exakte Bezeichnung
Poste ein Bild von der Vorderseite und der Rückseite deines Displays
Welche Schnittstelle hat dieses Display? I2C oder SPI?
Poste diese Infos einmal hier unten als Antwort und dann füge sie auch deinem ersten Posting hinzu

vgs

Ich benutze einen Arduino Uno (Atmega328). Das Display ist ein 1,3 Zoll
128x64 von Adafruit. Ich verwende die I2C Schnittstelle (der default). Ich habe nach dem constructor auch schon versucht, die I2C-Adresse (0X3D) zu setzen. Läuft trotzdem nicht.


Bei U8g2 sollte der damit funktionieren

U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ -1, /* data=*/ 17); // Data Pin anpassen 

wenn nicht tut dann stat -1 mall U8X8_PIN_NONE, probieren.
Habe den aber nicht deshalb nur Vermutung, meine haben kein Data Pin.
Funktioniert der auch ohne Data? Hat ja seitlich Port Verlängerung

Funktioniert in beiden Varianten nicht. Auch dann nicht, wenn ich die I2C-Adresse setze.

Wenn das mit der besseren Lib nicht funktioniert, dann versuch das mal so:

  char txtBuf[10];
...
  display.setCursor(70,40);
  sprintf(txtBuf,"%4d", Ramp );
  display.println(txtBuf);

Geht dann natürlich auch mit Speed

Müsste funktionieren :wink: