TfT with stepper motor

Hello, I don’t have a lot of programming knowledge but I have already done some personal projects with Arduino and so far it has been going well.
Now I wanted to use an Arduino UNO with Touchscreen to control the operation of a stepper motor that will have to work in a loop, does 160 steps and returns to 0,and so on.
For now I want a button to start the motor loop and another button to stop.
The code I made to try is this:

#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <TouchScreen.h>
#define MINPRESSURE 100
#define MAXPRESSURE 1000

#include <AccelStepper.h>

// Define stepper motor connections and motor interface type. Motor interface type must be set to 1 when using a driver:
#define motorInterfaceType 1
#define dirPin 11
#define stepPin 10

const int XP = 8, XM = A2, YP = A3, YM = 9; //ID=0x9341
const int TS_LEFT = 898, TS_RT = 120, TS_TOP = 74, TS_BOT = 903;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

Adafruit_GFX_Button on_btn, off_btn;

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
  TSPoint p = ts.getPoint();
  pinMode(YP, OUTPUT);      //restore shared pins
  pinMode(XM, OUTPUT);
  digitalWrite(YP, HIGH);   //because TFT control pins
  digitalWrite(XM, HIGH);

  bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
  if (pressed) {
    pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
    pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
  }
  return pressed;
}

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

int cycle ;

void setup(void)
{
  // Set the maximum speed in steps per second:
  stepper.setMaxSpeed(1000);
  stepper.setCurrentPosition(0);


  Serial.begin(9600);
  uint16_t ID = tft.readID();
  tft.begin(ID);
  tft.setRotation(0);            //PORTRAIT
  tft.fillScreen(BLACK);
  on_btn.initButton(&tft,  60, 200, 100, 40, WHITE, CYAN, BLACK, "ON", 2);
  off_btn.initButton(&tft, 180, 200, 100, 40, WHITE, CYAN, BLACK, "OFF", 2);
  on_btn.drawButton(false);
  off_btn.drawButton(false);
  tft.fillRect(40, 80, 160, 80, RED);

}


void buttons()
{
  bool down = Touch_getXY();

  on_btn.press(down && on_btn.contains(pixel_x, pixel_y));
  off_btn.press(down && off_btn.contains(pixel_x, pixel_y));
  if (on_btn.isPressed()) {
    cycle = 1;
    tft.fillRect(40, 80, 160, 80, GREEN);
  }
  if (off_btn.isPressed()) {
    cycle = 0;
    tft.fillRect(40, 80, 160, 80, RED);
  }
}

void motor() {
  if (cycle == 1)

  {
    // Set the current position to 0:
    stepper.setCurrentPosition(0);
    // Run the motor forward at 160 steps/second until the motor reaches 160 steps :
    while (stepper.currentPosition() != 160)
    {
      stepper.setSpeed(250);
      stepper.runSpeed();
    }
    stepper.setCurrentPosition(0);
    // Run the motor backwards at 160 steps/second until the motor reaches -160 steps :
    while (stepper.currentPosition() != -160)
    {
      stepper.setSpeed(-250);
      stepper.runSpeed();
    }
    if (cycle == 0)
    {
      // Set the current position to 0:
      stepper.setCurrentPosition(0);
    }
   }
  }

  void loop() {
    
    motor();
    buttons();

Serial.println(cycle);
  }

but my problem is that I can’t stop the motor loop when I want to, I press the off button and it doesn’t respond to the first touch.The start button works fine.
I´m using, a tft VMA412,Arduino Uno,tb6560 driver motor and a nema17.

It´s a program problem?Or something with using d10 and d11 pins from arduino to give the step and direction?

Thank you in advance

You are doing the complete movement inside your motor() function. While that is running, you are ignoring your buttons. You need to re-design your code so that each time you call motor() it only moves one step [no for() loops]. This will mean your program checks the buttons more often and will respond as intended.

check out this thread: Several Things at the same time

Thank you for rapid response,
I already saw that topic.

But i thought that every time that the motor comes to zero(after goes to 160 and come back) it run the all loop again and include read the buttons,and if the buttons aren´t pressed it continues the loop of the motor again.

Do you mean inside the void motor(), put code to read the state of the buttons too?,

Depending on how long your rotation takes, all the button presses dont have any influence at all. Only the one counts, when you are at the beginning of your loop again, which is probably not the behavior you are wishing for.

You have two possiblities. Either you add Stop Button queries into your motor / change the motor Execution sequence (see next post from jremington) or you will use ISR

Sadly the solution blh64offered will not work (queries with millis()) since it is the motor taking too long to rotate which blocks the software.

The Arduino does not read any buttons while executing this code. Fix that by adding code in the while loop to read buttons.

  1. remove the .setSpeed() command from the loop. It goes elsewhere.
  2. change .runSpeed() to .run()
   while (stepper.currentPosition() != 160)
    {
      stepper.setSpeed(250);
      stepper.runSpeed();
    }

Thank´s again

"Depending on how long your rotation takes, all the button presses dont have any influence at all. Only the one counts, when you are at the beginning of your loop again, which is probably not the behavior you are wishing for."

That´s a minor problem,stop the motor only in the end of his travel.In the future i will add various values for the time and travel for the rotation of stepper and if i have to wait with button pressed at the end of the travel it works like a security,each loop is a few seconds.

With your help i will do somes changes to the code and try.

Thank´s again

filipeumm:
Do you mean inside the void motor(), put code to read the state of the buttons too?

Yikes NO! You got it backwards!

Imagine loop() as a… err, room! Yeah. Door at each end. You walk in one door… out the other. Ok? Walk in, check your motors, ok check your buttons, ok, whatever else you need to do. All QUICK checks, NEVER slow down. exit other door. Done.

If you use that model, suddenly everything will be fine. Quick checks
“Is the user hitting a button?”
“Do we need to deal with the motors?”
“What time is it?”
“Is the rice done cooking?”
Exit.

Good luck!

-jim lee

dr-o:
Sadly the solution blh64offered will not work (queries with millis()) since it is the motor taking too long to rotate which blocks the software.

Why be sad? It will work just fine. I recommended taking out the for() loop (actually a while() loop) of the motor() function so you check the buttons more regularly. The link to the tutorial is more about how you would structure your code.