Sign in

username:

password:



Not a member?

Search basicx



Search tips

Subscribe to basicx



basicx by Keywords

Accelerometer | ADC | ADXL | Adxl20 | AVR | BasicStamp | BX-35 | BX28 | BX35 | COM3 | Compiler | Downloader | EEPROM | Electromagnet | GetADC | GP2D1 | GPS | I2C | IDE | Keypad | LCD | LCD+ | MIDI | Motors | Multitasking | Netmedia | Networking | PCB | PID | PlaySound | PWM | Relays | RTC | Servo | ShiftOut | SitePlayer | SPI | Stack | Timer | USB

Ads

Discussion Groups

Discussion Groups | BasicX | Re: Need faster code help

Discussion forum for the BasicX family of microcontroller chips.

Need faster code help - "James R. Parish" - Dec 27 0:02:50 2007

I'm querying a computer at 1200 baud using 2 chr ASCII commands. It
sends back a string of characters and I'm trying to get them into a
STRING in the BX-24 to process. This is the code I came up with many
years ago, it works but my sped bottle-neck is here. Is there a faster
way to send a TEXT to a serial port and grab the reply into a STRING?

'Gets a string of data from the selected serial port

'until the Queue is empty .

'Returns with a string of data in GETTDATA

PUBLIC Sub GetSerialData(ByVal SENDDATA as STRING)

ErrorFlag = 0

LAST = FALSE

TRY = 0

GETDATA = ""

CALL PUTPIN(RedLED, LEDoff)

' DO

CALL PutQueueStr(OutBuf,SENDDATA)

CALL SLEEP(0.4)

DO

IF (StatusQueue(INBUF)) THEN

GOTO CONT

END IF

TRY = TRY + 1

'DEBUG.PRINT"Trying to get DATA..."

'DEBUG.PRINT CSTR(TRY)

LOOP UNTIL(TRY = 5)

ErrorFlag = 1

GOTO ENDSUB

CONT:

GETDATA = ""

DO

IF (StatusQueue(INBUF)) THEN

CALL GetQueue(INBUF,INBYTE,1)

TEMP = CHR(INBYTE)

GETDATA = GETDATA & TEMP

ELSE

LAST = TRUE

END IF

LOOP UNTIL(LAST)

ENDSUB:

'DEBUG.PRINT"GETDATA =[";GETDATA;"]"

End Sub

[Non-text portions of this message have been removed]



(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )


Re: Need faster code help - Don Kirby - Dec 27 21:01:31 2007

Public Sub GetSerialData(ByVal SENDDATA as STRING)
GETDATA = ""
CALL PUTPIN(RedLED, LEDoff)
CALL PutQueueStr(OutBuf,SENDDATA)

Do While NOT(StatusQueue(INBUF))
Call Sleep(0) 'just sit idle
Loop

Do While (StatusQueue(INBUF))
CALL GetQueue(INBUF,INBYTE,1)
GETDATA = GETDATA & CHR(INBYTE)
Loop

End Sub

I think this is the fastest method, as far as code execution time.
You could also check the amount of data in the queue and read it all
at once, using GetQueueCount for a possible firther speed increase.
In your origional code, you wait for 0.4 seconds before you try to
read the data. That is what is holding up the code.

I would suggest you turn this sub into a separate task, and let it run
continuously. When used in that manner, it will not hold up the rest
of the application waiting for the data to arrive. Since tasks can't
take parameters, you'll have to make SENDDATA a global variable.
You'll need to impliment 2 flags, a Ready To Send Flag, and a Data
Received Flag. The GetSerialData task would sit in an idle loop until
the Ready To Send Flag is set. Once the data string is received,
GetSerialData will set the Data Received Flag. It's up to the rest of
the program to do something with the data and reset the flags.
The task version:

Public SENDDATA as String 'This is global now
Public DataReady as Boolean
Public ReadyToSend as Boolean

Public Sub GetSerialData()
GETDATA = ""

Do
'wait for the data to be ready so that
'we don't send partial data
'We also don't want to overwrite the string
'before it can get read by the rest of the
'program.
Do While NOT(ReadyToSend) OR (DataReady)
Call Sleep(0)
Loop

CALL PUTPIN(RedLED, LEDoff)
'Send the data
CALL PutQueueStr(OutBuf,SENDDATA)
'Wait until there is data in the queue
Do While NOT(StatusQueue(INBUF))
Call Sleep(0)
Loop
'Get the data
Do While (StatusQueue(INBUF))
CALL GetQueue(INBUF,INBYTE,1)
GETDATA = GETDATA & CHR(INBYTE)
Loop
'Set the flag
DataReady = True
'go back to waiting for SENDDATA to be ready
'Remember to reset the flags
Loop
End Sub

This version will hang if the data never shows up in the queue.
Depending on how long the PC side takes to respond, you can add a
counter in the loop:

Public SENDDATA as String 'This is global now
Public DataReady as Boolean
Public ReadyToSend as Boolean

Public Sub GetSerialData()
'Time in millisecinds to wait for a response
Const TimeOut As Integer = 500
Dim A as Integer

Do
'wait for the data to be ready so that
'we don't send partial data
'We also don't want to overwrite the string
'before it can get read by the rest of the
'program.
A = 0

Do While NOT(ReadyToSend) OR (DataReady)
Call Sleep(0)
Loop

CALL PUTPIN(RedLED, LEDoff)
'Send the data
CALL PutQueueStr(OutBuf,SENDDATA)
'Wait until there is data in the queue
Do While NOT(StatusQueue(INBUF)) OR (A = TimeOut)
Call Sleep(0.001) 'slow it down just a bit
A = A + 1
Loop
'Get the data
Do While (StatusQueue(INBUF))
CALL GetQueue(INBUF,INBYTE,1)
GETDATA = GETDATA & CHR(INBYTE)
Loop
'Set the flags if there is valid data
If Len(GETDATA) > 0 Then
DataReady = True
ReadyToSend = False
End If
'go back to waiting for SENDDATA to be ready
'Remember to reset the flags
'GETDATA should also be cleared elsewhere
'before DataReady is reset
Loop
End Sub

If the data isn't received before the TimeOut occurs, the task
continues it's loop. With no data in the queue, it loops around to
the beginning and tries again.

HTH
-Don
--- In b...@yahoogroups.com, "James R. Parish" wrote:
>
> I'm querying a computer at 1200 baud using 2 chr ASCII commands. It
> sends back a string of characters and I'm trying to get them into a
> STRING in the BX-24 to process. This is the code I came up with many
> years ago, it works but my sped bottle-neck is here. Is there a faster
> way to send a TEXT to a serial port and grab the reply into a STRING?
>
>
>
> 'Gets a string of data from the selected serial port
>
> 'until the Queue is empty .
>
> 'Returns with a string of data in GETTDATA
>
>
>
> PUBLIC Sub GetSerialData(ByVal SENDDATA as STRING)
>
> ErrorFlag = 0
>
> LAST = FALSE
>
> TRY = 0
>
> GETDATA = ""
>
>
>
> CALL PUTPIN(RedLED, LEDoff)
>
> ' DO
>
> CALL PutQueueStr(OutBuf,SENDDATA)
>
> CALL SLEEP(0.4)
>
> DO
>
> IF (StatusQueue(INBUF)) THEN
>
> GOTO CONT
>
> END IF
>
> TRY = TRY + 1
>
> 'DEBUG.PRINT"Trying to get DATA..."
>
> 'DEBUG.PRINT CSTR(TRY)
>
> LOOP UNTIL(TRY = 5)
>
> ErrorFlag = 1
>
> GOTO ENDSUB
>
>
>
> CONT:
>
> GETDATA = ""
>
> DO
>
> IF (StatusQueue(INBUF)) THEN
>
> CALL GetQueue(INBUF,INBYTE,1)
>
> TEMP = CHR(INBYTE)
>
> GETDATA = GETDATA & TEMP
>
> ELSE
>
> LAST = TRUE
>
> END IF
>
> LOOP UNTIL(LAST)
>
>
>
> ENDSUB:
>
> 'DEBUG.PRINT"GETDATA =[";GETDATA;"]"
>
> End Sub
>
> [Non-text portions of this message have been removed]
>



(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )

RE: Re: Need faster code help - "James R. Parish" - Dec 27 22:43:01 2007

Thanks for the reply. I tried the first suggestion and it fails
without the sleep(0.4) after the

CALL PutQueueStr(OutBuf,SENDDATA)

What I do to see if the RS232 is connected is send a (chr(13)) out
to the device, it responds back with a prompt of "==> and "
which I use to determine the device is connected and responding. The
command I send out is 4 chrs long

"D 4&CHR(13)" or "D4" which sends back an echo of the CHRS
then the requested data string which is about 15 chrs about followed by
.

I'm thinking the character echo needs to be addressed. Maybe?

From: b...@yahoogroups.com [mailto:b...@yahoogroups.com] On Behalf
Of Don Kirby
Sent: Thursday, December 27, 2007 8:59 PM
To: b...@yahoogroups.com
Subject: [BasicX] Re: Need faster code help

Public Sub GetSerialData(ByVal SENDDATA as STRING)
GETDATA = ""
CALL PUTPIN(RedLED, LEDoff)
CALL PutQueueStr(OutBuf,SENDDATA)

Do While NOT(StatusQueue(INBUF))
Call Sleep(0) 'just sit idle
Loop

Do While (StatusQueue(INBUF))
CALL GetQueue(INBUF,INBYTE,1)
GETDATA = GETDATA & CHR(INBYTE)
Loop

End Sub

I think this is the fastest method, as far as code execution time.
You could also check the amount of data in the queue and read it all
at once, using GetQueueCount for a possible firther speed increase.
In your origional code, you wait for 0.4 seconds before you try to
read the data. That is what is holding up the code.

I would suggest you turn this sub into a separate task, and let it run
continuously. When used in that manner, it will not hold up the rest
of the application waiting for the data to arrive. Since tasks can't
take parameters, you'll have to make SENDDATA a global variable.
You'll need to impliment 2 flags, a Ready To Send Flag, and a Data
Received Flag. The GetSerialData task would sit in an idle loop until
the Ready To Send Flag is set. Once the data string is received,
GetSerialData will set the Data Received Flag. It's up to the rest of
the program to do something with the data and reset the flags.

The task version:

Public SENDDATA as String 'This is global now
Public DataReady as Boolean
Public ReadyToSend as Boolean

Public Sub GetSerialData()
GETDATA = ""

Do
'wait for the data to be ready so that
'we don't send partial data
'We also don't want to overwrite the string
'before it can get read by the rest of the
'program.
Do While NOT(ReadyToSend) OR (DataReady)
Call Sleep(0)
Loop

CALL PUTPIN(RedLED, LEDoff)
'Send the data
CALL PutQueueStr(OutBuf,SENDDATA)
'Wait until there is data in the queue
Do While NOT(StatusQueue(INBUF))
Call Sleep(0)
Loop
'Get the data
Do While (StatusQueue(INBUF))
CALL GetQueue(INBUF,INBYTE,1)
GETDATA = GETDATA & CHR(INBYTE)
Loop
'Set the flag
DataReady = True
'go back to waiting for SENDDATA to be ready
'Remember to reset the flags
Loop
End Sub

This version will hang if the data never shows up in the queue.
Depending on how long the PC side takes to respond, you can add a
counter in the loop:

Public SENDDATA as String 'This is global now
Public DataReady as Boolean
Public ReadyToSend as Boolean

Public Sub GetSerialData()
'Time in millisecinds to wait for a response
Const TimeOut As Integer = 500
Dim A as Integer

Do
'wait for the data to be ready so that
'we don't send partial data
'We also don't want to overwrite the string
'before it can get read by the rest of the
'program.
A = 0

Do While NOT(ReadyToSend) OR (DataReady)
Call Sleep(0)
Loop

CALL PUTPIN(RedLED, LEDoff)
'Send the data
CALL PutQueueStr(OutBuf,SENDDATA)
'Wait until there is data in the queue
Do While NOT(StatusQueue(INBUF)) OR (A = TimeOut)
Call Sleep(0.001) 'slow it down just a bit
A = A + 1
Loop
'Get the data
Do While (StatusQueue(INBUF))
CALL GetQueue(INBUF,INBYTE,1)
GETDATA = GETDATA & CHR(INBYTE)
Loop
'Set the flags if there is valid data
If Len(GETDATA) > 0 Then
DataReady = True
ReadyToSend = False
End If
'go back to waiting for SENDDATA to be ready
'Remember to reset the flags
'GETDATA should also be cleared elsewhere
'before DataReady is reset
Loop
End Sub

If the data isn't received before the TimeOut occurs, the task
continues it's loop. With no data in the queue, it loops around to
the beginning and tries again.

HTH
-Don

--- In b...@yahoogroups.com , "James
R. Parish" wrote:
>
> I'm querying a computer at 1200 baud using 2 chr ASCII commands. It
> sends back a string of characters and I'm trying to get them into a
> STRING in the BX-24 to process. This is the code I came up with many
> years ago, it works but my sped bottle-neck is here. Is there a faster
> way to send a TEXT to a serial port and grab the reply into a STRING?
>
> 'Gets a string of data from the selected serial port
>
> 'until the Queue is empty .
>
> 'Returns with a string of data in GETTDATA
>
> PUBLIC Sub GetSerialData(ByVal SENDDATA as STRING)
>
> ErrorFlag = 0
>
> LAST = FALSE
>
> TRY = 0
>
> GETDATA = ""
>
> CALL PUTPIN(RedLED, LEDoff)
>
> ' DO
>
> CALL PutQueueStr(OutBuf,SENDDATA)
>
> CALL SLEEP(0.4)
>
> DO
>
> IF (StatusQueue(INBUF)) THEN
>
> GOTO CONT
>
> END IF
>
> TRY = TRY + 1
>
> 'DEBUG.PRINT"Trying to get DATA..."
>
> 'DEBUG.PRINT CSTR(TRY)
>
> LOOP UNTIL(TRY = 5)
>
> ErrorFlag = 1
>
> GOTO ENDSUB
>
> CONT:
>
> GETDATA = ""
>
> DO
>
> IF (StatusQueue(INBUF)) THEN
>
> CALL GetQueue(INBUF,INBYTE,1)
>
> TEMP = CHR(INBYTE)
>
> GETDATA = GETDATA & TEMP
>
> ELSE
>
> LAST = TRUE
>
> END IF
>
> LOOP UNTIL(LAST)
>
> ENDSUB:
>
> 'DEBUG.PRINT"GETDATA =[";GETDATA;"]"
>
> End Sub
>
> [Non-text portions of this message have been removed]
>

[Non-text portions of this message have been removed]



(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )

Re: Need faster code help - Tom Becker - Dec 28 12:16:35 2007

Jim, since the command you send, the echo you receive, and the command
response data are all terminated in a CR, why don't you use them to
steer your code?

Clear the caches, if that's necessary, PutQueue the command, spin
getting a byte at a time until you see the CR at the end of the
command echo, then build (concatenate) a string of response data until
you see its CR?
Tom



(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )

RE: Re: Need faster code help - "James R. Parish" - Dec 28 14:11:43 2007

Don, I tried all your suggestions and the one that I got to work was
using "GetQueueCount".

This SUB can be optimized some more I'm sure but I was just trying to
get it working. It's running as fast as I can get it to but I'm at a
loss as why I still need the SLEEP(0.001) to make it work. Something
about trying to get the buffer status to soon maybe? Since I know how
many characters are suppose to be sent from each query I decided to use
the GetQueueCount() and it works great. I really don't care that there
IS data in the queue but whether it is the correct data. I'm thinking
maybe the 1200 BAUD may be a bit slow, I might try stepping up to 9600
to see if that gets rid of the sleep statement.

Anyone else have any comments?

The serial port is setup for 1200,N,8,1

'Gets a string of data from the selected serial port

'until the Queue is empty .

'Returns with a string of data in GETTDATA

PUBLIC Sub GetSerialData(ByVal SENDDATA as STRING, ByVal QCOUNT as
integer)

ErrorFlag = 0

DIM COUNT as integer

LAST = FALSE

TRY = 0

GETDATA = ""

Call ClearQueue(InBuf)

Call ClearQueue(OutBuf)

CALL PUTPIN(RedLED, LEDoff)

CALL PutQueueStr(OutBuf,SENDDATA)

DO

CALL SLEEP(0.001)

IF (GetQueueCount(InBuf) = QCOUNT) THEN

GOTO CONT

END IF

TRY = TRY + 1

' DEBUG.PRINT"Trying to get DATA..."

' DEBUG.PRINT CSTR(TRY)

'Count = GetQueueCount(inbuf)

'Debug.Print "Count = "; CStr(Count);" QCOUNT NEEDS=";Cstr(qcount)

LOOP UNTIL(TRY = 255)

ErrorFlag = 1

GOTO ENDSUB

CONT:

GETDATA = ""

DO

IF (StatusQueue(INBUF)) THEN

CALL GetQueue(INBUF,INBYTE,1)

TEMP = CHR(INBYTE)

GETDATA = GETDATA & TEMP

ELSE

LAST = TRUE

END IF

LOOP UNTIL(LAST)

ENDSUB:

'DEBUG.PRINT"GETDATA = ";GETDATA;"=";CSTR(ASC(GETDATA))

End Sub

[Non-text portions of this message have been removed]



(You need to be a member of basicx -- send a blank email to basicx-subscribe@yahoogroups.com )