using a joystick: while a stepper is in motion, stop other stepper

Good morning, i am using a 2 axis joystick to control two steppers. my issue is that i need only one stepper to be functioning at a time. IE if the joystick is fully one direction and it veers off, it doesnt start the other motor moving.

I have this code so far and it works pretty well. Ive increased the area i call the “dead stick” to help combat this a bit, but id like just code it out

This is my loop code. anyone have any ideas?

 //FOCUS +Motion (Y)
 //===================================================================
if ((analogRead(Y_pin) > 560) && (analogRead(Y_pin) <= 1000) && (Focus_Steps < 1200)){ 
    Focus_Motor->setSpeed(lowspeed);
    Focus_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    FOV_Motor->release();
    Focus_Steps ++;
  }
  
if ((analogRead(Y_pin) > 1000) && (Focus_Steps < 1200)){ 
    Focus_Motor->setSpeed(highspeed);
    Focus_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    Focus_Steps ++;
}

//FOCUS - Motion (Y)
//===================================================================
  if ((analogRead(Y_pin) < 480) && (analogRead(Y_pin) >= 20) && (Focus_Steps > -1050)){
    Focus_Motor->setSpeed(lowspeed);
    Focus_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    Focus_Steps --;
  }

  if ((analogRead(Y_pin) < 20) && (Focus_Steps > -1050)){ 
    Focus_Motor->setSpeed(highspeed);
    Focus_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    Focus_Steps --;
}

 //FOV +Motion (X)
 //===================================================================
if ((analogRead(X_pin) > 548) && (analogRead(X_pin) <= 1000) && (FOV_Steps < 670)){ 
    FOV_Motor->setSpeed(lowspeed);
    FOV_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    FOV_Steps ++;
  }
if ((analogRead(X_pin) > 1000) && (FOV_Steps < 670)){ 
    FOV_Motor->setSpeed(highspeed);
    FOV_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    FOV_Steps ++;
}

//FOV - Motion (X)
//===================================================================
if ((analogRead(X_pin) < 468) && (analogRead(X_pin) >= 20) && (FOV_Steps > -620)){ 
    FOV_Motor->setSpeed(lowspeed);
    FOV_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    FOV_Steps --;
  }

if ((analogRead(X_pin) < 20) && (FOV_Steps > -620)){ 
    FOV_Motor->setSpeed(highspeed);
    FOV_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    FOV_Steps --;
  }

//===================================================================
if (!active)
   {Focus_Motor->release();
    FOV_Motor->release();
   }

//===================================================================

}
if ((analogRead(Y_pin) > 560) && (analogRead(Y_pin) <= 1000) && (Focus_Steps < 1200)){

How many times do you NEED to read the pin to determine if the value is in the range 560+ to 1000?

You read the y pin up to 6 times, to determine where the joystick is. That’s as many as 5 times more than needed.

Then you do the same with the x pin.

What is seems to me that you want to do is read each pin once, and then decide what to do with both values together. If the stick is far enough forward or backward, ignore the right to left value. If the stick is far enough to the left or to the right, ignore the forward to backwards value.

What do you want to have happen if the stick is pushed all the way forwards and to the right?

seems like i would need to check much less. I am a novice with coding and arduino, please bear with me.

that is exactly what i need to do. x axis runs one stepper at 2 speeds per direction. Y axis does the same.

the way i have it coded is the only way i've gotten it to work.

David7099:
the way i have it coded is the only way i've gotten it to work.

As the first thing in loop() read the values for the 2 axes and save the values into 2 variables.

Then use the values in the variables in all your tests. That way all the tests will use a consistent pair of numbers.

...R

got that in, thanks. any idea how i can make it run only one stepper at a time?

xposition = analogRead(X_pin);
yposition = analogRead(Y_pin);


 //FOCUS +Motion (Y)
 //===================================================================
if ((yposition > 560) && (yposition <= 1000) && (Focus_Steps < 1200)){ 
    Focus_Motor->setSpeed(lowspeed);
    Focus_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    FOV_Motor->release();
    Focus_Steps ++;
  }
  
if ((yposition > 1000) && (Focus_Steps < 1200)){ 
    Focus_Motor->setSpeed(highspeed);
    Focus_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    Focus_Steps ++;
}

//FOCUS - Motion (Y)
//===================================================================
  if ((yposition < 480) && (yposition >= 20) && (Focus_Steps > -1050)){
    Focus_Motor->setSpeed(lowspeed);
    Focus_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    Focus_Steps --;
  }

  if ((yposition < 20) && (Focus_Steps > -1050)){ 
    Focus_Motor->setSpeed(highspeed);
    Focus_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    Focus_Steps --;
}

 //FOV +Motion (X)
 //===================================================================
if ((xposition > 548) && (xposition <= 1000) && (FOV_Steps < 670)){ 
    FOV_Motor->setSpeed(lowspeed);
    FOV_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    FOV_Steps ++;
  }
if ((xposition > 1000) && (FOV_Steps < 670)){ 
    FOV_Motor->setSpeed(highspeed);
    FOV_Motor->step(1, FORWARD, DOUBLE); 
    active = true;
    FOV_Steps ++;
}

//FOV - Motion (X)
//===================================================================
if ((xposition < 468) && (xposition >= 20) && (FOV_Steps > -620)){ 
    FOV_Motor->setSpeed(lowspeed);
    FOV_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    FOV_Steps --;
  }

if ((xposition < 20) && (FOV_Steps > -620)){ 
    FOV_Motor->setSpeed(highspeed);
    FOV_Motor->step(1, BACKWARD, DOUBLE); 
    active = true;
    FOV_Steps --;
  }

//===================================================================
if (!active)
   {Focus_Motor->release();
    FOV_Motor->release();
   }

//===================================================================

}

any idea how i can make it run only one stepper at a time?

Which stepper has priority? If the y axis value has priority, when you discover that the value means far forward or far back, set the x value to 512 (if that's your midpoint deadzone).

If the x axis has priority, do the same to the y value when the x value is max or min.

David7099:
got that in, thanks. any idea how i can make it run only one stepper at a time?

I can't say I understand the problem.

Are you saying that if you move the left-right stick you want (say) motorA to move but not motorB. And if you move the fore-aft stick you want motorB to move but not motorA ?

Anytime I moved a joystick left-right I probably also inadvertently moved it a little in the fore-aft plane also. Is that the problem you are having. And do you want it to ignore fore-aft values when you are using the left-right movements?

I think you already said that you have a dead-zone so that small wiggles will be ignored.

How will the Arduino know which direction is the important one? If you can establish that then it is easy to set a variable to identify that (say) leftRightMotion = true in which case the values for fore-aft can be ignored.

But there is also the question of how the Arduino will know that you are finished with the left-right movement.

...R

i may be making this overly complicated but, what im kinda thinking is dividing each quadrant in half. a 45° boundary that only one motor can move at a time. once it goes over that boundary, the motor stops, and the other starts. i hope that made sense

David7099:
i may be making this overly complicated but, what im kinda thinking is dividing each quadrant in half. a 45° boundary that only one motor can move at a time. once it goes over that boundary, the motor stops, and the other starts. i hope that made sense

Does that mean that if the joystick for motorA is at (say) 60° and the joystick for motorB moves from 0° to 46° that motorA should stop and motorB should start moving?

I suspect not?

But I can't think what you really want to happen. If what I have written is incorrect (as I suspect) then it would be a good idea to write down in a simple table a series of examples of positions and what should happen in each case.

...R

sorry for the late response, been out of town.

could i use a while loop, read the joystick pin and as long as the read value != the "Zero" value keep me in the loop of one motor running? when the joystick returns to center then the other motor can operate, if it needs to?

My experience with joysticks indicate that they rarely report an exact value.

joystickAreas.png

From your description in reply #7, I drew this to help clarify.
The gray areas would only have motor A run.
The green areas would only have motor B run.

What do you think about Robin2’s concern with moving back and forth across the boundary? Should one motor instantly stop and the other instantly start if the user has the joystick near the 45 degree line and crosses?

Maybe you could put in a deadband, where the white areas produce no movement in either area.

joystickAreasWithDeadband.png

The deadband would be defined by a simple test. If the absolute value of the difference between the two joystick readings is less than some deadband constant, then you are in the deadband.

for this project it doesnt really matter where one takes over and the running motor stops. i really just cant have both running, its pulling too much current for this application. odds are in most scenarios the user wont ever encounter the cross over. im just trying to fool-proof it so that if the user does move the stick into a cross over position, my current doesnt spike.

David7099:
could i use a while loop, read the joystick pin and as long as the read value != the "Zero" value keep me in the loop of one motor running? when the joystick returns to center then the other motor can operate, if it needs to?

If that is how you want it to work, then yes.

...R

David7099:
for this project it doesnt really matter where one takes over and the running motor stops. i really just cant have both running, its pulling too much current for this application. odds are in most scenarios the user wont ever encounter the cross over. im just trying to fool-proof it so that if the user does move the stick into a cross over position, my current doesnt spike.

I am NOT a stepper motor expert.
But I thought that stepper motors pulled current all the time. I thought I had read that an idle stepper might pull more current than one running.

vinceherman:
I am NOT a stepper motor expert.
But I thought that stepper motors pulled current all the time. I thought I had read that an idle stepper might pull more current than one running.

they have a holding current that i turn off for this application so they dont heat up.

Robin2:
If that is how you want it to work, then yes.

...R

how would that look in code? im a novice at programming

Something like this pseudo code

    // check if everything has been at 0
if (xAxisWorking == false and yAxisWorking == false) {
        // then if the yVal is active
    if (xVal == 0 and yVal != 0) {
        yAxisWorking = true;
        xAxisWorking = false;
    }
        // or if the xVal is active
    if (xVal != 0 and yVal == 0) {
        yAxisWorking = false;
        xAxisWorking = true;
    }
        // or neither is active
    if (xVal == 0 and yVal != 0) {
        yAxisWorking = false;
        xAxisWorking = false;
    }
}
    // neither is active read both
if (yAxisWorking == false and xAxisWorking == false) {
    yVal = analogRead(ypin);
    xVal = analogRead(xpin);
}
    // else just read one axis
else if (yAxisWorking == true) {
    yVal == analogRead(ypin);
    xVal = 0;
}
else if ((xAxisWorking == true) {
    xVal == analogRead(ypin);
    yVal = 0;
}

...R