USB Joystick Rumble/Force Feedback on Teensy 3.1

Status
Not open for further replies.

DogP

Well-known member
Hey,

I've spent the last day working on code for a replacement controller for a USB HOTAS flight control with the Teensy 3.1... everything's going well, but I got thinking how it'd be nice to have a small rumble motor or two in the joystick. Has anyone attempted rumble or force feedback on the Teensy?

I found this project: https://github.com/tloimu/adapt-ffb-joy , which uses an AVR MCU to adapt an old force feedback Sidewinder joystick to USB. It looks quite complex though... not sure if that's because it has true force feedback vs. rumble, or if either of them are going to be complex. I've also heard of people emulating XBOX controllers, but I want to be a custom joystick (unless there's a way to just use the XBOX rumble portion).

I was hoping that there'd be a fairly simple interface to basically trigger the MCU to drive a motor at a certain speed (on a PWM pin for speed control). Obviously it'd require a drive circuit, shunt diode, etc... but the USB part is what I'm just not very familiar with.

Anyone know how rumble works (in a plug and play standard HID way)? Is it worth pursuing, or is it gonna be a major effort to make it work? It's really not a "need", but I'd definitely be willing to put some time into it (and of course share if I succeed).

Thanks,
Pat
 
No, honestly I have no idea about which HID usage numbers and conventions are used, or even whether they use the HID standard or some proprietary communication.

But I'm curious and watching to see if anyone posts good info....
 
But I'm curious and watching to see if anyone posts good info....
You and me both. :)

Tonight I'm finishing up the basics of my USB controller, so if everything goes well, I'll start looking into this in more detail soon. And I'll drop a post over in the General Discussion to show my project and share the details/code.

Thanks,
Pat
 
I am interested in all things joystick, and I do like a good vibrator, so i looked up how linux does it, and their drivers appear to be based on the PID subset of HID, here.

As for implementing that in a descriptor, well, that is different from using google .....
 
Ah... interesting. That looks very similar to what was implemented in adapt-ffb-joy. I was looking (hoping) for something simpler, kinda like the Xbox controller: http://euc.jp/periphs/xbox-controller.en.html . I'm not sure if that's a standard implementation or anything though. Maybe I'll grab one of those PS2 controller to USB adapters which support rumble and see how they handle it. I believe they require some sort of driver for rumble support though.

Thanks,
Pat
 
I've sorta put the rumble on hold for now... I've got my project working well without it, and it's not a critical feature.

I did some reading about USB joysticks, rumble, etc. though... it seems that Micro$oft has pushed away from DirectInput in favor of XInput. I assumed that was just a minor change of libraries or something, but no... it basically says all controller are fine, as long as they're an Xbox 360 controller. :p Basically, I have to make my controller enumerate as an Xbox 360 controller, and be limited to the number of axes and buttons available on one, then I can be an XInput controller. Maybe that's fine for gamepads, but that's pretty restrictive for general controller input. But, with XInput, it looks like rumble would be easily and natively supported.

I did find one project where someone used a Teensy to be an XInput device, though it doesn't look like they support rumble (but it does have two way communications for setting LEDs, so it probably wouldn't be difficult to add): http://www.zlittell.com/2015/07/fightstick/ . I may look into that in the future if I really want rumble, or need XInput.

DogP
 
Heh... well, sometimes stuff just falls in your lap. I was at Microcenter (computer parts store) and came across a cheap open box rumble gamepad for $7... so I figured I'd grab it and check it out. It uses something called the "Network Joystick" driver... no idea why they call it "network", but it seems to be commonly used on these cheap gamepads and controller converters. I grabbed the descriptors and sniffed the data.

I haven't gotten around to trying the Teensy with it yet, but it should be fairly simple if I use this driver with the Teensy. The controller also shows up as a keyboard and mouse, and has a utility that'll let you map controls to KB/mouse inputs... though I deleted those devices and the rumble still worked... so I don't think they're critical to have.

Below are the descriptors:

Code:
Connection Status Device connected 
Current Configuration 1 
Speed Low (1.5 Mbit/s) 
Device Address 2 
Number Of Open Pipes 2 

Device Descriptor Generic USB Joystick 
Offset Field Size Value Description 
0 bLength 1 12h  
1 bDescriptorType 1 01h Device 
2 bcdUSB 2 0100h USB Spec 1.0 
4 bDeviceClass 1 00h Class info in Ifc Descriptors 
5 bDeviceSubClass 1 00h  
6 bDeviceProtocol 1 00h  
7 bMaxPacketSize0 1 08h 8 bytes 
8 idVendor 2 0079h  
10 idProduct 2 0006h  
12 bcdDevice 2 0107h 1.07 
14 iManufacturer 1 01h "DragonRise Inc. " 
15 iProduct 1 02h "Generic USB Joystick " 
16 iSerialNumber 1 00h  
17 bNumConfigurations 1 01h  

Configuration Descriptor 1 Bus Powered, 500 mA
Offset Field Size Value Description 
0 bLength 1 09h  
1 bDescriptorType 1 02h Configuration 
2 wTotalLength 2 0029h  
4 bNumInterfaces 1 01h  
5 bConfigurationValue 1 01h  
6 iConfiguration 1 00h  
7 bmAttributes 1 80h Bus Powered 
 4..0: Reserved  ...00000   
 5: Remote Wakeup  ..0.....  No 
 6: Self Powered  .0......  No, Bus Powered 
 7: Reserved (set to one)
(bus-powered for 1.0)  1.......   
8 bMaxPower 1 FAh 500 mA 

Interface Descriptor 0/0 HID, 2 Endpoints
Offset Field Size Value Description 
0 bLength 1 09h  
1 bDescriptorType 1 04h Interface 
2 bInterfaceNumber 1 00h  
3 bAlternateSetting 1 00h  
4 bNumEndpoints 1 02h  
5 bInterfaceClass 1 03h HID 
6 bInterfaceSubClass 1 00h  
7 bInterfaceProtocol 1 00h  
8 iInterface 1 00h  

HID Descriptor 
Offset Field Size Value Description 
0 bLength 1 09h  
1 bDescriptorType 1 21h HID 
2 bcdHID 2 0110h 1.10 
4 bCountryCode 1 21h US 
5 bNumDescriptors 1 01h  
6 bDescriptorType 1 22h Report 
7 wDescriptorLength 2 0065h 101 bytes 

Endpoint Descriptor 81 1 In, Interrupt, 10 ms
Offset Field Size Value Description 
0 bLength 1 07h  
1 bDescriptorType 1 05h Endpoint 
2 bEndpointAddress 1 81h 1 In 
3 bmAttributes 1 03h Interrupt 
 1..0: Transfer Type  ......11  Interrupt 
 7..2: Reserved  000000..   
4 wMaxPacketSize 2 0008h 8 bytes 
6 bInterval 1 0Ah 10 ms 

Endpoint Descriptor 01 1 Out, Interrupt, 10 ms
Offset Field Size Value Description 
0 bLength 1 07h  
1 bDescriptorType 1 05h Endpoint 
2 bEndpointAddress 1 01h 1 Out 
3 bmAttributes 1 03h Interrupt 
 1..0: Transfer Type  ......11  Interrupt 
 7..2: Reserved  000000..   
4 wMaxPacketSize 2 0008h 8 bytes 
6 bInterval 1 0Ah 10 ms 

Interface 0 HID Report Descriptor Joystick
Item Tag (Value) Raw Data 
Usage Page (Generic Desktop) 05 01  
Usage (Joystick) 09 04  
Collection (Application) A1 01  
    Report ID (1) 85 01  
    Collection (Logical) A1 02  
        Report Size (8) 75 08  
        Report Count (4) 95 04  
        Logical Minimum (0) 15 00  
        Logical Maximum (255) 26 FF 00  
        Physical Minimum (0) 35 00  
        Physical Maximum (255) 46 FF 00  
        Usage (X) 09 30  
        Usage (Y) 09 31  
        Usage (Z) 09 32  
        Usage (Rz) 09 35  
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02  
        Report Size (4) 75 04  
        Report Count (1) 95 01  
        Logical Maximum (7) 25 07  
        Physical Maximum (315) 46 3B 01  
        Unit (Eng Rot: Degree) 65 14  
        Usage (Hat Switch) 09 39  
        Input (Data,Var,Abs,NWrp,Lin,Pref,Null,Bit) 81 42  
        Unit (None) 65 00  
        Report Size (1) 75 01  
        Report Count (12) 95 0C  
        Logical Maximum (1) 25 01  
        Physical Maximum (1) 45 01  
        Usage Page (Button) 05 09  
        Usage Minimum (Button 1) 19 01  
        Usage Maximum (Button 12) 29 0C  
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02  
        Usage Page (Vendor-Defined 1) 06 00 FF  
        Report Size (1) 75 01  
        Report Count (8) 95 08  
        Logical Maximum (1) 25 01  
        Physical Maximum (1) 45 01  
        Usage (Vendor-Defined 1) 09 01  
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02  
    End Collection C0  
    Collection (Logical) A1 02  
        Report Size (8) 75 08  
        Report Count (7) 95 07  
        Physical Maximum (255) 46 FF 00  
        Logical Maximum (255) 26 FF 00  
        Usage (Vendor-Defined 2) 09 02  
        Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02  
        Report Count (21) 95 15  
        Usage (Vendor-Defined 1:Vendor-Defined 3) 0B 03 00 00 FF  
        Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) B1 02  
    End Collection C0  
End Collection C0  
Usage Page (Generic Desktop) 05 01  
Usage (Keyboard) 09 06  
Collection (Application) A1 01  
    Report ID (2) 85 02  
    Usage Page (Keyboard/Keypad) 05 07  
    Usage Minimum (Keyboard Left Control) 19 E0  
    Usage Maximum (Keyboard Right GUI) 29 E7  
    Logical Minimum (0) 15 00  
    Logical Maximum (1) 25 01  
    Report Size (1) 75 01  
    Report Count (8) 95 08  
    Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02  
    Report Count (1) 95 01  
    Report Size (8) 75 08  
    Input (Cnst,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 03  
    Report Count (5) 95 05  
    Report Size (8) 75 08  
    Logical Minimum (0) 15 00  
    Logical Maximum (101) 25 65  
    Usage Page (Keyboard/Keypad) 05 07  
    Usage Minimum (Undefined) 19 00  
    Usage Maximum (Keyboard Application) 29 65  
    Input (Data,Ary,Abs) 81 00  
End Collection C0  
Usage Page (Generic Desktop) 05 01  
Usage (Mouse) 09 02  
Collection (Application) A1 01  
    Report ID (3) 85 03  
    Usage (Pointer) 09 01  
    Collection (Physical) A1 00  
        Usage Page (Button) 05 09  
        Usage Minimum (Button 1) 19 01  
        Usage Maximum (Button 3) 29 03  
        Logical Minimum (0) 15 00  
        Logical Maximum (1) 25 01  
        Physical Minimum (0) 35 00  
        Physical Maximum (1) 45 01  
        Report Count (3) 95 03  
        Report Size (1) 75 01  
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02  
        Report Count (1) 95 01  
        Report Size (5) 75 05  
        Input (Cnst,Ary,Abs) 81 01  
        Usage Page (Generic Desktop) 05 01  
        Usage (X) 09 30  
        Usage (Y) 09 31  
        Usage (Wheel) 09 38  
        Logical Minimum (-127) 15 81  
        Logical Maximum (127) 25 7F  
        Physical Minimum (-127) 35 81  
        Physical Maximum (127) 45 7F  
        Report Count (3) 95 03  
        Report Size (8) 75 08  
        Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit) 81 06  
    End Collection C0  
End Collection C0

When the gamepad is rumbling, it outputs two different sets of two 8-byte reports:
0x01 0xFA 0xFE 0x00 0x00 0x00 0x00 0x00
0xFA 0xFE 0x00 0x00 0x00 0x00 0x00 0x00

and:
0x01 0x51 0x00 <RIGHT LEVEL> 0x00 <LEFT LEVEL> 0x00 0x00
0x51 0x00 <RIGHT LEVEL> 0x00 <LEFT LEVEL> 0x00 0x00 0x00

When the gamepad isn't rumbling, it outputs two 8-byte reports:
0x01 0xF3 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0xF3 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

It looks like it uses a standard HID descriptor, so hopefully the driver will still work if I have more than the number of buttons and axes that this gamepad actually has.

I'll post more once I get around to trying it with the Teensy... just wanted to post this while I was thinking about it, in case it helps anyone else.

Pat
 
I haven't really made any progress yet, but I did rip apart the controller... figured I'd post a couple pics (though as expected, it's got an epoxy blob MCU).

DSC03527.JPG

DSC03526.JPG

Pat
 
Just wanted to echo the desire to see rumble support added to the Teensy Joystick emulation. I'd like to build a custom interface for VR gaming, and rumble is excellent feedback. I'll be watching this thread!
 
I'd like to build a custom interface for VR gaming, and rumble is excellent feedback.
Heh, same here! I've been away from PC gaming for quite a while... but I'm picking up the Rift and Vive, so I'm really excited about this stuff again. I'm particularly interested in racing, flight, and space sims... so I've been using the Teensy MCUs to replace the guts in various game controllers (HOTAS, flight yoke, rudder pedals, etc).

Just a quick update on the rumble status though... I spent a couple hours last week trying to implement this, and failed miserably. I'm guessing I screwed something up in the descriptor, because when I plugged it in, it basically froze the computer for about 20 seconds. When I unplugged it, it didn't detect that I unplugged it and wouldn't detect any other USB changes... and when I tried to reboot, it hung shutting down. After doing that twice, I decided to set it aside and come back to it later.

I'll drop back in on this project shortly, and use a USB analyzer to hopefully help debug.

Pat
 
Hi everyone,

I've successfully modified the Arduino Leonardo core (same MCU as teensy 2.0), you can have a look at this thread.
Here are the source (these are not the latest one, but they have the basic FFB feature) : http://www.aiwave.fr/downloads/ESP_WHEEL_0.3.zip

The files I've modified in the core are : USBCore.cpp, HID.cpp, USBAPI.h, USBCore.h, USBDesc.h

I started from the very helpful project adapt-ffbjoy : https://github.com/tloimu/adapt-ffb-joy

I've tried to adapt this to the Arduino Due, but with no success. I'm now looking at the Tennsy 3.2 as well, but that's another story :)

Hope this can help !
 
Last edited:
Hi, I just registered here because I wanted to ask how i would go about implementing this when I make a controller.

I'm planning on making a hand-held gaming device with built in controls similar to the xbox one with a teensy board instead of the actual controller, since I don't want to re-solder every connection on the pcb and to save space, and then have an emulator in the computer make the computer think that it's an xinput device.

How would I connect the rumblers and what code should I put were?
Sorry I don't mean to be annoying it's just that this is my first project like this and I could use some guidance.

JL
 
I recommend you try the MSF-XINPUT library by Zachery Littell.

He kindly expanded that library include rumble support for my PinSim project I published on Tested. No XINPUT translation layer is required on the PC -- the computer thinks the Teensy is an Xbox controller, plain and simple. Minimal latency. It's awesome.
Wow.. I'm not good at programming and the knowledge I have is basic at best and after reading through the code, I've got to say this is really F***ing impressive!

So from what I gather, I can use the xinput.cpp as reference for all of the buttons and to what pin(array number) I should solder them to?

And all of this is made for teensy 3.2 right? Saw that there were references to all teensy models but only teensy3 inside the core?

Wow I'm going to order this right away! I've not even received the "motherboard" for my project yet but I don't care, can't wait to create my own controller!
 
So did anyone successfully made Field Force enabled device? I'm building something similar. I have built a game wheel with 2 paddles it is working perfectly fine except vibration feature which I'm unable to implement it I'm using Arduino Micro so can anyone help me?
 
*
Force feedback works perfectly with the Zachery Littell library. I tested and modified a lot of time ago for Teensy 3.2, first version was only for Teensy LC.

Now I need mix, in one Teensy, Xbox360 + Mouse + Keyboard. This seem more complex, because the PID VID are different, and my PC computer only recognize Xbox360 gamepad or mouse/keyboard, but not the three devices.
 
Status
Not open for further replies.
Back
Top