View unanswered posts | View active topics It is currently Sun Dec 21, 2014 9:30 pm






Reply to topic  [ 6 posts ] 
Using Multiple Controler Buttons with ROBOT C 
Author Message
Rookie

Joined: Mon Oct 06, 2008 12:40 pm
Posts: 2
Post Using Multiple Controler Buttons with ROBOT C
I am having a problem when trying to program more than one buttons on a controller. I specified in the program to use button 2 to move the servo, but when I run the program on the robot button 1 controls its functions as well as the functions assigned to button 2. The code I am using is pasted below; the parts involving button 2 are in bold. Any help would be appreciated.

#pragma config(Hubs, S1, HTMotor, HTServo, none, none)
#pragma config(Sensor, S2, touch, sensorTouch)
#pragma config(Sensor, S3, touch2, sensorTouch)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

#include "JoystickDriver.c"

TJoystick joystick;

task main()
{
while (true)
{
getJoystickSettings(joystick);
motor[motorD] = joystick.joy1_y1;
motor[motorE] = joystick.joy1_y2;

if(joy1Btn(1) != 0) //If Joy1-Button1 is pressed
{
motor[motorA] = 100; // Turn Motor A On at full power

wait10Msec(100);

motor[motorA] = 0; // Turn Motor A Off

wait10Msec (100);

motor[motorB] = 100; // Turn Motor A On at full power

wait10Msec(100);

motor[motorB] = 0; // Turn Motor A On at full power

}

else //If Joy1-Button1 is NOT pressed

{
motor[motorA] = 0; // Turn Motor A Off

motor[motorB] = 0; // Turn Motor A On at full power
}


if(SensorValue(touch) != 0) //If Joy1-Button1 is pressed
{
motor[motorA] = 100; // Turn Motor A On at full power

wait10Msec(100);

motor[motorA] = 0; // Turn Motor A Off

wait10Msec (100);

motor[motorB] = 100; // Turn Motor A On at full power

wait10Msec(100);

motor[motorB] = 0; // Turn Motor A On at full power

}

else //If Joy1-Button1 is NOT pressed

{
motor[motorA] = 0; // Turn Motor A Off

motor[motorB] = 0; // Turn Motor A On at full power
}

if(SensorValue(touch2) != 0) //If Joy1-Button1 is pressed
{
PlayTone(1000, 100);
}

else //If Joy1-Button1 is NOT pressed

{
PlayTone(0, 0);
}



if(joy1Btn(2) != 0) //If Joy1-Button2 is pressed
{
servoTarget[servo1] = 240; // Move Servo1 to position '240'
}
else //If Joy1-Button1 is NOT pressed
{
servoTarget[servo1] = 50; // Move Servo1 to position '50'
}


}
}


Mon Oct 06, 2008 12:52 pm
Profile
Rookie

Joined: Sun Sep 28, 2008 1:06 pm
Posts: 27
Post Re: Using Multiple Controler Buttons with ROBOT C
To start, I don't believe there is a need for 'TJoystick joystick;'

Are you trying to press both buttons at once?

The help menu in RobotC can be a great reference.


Mon Oct 06, 2008 1:34 pm
Profile
Rookie

Joined: Mon Oct 06, 2008 12:40 pm
Posts: 2
Post Re: Using Multiple Controler Buttons with ROBOT C
basicxman wrote:
To start, I don't believe there is a need for 'TJoystick joystick;'

Are you trying to press both buttons at once?

The help menu in RobotC can be a great reference.


I am attempting to use the buttons separately. Also I checked the help section, there are some pointers but nothing specific. I am still a little stuck.
Thanks for the ideas.


Mon Oct 06, 2008 1:46 pm
Profile
Professor

Joined: Fri Sep 19, 2008 1:22 am
Posts: 200
Post Re: Using Multiple Controler Buttons with ROBOT C
There is already a declaration of the "joystick" global in JoystickDriver.c so you absolutely do not want to create another one in your code. I have complained to the RobotC guys already that their model for this is inconsistant and confusing for users. Hopefully they will clean it up soon.

_________________
Jeff McBride
Benson Robotics Club


Mon Oct 06, 2008 2:01 pm
Profile
Site Admin
Site Admin

Joined: Wed Jan 24, 2007 10:42 am
Posts: 616
Post Re: Using Multiple Controler Buttons with ROBOT C
I cleaned up your code for you somewhat... there are a few programmatic errors though.

1. If you notice a huge delay from when you release the button vs. the servo returning to it's position, it's because you are using wait statements. Wait statements will hold up the execution of your program, not allowing it to get to other part of your code and created the "delay" you speak of.

2. I changed your "if(joy1Btn(2) != 0)" to just "if(joy1Btn(2))"... both are correct, but the second form will prevent any possible issues.

Just as a note, if you think the joy1Btn and joy2Btn functions are "confusing", feel free to access the raw joystick values from joystick.joy1_buttons or joystick.joy2_buttons... the issue there is that you'll get a raw bitmap value and it will be difficult to read different buttons from each other (example: pressing button 1 returns a value of 1, pressing button 3 returns a value of 4... pressing both 1 and 3 together returns a value of 5)

Code:
#pragma config(Hubs, S1, HTMotor, HTServo, none, none)
#pragma config(Sensor, S2, touch, sensorTouch)
#pragma config(Sensor, S3, touch2, sensorTouch)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

#include "JoystickDriver.c"

task main()
{
  while (true)
  {
    getJoystickSettings(joystick);
    motor[motorD] = joystick.joy1_y1;
    motor[motorE] = joystick.joy1_y2;

    if(joy1Btn(1)) //If Joy1-Button1 is pressed
    {
      motor[motorA] = 100; // Turn Motor A On at full power
      wait10Msec(100);
      motor[motorA] = 0; // Turn Motor A Off
      wait10Msec (100);
      motor[motorB] = 100; // Turn Motor A On at full power
      wait10Msec(100);
      motor[motorB] = 0; // Turn Motor A On at full power
    }
    else //If Joy1-Button1 is NOT pressed
    {
      motor[motorA] = 0; // Turn Motor A Off
      motor[motorB] = 0; // Turn Motor A On at full power
    }

    if(SensorValue(touch) != 0) //If touch sensor is pressed
    {
      motor[motorA] = 100; // Turn Motor A On at full power
      wait10Msec(100);
      motor[motorA] = 0; // Turn Motor A Off
      wait10Msec (100);
      motor[motorB] = 100; // Turn Motor A On at full power
      wait10Msec(100);
      motor[motorB] = 0; // Turn Motor A On at full power
    }
    else //If Joy1-Button1 is NOT pressed
    {
      motor[motorA] = 0; // Turn Motor A Off
      motor[motorB] = 0; // Turn Motor A On at full power
    }

    if(SensorValue(touch2) != 0) //If Joy1-Button1 is pressed
    {
      PlayTone(1000, 100);
    }
    else //If Joy1-Button1 is NOT pressed
    {
      PlayTone(0, 0);
    }

    if(joy1Btn(2)) //If Joy1-Button2 is pressed
    {
      servoTarget[servo1] = 240; // Move Servo1 to position '240'
    }
    else //If Joy1-Button2 is NOT pressed
    {
      servoTarget[servo1] = 50; // Move Servo1 to position '50'
    }
  }
}

_________________
Timothy Friez
ROBOTC Developer - SW Engineer
tfriez@robotc.net


Tue Oct 07, 2008 12:04 pm
Profile
Rookie

Joined: Sun Nov 16, 2008 3:07 pm
Posts: 45
Post Re: Using Multiple Controler Buttons with ROBOT C
The reason this:
Quote:
2. I changed your "if(joy1Btn(2) != 0)" to just "if(joy1Btn(2))"... both are correct, but the second form will prevent any possible issues.

solved the problem is that joy1Btn is not a Function, but a Macro, defined using #define, and that causes some unexpected operator precedence problems.

In
#include "JoystickDriver.c"

There is a #define like
#define joy1Btn(btn) joystick.joy1_Buttons & (1 << (btn - 1))

When you use a #define instead of a function, the text is Literally substituted in where you use the name of the macro.

That means, when you type
if(joy1Btn(2) != 0)
the first thing the compiler will do is substitute the definition of joy1Btn like this:
if(joystick.joy1_Buttons & (1 << (2 - 1)) != 0)

When the compiler evaluates the resulting expression, it groups operations according to "operator precedence", http://www.difranco.net/cop2220/op-prec.htm

From that table, you can see that != has higher precedence than &, which means the operations will be performed as if you had put parenthesis like this:
if(joystick.joy1_Buttons & ((1 << (2 - 1)) != 0))
which simplifies to
if(joystick.joy1_Buttons & 1)

which is NOT what you wanted. You were hoping for this:
if((joystick.joy1_Buttons & ((1 << (2 - 1))) != 0))
which simplifies to
if (joystick.joy1_Buttons & 2)

Thus whenever you push button 1, that "if" is true.

The way experienced C programmers avoid problems like this is to overparenthesize the definitions of macros to prevent unexpected associations when they are expanded. For example, I would have written the #define like this:
#define joy1Btn(btn) (joystick.joy1_Buttons & (1 << (btn - 1)))

or maybe even like this, if I am worried that someone might invoke it like if (joy1Btn(4<<2))
#define joy1Btn(btn) (joystick.joy1_Buttons & (1 << ((btn) - 1)))
because without the parens around btn, it would expand like this:
if (joystick.joy1_Buttons & (1 << (4<<2 - 1)))
which due to the operator precedence table would give you
if (joystick.joy1_Buttons & (1 << (4<<(2 - 1))))
which is button 8, but you asked for button 16 (or something like that).

The moral of the story is that Parenthesis are free and you should use them, ESPECIALLY in #defines.

Perhaps the good people at CMU will update the JoystickDriver.c file with some extra parens, but in the meantime you can do it yourself or you can revise your code as suggested by Timothy Friez, or you can put extra parens at the point of invocation:
if((joy1Btn(2)) != 0)
which will look goofy and ignorant, but will insulate you from evil that lurks in #include'd files.

Good luck,
David Fort
Rockwell Automation
Mentor, Team 1001
Charles F. Brush High School
South Euclid-Lyndhurst, Ohio USA


Sun Nov 16, 2008 3:51 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 6 posts ] 

Who is online

Users browsing this forum: BurningLights and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.