Control of stepper in functions

So, I am building an automated skein winder for yarn, I have implemented the majority of it’s functionality with an a4988 stepper driver (and motor), arduino nano v3, 128x32 OLED display, a hall-effect sensor, and three momentary push buttons. I am using the AccellStepper library for my code, which is attached:

the problem comes at the function “runner()”… I would like to be able to set the stepper in motion for it’s long winding job to spool up 100+/- yards of yarn while still updating the display and checking inputs (to count rotations and check for stop requests)… as it is written the stepper never exceeds about 2 steps a second, I am pretty sure this is because my other functions are blocking it… however I thought calling the “stepper.run()” function from anywhere, including my functions, should point back to the stepper object and make it run… The documentation for the AccelStepper library seems to indicate this is the case but it appears I have misunderstood it…

Does anyone know a way I can execute this functionality? I’d love to avoid rewriting all my code, but it’s not that big honestly, and if there’s library or trick that will do accomplish what I want I am willing to rejigger significantly.

thanks,

code below:

//skeinwinder development sketch
#include <AccelStepper.h>
#include <Bounce2.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define HALL_PIN 8 //hall effect sensor for rotation counting
#define STSP_PIN 9 //start/stop button
#define INC_PIN 10 //increment button
#define DEC_PIN 11 //decrement button

int yardsWound = 0;
int yardsToWind = 100;
int adderlast = 0;
int decerlast = 0;
int stsplast = 0;
int hsenselast = 0;
int windingstatus = 0;

AccelStepper stepper(AccelStepper::FULL2WIRE, 3,2); 


Bounce hbounce = Bounce();
Bounce sbounce = Bounce();
Bounce ibounce = Bounce();
Bounce dbounce = Bounce();

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

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
    Serial.begin(115200);
    stepper.setEnablePin(4);
    stepper.setPinsInverted(false, false, true);
    stepper.enableOutputs();
    

    pinMode(HALL_PIN, INPUT_PULLUP);
      hbounce.attach(HALL_PIN);
      hbounce.interval(3); // interval in ms
    pinMode(STSP_PIN, INPUT_PULLUP);
      sbounce.attach(STSP_PIN);
      sbounce.interval(3); // interval in ms
    pinMode(INC_PIN, INPUT_PULLUP);
      ibounce.attach(INC_PIN);
      ibounce.interval(3); // interval in ms
    pinMode(DEC_PIN, INPUT_PULLUP);
      dbounce.attach(DEC_PIN);
      dbounce.interval(3); // interval in ms

    if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
    display.display();
    delay(1000);
    display.clearDisplay();
    display.setTextSize(2);             
    display.setTextColor(WHITE);        // Draw white text
    display.setCursor(26,10);             
    display.println(F("WELCOME!"));
    display.display();
    delay(1500);
    display.clearDisplay();
    display.setTextSize(1);             // Normal 1:1 pixel scale
    display.setTextColor(WHITE);        // Draw white text
    display.setCursor(10,5);             
    display.println(F("Please Wait While"));
    display.setCursor(5,15);         
    display.println(F("The Winder Homes..."));
    display.display();
    
    homer();      

}
void homer() {
  stepper.enableOutputs();
  stepper.setMaxSpeed(400);
  stepper.setAcceleration(200);
  stepper.moveTo(8000);
    int homed = 0;
    while (stepper.distanceToGo() != 0) {
    if (digitalRead(HALL_PIN) == LOW){
      stepper.stop();
      stepper.currentPosition();
      display.clearDisplay();
      display.setTextSize(1);             // Normal 1:1 pixel scale
      display.setTextColor(WHITE);        // Draw white text
      display.setCursor(15,10);             
      display.println(F("Homming Suceceded!"));
      homed = 1;
      display.display();
      delay(2000);
      break;
     }
     stepper.run();
    } 
    if (homed != 1) {
      display.clearDisplay();
      display.setTextSize(1);             // Normal 1:1 pixel scale
      display.setTextColor(WHITE);        // Draw white text
      display.setCursor(15,5);             
      display.println(F("Homming Failed!"));
      display.setCursor(15,15);
      display.println(F("Please Reset The"));
      display.setCursor(15,25);
      display.println(F("Winder"));
      display.display();
      stepper.disableOutputs();
      for(;;);
    }

}

void infoshow() { //update the display
  //default to 100 yeard skein
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(1,0);
  display.println(F("Set Yards"));
  display.setCursor(62,0);
  display.println(F("Yards Wound"));
  display.setTextSize(2);
  display.setCursor(10,9);
  display.println(yardsToWind);
  display.setCursor(80,9);
  display.println(yardsWound);
  stepper.run();
  display.setTextSize(1);
  display.setCursor(14,25);
  if (windingstatus == 1) {
    display.println(F("Press RED To Stop"));
  }
  else {
    display.println(F("Press RED To Wind"));
  }
  display.display(); 
  stepper.run();
  }
void stopper() {
  //when a stop is called for while running (stsp == LOW && windingstate == 1)
}
void runner() { //the steady state running mode, still check inputs to count up winds
  stepper.enableOutputs();
  stepper.setMaxSpeed(3000);
  stepper.setAcceleration(500);
  stepper.moveTo(80000); //need to figure how to update this to future position indefinitely until (yardsWound == yardsToWind)
  stepper.run();
  while (stepper.distanceToGo() != 0) {
       infoshow();
       stepper.run();
       buttonreader();
       stepper.run();
  }
}
void starter() { //when beginning wind is called for (stsp == LOW && windingstate == 0)
      display.clearDisplay();
      display.setTextSize(1);             
      display.setTextColor(WHITE);        
      display.setCursor(15,5);             
      display.println(F("Hold RED To Start"));
      display.display();
      int runstate = 0;
      while (runstate != 1) {
        sbounce.update();
        int st1 = sbounce.read();
        if (st1 == LOW) {
          delay(2000);
          sbounce.update();
          int st2 = sbounce.read();
          if (st2 == st1) {
             runstate = 1;
          }
        }
      }
      display.clearDisplay();
      display.setTextSize(1);             
      display.setTextColor(WHITE);        
      display.setCursor(5,5);             
      display.println(F("Beginning Winding..."));
      display.display();
      delay(2000);
      sbounce.update();
      windingstatus = 1;
      runner();
}

void buttonreader() { //check for changes in inputs
  ibounce.update();
  int adder = ibounce.read();
  stepper.run();
  dbounce.update();
  int decer = dbounce.read();
  stepper.run();
  sbounce.update();
  int stsp = sbounce.read();
  stepper.run();
  hbounce.update();
  int hall = hbounce.read();
  stepper.run();
  
  if (decer != decerlast && decer == LOW) {
    yardsToWind--;
  }
  stepper.run();
  if (adder != adderlast && adder == LOW) {
    yardsToWind++;
  }
  stepper.run();
  if (windingstatus == 0 && stsplast != stsp && stsp == LOW) {
    starter();
  }
  stepper.run();
  if (windingstatus == 1 && stsplast != stsp && stsp == LOW) {
    stopper();
  }
  stepper.run();
  if (windingstatus == 1 && hsenselast != hall && hall == LOW) {
    yardsWound++;
  }
  stepper.run();
  adderlast = adder;
  decerlast = decer;
  stsplast = stsp;
  hsenselast = hall;
  stepper.run();
  
}


void finnisher() {
  //end winding run and offer to reset... if (yardsWound == yardsToWind) figure this out last...
  
}
void loop() {
  
  infoshow();
stepper.run();
  buttonreader();
stepper.run();  
  
  stepper.disableOutputs();
//blah blah blah...

}

You should really write your program so that stepper.run() is called on a single line in loop() and nowhere else. And you should organize your code so that loop() repeats significantly faster than the fastest step rate that you need.

Code for updating a display tends to be slow so the trick is only to update a little bit of the display between each step.

...R
Stepper Motor Basics
Simple Stepper Code

The problem is that other libraries are blocking the processor for long periods I think.
This isn't a simple thing to fix..

The only real fix for this is to use a stepper library that uses interrupts to generate steps,
if there is such a beast (I'd guess there's some out there somewhere, have a look).

MarkT & Robin2: You're both right, the debouncer and display library were both blocking my code. There is a stepper library that does what I want directly (interrupt-generated steps):

https://www.pjrc.com/teensystep-fast-stepper-control-library/

however, it is only for Teensy T3.x boards. If I had one of those boards it would have solved my problem nicely.

However I have created a TimerOne interrupt for the stepper.run(); function and the global timer-based software interrupt is working quite well for the speeds I need... I have some logic issues to sort out yet with different accelerations and stepper.moveTo();s applying to the same stepper object in different functions, but I feel like I'm 90% of the way there now, as my stepper runs reliably (and sometimes when I don't want it too...)