none
Problems with USB speed from visual program to µController RRS feed

  • Question

  • Hello forum,

    well, I still don't know if this is the right forum for my question, but I just will try.

    Let me first describe my system:

    I have a Pic18 wich gathers measurement data from an external ADC. Everytime, a conversion finished on the ADC there is an interrupt event on the pic in which the data is read from the ADC. A buffer is filled with the data and then this data should be send to the PC via USB. On the PC I have a .exe written with delphi and a .dll written with visual studio (2013). The dll does most of the work, the exe is for clicking some buttons which activate the functions in the dll. The dll has another buffer which stores my data and from time to time the exe gathers the data from the dll and displays it in a chart.

    Some more aspects:

    Endpoints configured with 64Byte Packetsize (which is the maximum as I found out with some research), and Bulk transmission, the data is provided with some 100 Hz (100-1000Hz). There are 4 AD-canals with 3bytes per conversion, so I have a maximum amount of data of 12000Byte/s. So this is for sure much less than the specified data rate of full-speed usb (1,5Mbyte/s).

    Here are my problems:

    - I can't debug the firmware on the pic because the debugging and usb ports are on the same pins.

    - I cannot debug the .dll either, since it is a .dll, or at least I don't know how to.

    - The program runs for some time (seconds or minutes) and then it would just stop reading data. Sometimes it just stops reading data, sometime the exe (or dll?) crashes and doesn't react anymore and sometimes I even have to reset the µController

    - Even if the program runs "stable" it looses data from time to time

    - I didn't write all the code, I just have to fix the problem. And I'm not (yet) a professional in all these programming languages

    So here is my concrete question:

    Is there a possibility to configure USB for a reliable data transmission? I have the feeling that the problem is the synchronisation between dll and firmware, so if the dll looses some time because of whatever, the firmware has already new data and cannot transmit the old one.

    I already minimized the USB reading process as much as possible. The following code is in a while loop, so that it checks the USB endpoint permanently (except when reading data!?).

    OutLenPing = 0;
    if (!ReadFile(pThread->ReadWriteHandlePing, pThread->ReadBufferPing, pThread->PacketLength + 3, &OutLenPing, &OverlappedReadPing))
    {
    	if (GetLastError() == ERROR_IO_PENDING)
    	{
    		if (WaitForSingleObject(OverlappedReadPing.hEvent, pThread->TimeOut) == WAIT_OBJECT_0)
    		{
    			if (!GetOverlappedResult(pThread->ReadWriteHandlePing, &OverlappedReadPing, &OutLenPing, FALSE))
    			{
    				OutLenPing = 0;
    			}
    		}
    	}
    }
    ResetEvent(OverlappedReadPing.hEvent);
    
    while (1)
    {
    	DWORD res = WriteToFiFo(pThread->pDataFiFo, pThread->ReadBufferPing, OutLenPing - 3, 1);
    
    	if (res == 0)
    	{
    		ResetEvent(pThread->Events.IsSoftOverflow);
    		break;
    	}
    }

    I also tried to change the priority of the thread from normal to highest and time-critical, but this didn't change anything within my problem...

    And I implemented two endpoints for data transmission, so if the first one is still busy I can use the second one...

    So are there any ideas which aspects I should consider? The perfect result would be, to have a reliable data transmission without too much latency (no biiig buffer on the µController), without data loss, without program crashing, for sample rates up to 1000Hz.

    Thanks for all your thoughts about that topic.

    Regards, lh




    Friday, July 18, 2014 1:20 PM

All replies

  • the priority of the thread should not matter at all. you might want more than one pending read at a time. also, you should not need to Reset the hEvent in OverlappedReadPing if you create an auto reset event. Which driver are you using to control the device?

    you can debug the dll, you might have to run the app under VS though


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, July 18, 2014 4:44 PM
  • First of all, thanks for your answer.

    - I realized that the OverlappedReading events were created with auto reset, so I deletet the manual reset, but doesn't affect my problems...

    - I created a debug version from my dll, but when I try to start it in visual studio, I get the error message: program cannot be started. And I think, even if I would be able to start it, it wouldn't help, because I need the exe to control the dll functions...

    And if I load the debug dll into the exe it wouldn't make any difference, at least it wouldn't stop at the breakpoints I set.

    Any ideas on this?

    - I'm using mchpusb driver from microchip(?). The next great step is to change to winusb, but first I have to get this one run...

    - Can you explain your comment "you might want more than one pending read at a time."? How would I do that?

    - Is there the possibility to read more data than the 64byte max ep packet size with one read request?

    - How can I make sure that USB is read with reliable predictable time intervals?

    Regards...



    Monday, July 21, 2014 8:05 AM
  • ok, I solved the dll-debugging problem. But I still don't know why I lose data packets (or how I can stop losing them) or why my thread freezes some times (and how I can prevent this)...

    My visual program seems to by highly influenced by other stuff going on on the pc, like loading internet pages or building other programs. Is there a way to let my program run more stable? It has to collect the data via USB at least every 5-10ms...!!

    Would it make sense to implement the "continuous read" function? It seemed pretty complicated, but if it would solve my problem, perhaps I have to face it.

    Or would a timer be a solution? My concerns with timers are, that they are not exact enough for my application...and influenced as well by program delays...

    regards

    Tuesday, July 22, 2014 1:15 PM
  • ok, project went further, I solved a few problems but facing others now.

    1. I want to send data packets bigger than my maxPacketSize=endpoint size=64byte. assuming my packet has a size of 128byte, should this code work:

    if (!ReadFile(pThread->ReadWriteHandlePong, pThread->ReadBufferPong, 128, &OutLenPong, &OverlappedReadPong))
    {
    	if (GetLastError() == ERROR_IO_PENDING)
    	{
    		if (WaitForSingleObject(OverlappedReadPong.hEvent, pThread->TimeOut) == WAIT_OBJECT_0)
    		{
    			if (!GetOverlappedResult(pThread->ReadWriteHandlePong, &OverlappedReadPong, &OutLenPong, FALSE))
    			{
    			     OutLenPong = 0;
    			}
    		}
    		else
    		{
    			OutLenPong = 0;
    		}
    	}
    }

    a) when I split up the 128byte into two 64byte packets manually and send them when USBHandle isn't busy anymore

    b) when I just try to send 128byte with one turn. Or does this one depend on my driver, if it splits the packet automatically?

    I'm sure this has to work somehow, sending bigger transferpackets with only one read request, when one transfers a picture or something else, the data isn't transferred with thousands of read requests, is it?

    Regards, lh

    Friday, July 25, 2014 10:37 AM