Main Site Documentation

USBHost - Joystick


#1

Hey guys,

Was working on my robot today and I have discovered this:

joyStick.JoystickXYMove += JoystickXYMove;

Runs the JoystickXYMove only ONCE. So every XY event triggers the method only ONCE.

What would be a good method to have some sort of:

WHILE (JoystickXY) {CODE}

So that you could control servos with the XY of the joystick? Like joystickX1 triggers the servo position + 100 till you release the XY1…?

Any suggestions?


#2

That is normal. You will get an event only once if the joystick is not moving but then if you move it then you will have more events.
I am not sure I understand the problem


#3

The problem is: I would like to transfer the XY to the robot.

So let’s say I keep X pressed at 512 (right).
The code should be executed as long as I control the X.

So if the code is:
Position[0] += 100;

The index 0 should keep increasing with 100 while I keep control of the X.
If I release the joystick (position 0) the code should stop executing.

Do you understand now?


#4

You don’t need to use events in this case, try something like:
while(true)
{
MoveRobot(joystick.Cursor.X, joystick.Cursor.Y);
}


#5

It seems like my post got lost during the update…

Here it is again: (sort of)

This does not work, because the loop eats up processor capacity.
I thought about executing the code while a button was pressed, but till now no succes.

Here is the code:

public static void Main()
        {
            USBHostController.DeviceConnectedEvent += DeviceConnectedEvent;
            Thread.Sleep(Timeout.Infinite);
        }

        static void DeviceConnectedEvent(USBH_Device device)
        {
            Debug.Print("Device connected");

            switch (device.TYPE)
            {
                case USBH_DeviceType.Serial_FTDI: // FTDI connected 
                    Debug.Print("FTDI");
                    serialUSB = new USBH_SerialUSB(device, 115200, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One);
                    serialUSB.Open();

                    serialUSBThread = new Thread(SerialUSBThread);
                    serialUSBThread.Start();
                    break;

                case USBH_DeviceType.Joystick:
                    Debug.Print("Joystick connected");
                    joyStick = new USBH_Joystick(device);
                    joyStick.JoystickXYMove += JoystickXYMove;
                    joyStick.JoystickButtonDown += JoystickButtonPressed;
                    break;
            }
        }

        static void SerialUSBThread()
        {
            while (true)
            {
                for (int i = 0; i < 18; i++)
                {
                    byte[] data = Encoding.UTF8.GetBytes("#" + Servo[i].ToString() + "P" + Position[i].ToString() + "T150\r");
                    serialUSB.Write(data, 0, data.Length);
                    Thread.Sleep(10);
                }
            }
        }

        static void JoystickXYMove(USBH_Joystick sender, USBH_JoystickEventArgs args)
        {
            if (args != null)
            {
                if (args.ChangedButton == 1)
                {
                    Position[1] = Position[1] + 10;
                    Thread.Sleep(1000);
                }

                else { };
            }
        }

        static void JoystickButtonPressed(USBH_Joystick sender, USBH_JoystickEventArgs args)
        {
            switch (args.ChangedButton)
            {
                case 0:
                    for (int i = 0; i < Position.Length; i++)
                    {
                        Position[i] = 1500;
                    }
                    break;
            }
        }

#6

What about using a separate thread for this ?

You start the “Increment” thread during the first XY event (if appropriate, of course) and when an event appears some time after saying that XY is now 0, then you stop the “Increment” thread.


#7

Could you post a code snippet?

Thank you. :wink:


#8

In you code above, you could replace the content of the JoystickXYMove event with something like this :


static void JoystickXYMove(USBH_Joystick sender, USBH_JoystickEventArgs args)
        {
            if (args != null)
            {
                if (args.ChangedButton == 1 && args.ButtonState == USBH_JoystickButtonState.Pressed)
                {
                    IncrementThread.Start();
                }
                if (args.ChangedButton == 1 && args.ButtonState == USBH_JoystickButtonState.Released)
                {
                    IncrementThread.Abort();
                }
            }
        }

and add the following code :


static void IncrementThreadImplementation()
        {
            while (true)
            {
                Position += 10;
                Thread.Sleep(10);
            }
        }

In your DeviceConnected event, add the following :


IncrementThread = new Thread(IncrementThreadImplementation);

and declare the thread variable globally :


static Thread IncrementThread;

Of course, all this is untested because I don’t have a joystick and my FEZ is at home (I’m at work, right now :wink: ), but I hope you will see the idea behind this.

Also, the tests about “button.pressed” or “button.released” may not suit your needs, but that’s all I’ve seen at the moment to show the method.


#9

Better programming practice would use Thread.Suspend and Thread.Resume, of course. As I can’t test the code, I didn’t go too far.


#10
static void JoystickXYMove(USBH_Joystick sender, USBH_JoystickEventArgs args)
        {
            if (args != null)
            {
                if (args.ChangedButton == 1 && args.ButtonState == USBH_JoystickButtonState.Pressed)
                {
                    IncrementThread.Start();
                }
                if (args.ChangedButton == 1 && args.ButtonState == USBH_JoystickButtonState.Released)
                {
                    IncrementThread.Abort();
                }
            }
        }

        static void IncrementThreadImplementation()
        {
                Debug.Print("pressed");
                Thread.Sleep(100);           
        }

This does work partially. Still, it stays an event. It’s making me nuts. When I press (and keep) a button, both pressed and released get executed. Why? No idea. It does not recognize the button being pressed, it’s still a single event… :confused:

Here is the debug code which shows that it gets executed, and then gets stopped.

[quote]Device connected
Device connected
FTDI
Device connected
Joystick connected
pressed
The thread ‘’ (0x6) has exited with code 0 (0x0).[/quote]


#11

Maybe your joystick is not sending what GHI code is expecting ?
If you can, you could try to use the joystick as a raw USB device and see what you get in the receive buffer of the device (method xxxx.TransferData() )
Here, an USB sniffer might help.

Maybe you could also check the idea of a separate thread with an USB keyboard ? Keypressed events should be similar to those of the joystick. Then, when it’s working as you want, you may try to debug the joystick code separately, if needed.


#12

This costs a lot of time, and using a keyboard and switching back to the joystick/joypad is not an option.

I have no clue anymore… :confused:
Why are these events? Why is it not working?
Bec, don’t you have a joystick/joypad at home to try?


#13

No, I don’t have one :frowning: But I will try to get one from someone and make some coding this week-end.

The keyboard was here only to validate that the idea of a separate thread is ok for what you want to do, nothing else. If it works, then you can take time to see what’s happening with the joystick.
Also, if there’s a bug or an error in your code, GHI’s assembly or joystick’s data, then nothing will work as expected, no matter what you do. That’s why I suggested to check with the keyboard…

Btw, if I can get it to work with your code and my joystick, then you’re stuck :wink: Or maybe you could do the same : borrow another joystick from a friend ? Unless you don’t have friends :stuck_out_tongue: :wink:


#14

This thread got very confusing you you will probably not find the answer you are looking for!
Try this, on a new thread, instead of posting code, explain what you are trying to do and then someone will probably give you an outline of the right way to code it.


#15

But no one knows it, that’s the problem… There are only single events. I press a button, button pressed event gets fired. Done. There is no event that checks if the button is still pressed. That’s all I want to know. How to “ping” the position of the XY and the button. That’s all… :wink:


#16

Maybe you do not need events


#17

I do not need them indeed. I need to control the robot’s X and Y via realtime. Not single events…

That’s the problem :smiley:


#18

You mean that there’s no event fired when button is released ? :confused:


#19

Indeed. I press a button, the event gets fired…
But it seems not to be possible to check if the button is still being pressed or not.

I press, event gets fired, nothing more…
:confused:

At this point I have totally NO CLUE anymore what is going on here… :confused:


#20

Some tests with other joysticks seems mandatory, now… Investigations should be done to determine where the problem is : joystick or GHI’s code (or both ? :stuck_out_tongue: )

Because the ButtonState property of the event args does indeed expose USBH_JoystickButtonState.Released, which would suits your needs.