Now let’s have a look on XBox 360 controller buttons
For a start we will use Left stick to direct Lego NXT movements.
First we will make cosmetic change to button captions.
First we will move NXT and Controller object to globa scope so we can access them from any method.
Brick<Sensor, Sensor, Sensor, Sensor> nxt; XboxController selectedController; private void button1_Click(object sender, EventArgs e) { nxt = new Brick<Sensor, Sensor, Sensor, Sensor>("com3"); try { nxt.Connection.Open(); } catch (Exception e1) { MessageBox.Show("Error: " + e1.Message); } } private void button2_Click(object sender, EventArgs e) { try { selectedController = XboxController.RetrieveController(0); selectedController.StateChanged += selectedController_StateChanged; XboxController.StartPolling(); } catch (Exception e1) { MessageBox.Show("Error: " + e1.Message); } }
Clicking on first button will create nxt object and will try to open connection to it.
Clicking on second button will attach to first connected XBox controller.
There’s a single event exposed by the class named StateChanged
that is called if something about the controller’s state has changed from the last thethat it was called.The event arguments for this event contain the current and previous state of the controller. So this is event we have to observe.
It’s necessary to poll the controller to continually get updates about it’s state. In an XNA or DirectX program this would be part of your game loop and so you don’t really need to think about it. If you use the class in an environment without such a loop there are two options for getting updates to the controller. You could either callUpdateState
manually or you could call the static method XboxController.StartPolling
. The static method will create a new thread that will update the controller’s state on some frequency. By default I’ve set this to 25 times per second. If you want to change it to some other value assign the number of updates per second that you want to received to the static member UpdateFrequency
. When you nolonger wish to receive updates remember to call the XboxController.StopPolling
method to end the thread.
In Form close possible connections are closed too:
private void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (nxt != null) nxt.Connection.Close(); if (selectedController != null) XboxController.StopPolling(); }
The selectedController_StateChanged method is were actual communication control must take place. For a start we will make simplified code where Left stick up down will make NXT move forward and back with constant speed and moving left or right will command corresponding turn. As state update will give us simultaneously both X and Y direction values we will first save turning information to left_turning and right_turning variables. Also to avoid “noise” movements we implemented sensitivity threshold, all movements below it will be ignored.
sbyte left_turning = 0; sbyte right_turning = 0; int sensitivity = 4000; private void selectedController_StateChanged(object sender, XboxControllerStateChangedEventArgs e) { left_turning = 0; right_turning = 0; if (Math.Abs(selectedController.LeftThumbStick.X) > sensitivity) { if (selectedController.LeftThumbStick.X < 0) left_turning = 20; else right_turning = 20; } if (Math.Abs(selectedController.LeftThumbStick.Y) > sensitivity) { if (selectedController.LeftThumbStick.Y < 0) { nxt.MotorB.On((sbyte)(-20 - left_turning)); nxt.MotorC.On((sbyte)(-20 - right_turning)); } else { nxt.MotorB.On((sbyte)(20 + left_turning)); nxt.MotorC.On((sbyte)(20 + right_turning)); } } else { nxt.MotorB.Off(); nxt.MotorC.Off(); } }
selectedController.LeftThumbStick.X will give left-right side movements. It is type of short. XINPUT_GAMEPAD structure
Describes the current state of the Xbox 360 Controller.
typedef struct _XINPUT_GAMEPAD { WORD wButtons; BYTE bLeftTrigger; BYTE bRightTrigger; SHORT sThumbLX; SHORT sThumbLY; SHORT sThumbRX; SHORT sThumbRY; } XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
So value range is from -32768 to -32767. But for now we just control if the value is big enough
if (Math.Abs(selectedController.LeftThumbStick.X) > sensitivity)
If so then we calculate is it left
if (selectedController.LeftThumbStick.X < 0)
or right turn.
Next back-forward movement is detected
if (Math.Abs(selectedController.LeftThumbStick.Y) > sensitivity)
NXT motor speed is sixe of sbyte so in range -128 to 127. Negative value means reverse direction.
Next turning speed is added and command with total speed is sent to Motors. If thumbstick is concidered to be in neutral position then motors are stopped.
nxt.MotorB.Off(); nxt.MotorC.Off();
Next time we will make some improvements to create more responsive control instead of constant speed.