Seeking Methods to Increase Serial Throughput

Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
Post Reply
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Seeking Methods to Increase Serial Throughput

Post by liam.zbasic »

I wrote code for the ZX-40a to capture time (gettime) and voltage (getadc) for 30 seconds from a photoresistor and transmit serially (debug.print) to Matlab. My goal is to capture time histories in Matlab and compute Power Spectral Density plots to resolve frequencies of a vibrating structure. I used ZX-40a's hardware COM1 (19200bps) for this operation. All worked as planned. However, I was surprised that the update rate captured in Matlab was only 100Hz. If I remove the gettime() command, the update rate improves to 200Hz. If I remove the debug.print command, the update rate is 2,000Hz. So the debug.print command and console.write dramatically slow the transmission. Is there a way to increase serial throughput? Thank you.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Seeking Methods to Increase Serial Throughput

Post by dkinzer »

liam.zbasic wrote:Is there a way to increase serial throughput?
Up to a point, yes. You'll still be limited by the volume of characters that you're outputting. The minimum time required to transmit a character is 10 / baudRate (assuming 8 data bits, 1 stop bit). Obviously, you can reduce the aggregate transmission time by reducing the number of bytes transmitted or by increasing the baud rate.

Assuming that you're using Com1, the other thing that might be helpful is to use a larger output queue. The default queue only has space for 4 bytes of data. That means that any time you add data to the queue, you're program will likely stall waiting for queue space.

Here is a snippet of code showing how to do that while retaining the default input queue.

Code: Select all

Dim com1OutQueue(1 to 50) as Byte
...
Call OpenQueue(com1OutQueue)
Call CloseCom(1)
Call OpenCom(1, 19200, CByteArray(Register.RxQueue), com1OutQueue)
- Don Kinzer
pjc30943
Posts: 220
Joined: 01 December 2005, 18:45 PM

Post by pjc30943 »

It is possible to increase the baudrate of COM1 up to 115k; that will help some. You can also stream ADC data directly to com1 with Zbasic's built-in command ADCtoCOM1, which is much faster.
Paul
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

How does ADCtoCom1() treat the end of each ADC reading? Does it add a linefeed or carriage-return or both? Is there a 10-bit version of ADCtoCom1()? Thanks.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

liam.zbasic wrote:How does ADCtoCom1() treat the end of each ADC reading?
It simply sends a stream of 8-bit data values, each representing an ADC reading. There are no separators, terminators, etc.
liam.zbasic wrote:Is there a 10-bit version of ADCtoCom1()? Thanks.
No.
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

You say you want FASTER, but how fast do you NEED it to be?

115200 baud is probably the fastest reliable connection you will get. If you just send 2 bytes of ADC data, the time to send those 2 bytes will be 20/115200 seconds. I.E. 5760 Hz. Most likely you get half that speed in real life. But, I think it might be possible to do the ~2900Hz.

With reasonable pacingof the timing of the ADC conversions, you might be able to use a very short output queue.

I would not use Debug.Print for this purpose. Open Com1 as a real com port. I believe it will work in the background while debug.print will not.

It would be interesting to see the difference in speed for the VM vs. Native Mode actual bandwidth.

-Tony
liam.zbasic
Posts: 163
Joined: 24 March 2008, 23:33 PM
Location: Southern California (Blue)

Post by liam.zbasic »

How fast do I need? Up to 2,000Hz with 10bit ADC would work well for my random vibration purpose. Qual spectra for components usually run up to this frequency.
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

spamiam wrote:I would not use Debug.Print for this purpose. Open Com1 as a real com port. I believe it will work in the background while debug.print will not.
You're right, there is a subtle difference between Debug.Print and PutQueueStr(). When Debug.Print is invoked, the calling task is effectively locked during time required to add the characters of the string to the queue. Note, however, that each element of a semi-colon separated sequence of strings is handled separately and a task switch may occur between the strings. Console.Write() and Console.WriteLine() have the same behavior. In contrast, PutQueueStr() will yield to another task if there is insufficient space in the queue for the entire string provided.

The primary reason for this difference is so that Debug.Print/Console.Write can function with the relatively small default output queue size. If the output queue has enough empty space to accommodate the entire string, there is essentially no difference between Debug.Print/Console.Write() and PutQueueStr()
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

dkinzer wrote:
spamiam wrote:I would not use Debug.Print for this purpose. Open Com1 as a real com port. I believe it will work in the background while debug.print will not.
If the output queue has enough empty space to accommodate the entire string, there is essentially no difference between Debug.Print/Console.Write() and PutQueueStr()
Well, 2000Hz samples will be pushing the limits, I think. It is nearly 50% of the bandwidth of the 115200 baud connection right off the bat.

There will be VERY little room for additional info/control characters to go over the com port.

Since timing will be a bit of an issue to keep the interval between ADC samples very even, the com port should not require a big queue. Essentially only as large as all the data and control for one sample. If, on average, the data comes in faster than it can get out of the queue, eventually it will block or overrun.

I think it is potentially feasible to get close to 2KHz sampling. Probably the ADC unit will need to be set to do samples autonomously, then the ADC result gets read by the program at a specified interval. That 16 bit value gets put into the com queue, along with as little control data as possible.....

-Tony
Post Reply