Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.


Log in or register to post/reply in the forum.

RS232 data


hwebb Feb 10, 2009 05:59 PM

Hi,
I was looking for a little help here. I have a CR1000 data logger running a program the receives RS-232 data on com1(2 of the control line inputs). The RS232 data is a 36 or 24 bytes message, having a * for the starting character and a LF (line feed) for the ending character.

I have tried using SerialInRecord and setting the sync char to 42, and the termination char to 10. I set the number of bytes to 0, so it should pick up the whole string. I have found that this does not work. Unless I set the number of bytes to a set value, I do not get my data string through.

This seemed to work ok, as I was getting my string through. But does anyone know if the SerialInRecord clears the buffer when it finds a string? These messages are coming in about 7/second, and it seems as I only get 1/4 of the messages processed. So I'm wondering if the buffer gets cleared.

I'm running the RS-232 at 9600 baud rate, so it is not very fast. Does anyone have any suggestions on how to get all my messages through?

Thanks for the help,
Helene


Dana Feb 10, 2009 10:49 PM

Hello Helene,

The buffer is a "ring buffer". If NumBytes is set to 0, the buffer size will be the size of the SerialOpen buffer. In addition, if the program compiles in Pipeline mode, the buffer will be multiplied by the Scan BufferOption.

The buffer needs to be set to at least the number of bytes that can come in during a scan, plus at least once extra byte. If you don't have the extra byte, there may be instances where the datalogger does not know that any new data has been received in the buffer.

There were a few improvements in the instruction since it was first implemented in the OS, so make sure you have the most recent OS loaded if you continue to have problems (it can be downloaded from the CSI web site).

Regards,

Dana


buck Jul 23, 2009 06:12 PM

I'm having similar problems using the SerialIn command. Can you expand more about how to specify the termination character or string? My strings are CRLF terminated, so I want to specify either LF (10 ??) or CRLF (1310 ??). Please go over the semantics of this command since it doesn't seem to be doing what I need.


IslandMan Jul 24, 2009 10:08 AM

Hi Buck,

Typically the end of a string is terminated as CR then LF. With SerialInRecord you want to grab the characters before the CR so your EndWord in the command sould be &H0D(Hex) or "13". (I always use the Hex, OD being CR and OA being LF).

Here's an example i have for reading in the serial string from a compass with pitch and roll:

This is what the string looks like:
$OHPR,149.5,0.0,-0.1,30.3*10
The string is variable length so I start by using the "$" as BeginWord. This allows me to leave NBytes as zero and let the command figure out the length. What we're left with is OHPR,149.5,0.0,-0.1,30.3*10 in the variable compass$.
I then use SplitStr to break the string up into the variable components.

Public compass$ As String * 50
Public NBytesCom3
Public CompArray(4)
Alias CompArray(1) = Compass
Alias CompArray(2) = Pitch
Alias CompArray(3) = Roll
Alias CompArray(4) = CompTmp

'Main Program
BeginProg

SerialOpen (Com3,19200,3,0,50)

Scan (1,Sec,0,0)

SerialInRecord (Com3,compass$,&H24,0,&H0D,NBytesCom3,01)
SplitStr (CompArray(),compass$,",",4,4)

NextScan
EndProg

Hope this helps.

Regards,
IslandMan


aps Jul 24, 2009 10:56 AM

Another tip:

Make sure you get the right value in the last parameter called "LoadNaN". If you choose option 00 or 01 the logger skips over the oldest data in its buffers and returns the last whole record it received. The next time around it starts looking for the next record at the end of the last record it read.

If you are calling the instruction less often than the sensor is outputting data and you want to pick up every message sent, you need to use options 10 or 11 and a loop structure, something like:

i=1
Do SerialInRecord(Com1,SerialInDest(i),37,0,&H0D0A,NbytesReturned,11)
i=i+1
Loop Until Nbytesreturned = 0

Which will read out each record at a time from the buffer into an array of values, right up to and including the last whole record in the input buffer. The last time around nbytesreturned will be zero and the dest will hold NaN.


With regards to serialin, the way the termination character can be entered is perhaps too flexible and perhaps we need more examples.

If you have only one termination character you can enter is as a number, e.g. 10 for LF, if you want two or more characters then the parameter must contain a string which can be predeclared, e.g.

Const termstr = chr(13)+ chr(10) 'It could also be a variable

OR you can just put chr(13)+ chr(10) in place of the parameter in the serialin instruction. The string can be longer than two characters BTW.

For a reason I can't explain this different to the way start and termination characters are entered in serialinrecord where a long number is expected (which can be entered in hex) and a maximum of two characters can be used.


As a general rule it is much easier to use Serialinrecord, especially with unprompted data from a sensor (which can come in out of synchrony with the program) as the logger does all the work in terms of making sure you get only whole records to decode thereon. You can only use serialinrecord easily where there is a unique start character (or pair) and either a fixed message length or termination character though.


buck Jul 28, 2009 03:46 PM

Andrew-

When I try the loop you recommended:

i=1
Do SerialInRecord(Com1,SerialInDest(i),37,0,&H0D0A,NbytesReturned,11)
i=i+1
Loop Until Nbytesreturned = 0

the compiler complains that I am using SerialInRecord() illegally in a conditional statementl. Please help...


aps Jul 28, 2009 10:16 PM

That is a little problem with the compiler as it should really force the program into sequentialmode if it sees conditional use of serialinrecord (I'll report this). If you include the sequentialmode command in the program it should be OK.

FYI: serialinrecord is designed to be able to run in pipelinemode to enable the logger to synchronise serial data with other measurements in applications such as Eddy Covariance measurements.

Once of the characteristic of pipeline mode is that for each scan it should operate each measurement instruction the same numbers of times each scan so this can all be scheduled on a tightly controlled sequence needed for pipeline operation - this is why it cannot cope with conditional calls of measurement or some other special instructions.

BTW you need Serialinrecord on a newline after the Do, unfortunately this forum editor reformats much of what you type.


buck Jul 29, 2009 01:07 PM

Andrew-

I'm getting closer, but still have issues when I send the compiled program to the CR1000. The compiler says there is no matching, or out of place ( in each of these expressions:

' 83 is decimal representation for ascii S (Sensor data)
SerialInRecord (Com1,SensorStr,83,0,&H0D0A,NbytesRet,11)


' 67 is decimal representation for ascii C (Current data)
ix=1
Do
SerialInRecord(Com1,CurrentStr(ix,0),67,0,&H0D0A,NbytesRet,11)
ix=ix+1
Loop Until Nbytesret = 0


I don't see it in either one of these; please advise...


IslandMan Jul 29, 2009 05:09 PM

Buck,
You may have to put the 83 or 67 in quotation marks "83".
IslanMan


aps Jul 29, 2009 09:29 PM

No needs for the quotes.

It is hard to debug the last issues without seeing the full program. All I can tell you is that in the second example ou are referencing a two dimensional array with the second index at zero.

In CRBasic (as most other basics) array indices start at 1.

How are you declaring the string variables in your DIM or Public statements?


buck Jul 30, 2009 12:48 PM

Andrew-

The declarations are:

Public SensorStr As String * 100
Public CurrentStr(20,100) As String
Public WavesStr As String * 150

Also tried Dim instead of Public with the same results. Thx for your help.


aps Jul 30, 2009 02:35 PM

I think you really want:

Public SensorStr As String * 100
Public CurrentStr(20) As String * 100
Public WavesStr As String * 150

And in serialinrecord just currentstr(ix)


FYI what you had:

Public CurrentStr(20,100) As String

Will define a two dimensional array of strings of the default length which is 16 bytes (16 usable plus a terminator).

Even that would have worked to some degree (probably not how you wanted it to) in your program except you set an index of zero.


buck Jul 30, 2009 03:15 PM

Andrew-

I gave that a try, but still getting the same problem when I download to the CR1000.

I can send you the program if you give me your e-mail addr.

thx.


aps Jul 30, 2009 10:20 PM

Send to

andrew dot sandford at campbellsci dot co dot uk

Changing the obvious to suit

Log in or register to post/reply in the forum.