Has anyone used joystick outputs?

I’m thinking about making a custom joystick next year. I purchased some parts from Amazon. It’s pretty low cost. What I’m looking to accomplish would be to have a panel with lighted buttons, where the lights convey some information. We currently use a “fight stick” for some functions. (For those not familiar, it’s a box with buttons, and a nine position joystick. I think it got its name from use in the Mortal Kombat video game, but it might predate that specific game.)

I want something like a fight stick, but with buttons I can light from code. I want something that’s more like an industrial operator control panel, to convey important information to the driver through a medium other than the computer screen. I see that the joystick class in WPILib has a setOutputs() function, or a setOutput() function. I’m wondering if any teams have made use of such functions, and how. I am guessing that there is a standard inteface that those functions activate, but I don’t know what it is. I see in the WPILib source that the function just calls a corresponding function in the HAL, which I assume is the Hardware Abstraction Layer.

I read up a bit on what a standard joystick device USB interface is. There is capability for inputs and for outputs in the interface, but most of the description is for inputs, as we normally use them., to get positions of buttons or axes. (Or mouse and keyboard, which use the same interface in Windows.) I just wasn’t sure if there was an obvious way to make use of the setOutput() functions in the WPI Libraries.

For what it’s worth, the one thing that our team has used has been the rumble functions on game controllers. This year, there was feedback from the vision system to the operator. The Xbox controller would rumble when the shooter was ready to fire and alighned with the target. That worked great, but I don’t know how to make use of the other output functions.

So in the 2015 KOP there was an MSP430, and you can buy one pretty cheaply online as well. If you have the national instruments frc toolkit installed, in your program files (x86) folder there is a subfolder for the FRC gamepad tool, which allows you to flash the MSP with a custom firmware image that includes analog and digital inputs, as well as “digital indicators”, which might be what you are looking for. Each indicator has an index displayed in the flashing screen, and you probably can just call setOutput(index, true) to turn it on.
Note that if you are doing something custom you probably want to use GenericHID instead of Joystick.
I was going to build something this season with it but never got around to it, so ymmv.
Good luck!

It’s come up a few times:

Both the TI and Cypress boards are pretty painless ways to roll your own joystick/control panel/whatever, and both support using LEDs as outputs accessible from WPILib.

2 Likes

Yup. I am still interested if anyone gets NI’s ear to hear what that setOutput() API actually hooks to in the USB HID classes. FWIW, the STM32 I’ve been fiddling with was a one-day project to get up and running as an HID device, with a lot of obvious customization for where I could add new capabilities to the USB Descriptors. I just didn’t know which one to add, and figured reverse engineering it wasn’t worth my time.

But I too like putting blinky lights on things. In particular, blinky lights close to a driver’s face have the potential to be very useful.

I had forgotten that MSP430. I had a student who really wanted to use it, but he was just wanting to tinker.

(So am I, mostly, but it’s not build season.)

I might have to look up how that works and see if I can get other things to work similarly. I don’t want to spend a whole bunch of time coding that USB interface, but if I can figure out some fairly easy, “Set this function. It activates that pin”, I could see doing it.

I am not sure how much this helps, but we were able to get setOutput() to work with the PSOC.

Here is a link to my final post, but if you look at some of the others in that thread, it may give you what you are looking for.

The nice thing about the gamepad tool is it flashes it with prebuilt firmware. No programming is needed to set up the board. The wiring is about as hard as can be expected though.

You could try asking here! This is the most and best community engagement I have ever seen by NI on the DS.

2 Likes

Maybe more than you want, but if you’re really looking for

something that’s more like an industrial operator control panel

…and you’re willing to delve into some custom serial protocols, then this approach might be of interest.

When 6328 experimented with a “full-up” operator panel a couple of years ago, we included a lot of output capability. The controller we built supported a 20x4 character LCD, Neopixel ring, and PWM-controllable LEDs that could indicate multiple states including slow/fast blinking and pulsing as well as simple on/off. The initial panel build looked like this:

Control of the outputs was via a serial-over-USB interface with a simple protocol we invented. The inputs presented as normal joysticks (x2 with a total of 6 analog inputs and up to 24 button/switch inputs) and a keyboard (for e-stop). All outputs were driven with a Python script on the driver station that spoke NetworkTables on the backend and to the USB-serial port using our protocol. The hardware was based on an Arduino “Leonardo” 32u4 board with a custom shield we designed, and using an Adafruit 24-channel PWM LED driver.

Though this was fun to put together, in the end our recent drive teams have preferred XBox controllers so this got set aside. We’ve occasionally considered reviving it for use at demos (kids love this sort of thing - so many buttons and blinkenlights!) but to date haven’t really done so. If we seriously returned to this approach for competition use I think we’d revisit the controller hardware as there are newer boards that are better choices to base it on; we did have some issues with button inputs on this version that we never resolved, which were probably related to the I/O expander chip we had to use to get enough inputs into the Leonardo.

5 Likes

That’s one heck of an operator panel.

Here’s the part I don’t understand. How do people find protocols? For code running on the RoboRio, I’m going to stick 100% with WPI libraries, and code built with them. So, I know that I have a thing called setOutput(), and setOutputs(), that is part of the genericHID and its descendants, including Joystick.

Somewhere, that call does something. Presumably, it sends a message on the USB cable where the joystick lives. I don’t know if there’s some sort of standard chip that decodes that message and turns it into pin voltage levels, or if each response is custom for each device. (i.e. the joystick or game controller programmer reads the serial port and does whatever it’s supposed to do.)

Programming for a serial protocol is something I’ve done enough times in the past that I can see doing it again, but I don’t want to try and reverse engineer a protocol. How do I find out what I’m coding for?

I did take a look at the MSP430, but we don’t have the actual hardware we got in 2015. It seems like the program that the utility will put on the chip does…something with that hardware, but I don’t know how I would figure out what the “something” is. So I could program an MSP430 with that utility, but I still wouldn’t know what to do with it.

I was experimenting with some of the output functions with an Arduino Leonardo in WPILib simulation. Does anyone know if simulation supports setOutput/setOutputs? The reason I ask is that when I send a HID output through a tool like HIDPyToy I see it in my serial logger that I made and the litte RX light on the Arduino blinks. However, when I try to do it in simulation with setOutput in teleopInit and disabledInit nothing in my logger appears and the light does not blink. I should mention I’m doing this on MacOS

What kind of answer are you looking for? Do you want a wiring diagram or ideas of what to make the lights tell the driver or how to get the software going?

Well, I won’t send you on a goose chase, because I’m not likely to use an MSP430 anyway. Certainly I wouldn’t use the thing that we got in 2015, because I don’t have it and am not sure what to buy to replace it. Somewhere there was an FRC Gamepad…but I don’t know what it is. I can find an MSP430 or an MSP430 Launchpad. I’ve used TI launchpads before, and I think I even have one kicking around with TI’s programming studio available for it.

But I guess I would say that what I am looking for is the “Hello, World” project. “Hello, World” in this case is lighting an LED on something. I call joystick.setOutput(1,true), and somewhere a light lights up on something plugged into the PC’s USB port and running with the Driver Station. All that stuff between the WPI joystick object, and the light.

Given a pin that goes high and low, I know how to wire the light, but I don’t know how to make a pin go high and low after calling setOutput(1, true);

You’d need to implement the usb hid joystick protocol on a microcontroller. This is what the launchpad firmware does. I don’t know if there are any libraries (for arduino or similar) that implement the output functions of the usb specification.

For Arduino I used NicoHood’s HID Library. It works well for emulating a game controller and it seems to work well for normal HID OUT reports but I haven’t had any luck with WPILib simulation output. Not sure if this is a WPILib issue or one on the Arduino side.

2 Likes

Thanks, guys. The name of the protocol is a big step and a library will probably give me what I need.

On the MSP430 front, I also made some progress, and it might be worthwhile to someone else, so…here it is.

The FRC Gamepad tool was not included in the 2022 release. However, it is available for download here. Release 1.0.2022 · TI-FIRST/FRC-Gamepad-Tool (github.com)

That didn’t do me much good, because it still didn’t have any instructions with it. However, on a hunch, I decided to open the application, which was included in the download.

And there, on the front screen of the application, was an image of a Texas Instruments MSP430 Launchpad. And it had labels, for Axes, digital buttons, and indicators.

Googling it, it looks like you can buy one for 18 bucks from Mouser - although, there appear to be a couple of variants. They all work? Let’s hope.

So, I would hope that the answer is that I could use one of those things, and if I sent setOutput(1, true) the corresponding pin shown on the image would go high. Unless they are active low.

And I could hook up buttons or switches, and those would be the RawButtons, and…axes? I wonder what I put on an axis? In each configuration there’s 8 of them, so maybe those are analog inputs with a 0-5 volt range? I’ll bet the MSP430 datasheet would tell me that.

I wonder if the WPILib debounces switches. I think it does. I’ve never used a non-commercial joystick so I never had to worry about where the debouncing was.

But…I’m pretty sure I have enough to make it work right now.

And if I don’t, I probably just won’t do it anyway. Even if I have everything, it might be difficult to convince the team that what they really need is a custom controller. We’ll see. At least I can make it work now…probably.

1 Like

It doesn’t, but it doesn’t generally need to, as joystick button updates are only sent by the DS every 20 ms, and usually bounce is an order of magnitude faster than this.

So I got the setOutput to work with the Leonardo by pretty much appending the descriptor section for outputs of the launchpad to that of the joystick one of the Arduino joystick lib and adding some receive functionality to DynamicHID. I seem to only be able to 2 bytes (even when changing the usage max and report count. When report count is nothing but 16 DS does not even send anything) instead of the 4 I presumed would be available considering setOutput is 1-32. Code for this is available in this repo. Any thoughts on how to get the full 4 bytes would be appreciated.

2 Likes

Hi, just a quick note to say “thanks!” I’ve been struggling with this issue for two days trying to figure out what the DS wants, poring over pcaps with wireshark. i had expected it to produce “INTERRUPT OUT” reports aimed at an output endpoint, but it never produced anything at all with the descriptor i had written. running your code helped me to understand it is producing SET_REPORT reports over the control channel.

A real open source driver station sure would make this sort of thing easier. :slight_smile:

Anyway, thanks again.

1 Like

That’s a level lower than even the DS talks to, so source code wouldn’t help much. The DS just talks to the Windows XInput and DirectInput APIs, most likely in this case to the DirectInput Output Data API.