// Include the AccelStepper Library to control the stepper motors
#include <AccelStepper.h>

// Define pin connections for the first and second motor
#define dirPin 6
#define stepPin 7
#define dirPin2 4
#define stepPin2 5

// Motor settings for speed and acceleration
#define acceleration_speed 20  // Acceleration rate (steps per second^2)
#define speed 100              // Maximum speed (steps per second)

// INTERVAL IS BETWEEN 10000MS - 30000MS:

// Time interval settings for generating random step durations
#define minTime 10000          // Minimum time in milliseconds
#define maxTime 30000          // Maximum time in milliseconds

// Time when the motor is stopped at the end of the cycle
#define motorStopTime 3000

// Variables to store step count and phase
long steps;    // Number of steps to move in one phase
bool phase1, phase2;    // Phase indicator to toggle direction

// Variables to keep the motors stopped
unsigned long motorTimer1, motorTimer2;
bool fmotorTimer1, fmotorTimer2;

// Define motor interface type (1 for driver with step and direction pins)
#define motorInterfaceType 1

// Create instances of AccelStepper for both motors
AccelStepper Stepper1(motorInterfaceType, stepPin, dirPin);
AccelStepper Stepper2(motorInterfaceType, stepPin2, dirPin2);

void setup() {
  // Initialize Serial communication for debugging
  Serial.begin(9600);

  // Seed the random number generator with analog input
  randomSeed(analogRead(0));

  // Set the maximum speed and acceleration for both motors
  Stepper1.setMaxSpeed(speed);
  Stepper1.setAcceleration(acceleration_speed);

  Stepper2.setMaxSpeed(speed);
  Stepper2.setAcceleration(acceleration_speed);
}

void loop() {
  // Check if Motor 1 has reached its target position and stop motor
  if (!fmotorTimer1 && Stepper1.distanceToGo() == 0) {
    fmotorTimer1 = true;
    motorTimer1 = millis();
  }

  // Toggle direction and generate new steps when the stop time is reached
  if (fmotorTimer1 && motorTimer1 + motorStopTime < millis()) {
    fmotorTimer1 = false;

    if (phase1) {
      generateSteps();
      Stepper1.move(steps * -1);  // Move Motor 1 backward
      phase1 = false;
    }
    else {
      generateSteps();
      Stepper1.move(steps);       // Move Motor 1 forward
      phase1 = true;
    }
  }

  // Check if Motor 1 has reached its target position and stop motor
  if (!fmotorTimer2 && Stepper2.distanceToGo() == 0) {
    fmotorTimer2 = true;
    motorTimer2 = millis();
  }

  // Toggle direction and generate new steps when the stop time is reached
  if (fmotorTimer2 && motorTimer2 + motorStopTime < millis()) {
    fmotorTimer2 = false;
    if (phase2) {
      generateSteps();
      Stepper2.move(steps);       // Move Motor 2 forward
      phase2 = false;
    }
    else {
      generateSteps();
      Stepper2.move(steps * -1);  // Move Motor 2 backward
      phase2 = true;
    }
  }

  // Execute the steps to move the motors
  Stepper1.run();
  Stepper2.run();
}

// Function to generate a random number of steps based on the defined time interval
void generateSteps() {
  // Convert adjusted minTime from milliseconds to minutes, then calculate the equivalent number of steps.
  // The factor 29.5 represents the number of steps per minute at a given speed, multiplied by 2 to compensate half-stepping.
  // (50*speed) compensates the time for acceleration and deceleration.
  long minTimeConv = long((float(minTime - (55 * speed)) / 60000.0) * speed * 29.5 * 2);
  long maxTimeConv = long((float(maxTime - (55 * speed)) / 60000.0) * speed * 29.5 * 2);

  // Generate a random number of steps within the converted time range
  steps = random(minTimeConv, maxTimeConv);

  // Calculate the approximate time in milliseconds to complete the steps
  long timeTaken = long((float(steps) / speed) * 1000) + (55 * speed);

  Serial.print("Time generated (ms): ");
  Serial.println(timeTaken);
  Serial.print("Time to complete (ms): ");
  Serial.println(timeTaken + millis());
}
A4988
12V@6A power supply
A4988