Uart Feedback, Looped Script Error (sometimes)

 
#1

Hi all,

I'm having a bit of "sometimes" issue with calling for feedback through the EZB's Uart port from my Kangaroo. Maybe I'm not writing my script properly. I guess I'm a little unsure how the bytes are read by EZ Builder and how fast to set a loop at and send it through the Uarts.

I'm using the Kangaroo for position and speed control and it's attached to a Sabertooth. I'll start the motor moving that it's controlling and start the below script in a loop in EZ Builder. The script is asking for motor position feedback from the Kangaroo (the Roo is using an encoder for feedback). I want to know when the motor gets to a spot or while moving or even to the end of a move.

Most of the time the script will run and preform properly. Sometimes the script will stop and I'll get an error on the last line where it's told to:
print("Received: " + $Getp) . The error says something like an improper command or string quots " ".

Here's the Script that I know has no errors (see below it for my observations):

Code:


uartWrite(2, 0, "1, Getp", 0x0d)

:waitForData

$x = UartAvailable(2, 0)
print("Bytes in buffer: " + $x)

if ($x < 7) # Go back and wait for data again because we did not receive the least number of expected bytes
goto(waitForData)
endif

$Getp = UARTRead(2, 0, $x)
print("Received: " + $Getp)



I've noticed that:
*When run just once I'll never error and always get a position response.
*It helps (I think) but does not stop the error to place a small sleep() in the script but this slows down the loop.
I seem to get the error if there are more Bytes in the buffer before my " if ($x < 7)" command sent.
*If I know from past successful attempts that I'll need 8 bytes to get a correct reading and if I set the if "($x < 7)" four bytes to hi or low I'll either get the error or the script will loop for ever.

How is the best way to figure out the value of the bites I need to set the "if ($x < 7)" command at?

I've also noticed that sometimes when I know I'll get back a position feedback like 1,P850 , I'll only get back 1,P8 or even 1,P85. Has this got something to do with the bytes returned? Am I just asking for data too fast through the Uart ports? *confused*

#2

Can someone at EZ Robot just post a "Hi Dave" so I can give EZ Robot credit as resolving this question and save you guys a $3 credit I'd be giving someone else. Although I have not gotten an answer at all tho this thread, I'm getting messages from you guys to mark this thread resolved. I'm getting tired of seeing these "reminders".

As far as the problem; I still see the errors from time to time as the script runs. However it doesn't seem to be effecting running the script successfully to a conclusion. Maybe I'll try contacting Dimension Engineering to see if they know why their Kangaroo would send these error messages. *confused*

#3

This should never give you an error..

Code:


uartWrite(2, 0, "1, Getp", 0x0d)

:waitForData

$x = UartAvailable(2, 0)
print("Bytes in buffer: " + $x)

if ($x < 7)

# Go back and wait for data again because we did not receive the least number of expected bytes

sleep(100)

goto(waitForData)

endif

$Getp = UARTRead(2, 0, 7)

print("Received: " + $Getp)



I added a sleep before the goto() to prevent communication saturation.

I also added the UARTRead() to be 7 bytes, rather than all the data. This is because I believe you only want 7 bytes, which is one packet? The next time it runs, it will receive the next packet...

#4

Thanks for the personal reply DJ and help with the script.

In the past I've tried adding sleep commands throughout this script in different places and still got the random errors.

I do see the change you made to the UARTRead() to be 7 bytes rather then all data. I'm at a loss as to what the size of the packet returned from the Kangaroo should be. Is that always the same size or different from device to device? Should I ask Dimension Engineering what the size of the packet returned will be?

I'll try these new changes to see if the error stops popping up.

Thanks again. Smile

EDIT: What would happen and how would I change the script if I used the UARTReadAvailable( boardIndex, port ) command instead of the UARTRead( boardIndex, port, numBytes ) ? Looks like the first command gets all the bytes in the buffer instead of the latter command trying to receive a set amount. The error seems to happen if there are more then 8 bytes in the buffer. The print request will show 9, 12, or more bytes in there when the error happens. Does this mean the comm is saturated? If I use the UARTReadAvailable() with the Comm flooded will what is trying to be read unreadable?

#5

1) Always sleep() when looping

2) Because your code had an IF > 7, i assumed the packet size was 7. A packet is the minimum number of bytes that you require for the data.

3) Read Available will read all data that is available, but it may be more difficult to parse.

4) I have no idea what the data that you're reading looks like so it's difficult to assist with parsing. At this point, i can recommend adding a Sleep() in the loop. As for the parsing, that would be a different question requiring different information, such as example data and datasheets etc...

#6

Yes, Sorry. It's hard to answer questions if there is no info given to start with.

I simply want the script to know the position of the motor as reported by the Kangaroo from the encoder that it's connected to. So when I send the "getp" (Get position) command to the Kangaroo it will returns the channel number, followed by a comma, followed by a capital P if the move is completed or a lowercase p if the move is still going on, followed by the position in units (plain text) followed by a return and a newline. It will look like this in the control window:
1,p1235 or 1,P1235

I seemed to be having trouble with the script if it reads the whole returned value and if it was a P or a p returned. Perhaps the issue is the return and a newline value sent at the end that can't been seen? Don't know. Because of what I am doing I just really needed the number value. So I wrote a script to check to see if the return was a P (move completed) or a p (move still going on) and then it splits and reads just the numbers after the p or P and sets these numbers as a variable. I'll loop this whole thing till the variable reaches the target value and then a different script that is watching and waiting for this target will restart. This way the carriage wont start to retract into the robot's body until the arm is centered or the arm wont start to move up or down until the carriage is fully out of the robot's body. The carriage position script looks like this:

Code:


##this Script will return the actual position number
## from the Kangaroo without the 1,p in the beginning.
##Returning feedback with the 1,p causes problems.
##Do Not Delete. Other scripts depend on this script!

#-------------------------------------
# Get Roo position

uartWrite(2, 2, "1, Getp", 0x0d)

# :waitForData
Sleep(30)

$y = UartAvailable(2, 2)
Sleep(30)
print("Bytes in buffer: " + $y)

# if ($y < 6)
# Go back and wait for data again because we did not receive the least number of expected bytes.
# goto(waitForData)
# endif
Sleep(30)
$Get_Rt_Carrage_P = UARTRead(2, 2, $y)
Sleep(30)
print("Received:" + $Get_Rt_Carrage_P)

Sleep( 50 )

# -------------------------------
# Find out and print if the P is upper or lower case.
# Upper case means motor has finished move and stopped.
# Lower Case means that motor is still moving.

$P_or_p = GetCharAt($Get_Rt_Carrage_P, 2) #Assign a variable to either a capitol P or Small case p returned by Kangaroo.

Print("P_or_p: " + $P_or_p)

#-----------------------------
#Defeat the P_or_p

if ($P_or_p = "p")
Goto(Lower_p_Split)
ELSEif ($P_or_p = "P")
Goto(Upper_P_Split)
endif

Sleep( 50 )

:Lower_p_Split

$Rt_Carrage_Position = Split($Get_Rt_Carrage_P, "p",1) #1,pXXXX is returned. Get everything after the Lower case p (P is case sensitive).
Sleep(30)
print("Received:" + $Rt_Carrage_Position)
Halt()

:Upper_P_Split
$Rt_Carrage_Position = Split($Get_Rt_Carrage_P, "P",1) #1,pXXXX is returned. Get everything after the Upper case P (P is case sensitive).
Sleep(30)
print("Received:" + $Rt_Carrage_Position)