Shopping Cart

Posts

Using Logitech Extreme 3D Pro joystick with Arduino HID library

Logitech joystick connected to Arduino

Logitech joystick connected to Arduino

HID report parsing explained in the previous article works pretty well with properly aligned HID reports. The analog controls are placed on a byte or word boundary and buttons occupy dedicated fields. The majority of HID devices are designed this way, however, some other devices are not that simple to interface and today I’m going to show how to handle one of those.

A Logitech Extreme 3D Pro joystick is one nice HID device. It is good looking, well-built, and have a twist handle, which adds third axis to a stick making this model popular among FPV fliers since you can control pitch, roll and yaw with one hand. Also, X and Y axis are 10 bits which gives good precision. There is one problem with this joystick – its input report.

Logitech, in its infinite wisdom, decided to pack all the high and low resolution analog controls plus 12 buttons in 6 bytes of input report. The report looks like this – 10 bits of X, 10 bits of Y, and 4 bits of hat switch. After that, things become easier – one byte of Rz AKA “twist handle”, one byte of buttons, one byte of throttle (called “slider” in the report), and finally, one partially filled byte holding the rest of the buttons. Take a look at the screenshot below – two most important controls are not byte aligned, therefore, simple straightforward parsing of the report is not possible. Also, USBHID_descr won’t show this report correctly.

To demonstrate how to deal with this report I wrote a simple Arduino sketch. It was made by modifying an example from the previous article. I also made it as simple as possible – as soon as any of the controls changes its value, new report is printed on the serial terminal. The sample output is shown below followed by code explanation.

Start
HU Init
Addr:1
NC:1
 
Cnf:1
HU configured
 
Buf: FCF18780000000
X: 01FC Y: 01FC Hat Switch: 08 Twist: 80 Slider: 00 Buttons A: 00 Buttons B: 00
 
Buf: FCF18780000200
X: 01FC Y: 01FC Hat Switch: 08 Twist: 80 Slider: 02 Buttons A: 00 Buttons B: 00
 
Buf: FCF18783000200
X: 01FC Y: 01FC Hat Switch: 08 Twist: 83 Slider: 02 Buttons A: 00 Buttons B: 00
 
Buf: FCF18786000200
X: 01FC Y: 01FC Hat Switch: 08 Twist: 86 Slider: 02 Buttons A: 00 Buttons B: 00

The first important piece of the code is the report representation. To be able to access every control the following structure has been declared – compare it with the screenshot produced by my trusty Totalphase Beagle USB protocol analyzer:

struct GamePadEventData
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t hat : 4;
      uint32_t twist : 8;      
    };
  };
  uint8_t buttons_a;
  uint8_t slider;
  uint8_t buttons_b;
};

Logitech input report

Logitech input report


The Parse() method works similarly to the original code – it receives the report from the device and compares it with the stored copy of the previous reading. If reports are different, OnGamePadChanges() is called, which simply prints the report on the terminal. It can easily be modified to do something useful like change PWM pulse width to control motor speed, servo pulse or generate analog signal.

void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{
	bool match = true;
 
	// Checking if there are changes in report since the method was last called
	for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) {
		if( buf[i] != oldPad[i] ) {
			match = false;
			break;
		}
  }
  	// Calling Game Pad event handler
	if (!match && joyEvents) {
		joyEvents->OnGamePadChanged((const GamePadEventData*)buf);
 
		for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) oldPad[i] = buf[i];
	}
}

This simple technique is very helpful when dealing with awkward reports. If you need help with parsing output from your HID reports or would like to see more detailed explanation of the code, please let me know.

Oleg.

No related posts.

29 comments to Using Logitech Extreme 3D Pro joystick with Arduino HID library

  • Hi, I used V1 usb host shield with Saitek X45 and all was ok.
    Now i try on ADK and de len report is 11 Bytes but he cut at 8.

    I show you the desciptor! could you help me?

    Start
    HU Init
    Addr:1
    NC:1

    Cnf:1
    HU configured
    0000: 05 01 09 04 A1 01 09 30 16 00 00 26 FF 0F 75 0C
    0010: 95 01 81 02 09 31 16 00 00 26 FF 0F 75 0C 95 01
    0020: 81 02 09 36 15 00 26 FF 00 75 08 95 01 81 02 09
    0030: 35 15 00 26 FF 00 75 08 95 01 81 02 09 37 15 00
    0040: 26 FF 00 75 08 95 01 81 02 09 33 15 00 26 FF 00
    0050: 75 08 95 01 81 02 05 09 15 00 25 01 19 01 29 1A
    0060: 75 01 95 1A 81 02 75 02 95 01 81 01 05 01 09 39
    0070: 15 01 25 08 35 00 46 3B 01 66 14 00 75 04 95 01

    Usage Page Gen Desktop Ctrls(01)
    Usage Game Pad
    Collection Application
    Usage X
    Logical Min(0000)
    Logical Max(FF0F)
    Report Size(0C)
    Report Count(01)
    Input(00000010)
    Usage Y
    Logical Min(0000)
    Logical Max(FF0F)
    Report Size(0C)
    Report Count(01)
    Input(00000010)
    Usage Slider
    Logical Min(00)
    Logical Max(FF00)
    Report Size(08)
    Report Count(01)
    Input(00000010)
    Usage Rz
    Logical Min(00)
    Logical Max(FF00)
    Report Size(08)
    Report Count(01)
    Input(00000010)
    Usage Dial
    Logical Min(00)
    Logical Max(FF00)
    Report Size(08)
    Report Count(01)
    Input(00000010)
    Usage Rx
    Logical Min(00)
    Logical Max(FF00)
    Report Size(08)
    Report Count(01)
    Input(00000010)
    Usage Page Button(09)
    Logical Min(00)
    Logical Max(01)
    Usage Min(01)
    Usage Max(1A)
    Report Size(01)
    Report Count(1A)
    Input(00000010)
    Report Size(02)
    Report Count(01)
    Input(00000001)
    Usage Page Gen Desktop Ctrls(01)
    Usage Hat Switch
    Logical Min(01)
    Logical Max(08)
    Physical Min(00)
    Physical Max(3B01)
    Unit(1400)
    Report Size(04)
    Report Count(01)
    Buf: 9EE0085CB1515200
    Game Pad X(E0)
    Y(E8)
    Slider(5C)
    Rz(B1)
    Dial(9E)
    Rx(0E)
    Btn1(00) Btn2(00) Btn3(00) Btn4(01) Btn5(00) Btn6(00) Btn7(00) Btn8(00) Btn9(00) BtnA(00) BtnB(01) BtnC(01) BtnD(01) BtnE(00) BtnF(01) Btn10(00) Btn11(01) Btn12(00) Btn13(00) Btn14(00) Btn15(01) Btn16(01) Btn17(00) Btn18(01) Btn19(01) Btn1A(00)
    (00)
    Hat Switch
    Buf: 0C0000
    Game Pad X(C0)
    Y(00)
    Slider(00)
    Rz(00)
    Dial(0C)
    Rx(00)
    Btn1(00) Btn2(00) Btn3(00) Btn4(00) Btn5(00) Btn6(00) Btn7(00) Btn8(00) Btn9(00) BtnA(00) BtnB(00) BtnC(00) BtnD(00) BtnE(00) BtnF(00) Btn10(00) Btn11(00) Btn12(00) Btn13(00) Btn14(00) Btn15(00) Btn16(00) Btn17(00) Btn18(00) Btn19(00) Btn1A(00)
    (00)
    Hat Switch

    • andy

      Hi all – and thanks Oleg for a great shield and library! I know i am replying to an old question here but i had a similar problem with version 2 of the library that i found a solution to that i wanted to share. In my case i have a Microsoft wireless mobile mouse 3000 for which i was receiving a cut off HID report in report mode (not boot!) in the sample USBHID_desc as well as in my own code – as per described by Sisco.

      Basically the issue is down to this device having a particularly long hid report, so this will be true for any device with a long HID report. I tracked the problem down to a hard coded value in the HID.cpp USB library code for GetReportDescr.

      Here is the code – the pUsb->ctrlReq call has the 8th parameter value set to 128 which limits the max length of the hid report:

      int8_t HID::GetReportDescr( uint8_t ep, USBReadParser *parser )
      {
      const uint8_t constBufLen = 64;
      uint8_t buf[constBufLen];

      uint8_t rcode = pUsb->ctrlReq( bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0×00,
      HID_DESCRIPTOR_REPORT, 0×0000, 128, constBufLen, buf, (USBReadParser*)parser );

      //return ((rcode != hrSTALL) ? rcode : 0);
      return rcode;
      }

      If like me you find your hid report terminates too early, increase the parameter value from 128. For my mouse I had to up to 320 and the HID report now gets returned complete. Hope this helps.

      THX
      Andy

      • You mean your _report_ is that long? I’ve seen report descriptors which were quite large but not reports themselves.

        • andy

          Yes seems petty long for what seems a basic mouse with wheel!!

          For interest here is the full USBHID_desc output:
          HU configured
          0000: 05 0C 09 01 A1 01 05 01 09 02 A1 02 85 13 05 0C
          0010: 0A 38 02 95 01 75 08 15 81 25 7F 81 06 85 14 06
          0020: 00 FF 0A 01 FE 75 02 15 00 25 03 81 02 0A 02 FE
          0030: 0A 00 FE 95 02 75 01 25 01 81 02 0A 03 FF 95 01
          0040: 75 02 25 03 81 02 81 01 85 15 75 01 25 01 0A 0B
          0050: FF 81 02 75 07 81 01 0A 0D FF 75 10 27 FF FF 00
          0060: 00 81 02 85 17 0A 06 FF 0A 0F FF 25 01 35 01 45
          0070: 10 95 02 75 02 B1 02 0A 04 FF 35 00 45 00 95 01
          0080: 75 01 B1 02 75 03 B1 01 C0 C0 05 01 09 02 A1 01
          0090: 05 01 09 02 A1 02 85 11 09 01 A1 00 05 09 19 01
          00A0: 29 05 95 05 75 01 25 01 81 02 75 03 95 01 81 01
          00B0: 05 01 09 30 09 31 95 02 75 08 15 81 25 7F 81 06
          00C0: A1 02 85 12 09 48 95 01 75 02 15 00 25 01 35 01
          00D0: 45 10 B1 02 85 11 09 38 35 00 45 00 15 81 25 7F
          00E0: 75 08 81 06 C0 A1 02 85 12 09 48 75 02 15 00 25
          00F0: 01 35 01 45 10 B1 02 35 00 45 00 75 04 B1 01 85
          0100: 11 05 0C 15 81 25 7F 75 08 0A 38 02 81 06 C0 C0
          0110: C0 C0
          Usage Page Consumer(0C)
          Usage Consumer Ctrl
          Collection Application
          Usage Page Gen Desktop Ctrls(01)
          Usage Mouse
          Collection Logical
          Report Id(13)
          Usage Page Consumer(0C)
          Usage AC Mir H
          Report Count(01)
          Report Size(08)
          Logical Min(81)
          Logical Max(7F)
          Input(00000110)
          Report Id(14)
          Usage Page Undef(00)
          Usage
          Report Size(02)
          Logical Min(00)
          Logical Max(03)
          Input(00000010)
          Usage
          Usage
          Report Count(02)
          Report Size(01)
          Logical Max(01)
          Input(00000010)
          Usage
          Report Count(01)
          Report Size(02)
          Logical Max(03)
          Input(00000010)
          Input(00000001)
          Report Id(15)
          Report Size(01)
          Logical Max(01)
          Usage
          Input(00000010)
          Report Size(07)
          Input(00000001)
          Usage
          Report Size(10)
          Logical Max(FFFF0000)
          Input(00000010)
          Report Id(17)
          Usage
          Usage
          Logical Max(01)
          Physical Min(01)
          Physical Max(10)
          Report Count(02)
          Report Size(02)
          Feature(00000010)
          Usage
          Physical Min(00)
          Physical Max(00)
          Report Count(01)
          Report Size(01)
          Feature(00000010)
          Report Size(03)
          Feature(00000001)
          End Collection
          End Collection
          Usage Page Gen Desktop Ctrls(01)
          Usage Mouse
          Collection Application
          Usage Page Gen Desktop Ctrls(01)
          Usage Mouse
          Collection Logical
          Report Id(11)
          Usage Pointer
          Collection Physical
          Usage Page Button(09)
          Usage Min(01)
          Usage Max(05)
          Report Count(05)
          Report Size(01)
          Logical Max(01)
          Input(00000010)
          Report Size(03)
          Report Count(01)
          Input(00000001)
          Usage Page Gen Desktop Ctrls(01)
          Usage X
          Usage Y
          Report Count(02)
          Report Size(08)
          Logical Min(81)
          Logical Max(7F)
          Input(00000110)
          Collection Logical
          Report Id(12)
          Usage Res Mult
          Report Count(01)
          Report Size(02)
          Logical Min(00)
          Logical Max(01)
          Physical Min(01)
          Physical Max(10)
          Feature(00000010)
          Report Id(11)
          Usage Wheel
          Physical Min(00)
          Physical Max(00)
          Logical Min(81)
          Logical Max(7F)
          Report Size(08)
          Input(00000110)
          End Collection
          Collection Logical
          Report Id(12)
          Usage Res Mult
          Report Size(02)
          Logical Min(00)
          Logical Max(01)
          Physical Min(01)
          Physical Max(10)
          Feature(00000010)
          Physical Min(00)
          Physical Max(00)
          Report Size(04)
          Feature(00000001)
          Report Id(11)
          Usage Page Consumer(0C)
          Logical Min(81)
          Logical Max(7F)
          Report Size(08)
          Usage AC Mir H
          Input(00000110)
          End Collection
          End Collection
          End Collection
          End Collection

  • Ben

    Hi guys,

    thanks for the work you did, im very aprichiate about your homepage!

    i hav estill some questions about the usb host 2 library. im using a microsoft sidewinder with my arduino mega adk. everything is working fine. im getting good rrsults in the serial monitorlike
    Buf: 08EDFF0F0040
    X: 08 Y: ED Z: FF Z: 0F Rz: 00

    Buf: 08EDFFEF0340
    X: 08 Y: ED Z: FF Z: EF Rz: 03

    Buf: 08EDFF0F0040
    X: 08 Y: ED Z: FF Z: 0F Rz: 00

    but unfortunately i dont know how to get something different modified like you said ” It can easily be modified to do something useful like change PWM pulse width to control motor speed, servo pulse or generate analog signal.” i tried to find something how can i modify f.e. motors with pwn. can you say me please how i work with these datas?

    best from big berlin

    ben

  • newwzp

    Sometimes, it was not able to start with logitech Extreme 3D pro. The program stopped after print “NC:1″.

  • newwzp

    I tryed BETOP BTP-4328 and Thrustmaster T16000M, and they all worked well with the Arduino USB Shield 2.0. It seems that there is something wrong with my Extreme 3D pro, although the joystick works well with my computer.
    (Maybe the reason is that all of the Extreme 3D pro joysticks in China are cost-down version….)

    THX

  • Pavel

    Hello!

    Could you please help me to find info about how to connect and interact between Logitech Wireless Gamepad F710 and ArduinoUno + USB Host Shield?

    Thank you.

    • Chumpon

      I recently have logitech F710 . My usb host shild 2.0 just arrived yesterday from my local seller. I put it on my uno and then upload with the sample sketch for hidjoystick it not work at first but i manage to have it work with following steps
      1. Plug the reciever to a pc
      2. Install the gaming control software came with the f710 follow the installation until the joystick testing is display and confirm the joystck is working properly.
      3 switch the joystick mode switch to ‘D’ mode yhen test it again on pc. I try it with mode ‘X’ on the hostshield but it seem to not working i not try with the xbox sample yet it probably work as well.
      4 unplug the reciever from pc them put it on the usb hostshield then plug the arduino on o the pc usb port open the serial monitor in the arduino ide.
      5. The sample just work without any modification. It will display start then immediately display the buttons status that was pressed in the serial monitor.
      Ther is no need to do connection between the reciever and the joystick because it have been sync during the test perform on the pc and it will stay connected.
      Hope this help

  • James Schubert

    I have a sainsmart mega 2560 and sainsmart usb 2.0 board and a logitech extreme 3d joystick.

    I have the latest from master github branch.

    When I run the sketch on it it just says Start and doesn’t repsond to key presses. If I do as newwzp did by resetting several times then it responded – once.

    I have tried with both external power from my sabertooth and without external power.

    If I run USBHID_Desc it does the same thing.
    If I run USC_desc I get the following report, with no more output than than. -

    Start

    01

    Device descriptor:
    Descriptor Length: 12
    Descriptor type: 01
    USB version: 0110
    Device class: 00
    Device Subclass: 00
    Device Protocol: 00
    Max.packet size: 08
    Vendor ID: 046D
    Product ID: C215
    Revision ID: 0204
    Mfg.string index: 01
    Prod.string index: 02
    Serial number index: 00
    Number of conf.: 01

    Configuration descriptor:
    Total length: 0022
    Num.intf: 01
    Conf.value: 01
    Conf.string: 00
    Attr.: 80
    Max.pwr: 0F

    Interface descriptor:
    Intf.number: 00
    Alt.: 00
    Endpoints: 01
    Intf. Class: 03
    Intf. Subclass: 00
    Intf. Protocol: 00
    Intf.string: 00
    Unknown descriptor:
    Length: 09
    Type: 21
    Contents: 10012101227A000705

    Endpoint descriptor:
    Endpoint address: 81
    Attr.: 03
    Max.pkt size: 0007
    Polling interval: 0A

    Addr:1(0.0.1)

  • James Schubert

    FYI – I finally got my Logitech Extreme 3D Pro joystick to working!!

    Found this link – his version of the code works for me and my mega and usb host 2.0 – I am getting data in serial monitor and it looks correct.

    HIS webpage is here –
    http://www.ianjohnston.com/index.php?option=com_content&view=article&id=79

    Close to bottom of page he says he fixed the bug –

    HIS Joystick code – havent tried yet 0
    http://www.ianjohnston.com/images/stories/IanJ/JoystickV3/code/RCJoystickTx_USB_LE3DP_ArdMega_IDEV1_V8_76.zip

    HIS library -
    http://www.ianjohnston.com/images/stories/IanJ/JoystickV3/code/USBHostShield2.zip

    Can also be found here – http://www.rcgroups.com/forums/showthread.php?t=1704110

  • James Schubert

    I need to know how to get the report values from the CPP file into the sketch. I know inside the loop after the usb.task….but how to access – (evt->x), (evt->y), (evt->twist)….etc…

    I am wanting to use values to run 2 servos – sabertooth…..

    any help appreciated…

  • Perondi

    How do I get the evt-> x, evt-> y … the sketch in arguivo. ino. I am trying to pass this data to a radio controller.

  • AndyInAnnArbor

    I have a Logitech Extreme 3D, Uno and your USBHost shield and I installed your sketch and USBHost 2.0 library and it seems to work, but when I monitor activity on the serial monitor, I see a constant stream of stuff that doesn’t appear to be from your code that fills the time between stick events. There’s a snippet below from the end of the initialization. The Address, EP, NAK Power and NAK Limit messages are constantly streaming past and I’m wondering if there’s a way to suppress this chatter that’s unrelated to the joystick? Is this part of the USB handshaking?

    Thanks

    Buf: 0002888000CE00
    X: 0200 Y: 0200 Hat Switch: 08 Twist: 80 Slider: CE Buttons A: 00 Buttons B: 00

    Address: 1
    EP: 1
    NAK Power: 1
    NAK Limit: 1

    Address: 1
    EP: 1
    NAK Power: 1
    NAK Limit: 1

    Address: 1
    EP: 1
    NAK Power: 1
    NAK Limit: 1

    Address: 1
    EP: 1
    NAK Power: 1
    NAK Limit: 1

    Address: 1
    EP: 1
    NAK Power: 1
    NAK Limit: 1

    Address: 1
    EP: 1
    NAK Power: 1
    NAK Limit: 1

  • Daniel Gonzalez

    Hello there. I am trying to use an Arduino Uno to control Victor 888′s and power four CIMs. At this point I know how to use servo code to make the Victors work, the only thing is that I need to get the code to read joystick values. In RobotC I can just include the #include.”joystick.driver”; and have it work. However in Arduino I don’t know how to get the UNO to prompt my laptop for old or new joystick values, therefore making me unable to create variables and integers in the code to modify servo speed values. Help? ALSO I for now am just plugging the joystick into the computer and connecting the arduino into the PC.

  • manitou

    Thanks for the library. I had a couple of Logitec Pro joysticks that got fried somehow on an XP box. I was able to use the HID example sketch le3dp to confirm which inputs were bad … sigh. I used a sparkfun USB host shield, and that required jumpers to pins 10-13, a pin 7 to RESET jumper, and to get the joystick to respond, I needed 7.5v to DC input jack on 2560 board. All that finally worked!

  • Maleche

    I have tried the Arduino Sketch from the link above and it fails to compile on three different Arduinos. Is this the current sketch?
    Thanks so much!
    Doyle

Leave a Reply

  

  

  



You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">