Struggling to program macros

I am having trouble programming Marcos for an auto stack program, and I also need some ideas on how to for the lift to go up with our tray at the same time. Below is my driver control program:

void usercontrol(void) {
  // User control code here, inside the loop
  while (1) {
    // This is the main execution loop for the user control program.
    // Each time through the loop your program should update motor + servo
    // values based on feedback from the joysticks.

    // ........................................................................
    // Insert user code here. This is where you use the joystick values to
    // update your motors, etc.
    ChassisControl();


    // 吸方塊

    if(Controller1.ButtonR1.pressing()){
        SuckL.spin(directionType::fwd, 200, velocityUnits::rpm);
        SuckR.spin(directionType::rev, 200, velocityUnits::rpm);

    }
    
    else if (Controller1.ButtonR1.pressing() || Controller1.ButtonR2.pressing() == false){
      SuckL.stop(brakeType::hold);
      SuckR.stop(brakeType::hold);
    }

    // 吐方塊
    if (Controller1.ButtonR2.pressing()) {
      SuckL.spin(directionType::fwd, -200, velocityUnits::rpm);
      SuckR.spin(directionType::rev, -200, velocityUnits::rpm);
    }

    // tray push (stack)
    else if (Controller1.ButtonX.pressing()) {
      Tray.spin(directionType::rev, 40, velocityUnits::rpm);
    }

    else if(Controller1.ButtonUp.pressing()){
   Tray.spin(directionType::rev, 80, velocityUnits::rpm);
    }

    //  tray return
    else if (Controller1.ButtonB.pressing() &&  LimitSwitchB.pressing() == false) {
      Tray.spin(directionType::fwd, 80, velocityUnits::rpm);

    } else if (Controller1.ButtonA.pressing() == false){
      Tray.stop(brakeType::hold); 
    }

    else if (Controller1.ButtonA.pressing()){ 
      if(suckSwitch == 1){
      Tray.rotateFor(-300, rotationUnits::deg, 30, velocityUnits::pct, true);
      Tray.setStopping(hold);
      Tray.rotateFor(-200, rotationUnits::deg, 15, velocityUnits::pct, true);
      Tray.setStopping(hold);
      suckSwitch = 0;
      }
      }

    // lift up
    if (Controller1.ButtonL1.pressing()) {
      Lift.spin(directionType::fwd, -200, velocityUnits::rpm);
    }

    // lift down
    else if (Controller1.ButtonL2.pressing()) {
      Lift.spin(directionType::fwd, 200, velocityUnits::rpm);

    } else {
      Lift.stop(brakeType::hold);
    } 
    }

    wait(100, msec);
    // ........................................................................

    wait(20, msec); // Sleep the task for a short amount of time to
                    // prevent wasted resources.
  }

The auto stack program is at the bottom that is toggled with button A. There is also an int suckSwitch at the very top. Any advice and constructive criticisms will be very much appreciated. Thanks!

I would suggest checking the rpm of the motors to turn on/off the rollers.

If the rollers are spinning the opposite way/turned off (so less than 5 pct would be a good number) and the button is pressed, make the rollers spin the correct way. If the rollers are over 80 pct and the button is pressed then turn off the roller.

If you want the tray and lift to move at the same time, you can make em both spin at the same time using Motor.spin()

1 Like

@73335T, whenever you program a macro that executes during interactive user control period you need to define at least one state variable outside of the while(1) loop.

Please, see the following example:

int iMacroStateVar = 0; // 0 - macro is not running
uint32_t  macroStepEndTime = 0;
while(1)
{
    int userVal = 0;

    int joyVal = Controller1.Axis1.position(pct);
    if( fabs(joyVal) > 10 ) // if using joystick
    {
        userVal = joyVal;
    }

    // if using buttons
    if( Controller1.ButtonR1.pressing() ) // forward
    {
          userVal = 50; // percent of velocity
    }
    else if( Controller1.ButtonR2.pressing() ) // backward
    {
          userVal = -50; // percent of velocity
    }

    if( userVal != 0 )
    {
        motor1.spin(forward, userVal, pct);
        iMacroStateVar = 0; // cancel any macro run
    }
    else if( Controller1.ButtonA.pressing() && iMacroStateVar==0 )
    {  // user pressed A to start macro and macro is not running
        iMacroStateVar = 1; // run motor in reverse for 1 sec or if run into wall
        macroStepEndTime = vex::timer::system() + 1000; 
        motor1.spin(reverse,20,pct); 
    }
    else if( iMacroStateVar==1 && // check when its time to end step 1
             (backBumperSwitch.pressing() ||
              vex::timer::system() > macroStepEndTime ) )
    {
        iMacroStateVar = 2; // run motor forward for 200 units or up to 1.5 sec
        macroStepEndTime = vex::timer::system() + 1500; 
        motor1.spinFor(forward, 200, rotationUnits::deg, 15, velocityUnits::pct, false); 
    }
    else if( iMacroStateVar==0 ||  vex::timer::system() > macroStepEndTime )
    { 
        motor1.stop();
        iMacroStateVar = 0;
    }
    vex::task::sleep(1);
}

In this example user could control motor1 with either value of joystick on Axis1 or by pressing buttons R1 or R2.

When user presses button A it will start the macro and remember its start time.

At any time while macro is running user can take over control and macro sequence will be canceled.

https://api.vexcode.cloud/v5/html/classvex_1_1motor.html
https://api.vexcode.cloud/v5/html/classvex_1_1timer.html
https://api.vexcode.cloud/v5/html/classvex_1_1bumper.html

1 Like