I’ve spent at least 3 days converting my Amp Delay Service from Serial communication to Raw HID communication protocol. My CarPC was using at one point 5 COM ports for the various devices connected to it. Iw was becoming a real pain keeping track of each COM port and the actual device that it represents. So I decided to convert my devices to plain USB devices rather than Serial.
Everything was going great until I tried sending data to Teensy while converting the Amp Delay box. The Amp Delay service needs to ping the Teensy device but for some reason (which is still unknown to me) sending data to the Emulated Serial device doesn’t work.
I’ve tried a handful of 3rd party USB libraries, tried rolling my own, tried synchronous vs overlapped IO. Nothing worked. I just could not send data to the device.
After hours of Googling, I finally stumbled on a solution. Turns out that when Teensy operates in Raw HID mode it presents itself to the PC as two devices:
VID_16C0&PID_0486&MI_00 – Raw HID Device
VID_16C0&PID_0486&MI_01 – Emulated Serial device
The “Serial” object in Arduino can send data to the Emulated Serial device which is the method I used to send the Gauge Pod Sender data to the PC. There seems to be a problem however sending data from the host to the device over this protocol.
The correct solution was:
1. Connect to the RAW HID Device instead.
2. Use RawHID.send and RawHID.read in Arduino code to communicate with the host.
I completely accidentally stumbled upon the RawHID object. It is not documented ANYWHERE. The difference is that Serial.print sends data to the Emulated Serial device and RawHID.send sends it to the RAW HID device.
void SendHID(String text)
{
uint8_t sendMessage[64]; //buffer
text.getBytes(sendMessage, text.length()+1); //convert text to bytes
//fill rest of buffer with zero
for (int idx = text.length(); idx < 64; idx++)
sendMessage[idx] = 0;
//send to PC, allow 100ms for sending the frame
int sent = RawHID.send(sendMessage, 100);
}
Another interesting tidbit.
arduino-1.0.3\hardware\teensy\cores\usb_rawhid\usb_private.h
holds the VendorID and ProductID that can be changed. When the sketch is uploaded to the device the values are changed on it. This makes it easy to distinguish multiple Teensy devices on the same PC. By changing the Product ID I can have the Amp Delay box and the Gauge Pod sender uniquely identified and don't have to worry about the program connecting to the wrong box.
Hi Tom,
Very glad I ran across someone else communicating with a Teensy using C#.
It seems you have had a lot more luck on the HID side than I have had. Would you be willing to post some code from the host C# side?
I have been using http://awtfy.com/2011/05/23/a-minimal-arduino-library-for-processing-serial-commands/ for the serial interface between a host PC (VS C# Express running under Win7). It works really well, I have dozens of commands defined for my application.
But I ran into something I have been stuck on for days. I would like to be able to have the host PC reset the Teensy to the user program. On the original Arduinos, I could toggle the serial port DTR pin, wait a bit and know I was executing my Arduino sketch from the beginning. This allowed the host to overcome hardware hangups, etc.
I have explained the problem and my attempted solutions here:
http://forum.pjrc.com/threads/24191-Host-Initiated-Reset-for-Teensy2-(Visual-C-Win7-environment)
If you have any thoughts on this I would love to hear them. Thanks for the Arduino HID tips!
Bill