Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Problem with Teensy USB HID / Joystick implementation ?

  1. #1
    Junior Member
    Join Date
    Oct 2018
    Posts
    6

    Problem with Teensy USB HID / Joystick implementation ?

    I made a special joystick for a boy with a disability using TeensLC and it works nicely on the PC,
    however when i attach it to the XBOX adaptive controller
    https://www.xbox.com/de-DE/xbox-one/...ive-controller

    the joystick does not work at all. (i tested other devices including gamepads and also USB composite devices - they all worked).

    I cloned the device-/configuration- and HID-descriptors of working devices (by modifying the teensyduino source code accordingly)
    but that did not solve the issue.

    i tracked the problem down into the send-routine of the joystick implementation:


    int usb_flipjoystick_send(void)
    {
    uint32_t wait_count=0;
    usb_packet_t *tx_packet;

    while (1) {
    if (!usb_configuration) {
    return -2;
    }
    if (usb_tx_packet_count(FLIPJOYSTICK_ENDPOINT) < TX_PACKET_LIMIT) {
    tx_packet = usb_malloc();
    if (tx_packet) break;
    }
    if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
    transmit_previous_timeout = 1;
    return -1;
    }
    yield();
    }

    transmit_previous_timeout = 0;
    memcpy(tx_packet->buf, usb_flipjoystick_data, 3);
    tx_packet->len = 3;
    usb_tx(FLIPJOYSTICK_ENDPOINT, tx_packet);

    return 0;
    }



    this always runs into the timeout - it seems that usb_tx() does not succeed in sending the packets !

    i tried the same with teensy 3.1 and also teensy 2++ (using an AVR MCU) - same problem:
    works on PC, does not work on the XBOX adaptive controller !

    BTW: the HID joystick implementation in Arduino for the Leonardo/Pro Micro devices works fine...

    any ideas what could be wrong or what we could try to solve the issue ?

    thanks,
    chris

  2. #2
    Junior Member
    Join Date
    Jul 2018
    Posts
    19
    See my reply on this thread about the MSF-XINPUT library which might help.

    https://forum.pjrc.com/threads/53786...y-HID-Joystick

  3. #3
    Junior Member
    Join Date
    Oct 2018
    Posts
    6
    Thank you for your reply!

    Unfortunately, i have already tried all suggested strategies (implement single joystick device, mimick working joystick HID descriptors, implement XINPUT device)
    - and all of them failed.

    I think that the problem is a small difference in how the USB interrupts are handled / the usb_tx() function is implemented in the teensyduino code base ...

  4. #4
    Junior Member
    Join Date
    Jan 2015
    Posts
    7
    GD, thanks for reviving this thread!

    Modifying the drivers is unfortunately a bit above my level, if you know what I mean. I trust the XInput author over myself on this, for sure.

    Unfortunately, I couldn't get XInput working either. I couldn't get "XInput" to show up in the "USB Type" menu, even after copying over all the modified Teensyduino files. And in fact, doing so briefly bricked Teensyduino so that all of the options other than "Board" were greyed out. If anyone reading this tries installing XInput, be sure to back up the originals of those files!

    I suspect that this may have something to do with me using a significantly older version (IDE 1.0.6, Teensyduino 1.35). But I've broken some of my other code by updating the IDE before, so I'm hesitant to try that.

    In any case, Chris' linked thread doesn't make it sound too optimistic, even if I did get XInput working as intended.

    Thanks both of you for your help, but in the end, it sounds like the Adaptive Controller just doesn't like to play nicely with Teensy. Which is a real shame. If there's any device that Microsoft should make open-ended for the DIY community, the Adaptive is it.

  5. #5
    Junior Member
    Join Date
    Oct 2018
    Posts
    6
    Yes - maybe a conflict caused by the older Teensyduino version!
    backup of the Teensyduino files before modifying is a good advice indeed
    I got the XINPUT USB device code (and menu selection) working nicely, and the USB device appears and works on the PC,
    but (as said) no luck on the XBox Adaptive controller also with an XINPUT device implemented using Teensyduino's USB routines ....

    Quote Originally Posted by steve.mcgie View Post
    it sounds like the Adaptive Controller just doesn't like to play nicely with Teensy. Which is a real shame. If there's any device that Microsoft should make open-ended for the DIY community, the Adaptive is it.
    I suspect a small issue so that either the Teensyduino's USB device implementation - or the XBOX adaptive controller's USB host implementation - behaves slightly different from the USB standard. Anyhow: all other USB joysticks and game controllers I tried worked with the adaptive controller - so I suppose the problem _could_ be fixed on the Teensyduino side...

  6. #6
    Junior Member
    Join Date
    Jul 2018
    Posts
    19
    I now have an XAC but no USB joysticks. I can confirm the following do not work: MSF_XINPUT, teensyLC joystick, and arduinojoysticklibrary on SAMD. I will try the arduino joystick library on a pro micro 32u4.

    I hacked the teensy code to remove the teensy serial port so the teensy joystick has only 1 interface but this still does not work. Could be slight differences in the HID report descriptor.

  7. #7
    Junior Member
    Join Date
    Jul 2018
    Posts
    19
    The Teensy LC and probably Teensy 3 work on the Xbox Adaptive Controller (XAC) using the modified Teensyduino 1.44 files are in the zip file. The changes creates a USB Type Joystick which does not include keyboard, mouse, or serial. Auto upload does not work but upload can be manually started by clicking the Teensy program/reset button.

    The example program Teensy | USB Joystick | Complete works but change all references from Serial to Serial1. This program is handy because it sends axes movement messages without having to connect hardware joysticks. Very handy on a crowded desk. The XAC is larger than I expected.

    I am still not sure why the triple interface Keyboard, Mouse, Joystick USB Type fails.

    joystick_teensy.zip

  8. #8
    Junior Member
    Join Date
    Oct 2018
    Posts
    6
    Quote Originally Posted by gdsports View Post
    The Teensy LC and probably Teensy 3 work on the Xbox Adaptive Controller (XAC) using the modified Teensyduino 1.44 files are in the zip file. The changes creates a USB Type Joystick which does not include keyboard, mouse, or serial.
    joystick_teensy.zip
    Wow - very cool! This really amazes me because

    1) i replicated the configuration-, device- and HID-report descriptors from a working device (which is a single joystick, no serial port) without success,
    2) another mouse/keyboard/joystick composite device works fine with the XAD - so this can't be the reason ....


    however, in the zip you provided, the usb_desc.c file is identical with the original version of teensyduino 1.44
    - could it be that you put the wrong file into that .zip ?

    many thanks + cheers!
    chris

  9. #9
    Junior Member
    Join Date
    Jul 2018
    Posts
    19
    Oops, that should have been usb_desc.h, not usb_desc.c. Attached is an update zip file.
    joystick_teensy_20181107.zip

  10. #10
    Junior Member
    Join Date
    Oct 2018
    Posts
    6
    Hi GD!
    i can confirm that the Joystick-only HID version works with the XBox Adaptive Controller! how nice!
    thanks for your help

    i am still looking for the reason why the composite device with mouse/keyboard/joystick does not work.
    in fact, for my application i need the serial CDC device also - so the challenge continues ... but the working joystick is a huge step forward !

    best regards,
    chris

  11. #11
    Junior Member
    Join Date
    Jul 2018
    Posts
    19
    Chris, I am glad to hear the new Joystick working out.

    I sketched out an IMU to joystick program for a head, hand, or finger controlled joystick. I have to step away from XAC for a while so I am posting the code in case someone wants to give it a try.


    Code:
    /*
     *  Proof of concept head controlled joystick. Not tested with gameplay. 
     * 
     * Read quaternions from the BNO055, convert to heading, pitch, roll. Then
     * convert roll and pitch to USB joystick X,Y to Xbox Adaptive Controller.
     * Should work with other BNO055 boards. tindie.com has dime size BNO055
     * boards. Could be mounted on a hand or finger instead of head.
     * Set USB Type: Joystick
    
       Connections to Adafruit BNO055 breakout board and Teensy LC
       ===========
       Connect SCL to 19 SCL0
       Connect SDA to 18 SDA0
       Connect Vin to 3V
       Connect GND to GND
    
       TODO Do not send joystick USB data if x and y are not changing. Keep track
       of last x and last y. See if send_now() checks for no change. If so,
       the sketch does not have to worry about this.
       
       TODO Needs sensitivy adjust. Currently large IMU movement, -180..180
       degrees, is required to get full range of joystick movement. Probably should
       default to -15..15 or something. Use 2 potentiometers connected to
       analog inputs for X and Y sensitivity adjustment.
    
       TODO Try capacitive touch inputs for zero force "buttons". Adafruit sells
       conductive fabric strips as a better looking alternative to copper tape or
       wire.
    
       Public domain code based on Adafruit and PJRC example programs.
    */
    
    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BNO055.h>
    #include <utility/imumaths.h>
    
    #include <elapsedMillis.h>
    
    #define DEBUG_IMU (0)
    
    /* Set the delay between fresh samples. The BNO055 produces at most 100
     * updates per second. */
    #define BNO055_SAMPLERATE_DELAY_MS (10)
    
    Adafruit_BNO055 bno = Adafruit_BNO055();
    
    elapsedMillis imuElapsed;
    
    void setup(void)
    {
      Serial1.begin(115200);
      Serial1.println(F("\nOrientation Sensor Raw Data Test")); Serial1.println();
    
      // configure the joystick to manual send mode.  This gives precise
      // control over when the computer receives updates, but it does
      // require you to manually call Joystick.send_now().
      Joystick.useManualSend(true);
    
      Serial1.println("Begin Complete Joystick Test");
      /* Initialise the sensor */
      if (!bno.begin())
      {
        /* There was a problem detecting the BNO055 ... check your connections */
        Serial1.print(F("BNO055 not found, Check your wiring or I2C ADDR!"));
        while (1) delay(1);
      }
    
      bno.setExtCrystalUse(true);
      /* Display the current temperature */
      delay(1000);
      int8_t temp = bno.getTemp();
      Serial1.print(F("Current Temperature: "));
      Serial1.print(temp);
      Serial1.println(F(" C"));
      Serial1.println();
    }
    
    void joy_loop()
    {
      // Other joystick stuff such as checking buttons.
      //
      // Because setup configured the Joystick manual send,
      // the computer does not see any of the changes yet.
      // This send_now() transmits everything all at once.
      Joystick.send_now(); 
    }
    
    void imu_loop()
    {
      // Thanks to gammaburst @ forums.adafruit.com for this conversion.
      imu::Quaternion q = bno.getQuat();
      // flip BNO/Adafruit quaternion axes to aerospace: x forward, y right, z down
      float temp = q.x();  q.x() = q.y();  q.y() = temp;  q.z() = -q.z();
      q.normalize();
    
      // convert aerospace quaternion to aerospace Euler, because BNO055 Euler data is broken
      float heading = 180/M_PI * atan2(q.x()*q.y() + q.w()*q.z(), 0.5 - q.y()*q.y() - q.z()*q.z());
      float pitch   = 180/M_PI * asin(-2.0 * (q.x()*q.z() - q.w()*q.y()));
      float roll    = 180/M_PI * atan2(q.w()*q.x() + q.y()*q.z(), 0.5 - q.x()*q.x() - q.y()*q.y());
      heading = heading < 0 ? heading+360 : heading;
    
    #if DEBUG_IMU
      Serial1.print(F("Heading,Pitch,Roll: "));
      Serial1.print(heading);  // heading, nose-right is positive
      Serial1.print(F(" "));
      Serial1.print(pitch);    // pitch, nose-up is positive
      Serial1.print(F(" "));
      Serial1.print(roll);     // roll, leftwing-up is positive
      Serial1.println(F(""));
    #endif
    
      // Convert pitch to joystick y axis, roll to joystick x axis
      // Joystick.X, .Y expect values between 0..1023
      // Convert -180..180 to 0..1023
      int x = ((round(roll)  + 180) * 1024) / 360;
      int y = ((round(pitch) + 180) * 1024) / 360;
      Joystick.X(x);
      Joystick.Y(y);
    #if DEBUG_IMU
      Serial1.print(F("x,y "));
      Serial1.print(x);
      Serial1.print(',');
      Serial1.println(y);
    #endif
    }
    
    void loop(void)
    {
      if (imuElapsed > BNO055_SAMPLERATE_DELAY_MS) {
        imuElapsed = 0;
        imu_loop();
        joy_loop();
      }
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •