Serial Data Speed


Recommended Posts

I have two RS232 data streams that I receive via virtual com ports (Bluetooth radio). Each stream is one number in ASCII form at approximately 125 HZ. I created serial comm devices to receive the data.

I have serious problems with delays in the data received. Is there a way to collect data at these rates? Any examples would be appreciated.

Regards:

whiggins

Link to comment
Share on other sites

You can do it, but you are probably not going to be able to use the OnReceive as described in the serial / ethernet comm manual. Instead you are going to need to make a sequence that reads maybe 5 points at a time, then pauses a short bit. Before I go into detail, can you give more detail on the exact protocol? Is it an ASCII number with a carriage return? Is there anything else? Perhaps you can post a screenshot of the monitor window.

Link to comment
Share on other sites

Thanks for the prompt reply. Yes, data comes in as an ASCII number with a carriage return and looks like 9999.99. Currently, I'm using the OnReceive and the following protocol:

if (strIn == Chr(13))
   private string datain = ReadUntil(13)
   Channel.AddValue(strDevice, 0, "Input", 0, StrToDouble(DataIn))
Endif

Thanks for your assistance.

Bill

Link to comment
Share on other sites

Yeah, the OnReceive isn't going to be able to handle that much traffic. OnReceive was a good idea in concept and (almost) required if you want to create your own protocol that you can easily reuse between docs, but due to the current speed of DAQFactory script, the overhead is just too much. Fortunately, there's a better way (and in 6.0 I'd imagine script will be quite a bit faster, so this will be less of an issue, but that is another story.

Anyhow, what you want to do is create a regular sequence, and let DAQFactory internally buffer each character until the 13 arrives. It'd look something like this:

private string datain
while(1)
   try
	  datain = readuntil(13)
	  MyChannel.AddValue(strToDouble(datain)
   catch()	  
   endcatch
endwhile

It may look like an infinite loop, but the readuntil() is a blocking call until either the timeout occurs or a 13 arrives. The 13 should arrive every 1/125th of a second, so the maximum delay there is 1/125th of a second. Depending on your CPU (especially single core ones), this may not be enough and you may need to stagger out the reads and do it in blocks. Doing so is simply a matter of adding a delay and shortening the timeout, but you lose a precise timestamp on your data as all the values in the block will have about the same time:

while(1)
   try
	  datain = readuntil(13)
	  MyChannel.AddValue(strToDouble(datain)
   catch()	  
	  delay(0.02)
   endcatch
endwhile

For this to work, though, you have to set the timeout on the serial port to 1 millisecond. That way if data isn't immediately ready (well, within 1 ms), it will throw an error, delay 20 milliseconds and then dump whatever data has accumulated in that 20 milliseconds. The delay in the catch allows the data to buffer internally whenever data isn't immediately available. The delay will also allow the rest of DAQFactory, and for that matter Windows, to do its thing.

Finally, since this is pretty CPU intensive either way, I would first run these sequences at priority 0 so they don't hang the system. I'd also save often, especially before starting the sequence. Then, once it works at priority 0, you can bump it up to 5 to get faster response.

Link to comment
Share on other sites

Thank you! I'll give this a try.

I'm running on a laptop with a Centrino Duo T2050 @ 1.60GHZ. I know it depends on a lot of things, but what is the practical limitations of the speed at which I can collect two channels of data? Is the 125HZ pushing the limit?

Regards:

whiggins

Link to comment
Share on other sites

I'd have to look at what the internal buffer size is. I think its 64K. Basically, at least with a single core machine, you have to release the processor every so often to allow Windows to respond to mouse movements and draw the screen, not to mention let DAQFactory do its thing. With two cores, the sequence may stick on one processor and just dominate it and Windows and DAQFactory will use the other one. It also may not, its kind of up to Windows. So, you can either constantly read the port as I did in the first example and that will release the cpu every 1/125th of a second for a millisecond or two, but that may not be enough.

Or, you can do as I did in the second example and batch read. Here, instead of doing a lot of really small chunks of code really fast, you do a larger chunk of code less often. This creates larger holes for Windows and less task switching and so tends to work better. The disadvantage is that you don't have precise timing info, though if your device is constantly streaming at a constant rate, it can be calculated based on the first reading (provided you purge() first).

In the second method, then, the max speed is largely determined by the internal buffer size. If its 64K, then your blocks need to be quick enough so that the full 64K is not filled. With serial this is really never an issue. Even at 256Kbaud, you are only talking 32K bytes per second (actually a little less), so it would take 2 seconds to fill the buffer. With Ethernet speeds can be higher, but that is partially why the really high speed stuff like CAN typically are handled in hardware.

These concepts are essentially the same for regular acquisition with a DAQ device. You can software poll at a max of about 100hz, or you can let the hardware buffer a bunch of fast reads and the read the values in blocks. For serial, the internals of DAQFactory are the like the hardware because the internals are low level C code and can real very fast.

So, I guess the bottom line is that 125hz is not going to be a problem. You just might have to tweak the sequences a little to get it to work. And of course, we're here to help. Worse case, we can write a quick low level protocol (like the Modbus, AB and Mitsubishi ones) to do it since this is a pretty common format. (actually, ask me again on Monday and it might just appear for you B) ) We'd make it capable of taking any delimited, CR ending stream.

Link to comment
Share on other sites

If that would magically "appear" on Monday I would be very grateful. It would really help me out.

As a side note, of all the vendors I deal with you have the best support. I've called from the job site with problems in the past and always received a quick response and great solution.

Thanks again,

whiggins

Link to comment
Share on other sites

OK, something for you to try. Its still definitely beta and needs a few things to allow you to use it on more than one device and some additional features that others might find useful, but for one device under your specs, it should work fine.

To get it go to www.azeotech.com/daqfactory.exe (Note to anyone reading this, the change will be in the 5.80 and later releases, so if 5.8 is released by the time you read this you should simply download the update as this link may be dead). Copy the file over the existing. It is Build 1579. You can check by going to Help-About in DAQFactory.

When you start back up you'll see a new protocol called Async ASCII Delimited. You can select this just like Modbus. It has only one I/O type, called Input. Create channels for each delimited value you have. In your case you only have one, but this protocol will do things like 1,2,3 and split into three channels. The D# should always be 0, the channel should be the index of the value you want, starting with 0 (in your case, just 0). There is no timing since its async and the device is streaming it without any polling.

I don't know what the max speed would be for this, but I'm guessing its pretty fast. We could make it quite a bit faster by blocking the data (an appropriately design DF driver can do over 1mhz!), but that probably only becomes an issue above 1khz lines and I don't know many devices that output that fast and still use ASCII (I've seen some accelerometers come close...). Also, blocked data doesn't work well for the more typical, slower devices.

Link to comment
Share on other sites

  • 1 month later...

Okay, I'm finally back on this project. This seems to work very,very well on one channel of incoming serial data. Is there a way to make this work for two channels of incoming serial data. I've tried it but it only seems to respond to one channel.

Thanks for your assistance.

whiggins

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.