Hobby project – Lego NXT, XBox 360 controller, PC and C#. Part 4

By | 11. August 2015

Now let’s have a look on XBox 360 controller buttons

XBOX 360 Controller Buttons

XBOX 360 Controller Buttons (wikipedia)

For a start we will use Left stick to direct Lego NXT movements.

First we will make cosmetic change to button captions.

Main Screen

Main Screen

 

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.

Leave a Reply