I'm playing around with STM32F4 Discovery board and libopencm3. I want to send data acquired from ADC channels over usb and display some charts on the computer. After doing some research on USB class codes I'm a bit confused: which one should I choose for my application? At first I was thinking that USB-CDC it the way to go, since it's easier to implement but I don't think that it's the optimal solution.
Electronic – What USB class should I implement
stm32stm32f4usbusb device
Related Solutions
You need to change few others things to make it work as a gamepad. In usbd_hid_core.c you need to change :
0x02, //nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse
to the 0x00 value.
Other thing, the report descriptor has to be changed, this is mine for a 3-buttons 2-axis gamepad, (you can change it to add button or anything else with the HIDtool) :
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game Pad)
0xA1, 0x01, // COLLECTION (Application)
0xA1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x07, // INPUT (Cnst,Var,Rel)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xC0, 0xC0 // END_COLLECTION x2
};
The size of the report descriptor has changed so modify it in usbd_hid_core.c :
#define HID_MOUSE_REPORT_DESC_SIZE 48
Now the gamepad would be recognized. You only need to send a 3 bytes report (the first for the button, et the two others for the axis). For a test you could do it by using this code in stm32xx_it.c :
static uint8_t *USBD_HID_GetPos (void)
{
static uint8_t HID_Buffer[3] = {0};
static int8_t val_abs_x=0;
static uint8_t sens_x=0;
HID_Buffer[1] = 0;
HID_Buffer[2] = 0;
// X move
if (val_abs_x > 120)
{
sens_x = 0; // --
HID_Buffer[0]=0;
}
else if (val_abs_x < -120)
{
sens_x = 1; // ++
HID_Buffer[0]=1;
}
if (sens_x == 1)
val_abs_x = val_abs_x + 3;
else
val_abs_x = val_abs_x - 3;
HID_Buffer[1] = val_abs_x;
HID_Buffer[2] = 0;
return HID_Buffer;
}
Anf finally change the line (in the same file) :
USBD_HID_SendReport (&USB_OTG_dev, buf, 4);
to :
USBD_HID_SendReport (&USB_OTG_dev, buf, 3);
This should work well on the STM32f4 discovery board. If not try change the PID by adding 1 (like 0x5711) in usbd_desc.c).
Simplest is to make USB to virtual serial port (USB VCP), you have a library for that as well the example and drivers for windows. Once you plug it, you will see a serial port at your PC. Then in mcu program you can send it in orther you want with print function.
If you are familiar with Matlab then you can use STM32-MAT/TARGET and have possibility to use STM32 with Matlab/Simulink.
PS: 2-3Mbit that would be a little difficult with this approach. But do you really can process such stream of data at the PC side?
Best Answer
The USB CDC class is easy to implement and use, since on the PC side it creates a virtual COM port. You can easily test the interface with a program like RealTerm, which can display either ASCII or binary data. You will need to write a program to capture the data, convert it to ASCII, and save to a file for input to a spreadsheet program like Excel to do the charting.
The only gotcha is the COM port number that is assigned can't usually be predicated in advance so you have to have some sort of configuration file that specifies which one to use (once the system chooses a COM port for the USB device, it should continue to use the same one after that).
You don't mention what data rates you need to support, or how long a sample. At 115K baud, you can send one ADC sample (12 bits, expanded to 16) in a little under 175 µS, or about 5000 kHz. I'm guessing you need something faster than that. Since you have 192K RAM available, you can buffer up to 90,000 or so samples. At 44.1 kHz, that's a little over two seconds.
If you are going to sample first and then send, you might find the HID class even easier to use. It can present itself as a virtual keyboard, so there is no software to write on the PC side. You can open up a program like Excel, and as long as the firmware in the STM32F4 is sending the data as ASCII characters followed by a carriage/line feed for each sample, each line will be entered as an additional row in the spreadsheet, ready to graph.