Accelstepper and a touchscreen

I'm working on a touchscreen controlled motor control system. Most of it is working fine - I've built the UI, successfully read data from the touchscreen and got the stepper to run to a defined position with the AccelStepper library and the "moveTo" method.

What I'm struggling to do is to let the motor run while pressing a button and stopping on release. It seems that the initial press and the hold are registered but not the release. Also, I get only a weird Serial Monitor reading (see below), but no (visible) motor movement.

This is my code so far (excerpt):

// I created the other buttons, initialized the screen, did everything to get the touch functionality running until here. Button 3 is my start button

[...]

     buttons[3].initButtonUL(&tft, buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, "START", 3); // START Button
     buttons[3].drawButton();

[...]

// Here starts the logic for the button press

if ((p.y >= 10) && (p.x >= 250) && (p.y <= 100) && (p.x <= 310) ) {  //Coordinates for my button. The button press is working fine.       
 
buttons[3].press(true);      
     
        if (buttons[3].justPressed()){  //  code to run at press time

              digitalWrite(ENABLE_PIN, LOW); 

            Serial.print("start run start at pos "); 
            Serial.print(stepper.currentPosition());
            Serial.print("\r\n");

        stepper.setAcceleration(100);
        stepper.setSpeed(speed_set);   
        }

        if (buttons[3].isPressed() ) { //  code to run while the button is held        
            stepper.run();  
           Serial.print("running:"); 
           Serial.print(stepper.currentPosition());
            Serial.print("\r\n");
            }

        if ( buttons[3].justReleased() ) { //  code to run at release time
          stepper.stop();          
          Serial.print("normal run stopped \r\n"); 
          Serial.print(stepper.currentPosition());
          Serial.print("\r\n"); 
          digitalWrite(ENABLE_PIN, HIGH); 
        }            
      }

The serial monitor output:

start run start at pos 0
running:1
running:1
running:1
running:1
running:1
running:1
running:1
running:1
running:1
running:1
running:1
running:1
running:0
running:0
running:0
running:0
running:0
running:0
running:0
running:0
running:0
//(continueswith 0 as long as i hold the button)

References I've used:
https://forums.adafruit.com/viewtopic.php?t=85486
https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html

Please, post the complete sketch.

When multiple events are competing for attention and "everything works but it doesn't," "blocking" code (does not share processor time) is usually the reason.

If you insist - it's a longer read :wink: The BACKW, HOME, TIME, STEPS and Timelapse Button are from an older version of the sketch and thus mostly commented out. I'm modifying a project from another author. NORMAL, ACCELERATED and SPEED are working fine.

/* Slider Control V1 Variant for 3.5" Parallel TFT-tft Shield Display with Adafruit_GFX
// Original by Mega-Testberichte.de - Marco Kleine-Albers
// Variant by gregorurabl.at - Gregor Urabl

//docs
//https://www.pjrc.com/teensy/td_libs_AccelStepper.html
//https://www.airspayce.com/mikem/arduino/AccelStepper/
//http://domoticx.com/arduino-library-accelstepper/
//good example https://www.brainy-bits.com/setting-stepper-motors-home-position-using-accelstepper/
//example: http://www.schmalzhaus.com/EasyDriver/Examples/EasyDriverExamples.html

//1,8°, 360/1,8 = 200
//200 steps is a full turn in fullstep mode
//use microstepping for smoother motion. see later in code

Standard TFT tft Pin Mappings:

*pin usage as follow:
*                  tft_CS  tft_CD  tft_WR  tft_RD  tft_RST  SD_SS  SD_DI  SD_DO  SD_SCK 
*     Arduino Uno    A3      A2      A1      A0      A4      10     11     12      13   
                         
*Arduino Mega2560    A3      A2      A1      A0      A4      10     11     12      13                           

*                  tft_D0  tft_D1  tft_D2  tft_D3  tft_D4  tft_D5  tft_D6  tft_D7  
*     Arduino Uno    8       9       2       3       4       5       6       7
*Arduino Mega2560    8       9       2       3       4       5       6       7 

*Remember to set the pins to suit your display module!
*/

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_TFTLCD.h> // tft Library
#include <TouchScreen.h> // Touchscreen Library
#include <MCUFRIEND_kbv.h> // Touchscreen Hardware-specific library
#include <AccelStepper.h>

#define tft_CS A3 // Chip Select goes to Analog 3
#define tft_CD A2 // Command/Data goes to Analog 2
#define tft_WR A1 // tft Write goes to Analog 1
#define tft_RD A0 // tft Read gies to Analog 0

#define tft_RESET A4 // Can alternately just connect to Arduino's reset pin

// define pins for resistive touchscreen
#define YP A1 // must be an analog pin, use "an" notation!
#define XM A2 // must be an analog pin, use "an" notation!
#define YM 7 // can be a digital pin
#define XP 6 // can be a digital pin

// define touchscreen pressure points
#define MINPRESSURE 10
#define MAXPRESSURE 1000

// Define touchscreen parameters
// Use test sketch to refine if necessary
#define TS_MINX 930
#define TS_MAXX 130
 
#define TS_MINY 200
#define TS_MAXY 970
 
#define STATUS_X 10
#define STATUS_Y 65

// Colors
#define BLACK       0x0000
#define WHITE       0xFFFF
#define RED         0xF800
#define ORANGE      0xFD20      
#define BLUE        0x001F
#define DARKCYAN    0x03EF      
#define GREEN       0x07E0
#define DARKGREEN   0x03E0      
#define LIGHTGREY   0xC618      
#define DARKGREY    0x7BEF      
#define MAGENTA     0xF81F  

//motor pins
int ENABLE_PIN = 23;
int STEP_PIN = 25;
int DIR_PIN = 27;

//microstepping Pins M1 =A8, M2=A9, M3=A10
//TABELLE, Abschnitt Software: https://www.mega-testberichte.de/testbericht/einen-kameraslider-motorisieren-arduino-a4988-steppermotor-touchdisplay-do-it-yourself
//pin mappings 
int M1 = A8;
int M2 = A9;
int M3 = A10;

//when we do 1/2. 1/4, 1/8 odr 1/16 we multiply the base fullsteps with 2,4,5 or 16
//fullstep set to 1
int step_multiplier = 16;

//1 is the DRIVER interface as i use a driver board
AccelStepper stepper(1, STEP_PIN, DIR_PIN); 

// Define object for TFT display
MCUFRIEND_kbv tft;
 
// Define object for touchscreen
// Last parameter is X-Y resistance, measure or use 300 if unsure
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

//debug/msg
int x, y;
String msg="";
char text_buffer[80];

//--button for speed
long int speed_set = 10*step_multiplier;
long int raise_speed_by = 10*step_multiplier;
long int speed_max = 400*step_multiplier;

//--needed for timelapse, buttons
int time_set = 60; //later multiplied with 1000, because the delay funct want millisec
int raise_time_by = 10;
int time_max = 400;

//--steps for timelapse
long int steps_set = 10*step_multiplier; //200 steps is a full turn in fullstep mode, in 1/16 a full turn is 16*200=3200
long int steps_max = 200*step_multiplier;
long int raise_steps_by = 10*step_multiplier; //raised by steps

//--slider length in steps
//slider length is 90 cm = 4000 fullsteps, with 1/16 it is 4000*16=64000
// Shorter Slider 64 cm = 2844 fullsteps , with 1/16 it is 2844*16=45511
long int slider_length = 45500;  
//1/16 31000
//fullstep 4000

/*************************
**   Draw UI  **
*************************/

char buttonRadius = 10;
char buttonHeight = 60;
char buttonSpacing = 10;
uint16_t smallButtonWidth = 147;
uint16_t bigButtonWidth = 303;

// Define button array object
Adafruit_GFX_Button buttons[9];

  void drawButtons() {

  tft.setTextColor(WHITE);
  tft.setTextSize(3);

// Create Buttons - initButton would create a Button from x and y coordinates in it's center. initButtonUL uses the top left corner
     buttons[0].initButtonUL(&tft, buttonSpacing, buttonSpacing, bigButtonWidth, buttonHeight, WHITE, GREEN, WHITE, "NORMAL", 3); // NORMAL Button
        int_to_string(speed_set, text_buffer); 
     buttons[1].initButtonUL(&tft, bigButtonWidth+2*buttonSpacing, buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, text_buffer, 3); // SPEED Button
     buttons[2].initButtonUL(&tft, buttonSpacing, buttonHeight+2*buttonSpacing, bigButtonWidth, buttonHeight, WHITE, ORANGE, WHITE, "", 3); // ACCELETATE Button - Due to a limitation in the Adafruit_GFX_Button Object the Label of a Button is limited to 9 Characters. So we draw this one without label and add it with tft.print afterwards
     buttons[3].initButtonUL(&tft, buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, "START", 3); // START Button
         int_to_string(time_set, text_buffer); 
     buttons[4].initButtonUL(&tft, smallButtonWidth+2*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, BLUE, WHITE, text_buffer, 3); // TIME Button (set number)
         int_to_string(steps_set, text_buffer); 
     buttons[5].initButtonUL(&tft, 2*smallButtonWidth+3*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, MAGENTA, WHITE, text_buffer, 3);// STEPS Button (set number)
     buttons[6].initButtonUL(&tft, buttonSpacing, 3*buttonHeight+4*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, GREEN, WHITE, "TIMELAP", 3);// TIMELAPSE START Button
     buttons[7].initButtonUL(&tft, smallButtonWidth+2*buttonSpacing, 3*buttonHeight+4*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, ORANGE, WHITE, "BACKW", 3);// BACKW Button
     buttons[8].initButtonUL(&tft, 2*smallButtonWidth+3*buttonSpacing, 3*buttonHeight+4*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, RED, WHITE, "HOME", 3); // HOME Button

// Draw Buttons
        for(uint8_t buttonCounter = 0; buttonCounter <= 8; buttonCounter++) 
        {
        buttons[buttonCounter].drawButton();
        }
      
  tft.setCursor(40, 100);
  tft.print("ACCELERATED");

}

/*************************
**  Required functions  **
*************************/
void setup() {  

tft.reset();

  //motor
  pinMode(ENABLE_PIN, INPUT);
  digitalWrite(ENABLE_PIN, HIGH); 

  //mircosteppin
  pinMode(M1, OUTPUT);
  pinMode(M2, OUTPUT);
  pinMode(M3, OUTPUT);

  //1/16 had the lowest vibration
  //see table for step values: https://forum.arduino.cc/index.php?topic=415724.0
  digitalWrite(M1, HIGH);
  digitalWrite(M2, HIGH);
  digitalWrite(M3, HIGH);

  // Setup the Display
  tft.begin(tft.readID());
  tft.setRotation(1);
  tft.fillScreen(BLACK);

  //call function to draw our gui  
  drawButtons();
  
  Serial.begin(9600);
  Serial.println("Starting Stepper Test\r\n");  
  Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height());

  //Setup for motor
  //disable the power of the motor
  stepper.disableOutputs();
  
  //Set Max Speed and Acceleration of each Steppers at startup
  stepper.setMaxSpeed(1000); //Set Max Speed of Stepper (Slower to get better accuracy). Steps per second
  stepper.setAcceleration(100); // Set Acceleration of Stepper
  stepper.setSpeed(1000);    
  
  //debug test
  /*
    digitalWrite(ENABLE_PIN, LOW);  
    stepper.runToNewPosition(0); Serial.println(stepper.currentPosition());
    stepper.runToNewPosition(45500); Serial.println(stepper.currentPosition());
    stepper.runToNewPosition(0); Serial.println(stepper.currentPosition());
    digitalWrite(ENABLE_PIN, HIGH);  */
}

void loop() {

    //touchscreen
  uint16_t i;
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);

  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
  {

    p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(),0);
    p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(),0);

      //debug
      //check the area where we drew the buton for touch
      /*
      Serial.print("Touch X is:");
      Serial.print(p.x);
      Serial.print("\r\n");

      Serial.print("Touch Y is:");
      Serial.print(p.y);
      Serial.print("\r\n");*/

      //--------------------------NORMAL button 
      if ((p.y >= 10) && (p.x >= 40) && (p.y <= 220) && (p.x <= 100) ) { 
        touchBorder(buttonSpacing, buttonSpacing, bigButtonWidth, buttonHeight, p.z);
        updateStr("Starting Motor");          
        
        //enable disable power manuelly
        digitalWrite(ENABLE_PIN, LOW);           
        
        stepper.setCurrentPosition(0); //must be set to 0 because manual moving START/BACKW/HOME may have changed the position and normal must always begin at start/0
        stepper.moveTo(slider_length);

        /****************************************************************************************************/
        /* IMPROTANT: DO NOT USE Serial.print in hihly repeated loops. Slows down everything. See code above
        /****************************************************************************************************/
        
        while (stepper.currentPosition() != slider_length) {
          //Serial.print("START");                    //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
          //Serial.print(stepper.currentPosition());  //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
          //Serial.print("\r\n");                    //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY          
          stepper.setSpeed(speed_set);  
          stepper.run();          
        }               

        //after the run move back to position 0. that happens with acceleration
        //Serial.print("END");        
        stepper.runToNewPosition(0);        
        digitalWrite(ENABLE_PIN, HIGH);             
      }

      //---------------------ACCELERATE button
      if ((p.y >= 10) && (p.x >= 140) && (p.y <= 220) && (p.x <= 210) ) { 
        touchBorder(buttonSpacing,buttonHeight+2*buttonSpacing, bigButtonWidth, buttonHeight, p.z); 
        updateStr("Accelerate Motor");    
        
        digitalWrite(ENABLE_PIN, LOW);    
        stepper.setCurrentPosition(0); //must be set to 0 because manual moving START/BACKW/HOME may have changed the position and normal must always begin at start/0        
        
        stepper.setSpeed(speed_set);  
        stepper.runToNewPosition(slider_length);  

        //after the run move back to position 0
        stepper.runToNewPosition(0);        
        digitalWrite(ENABLE_PIN, HIGH);               
      }

      //---------------------START button
      if ((p.y >= 10) && (p.x >= 250) && (p.y <= 100) && (p.x <= 310) ) {   
        buttons[3].press(true);      
        //touchBorder(10, 170, 100, 220, p.z); //can not use that here because it will block because we press and hold      
        if (buttons[3].justPressed()){  //  code to run at press time
        updateStr("START");   

        digitalWrite(ENABLE_PIN, LOW); 

            Serial.print("start run start at pos "); 
            Serial.print(stepper.currentPosition());
            Serial.print("\r\n");

        stepper.setAcceleration(100);
        stepper.setSpeed(speed_set);   
        }

        if (buttons[3].isPressed() ) { //  code to run while the button is held        
            stepper.run();  
           Serial.print("running:"); 
           Serial.print(stepper.currentPosition());
            Serial.print("\r\n");
            }

        if ( buttons[3].justReleased() ) { //  code to run at release time
          stepper.stop();          
          Serial.print("normal run stopped \r\n"); 
          Serial.print(stepper.currentPosition());
          Serial.print("\r\n"); 
          digitalWrite(ENABLE_PIN, HIGH); 
        }            
      }

     //---------------------BACKW button
      if ((p.y >= 125) && (p.x >= 360) && (p.y <= 220) && (p.x <= 420) ) {   
        //touchBorder(110, 170, 200, 220); //can not use that here because it will block      
        updateStr("BACKWARDS");         
              
        digitalWrite(ENABLE_PIN, LOW); 
        Serial.print("backward run start at pos \r\n"); 
        Serial.print(stepper.currentPosition());
        Serial.print("\r\n");    
        
        stepper.setAcceleration(100);
        stepper.setSpeed(speed_set);  

     /*   while (Touch.dataAvailable() == true) {
          stepper.setSpeed(-speed_set);  
          stepper.run();          
          //Serial.print("running by button pressed backwards"); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
        }    
*/
        Serial.print("backward run stopped \r\n"); 
        Serial.print(stepper.currentPosition());
        Serial.print("\r\n");      

        //stop completely after, otherwise movement is still there
        stepper.stop();
        //Serial.print("backward run stopped"); 
        
        digitalWrite(ENABLE_PIN, HIGH);                           
      }     

      //--------------------->HOME button
      if ((p.y >= 230) && (p.x >= 360) && (p.y <= 310) && (p.x <= 410) ) {   
      touchBorder(2*smallButtonWidth+3*buttonSpacing, 220, smallButtonWidth, buttonHeight, p.z);
        updateStr("HOME"); 

        digitalWrite(ENABLE_PIN, LOW);

        Serial.print("Home start, current POS is:");          
        Serial.print(stepper.currentPosition());
        Serial.print("\r\n");         
    
        stepper.setSpeed(speed_set);         
        stepper.setCurrentPosition(stepper.currentPosition()); //set correct position because its not known by default

        //after the run move back to position 0
        stepper.runToNewPosition(0);             
        
        digitalWrite(ENABLE_PIN, HIGH);                     
      }      

      //------------------------SPEED button with UPDATE of number
     if ((p.y >= 240) && (p.x >= 40) && (p.y <= 330) && (p.x <= 110) ) {   

        //one touch raises speed by X up to "speed_max"
        if(speed_set < speed_max) {
          speed_set = speed_set + raise_speed_by;  
        }
        else {
          speed_set = 10;
        }        

        //if i dont set that here the manual START/REWIND will not work after i change the speed and press them again. why....
        stepper.setSpeed(speed_set);  

        int_to_string(speed_set, text_buffer); 
        buttons[1].initButtonUL(&tft, bigButtonWidth+2*buttonSpacing, buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, text_buffer, 3); // SPEED Button
        buttons[1].drawButton();

        touchBorder(bigButtonWidth+2*buttonSpacing, buttonSpacing, smallButtonWidth, buttonHeight, p.z);
        String speedMsg = "Speed set to ";
        speedMsg.concat(text_buffer);
        updateStr(speedMsg);
      }
      
      //------------------------TIMELAPSE START button START
      if ((p.y >= 10) && (p.x >= 350) && (p.y <= 100) && (p.x <= 420) ) {   
          
        int_to_string(speed_set, text_buffer); 
        tft.setCursor(237, 26);
        tft.print(text_buffer);  

        Serial.print("Starting Timelapse\r\n");  

        //@good blog, method for using a cable to the camera for timalapse https://photoscs.wordpress.com/2014/03/25/arduino-stepper-code-time-lapse/

        //enable disable power manually
        digitalWrite(ENABLE_PIN, LOW); //motor an             

        Serial.print("Timelapse start, current POS is:");          
        Serial.print(stepper.currentPosition());
        Serial.print("\r\n"); 

        //see: http://forum.arduino.cc/index.php?topic=206796.0
        //multiplied with 1000, we need millicseconds //use millis() instead later, non blocking
        long ms_time = time_set*1000L;       
        Serial.print("Delay time set in MS:\r\n"); 
        Serial.print(ms_time);
        Serial.print("\r\n");
        
        while (stepper.currentPosition() != slider_length) {
          
          stepper.runToNewPosition(steps_set);
          steps_set = steps_set+ raise_steps_by;         
          stepper.run();  
          digitalWrite(ENABLE_PIN, HIGH); //motor aus           
          delay(ms_time); //wait, delay     
          digitalWrite(ENABLE_PIN, LOW);  //motor an   
          
          //Serial.print("Timelapse running, current POS is:");  //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY        
          //Serial.print(stepper.currentPosition());             //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
          //Serial.print("\r\n");                                //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
        }
            
        digitalWrite(ENABLE_PIN, HIGH); //finish. motor off            

        //we start the timelapse. Move Motor by x              
        touchBorder(10, 130, 150, 170, p.z);
        updateStr("TIMELAPSE");
      }     

      //------------------------TIME button with UPDATE of number
      if ((p.y >= 125) && (p.x >= 245) && (p.y <=220) && (p.x <= 315) ) {   

        //one touch raises time by X up to time_max
        if(time_set < time_max) {
          time_set = time_set + raise_time_by;  
        }
        else {
          time_set = 10;
        }             

        int_to_string(time_set, text_buffer); 
        buttons[4].initButtonUL(&tft, smallButtonWidth+2*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, BLUE, WHITE, text_buffer, 3);       
        buttons[4].drawButton();

        touchBorder(smallButtonWidth+2*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, p.z);
        String timeMsg = "Time set to ";
        timeMsg.concat(text_buffer);
        updateStr(timeMsg);
      }      

       //------------------------STEPS button with UPDATE of number 230, 130, 310, 170
      if ((p.y >= 235) && (p.x >= 250) && (p.y <=325) && (p.x <= 320) ) {  
        //one touch raises steps by 10 up to steps_max
        if(steps_set < steps_max) {
          steps_set = steps_set + raise_steps_by;  
        }
        else {
          steps_set = 10;
        }       

        int_to_string(steps_set, text_buffer); 
        buttons[5].initButtonUL(&tft, 2*smallButtonWidth+3*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, MAGENTA, WHITE, text_buffer, 3);
        buttons[5].drawButton();

        touchBorder(2*smallButtonWidth+3*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, p.z);
        String stepsMsg = "Steps set to ";
        stepsMsg.concat(text_buffer);
        updateStr(stepsMsg);
      }    
      
    }

}


/***************************************************************************
 * update string so we see what has been touched - debug help
 ****************************************************************************/
void updateStr(String msg){ 
    tft.fillRect(0, tft.height()-30, tft.width(), 30, LIGHTGREY);
    tft.setCursor(20,tft.height()-22);
    tft.setTextSize(2);
    tft.setTextColor(BLACK); 
    tft.print(msg);    
}

/****************************************************************************
 * Draw a border while a button is touched  
 ****************************************************************************/
void touchBorder(int x1, int y1, int x2, int y2, int touched) {
  //while (touched > MINPRESSURE && touched < MAXPRESSURE){
    tft.drawRoundRect (x1, y1, x2, y2, buttonRadius, RED);
    //}

 /* while (Touch.dataAvailable())
    Touch.read();*/
 // tft.fillRoundRect (x1, y1, x2, y2, buttonRadius, RED);
}

/*****************************************************************************
 * convert X to String
 ****************************************************************************/
void int_to_string(int val, char* string) {
  if(string) 
     sprintf(string, "%d", val);  
  return;  
}

I got it to work...more or less. If I change:

 if (buttons[3].isPressed() ) { //  code to run while the button is held        
            stepper.run();  
           Serial.print("running:"); 
           Serial.print(stepper.currentPosition());
            Serial.print("\r\n");
            }

to:

 if (buttons[3].isPressed() ) { //  code to run while the button is held        
            stepper.runSpeed();  
           Serial.print("running:"); 
           Serial.print(stepper.currentPosition());
            Serial.print("\r\n");
            }

I get a correct reading in the Serial Monitor and the motor is moving now. But at a much slower speed then with NORMAL Run and regardless of the values in stepper.setSpeed(speed_set);
The "justReleased" Method also seems to be never called as I never get a reading via Serial.

Starting Stepper Test

TFT size is 480x320
start run start at pos 0
running:1
running:2
running:3
running:4
running:5
running:6
running:7
running:8
running:9
running:10
running:11
running:12
running:13
running:14
running:15
running:16
running:17
running:18
running:19
running:20
running:21
running:22
running:23
running:24
running:25
running:26
running:27

You posted the reference to the AccelStepper docs, but obviously you didn't read or didn't understand it, because there are a lot of missuses of the AccelStepper methods in your sketch.

  pinMode(ENABLE_PIN, INPUT);

Shouldn't that be OUTPUT?

        stepper.setSpeed(speed_set);
        stepper.run();

Don't use setSpeed() and run() together, because run() uses setSpeed() internally. So this calls compete with each other.
Use runSpeed() if you want to move the stepper with the speed set by setSpeed().

      if (buttons[3].isPressed() ) { //  code to run while the button is held
        stepper.run();

stepper.run() only creates steps, if a target position was set, and the stepper has not yet reached this position. If the stepper is at this target position run() does not create steps anymore. And be aware, that run creates at most only one step per call.

      if ( buttons[3].justReleased() ) { //  code to run at release time
        stepper.stop();

stepper.stop() only makes sense together with run(). It simply sets a new target position, that can be reached with using run() and the actually set acceleration. It does NOT inhibit generating steps.

      stepper.setCurrentPosition(stepper.currentPosition()); //set correct position because its not known by default

That does not make sense either. It sets the current position to the current postion - so nothing will change.

So keep in mind:
run(): creates at most one step until the formerly set target position is reached. Uses acceleration, and the speed is defined ba setMaxSpeed(). Don't use together with setSpeed().

runSpeed(): creates at most one step, depending on the speed set with setSpeed(). Doesn't care about target position, doesn't use acceleration

runSpeedToPosition(): creates at most one step, depending on the speed set with setSpeed(). Stops creating steps when the target position is reached.

All these three methods must be called more often than actual step frequency. Otherwise the set speed will not be reached.

P.S. may be easier for you to use the MobaTools library :thinking: ( if you use a supported board ).

Thanks @MicroBahner , I'll implement your Feedback and report back.
On a personal, german speaking Note: Ich wäre deutschsprachig, falls du also lieber auf Deutsch reden magst (via PM oder der deutschen Subsektion), können wir das auch gerne so machen :wink:

Update: I've changed the Input to Output - makes absolute sense that way, I have no Idea why that was set as Input in the original sketch in the first place.

I also changed the "NORMAL" funktionality to stepper.setMaxSpeed() and stepper.run(), this works great, thanks for the feedback.

I still was not able to get the manual run (START) to work propperly, but I've reached out to the original author in the meantime to ask him what he intended to do with some parts of the code.

Concering

stepper.setCurrentPosition(stepper.currentPosition());

I think that should set the current Position as new 0 Position for future runs. But that's also something I'll ask the original author because I don't realy understand what the HOME function does.

EDIT: It seems to work (kind of) with this code now, thanks again for pointing me in the direction of runSpeed(). Seems like the Serial Monitor calls reduced the frequency of how often runSpeed could been called, so I removed them. It's slower at slower values from setSpeed now and a little bit faster at higher values (as intended), but the 6400 are also still a lotslower than 6400 in setMaxSpeed at the Normal Run.

      //---------------------START button
      if ((p.y >= 10) && (p.x >= 250) && (p.y <= 100) && (p.x <= 310) ) {   
        buttons[3].press(true);      
       
        if (buttons[3].justPressed()){  //  code to run at press time
        updateStr("START");   
        digitalWrite(ENABLE_PIN, LOW); 
        
            Serial.print("start run start at pos "); 
            Serial.print(stepper.currentPosition());
            Serial.print("\r\n");
       
           stepper.setSpeed(speed_set);
           Serial.print("Speed set to "); 
            Serial.print(speed_set);
            Serial.print("\r\n");
        }

        if (buttons[3].isPressed() ) { //  code to run while the button is held    
           stepper.runSpeed();  
            }

        if ( buttons[3].justReleased() ) { //  code to run at release time
                  digitalWrite(ENABLE_PIN, HIGH); 
        }            
      } else {buttons[3].press(false); }

That's your decision. But this is an open forum, and discussing problems via PM is not the point. Everyone should be able to benefit from the discussion.

If you want to, you can open a new topic in the German section and post a link here that you want to continue there.
But of course you will get more help in English. A discussion in both sections is highly unwanted ( crossposting ) and against the forum rules.

I think the main problem is, that this is - opposite to the others - not a blocking run of the stepper. As it is now, you can get max one step per loop() cycle. And because of all this Serial prints and graphical stuff in loop, your loop cycle is fairly slow. What makes things worse is your low baudrate:

  Serial.begin(9600);

Increase at least to 115200

That would be

stepper.setCurrentPosition(0);

as it is on many other places in the sketch.

Can you post a link to that original sketch ( or post it here )

This is the original sketch: mega_slider/Slider-GUI-v1.ino at master · mega-testberichte/mega_slider · GitHub

I have also been in contact with it's author in the meantime and shared the link to this thread with him. I'll implement the changes you wrote and report back. Your help is really appreciated, thanks a lot.

I was thinking about what @MicroBahner said about doing blocking runs of the stepper Vs "free runs without a target destination" and wrote a variant of the manual run that should calculate the distance from it's current position until the end of the allowed range and do a normal run starting from that Delta Position. After that it will not move at all as slider_length-currentPosition will be 0, but I have a Backwards Button to drive it back manually then. I assume the code for that button will be quite similar to this but in the other direction.

The motor is moving that way, but it's still way to slow - is this another issue with the loops and how fast the tft gets inputs from the button?

      //---------------------START button aka "Manual Run"
      if ((p.y >= 10) && (p.x >= 250) && (p.y <= 100) && (p.x <= 310) ) {   
        buttons[3].press(true);   
        if (buttons[3].justPressed()){ //run once when button is pressed
          updateStr("Starting Manual Run");          
        
        digitalWrite(ENABLE_PIN, LOW);           
        
        long int normalRunBuffer = slider_length-stepper.currentPosition();

        Serial.print("Current Position: "); Serial.print(stepper.currentPosition());
        Serial.print("Distance to go: "); Serial.print(normalRunBuffer);

        stepper.moveTo(normalRunBuffer);
        stepper.setMaxSpeed(speed_set);  
        }
        
        if (buttons[3].isPressed() && stepper.currentPosition()<slider_length-stepper.currentPosition()) { //  code to run while the button is held    
           stepper.run();  
            }         
 
        if (buttons[3].justReleased()){digitalWrite(ENABLE_PIN, HIGH);} //disable the motor after the touch input is gone             
        } else {buttons[3].press(false);}

I think so - as already mentioned. This

          if (buttons[3].isPressed() && stepper.currentPosition()<slider_length-stepper.currentPosition()) { //  code to run while the button is held    
           stepper.run();  
            }         

creates only one step per loop cycle. And because of that many tft commands your loop cycle time is probably fairly slow.

You still did not tell which board you are using. Switching to MobaTools maybe a solution, because the step pulses are created via interrupt in the background. So they even can be created during your many tft commands.

I was afraid so. Seems I have to cook up some sort of workaround and/or implement MobaTools. I'll have a look into this. And sorry, seems I missed the question about the board before. I'm using a Arduino Mega 2560 with a RepRap/Pololu A4988 Motor Driver

Ok, that's really not the fastest with that much graphical commands . But it is completely supported by MobaTools :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.