Continuous motion of stepmotor inside complex project

hey
i am trying to create a continuous motion of a stepmotor nema 17 with AccelStpper library and A4988 driver.
each loop i am reading the speed from the speed control analogInput, writing it to the setSpeed() and sending to the driver with runSpeed(), and continue to the rest of the loop calculation.
the problem is that the motor is moving as long as the arduino isnt doing something else.
for example: when i run the code with a delay(1000) after the run command, it wil move for 1000ms, and than stop for few ms while computing the rest of the code, and run again in the second loop.

is there a way to create a smooth, speed controllable motion while doing other computes?

code below:

//LCD config
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);  //sometimes the adress is not 0x3f. Change to 0x27 if it dosn't work.

//Thermistor needed libraries
#include <thermistor.h>           //Download it here: https://electronoobs.com/eng_arduino_thermistor.php
thermistor therm1(A0,0);          //Connect thermistor on A0, 0 represents TEMP_SENSOR_0 ( configuration.h for more)


//I/O
int PWM_pin = 5;                  //Pin for PWM signal to the MOSFET driver (the BJT npn with pullup)
int speed_pot = A1;
int but1 = 7;
int EN = 2;
int STEP = 3;
int DIR = 2;
int LED = 13;

//Variables
float set_temperature = 200;            //Default temperature setpoint. Leave it 0 and control it with rotary encoder
float temperature_read = 0.0;
float PID_error = 0;
float previous_error = 0;
float elapsedTime, Time, timePrev;
float PID_value = 0;
int button_pressed = 0;
int menu_activated=0;
float last_set_temperature = 0;
int max_PWM = 255;

//Stepper Variables
int max_speed = 3000;
int main_speed = 0;
bool but1_state = true;
bool activate_stepper = true;
int rotating_speed = 0;
float timeBeforeRun;



#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper1(1, STEP, DIR); // (Type of driver: with 2 pins, STEP, DIR)

//PID constants
//////////////////////////////////////////////////////////
int kp = 90;   int ki = 30;   int kd = 80;
//////////////////////////////////////////////////////////

int PID_p = 0;    int PID_i = 0;    int PID_d = 0;
float last_kp = 0;
float last_ki = 0;
float last_kd = 0;

int PID_values_fixed =0;



void setup() {  
  pinMode(EN, OUTPUT);
  digitalWrite(EN, HIGH);     //Stepper driver is disbled
  stepper1.setMaxSpeed(max_speed);  
  pinMode(but1, INPUT_PULLUP);
  pinMode(speed_pot, INPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  
  pinMode(PWM_pin,OUTPUT);
  TCCR0B = TCCR0B & B11111000 | B00000010;    // D6 adn D6 PWM frequency of 7812.50 Hz
  Time = millis();

  TCCR1A = 0;             //Reset entire TCCR1A register
  TCCR1B = 0;             //Reset entire TCCR1B register
  TCCR1A |= B00000010;    //   /8
  TCNT1 = 0;              //Reset Timer 1 value to 0
  
  Serial.begin(9600);   //initialize serial communication at a baud rate of 9600
  
  lcd.init();
  lcd.backlight();
}

void loop() {


  if(!digitalRead(but1) && but1_state){
    but1_state = false;
    activate_stepper = !activate_stepper;
    Serial.println("________________________________________________________________________________change");
    Serial.println(activate_stepper);
    delay(10);
  }
  else if(digitalRead(but1) && !but1_state){
    but1_state = true;
  }
  
  if(activate_stepper){

    digitalWrite(LED, HIGH);
    digitalWrite(EN, LOW);    //We activate stepper driver
    rotating_speed = map(analogRead(speed_pot),0,1024,main_speed,max_speed);
    stepper1.setSpeed(rotating_speed);
    timeBeforeRun = millis();
    stepper1.runSpeed();
  }
  else
  {
    digitalWrite(EN, HIGH);    //We deactivate stepper driver
    digitalWrite(LED, LOW);
    stepper1.setSpeed(0);
    stepper1.runSpeed();
  }
  
  // First we read the real value of temperature
  temperature_read = therm1.analog2temp(); // read temperature


  //Next we calculate the error between the setpoint and the real value
  PID_error = set_temperature - temperature_read + 6;
  //Calculate the P value
  PID_p = 0.01*kp * PID_error;
  //Calculate the I value in a range on +-6
  PID_i = 0.01*(PID_i + (ki * PID_error));
  
  
  //For derivative we need real time to calculate speed change rate
  timePrev = Time;                            // the previous time is stored before the actual time read
  Time = millis();                            // actual time read
  elapsedTime = (Time - timePrev) / 1000; 
  //Now we can calculate the D calue
  PID_d = 0.01*kd*((PID_error - previous_error)/elapsedTime);
  //Final total PID value is the sum of P + I + D
  PID_value = PID_p + PID_i + PID_d;

  
  //We define PWM range between 0 and 255
  if(PID_value < 0){
    PID_value = 0;
  }
  if(PID_value > max_PWM){
    PID_value = max_PWM;
  }
  
  //Now we can write the PWM signal to the mosfet on digital pin D5
  analogWrite(PWM_pin,PID_value);
  previous_error = PID_error;     //Remember to store the previous error for next loop.
  
  delay(250); //Refresh rate + delay of LCD print
  lcd.clear();
  
  lcd.setCursor(0,0);
  lcd.print("T: ");  
  lcd.print(temperature_read,1);
  lcd.print(" S: ");  
  lcd.print(rotating_speed);
  
  lcd.setCursor(0,1);
  lcd.print("PID: ");
  lcd.print(PID_value);
 
}//Void loop end

Hi @einavf4

welcome to the Arduino-Forum.

Throw away the AccelStepper-library and use the MobaTools-library.

The MobaTools-library creates the step-pulses with a timer-interrupt "in the background".
This means your code can do a lot of different things "in parallel" to the step-pulse-creation.

If you only need a (almost) inifinite rotating stepper-motor this can be done by the MobaTools-function rotate(1); / rotate(-1)
minus one -1 for opposite rotation-direction

You can install the MobaTools library with the library-manager of the Arduino-IDE
After installing there is a subfolder with examples

There is a bareminimum-example for making a stepper-motor rotate.
You can use this example as a starting point and modify it

MobaTools-code below

/* ====== minimumStepper =======================================
 *  Bare minimum to get a stepper with step/dir driver turning
 */
#include <MobaTools.h>
// Stepper connections - Please adapt to your own needs.
const byte stepPin = D6; // muss je nach microcontroller evtl. angepasst werden
const byte dirPin  = D5; // muss je nach microcontroller evtl. angepasst werden

const int stepsPerRev = 200;    // Steps per revolution - may need to be adjusted

MoToStepper stepper1( stepsPerRev, STEPDIR );  // create a stepper instance

void setup() {
  stepper1.attach( stepPin, dirPin );
  stepper1.setSpeed( 300 );              // 30 rev/min (if stepsPerRev is set correctly)
  stepper1.setRampLen( stepsPerRev / 2); // Ramp length is 1/2 revolution
  stepper1.rotate(1);                    // start turning, 1=vorward, -1=backwards                    
}

void loop() {
  // do all kind of stuff here
}

best regards Stefan

perhaps you should use millis() to determine when to update the LCD instead of the 1/4 sec delay

Sending data to an LCD-display maybe need still too much time so that calling

can't be done fast enough = can't be done at the mimimum required frequency

For using the MobaTools-library there is a limitation
quote from the documenation

2.1 AVR ( Atmega, Attiny )
The MobaTools intensively use the Timer 1 of Arduino (AVR).
Therefor all other libraries or functions that also use the Timer1 can not be used simultaneously. This concerns, for example, the standard ServoLib and analog write on pins 9 + 10. If timer 3 is available, it is used instead. This applies to Arduino Leonardo, Micro and Mega.

Your code is using timer1 for PWM.
So I was searching for PWM-creation with a different timer
and found this

If you can change the PWM-pin from IO-pin 5
to io-pin 3 or io-pin 11
this should work
best regards Stefan

see post # 4

which I already wrote about in post #4

and suggested a solution

best regards Stefan

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