Run 2 motors with no conflict

Hello, I'm trying to run a motor inside "SetPhaseTwoOn" forward then reverse then forward again. But it needs to not interrupt "phaseonemotor" at all.

I have 2 relays setup as an H-bridge for the phase 2 motor. There are no problems with it going forward or reverse.

I need something like this:

digitalWrite(arduinoPin11, LOW); 
digitalWrite(arduinoPin3, HIGH);   // motor forward

delay(600);

digitalWrite(arduinoPin11, HIGH); 
digitalWrite(arduinoPin3, LOW);   // motor reverse

delay(500);

digitalWrite(arduinoPin11, LOW); 
digitalWrite(arduinoPin3, HIGH);   // motor forward again

// then motor off and the code cycles again.
/////////////////////////////////////////////////////////////////////////////////////////////////////

I'm pretty sure I can't use the delays like that because it interrupts "phaseonemotor". Hopefully it helps show what I'm trying to do. I've tried millis stuff but haven't been able to get it to work.

Arduino Uno if that's needed.

I would be very grateful if anyone has any thoughts for me to try. Thank you!



/////////////////////////    code   //////////////////////////////////
const int arduinoPin11 = 11;
const int arduinoPin3 = 3;
const int arduinoPin12 = 12;
const int cycleTimeCheckDelay = 2500;

void setup() {
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
  pinMode (8, OUTPUT);
  pinMode (9, OUTPUT);
 
  pinMode (11, OUTPUT);
  pinMode (3, OUTPUT);
  digitalWrite(11, HIGH);
  digitalWrite(3, LOW);
  pinMode(arduinoPin12, INPUT);
  digitalWrite(8, HIGH);

  pinMode(LED_BUILTIN, OUTPUT);

  GetToStartingPosition();
}

void loop() {
  bool phase1CycleComplete = false;
  unsigned long startTimeMillis = millis();
  int phase1InitialStepCount = 19500;
 
  // at this point we know for sure the switch is at the start, so continue the normal cycle
  // step initial phase 1 steps; and then kick on phase two
  StepPhaseOneMotor(phase1InitialStepCount); // 24000 full revolution
 
  SetPhaseTwoOn(true);
   
  // run the paper feed cycle, until we reach the end of phase 1 full revolution
  int steps = 10;
  while (!phase1CycleComplete) // 24000 = full revolution
  {
    // move a tiny bit of steps
    StepPhaseOneMotor(steps);
    phase1InitialStepCount += steps;

    // check for starting position (ONLY if after cycleTimeCheckDelay)
    if (millis() - startTimeMillis > cycleTimeCheckDelay && debounceButton(arduinoPin12, false))
    {
      phase1CycleComplete = true;
    }
  }

  // get the value from the potentiometer, to see how long we want to wait before the next cycle begins
  unsigned long newSheetDelay = analogRead(0);
  newSheetDelay = map(newSheetDelay, 0, 1023, 1250, 11500);
 
  unsigned long startPhaseTwoMillis = millis();
  int paperPushMillis = 4500;
   
  // let phase 2 finish pushing the paper out, before shuting off the phase 2 motor
  // AND check for new sheet delay at the same time
  while(abs(millis() - startPhaseTwoMillis) < newSheetDelay){ //abs() in case the millis overflow after 50 days
    // turn off phase 2 motor if new sheet delay is longer than paper push delay
    if (millis() - startPhaseTwoMillis > paperPushMillis)
    {
      SetPhaseTwoOn(false);
    }
    delay (10); // short delay just because
  }
 
}

void StepPhaseOneMotor(int steps){
  for (int i = 0; i <= steps; i++)  // 24000 full revolution
    {
      digitalWrite(9, LOW);
      digitalWrite(9, HIGH);
      delayMicroseconds (200);
    }
}


void SetPhaseTwoOn(boolean setOn){
  if (setOn){
    digitalWrite(arduinoPin11, LOW); 
       digitalWrite(arduinoPin3, HIGH); 
  }
  else{
    digitalWrite(arduinoPin11, HIGH);  
    digitalWrite(arduinoPin3, HIGH);  
  }
}

boolean debounceButton(int pin, boolean state)
{
  boolean stateNow = digitalRead(pin);
  if(state!=stateNow)
  {
    delay(10);
    stateNow = digitalRead(pin);
  }
  return stateNow;  
}

void GetToStartingPosition() {
  // read the position of the phase one motor
  bool isPhaseOneAtStart = (digitalRead(arduinoPin12) == 1);

  // verify the phase one motor is at the starting postion  
  if (isPhaseOneAtStart)
  {
    // everything is good!!
    // but still clear out phase 2 motor just to be safe
    SetPhaseTwoOn(true);
    delay(3500);
    SetPhaseTwoOn(false);
  }
  else{
    // get the printer back to the starting position
    // start the phase two motor so it is clearing out the paper while we step phase one back to the starting position
    SetPhaseTwoOn(true);
     
    while (!isPhaseOneAtStart){
      // step of the phase one motor
      StepPhaseOneMotor(10);

      // check for start position
      isPhaseOneAtStart = debounceButton(arduinoPin12, isPhaseOneAtStart);      
    }

    // continue the phase two motor for a while, to make sure all paper is cleared out of the cycle
    delay(4500); // 1000 = 1.0 seconds
    SetPhaseTwoOn(false);
   }
 }

You cannot use delay() in this case. Study this excellent tutorial: https://www.baldengineer.com/blink-without-delay-explained.html

Thanks! I'm reading it. Do you believe implementing millis will be the solution to this problem? I'm going to read it nonetheless

It is the solution to the problem as you have stated it.

it's hard (for me) to figure out what or how you intend your code to work. it's not obvious if you have DC motors controlled using a motor shield (e.g. L298) or if they are stepper motors that may be driven with a board having a direction and step pins.

using hardcode pin #s doesn't describe what the pin does (e.g. direction, enable, step)

it's not clear if the above logic intends to so something, StepPhaseOneMotor(steps); for a limited amount of time or until some limit switch, " debounceButton()" is reached. (the logic is that it is complete when both conditions are true instead of when either is true which would use an OR, "||" instead of AND, "&&".

this makes a bit more sense, that something is done every "paperPushMillis", but it looks like paperPushMillis is 4.5 seconds and the outer loop is at most 11.5 seconds and as little as 1.25

it's also not clear what SetPhaseTwoOn(false); is expected to do since it seems to set output pins to the same values each time it is called.

consider the following which independently toggles two LEDs at different rates and toggle a "direction" LED when a button switch is pressed

struct Motor {
    const byte PinStep;
    const byte PinDir;

    unsigned long msecPeriod;
    unsigned long msecLst;
};

Motor mots [] = {
    { 13, 11, 500 },
    { 12, 10, 225 },
};
#define N_MOT    (sizeof(mots)/sizeof(Motor))

const byte PinBut = A1;
byte       butState;

enum { Off = HIGH, On = LOW };

// -----------------------------------------------------------------------------
void
loop (void)
{
    unsigned long msec = millis ();

    for (unsigned n = 0; n < N_MOT; n++)  {
        if ( (msec - mots [n].msecLst) > mots [n].msecPeriod)  {
            mots [n].msecLst = msec;
            digitalWrite (mots [n].PinStep, ! digitalRead (mots [n].PinStep));
        }
    }

    byte but = digitalRead (PinBut);
    if (butState != but)  {
        butState = but;
        if (LOW == but)
            digitalWrite (mots [0].PinDir, ! digitalRead (mots [0].PinDir));
    }
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);


    for (unsigned n = 0; n < N_MOT; n++)  {
        digitalWrite (mots [n].PinStep, Off);
        digitalWrite (mots [n].PinDir,  Off);

        pinMode (mots [n].PinStep, OUTPUT);
        pinMode (mots [n].PinDir,  OUTPUT);
    }

    pinMode (PinBut, INPUT_PULLUP);
    butState = digitalRead (PinBut);
}

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