Joystick randomly stops working

So we are currently using a X drive with the controller programmed with the right joystick for translational movement of the chassis, and the left joystick is Rotation of the chassis. Quite frequently, while I’m driving, the right joystick will completely stop registering me doing anything and the robot will stop. The other joystick and buttons work fine. Then after a couple seconds it works again. This happens with our mogo lift occasionally as well. Is this a joystick issue? Or is it a programming issue? Does anyone have experience with this? Help is greatly appreciated, thanks in advance.

While I would pin this as a motor controller or cortex issue at first, the fact that it’s happening across multiple mechanisms tells me it’s probably something with the code, so if you wouldn’t mind posting that, perhaps we could find the possible error there.

Ok, I’ll try to get it tomorrow, since I’m not at school right now.

sometimes the motors get overheated and that could cause the joystick to malfunction. Or the controller seems to get disconnected.

If it’s not one of the above problems (which I’m guessing you have the capability of diagnosing yourself), I would highly recommend to check before you even post it to make sure that your drive code doesn’t accidentally enter a while loop that could possibly not have its condition satisfied (other than the main while loop in the drive code, of course), as it seems like the robot is waiting for something to happen, and that’s why everything stops working for a a few seconds.

Just curious, is all of your drive code taking place inside the main while loop, or do you have separate tasks that take care of multiple things (if you know without having to see it at school)? And if you do know, does your drive code use PID control at all?

I am not the programmer, I am the driver that can’t program very much, so is it ok if I just post the code and let you answer your own question? But I do know we don’t use PID in teleop. I can get the code this morning, thanks for the help so far. Also I know it’s not motors overheating, I know how that works

@Mystellianne here is part of our code (not including the #include stuff etc.). Also it was programmed in PROS if this makes a difference. :

short botVelocityX = 0;  // Velocity relative to x-coordinate in xy-coordinate plane
short botVelocityY = 0;  // Velocity relative to y-coordinate in xy-coordinate plane
short botVelocityZ = 0;  // Rotation
/* Private Function Prototypes */


void calcQuad(short* quad);
void calcNFM(short speed, short quad, short* nfm);
void calcSpeed(short* speed);


unsigned char offset(short motor, short offset);
void motorSetAdj(unsigned char channel, int speed);


/* External Functions */


void setVelocityX(short x) {
  if (x == 0) return;


  //If x is not within +/- 127 adjust to max value for direction
  botVelocityX = x;
  botVelocityZ = 0;
}


void setVelocityY(short y) {
  if (y == 0) return;


  //If y is not within +/- 127 adjust to max value for direction
  botVelocityY = y;
  botVelocityZ = 0;
}


void setVelocityZ(short z) {
  if (z == 0) return;


  //If z is not within +/- 127 adjust to max value for direction
  botVelocityZ = z;
  botVelocityX = 0;
  botVelocityY = 0;
}




void doMotorTick() {
  if (botVelocityZ != 0) {
    // TODO: Add handling for Rotation (i.e. set all motors to botVelocityZ)


    motorSetAdj(RIGHT_FRONT_MOTOR, -botVelocityZ);
    motorSetAdj(LEFT_FRONT_MOTOR, -botVelocityZ);
    motorSetAdj(LEFT_REAR_MOTOR, -botVelocityZ);
    motorSetAdj(RIGHT_REAR_MOTOR, -botVelocityZ);


    resetVelocity();
    return;
  }


  /* calculates motor speeds */
  short nfmSpeed = 0, botSpeed = 0, quad = 0;
  calcSpeed(&botSpeed);
  calcQuad(&quad);
  calcNFM(botSpeed, quad, &nfmSpeed);
  /* Uses getQuad and getnfm to determine the speed of the motors */
  msg_debug("X:%d Y:%d Z:%d\n", botVelocityX, botVelocityY, botVelocityZ);
  msg_debug("NFM:%d BSP:%d QUAD:%d\n", nfmSpeed, botSpeed, quad);


  /* Set Motors to correct speed (angle adjusted) */
  motorSetAdj(offset(RIGHT_FRONT_MOTOR, quad), nfmSpeed);
  motorSetAdj(offset(LEFT_FRONT_MOTOR, quad), -botSpeed);
  motorSetAdj(offset(LEFT_REAR_MOTOR, quad), -nfmSpeed);
  motorSetAdj(offset(RIGHT_REAR_MOTOR, quad), botSpeed);


  resetVelocity();
}


/* Calculations for Holonomic Drive */


void calcQuad(short* quad) {
  /* determines what quadrant the velocity is in */
  if (botVelocityY >= 0) {
    *quad = (botVelocityX > 0 ? 1 : 2);
  } else {
    *quad = (botVelocityX > 0 ? 4 : 3);
  }
}


void calcNFM(short speed, short quad, short* nfm) {
  /* Get non facting local motor speed */
  short high = (abs(botVelocityY) - abs(botVelocityX)) * speed;
  short low = abs(botVelocityY) + abs(botVelocityX);


  *nfm = (high / low) * (quad % 2? 1 : -1);
}


void calcSpeed(short* speed) {
  /* Takes a short* and assigns the speed of the robot */
  *speed = (short)sqrtf(botVelocityX * botVelocityX + botVelocityY * botVelocityY);
  *speed = SPEED_LIMIT(*speed);
}


/* Basic Utility Functions */


unsigned char offset(short motor, short offset) {
  motor += offset - 1;
  return (unsigned char)(RIGHT_REAR_MOTOR >= motor? motor: motor - 4);
}


void resetVelocity() {
  botVelocityX = 0;
  botVelocityY = 0;
  botVelocityZ = 0;
}


void motorSetAdj(unsigned char channel, int speed) {
  int adj] = {1,1,1,1,1,1,1,1,1,1};
  motorSet(channel, speed * adj[channel - 1]);
}

All of that looks fine to me. Could you post the portion of code where these functions are actually called (where it takes joystick input)? That is most likely where the error is. Assuming there is no while loop that is getting in the way, my best guess would be that because joysticks are analog, they don’t always return exactly zero when they’re at the neutral position. Without seeing the code, I would say that maybe the


setVelocityZ

function is being called with the raw input of the joystick. The function will override movement and rotate the robot if the input to that function is not zero, so I would hazard to guess that maybe the input to that function is NEAR zero, but not exactly (maybe 2 or 3), meaning that it will override the translation and only rotate. Of course, a motor power of 2 wouldn’t be able to move it at all, making it stop. Again, there’s no way to actually check this without seeing where these functions are called, so if you could provide that it would help.

@ZachDaChampion here is the code, thanks for the help so far!

#include "constants.h"
#include "debug.h"
#include "API.h"
#include "main.h"
#include "velocity.h"
#include "appendages.h"

void debugControl() {
  msg_warn("%s\n", "WARN. Using debug loop");

  char xVelocity = 50;          // For using motors w/ buttons (X)
  char yVelocity = 50;          // For using motors w/ buttons (Y)

  while (1) {
    if (joystickGetDigital(1,7,JOY_UP)) {
      setVelocityX(xVelocity);
      setVelocityY(yVelocity);
    }
    else if (joystickGetDigital(1,7,JOY_DOWN)) {
      setVelocityX(-xVelocity);
      setVelocityY(-yVelocity);
    }
    else if (joystickGetDigital(1,7,JOY_LEFT)) {
      setVelocityX(-xVelocity);
      setVelocityY(yVelocity);
    }
    else if (joystickGetDigital(1,7,JOY_RIGHT)) {
      setVelocityX(xVelocity);
      setVelocityY(-yVelocity);
    }
    doMotorTick();
  }
}

/*
 * Runs the user operator control code. This function will be started in its own task with the
 * default priority and stack size whenever the robot is enabled via the Field Management System
 * or the VEX Competition Switch in the operator control mode. If the robot is disabled or
 * communications is lost, the operator control task will be stopped by the kernel. Re-enabling
 * the robot will restart the task, not resume it from where it left off.
 *
 * If no VEX Competition Switch or Field Management system is plugged in, the VEX Cortex will
 * run the operator control task. Be warned that this will also occur if the VEX Cortex is
 * tethered directly to a computer via the USB A to A cable without any VEX Joystick attached.
 *
 * Code running in this task can take almost any action, as the VEX Joystick is available and
 * the scheduler is operational. However, proper use of delay() or taskDelayUntil() is highly
 * recommended to give other tasks (including system tasks such as updating LCDs) time to run.
 *
 * This task should never exit; it should end with some kind of infinite loop, even if empty.
 */

void operatorControl() {
  /* Set some default values */
  // char mainLoop = 1;            // Debugging bypass
  resetVelocity();

  // if (!mainLoop) { debugControl(); }
  /* Testing Loop */

  /* Main Loop */
  while (1) {
    setVelocityX(joystickGetAnalog(JOY_RX));
    setVelocityY(joystickGetAnalog(JOY_RY));
    setVelocityZ(joystickGetAnalog(JOY_LX));

    setVelocityA(joystickGetDigital(ARM_OUT) ? -1 : joystickGetDigital(ARM_IN));
    setVelocityC(joystickGetDigital(CLAW_CLOSE) ? -1 : joystickGetDigital(CLAW_OPEN));
    setVelocityL(joystickGetDigital(LIFT_IN) ? -1 : joystickGetDigital(LIFT_OUT));

    doAuxTick();
    doMotorTick();
    delay(20);
  }
}

Wow, I think I may have been right! pats self on back Try changing


setVelocityZ(joystickGetAnalog(JOY_LX))

(near the bottom) to something like


int z =joystickGetAnalog(JOY_LX);
if (abs(z) >= 20) {
    setVelocityZ(joystickGetAnalog(JOY_LX));
}

You may have to add


#include "math.h"

to the top of your code.

See if that works.

Thanks! We will try that tomorrow!