I am going crazy

My team wants me and my other programming buddy to program the arm as a digital so that it moves up and down when you push a button and release. How the heck do I do that???They try telling me to look it up but so far I have not found it.

I’m not sure I understand what your team wants you to do… Do you want to make two buttons, one that moves the arm up, and the other to move it down, or are looking for one button to do both…? What will releasing the button do, exactly? Please explain so that everyone can help better.

Are you programming in MPLAB or easyC?

Um. Don’t you need sensors or something? Maybe a limit switch.

Limit switches are the preferred way to do this. Using simple state machine code is a good way to code the behavior. Check out this simple code from last year, the RunArm function is called each time through the slow loop.

typedef enum
{
ARM_UNKNOWN,
ARM_EXTENDING,
ARM_RETRACTING,
ARM_EXTENDED,
ARM_RETRACTED,
ARM_LAST
} ARM_STATES;

typedef struct
{
CLAW_STATES eClawState;
ARM_STATES eArmState;
MAST_STATES eMastState;

} ARM_DATA;

#define ARM_MOTOR_EXTEND_DRIVE 192
#define ARM_MOTOR_RETRACT_DRIVE 64
#define ARM_MOTOR_OFF_DRIVE 128

#define RHS_ARMEXTEND_IN p1_sw_top
#define RHS_ARMRETRACT_IN p1_sw_top

#define RHS_ARM_MOTOR pwm04

#define RHS_ARM_EXTEND_LIMIT rc_dig_in06
#define RHS_ARM_RETRACT_LIMIT rc_dig_in07

static void RunArm(ARM_DATA *pData)
{
// if we are in an out of range state

if (pData->eArmState >= ARM_LAST)
{
pData->eArmState = ARM_UNKNOWN;
}

switch (pData->eArmState)
{
case ARM_UNKNOWN:
// always extend the arm if in an unknown state

     pData->eArmState = ARM_EXTENDING;
     break;

  case ARM_EXTENDING:
     if (RHS_ARM_EXTEND_LIMIT)
     {
        // still opening

        RHS_ARM_MOTOR = ARM_MOTOR_EXTEND_DRIVE;
     }
     else
     {
        // we are open

        pData->eArmState = ARM_EXTENDED;
     }
     break;

  case ARM_RETRACTING:
     if (RHS_ARM_EXTEND_LIMIT)
     {
        // still closing

        RHS_ARM_MOTOR = ARM_MOTOR_RETRACT_DRIVE;
     }
     else
     {
        // we are closed

        pData->eArmState = ARM_RETRACTED;
     }
     break;

  case ARM_EXTENDED:
     RHS_ARM_MOTOR = ARM_MOTOR_OFF_DRIVE;

     if (RHS_ARMRETRACT_IN)
     {
        // follow command to close

        pData->eArmState = ARM_RETRACTING;
     }
     break;

  case ARM_RETRACTED:
     RHS_ARM_MOTOR = ARM_MOTOR_OFF_DRIVE;

     if (RHS_ARMEXTEND_IN)
     {
        // follow command to open

        pData->eArmState = ARM_EXTENDING;
     }
     break;
     break;

  default:
     RHS_ARM_MOTOR = ARM_MOTOR_OFF_DRIVE;
     pData->eArmState = ARM_UNKNOWN;
     break;

}
}

HTH

Wow, yours seems kind of confusing. Another way of doing it which in my opinion is easier is

unsigned char motorup = TRUE;
unsigned char motordown = TRUE;

if (rc_dig_in01 == 1) //If the limit switch at the top is pressed
{
motorup = FALSE;
}
else
{
motorup = TRUE;
}
if (rc_dig_in02 == 1) //Limit switch at bottom
{
motordown = FALSE;
}
else
{
motordown = TRUE;
}
if (p1_sw_trig == TRUE && motorup == TRUE)
{
pwm01 = 200; //Assuming that a # higher that 127 goes up
}
if (p1_sw_top == TRUE && motordown == TRUE)
{
pwm01 = 50; //Assuming lower # goes down
}
else
{
pwm01 = 127;
}

This is how I like to do it. If you think another way is easier go for that. it is all about how you feel comfortable using code. Also I just made up the values and pwm numbers use whatever your motors and sensors are plugged into. Also im sorry about the font. I pressed a button and it changed the font and im not sure how to put it back to normal
Joey

Well, it depends on how your robot is designed, and what your program already has in it.
The button pushing part is easy, just look in dashboard to find the button you want. Something like the following will toggle up/down on press. You don’t need to hold the button with this routine either:


//at the top:
#define BUTTON p3_sw_trig

//in the loop:
static char armMove;

if(BUTTON & armMove==0){
     if(the arm is down)
         armMove = 1;
     else
         armMove = 2;
}

if(armMove){//this uses the fact that both 1 and 2 will be true, while 0 will be false.
    if(moveArm(armMove))
        armMove = 0;
}     


then, down the page (or in another file), you need to have a function that actually moves the arm, and returns true if the arm is done moving.


int moveArm(char way){
    char finished
    if(way == 1){
        //move the arm up, set pwms.
        //you probably want to use a PID loop.
        //return 1 if the arm is there already, and set the pwm to 127.
    } else {
        //move the arm down, set pwms.
        //you probably want to use a PID loop.
        //return 1 if the arm is there already, and set the pwm to 127.
    }

   return 0;

Thats the way I would attempt to do it. Depending on your bot, you may have to use some sort of a PID loop to get the arm to the correct position. If you use limit switches instead of a POT, you could probably do it with just a P loop.

“Wow, yours seems kind of confusing”

Our algorithm is a state machine. If we drew each algorithm on a white board, ours would look much simpler than yours. And ours is more efficient, each time it is called only the code in one case is executed. Yours seems just as complex. You have almost as many ‘if’ clauses as we have cases. I reckon the use of macros and a switch statement would make it look more complex to a less experienced programmer. But our team has a number of software mentors to help the students.

HTH

We are doing exactly as you describe. It takes to simple functions, call the first one then call the second. The first one looks at the button inputs on the console, the second one sends the command to the lift function.

int Get_Oi_Switch (void)
{
	if (p1_sw_top == 1)
	{
		liftcmd = LOAD;
	}
	if (p1_sw_trig == 1)
	{
		liftcmd = HURDLE;
	}
	if (p1_sw_aux1 == 1)
	{
		liftcmd = PICK;
	}
	if (p1_sw_aux2 == 1)
	{
		liftcmd = PLACE;
	}
	return liftcmd;	
}
int Set_Lift_Height (int pos_demand)
{
  int liftdrv;
  int liftvel;
	liftpos = ((int)Get_Encoder_5_Count());
	liftposerr = (pos_demand - liftpos);
	liftvel = (liftpos - lastliftpos);
	lastliftpos = liftpos;  // Save position for next loop
	liftdrv = ((liftposerr * LIFT_KP) + (liftvel * LIFT_KD));  // Actual PD equation
	if (liftdrv > LIFT_MAX_V)
	{
		liftdrv = LIFT_MAX_V; // Limit lift speed to defined range
	}
	if (liftdrv < -LIFT_MAX_V)
	{
		liftdrv = -LIFT_MAX_V;
	}
	
	return (liftdrv + 127);
}

As you can see, there are some definitions that are set up outside of this file that define the individual heights and velocities. Also included in the Set_Lift_Height function is a PD loop. We are not using the integral function of a PID loop.

EDIT: If it helps, feel free to use this code. Just make sure you understand it and modify it to match your system. All I ask is that you let us know how it works out for you.

WOW!!! thinks for all the help and sorry I was not to specific with the function but I think my team member and I can put something together now. So Thanks a bunch.