I'm doing a USB device is to control stepper motors. I've done this before using a parallel port. because these ports do not exist in current motherboards, I decided to implement a USB communication between my device and the PC (host).
To achieve My objective, I endowed the freescale microcontroller the device with that has a USB module 12Mbps.
My USB device must receive 4 bytes (one for each motor driver) at a given time, because every byte is a step that should move the engine.
In the PC (Host) an application of user processes a text file with information and make the trajectory coordinates sending bytes at a certain rate for each motor (time is trivial to achieve the acceleration and speed of the motors) .
Using the parallel port was an easy the task because each byte is sent sequentially to a time determined by the user app.
doing a little research about full speed USB protocol understood that the frame is sent every 1ms.
then you can send 4 byte or many more every 1ms but I can not manage time like I did with the parallel port.
My microcontroller can send up to 64 bytes per frame (Based on transfer papers type Control, Bulk, Int, Iso ..).
question 1:
I want to know in what way I can send 4-byte packets faster than every 1 ms?
question 2:
What type of transfer can advise me for these type of devices?
Thanks.
Like Ricardo said, USB-serial will suffice.
As for the type of transfer, try implementing a CDC stack and use your SCI receiver to listen for PC commands. That will give you a receive buffer which will meet your needs.
Initialize your SCI (baud, etc)
Enable receiver and interrupt
On data receive, move it to your 4-byte command buffer
Clear receive buffer, wait for more
When you have all 4 bytes, fire off the steppers! Four bytes should take µs.
Check with Freescale to see if your processor is supported.
http://cache.freescale.com/files/microcontrollers/doc/support_info/USB_STACK_RELEASE_NOTES_V4.1.1.pdf?fpsp=1
There might even be some sample code to get you started.
-Cheers
I am achieving the same goal (driving/control CNC machines) like this:
the USB device is just synchronous I/O parallel port. Using continuous bulk transfer one pipe as input and one as output. This way I was able to achieve synchronous 64bit parallel communication with ~70KHz sample rate. It uses traffic around (i)4.27+(o)4.27 MBit/s that is limit for mine MCU and code. Bigger speeds cause jitter on the output due to USB events interrupts.
How to do it (on MCU side)
I have 2 FIFO's one for ingoing and one for outgoing data. I have timer interrupt occurring with sample rate frequency. In it I read the inputs and feed it to the first FIFO and read data from the other FIFO and send it to the outputs.
On top of that the USB task is called (inside the same interrupt) checking FIFO for sending to and incoming data from USB handling the transfer itself
I choose ATMEL AT32UC3A chips for this task. After a long and pain full research I decided these MCU's because they have enough memory for both FIFO's and program so no need for additional IC. It has FPGA package which can be used (BGA is not an option). It has HS USB (most USB MCU's have only FS like yours). It runs at 66MHz. It supports many interesting features (did interesting projects with it in the past) and of coarse I have experience with ATMEL MCU's from past
So if you want to achieve something similar then
start with bulk transfer (PC -> USB -> MCU -> output)
add FIFO if needed
do not know the sample rate you need. The old LPT's could handle from 80-196KHz depend on the manufactor. The modern ones are much much slower (which is silly and sad).
measure the critical sample rate
you need oscilloscope or very good hearing for this. The output data must be synchronous so no holes in it, no jitter, etc...
if any of these are present you have to lower the sample rate. Mine setup could handle even 1MHz sample rate but the USB jitter was present (sometimes USB event froze the sending for longer that one sample...) so I achieve only 70KHz of stable output.
if needed also inputs then add them
but only if the output is working as it should. Do not forget to lower the sample rate after this too ... Use separate bulk pipes and FIFOs for input and output.
Related
I'm currently working on an application where an MCU is receiving data from a hardware chip in the form of an asynchronous serial bit transmission at 2Mbps. This data has no encoding and no protocol aside from a start sequence, after which it is raw binary data.
The current approach for recovery is using the SPI module in 3-pin mode to oversample the stream 4x at 8MHz, allowing for recovery of the asynchronous data. While seemingly effective thus far with a simulated testbench, this method is rather complicated as an internal clock needs to be routed to the SPI CLK as the device is run in slave mode in order for DMA to recover the transmitted data while the processor executes another task.
Would it be possible to use any other peripherals efficiently for this task aside from SPI? Faking a communication protocol to recover a serial bit stream seems a bit roundabout, but I am not sure how to utilize UART or I2C without doing the same, and those might not even be possible to use as the protocol bits are not present in the stream. I also want to avoid using an ADC in the interest of power, along with the fact that the data is already digital so it seems unnecessary.
Could you please tell me what is the difference between receive/transmit FIFO and the data register in UART?
This is the first time I develop driver code for UART and so the first time I have come across with this. I am really not able to understand the difference. Please help me!
A FIFO (first-in-first-out) buffer in a UART is a hardware implemented queue of received or transmitted data. You do not access the FIFO directly, instead you read or write the data register and this data is automatically read or written from the head of the queue.
A FIFO can improve link efficiency because it allows software data read/write timing to vary while maintaining streaming data on the physical link.
When the FIFO is disabled or for a UART with no FIFO, there are only two bytes of buffering - the shift-register and the data-register. For input data, if the software does not read the data register in time before new data is received, it will be overwritten and data will be lost. Equally for transmission, if data is not written as quickly as it is transmitted, the full bandwidth and efficiency of the link may not be realised.
A FIFO is perhaps most useful on systems without deterministic real-time performamce where there may be no guarantees on timely servicing of the UART (such as a Desjktop PC running a general-purpose OS such as Windows for example), however on an embedded system where buffered interrupt driven serial I/O is used, the FIFO may not be entirely necessary for low to moderate data rates in many cases. On microcontrollers UARTS lacking a FIFO often support DMA instead which can be more effective at managing large streaming data bursts.
Once you write to the Transmit Data Register, the byte will go to the transmit FIFO, it will sit there until physical lines are ready to transmit.
The other way arround is the same, data come from physical lines and go to the receive FIFO, waiting the user code to collect it by reading a Received Data Register.
I've been given the task of getting ADC samples onto an embedded linux computer at the highest rate I can (up to about 300kSPS). I am playing with several different platforms (odroid, edison) but easrly on I realized the limitations of using the build in ADCs from within linux and timing (I am relativly new to this).
Right now I am reliably getting 150kSPS using a teensy 3.2 with a very basic swapping buffer, a PDB, and the USB connection. USB writes take 2.5usec no matter my buffer size so any faster and the ADC read interrupt collides with the USB and I get nothing.
My question is: Would using an external ADC chip enable faster speeds? I see chips on Digikey and Mouser advertising 600kSPS and higher with SPI and even parallel outputs... but I fell like the bottleneck is the teensy with USB writes. Even if it could (and I am sure it could) read values 600k times a second how do you get it onto the computer without falling behind?
also, it is for long term collection so I can't just store everything and write it once the collection is over. The edison has a built in microcontroller, but no SPI implemented yet.
Edit:
To clarify, my question is weather there is any way to get large amounts of data very fast into my embedded linux device programmatically or is there some layer between a fast SPI device and the comptuer that I don't know about. So far my mentors have suggested I 1) learn to write a device driver for the SPI device or 2) recompile an image with RT_PREEMPT.
I'm attempting to speed up a rather sluggish bootloader. Currently I'm sending data on a single USB HID output endpoint, and as it's a low-speed device I'm apparently limited to one 8-byte packet per 10 ms interval for a whopping 800 bytes/second.
Is it possible to increase the reporting frequency somehow? Or to use multiple output endpoints in a single interface or as part of a composite device? Or perhaps to abuse the control endpoint to send additional data?
Better compression is always an alternative I suppose, but it's an area of diminishing returns, and redesigning the hardware to allow full-speed USB isn't really an option.
For the record I'd be happy with a Windows-only solution.
Or perhaps to abuse the control endpoint to send additional data?
You can use "Vendor specific requests" for that. The TI TUSB3410 Chip works that way AFAIK. Many USB stacks have the hooks for them already in place.
This requires a driver or libusb on the host side, however.
I was able to speed up the upload by orders of magnitude by using SET_REPORT requests on the control endpoint, instead of declaring a separate interrupt out endpoint. That way you get all of the bandwidth available for control transfers.
Also using a larger report split into multiple segments helped reduce the number of SETUP packets needed.
Who says you are limited to an 8-byte packet per 10ms? I don't know the exact numbers off the top of my head, but I know you can send larger packets than that. I did an HID device and was using 64-byte packets. I think I could go larger, but that limit is probably hardware-specific. What hardware are you using?
Also, have you consulted USB in a NutShell?
The actual limit is 8 bytes every 10ms for low-speed devices, and 64 bytes every 1ms for high-speed devices, per interrupt-based endpoint.
So it seems that the first thing to try is switching to high-speed mode, if the hardware supports it. The next thing on the list is using multiple endpoints. If you really want to get the highest possible transfer rate, the HID class is a bad choice.
I'm using USB for communication. Our device sends 100k/s data (ARM7, very small memory size), and the PC needs to receive and process it all.
My previous design was implemented as a mass storage device, and extended a command for the communication protocol. The PC software runs a thread with a loop to receive the data.
The issue is: sometime it loses data.
So we used another solution: usb sim com (RS232).
But I don't know whether or not the OS can contain that much data before I get it using MFC (or pyserial). How can I get/set the buffer size?
We regularly punch about 100KByte/sec through our USB CDC implementation, the PC is fast enough to receive all data. But it seems that the built-in limits are lower with usb-serial (CDC) than with mass-storage protocol (in our case ~600KB/s versus ~100KB/s CDC).
The PC receive thread should have a buffer that's "big enough".
Edit: I don't know Windows' Buffer sizes, or how to get them, though.