Hi there
I've come up with a routine that performs a serial read using the Win32:SerialPort library for a script I am writing.
My issue is that everytime I run the script my output for the @buffer array is not completely what I expect. The size of the buffer is maximum of 80 bytes, any data beyond this point is ignored unless the 80 bytes collected do not include the packet of interest of which the collected data are disposed of and new data coming is stored.
I am using a program called Docklight to simulate a serial port and test out various conditions for a packet that is built up of only
[STX|VARIABLE PAYLOAD|ETX]. They are:
* STX / ETX have been found, example: 02 30 39 44 CE26 03
* > 80 bytes received on the serial line
* > 80 bytes received but no STX/ETX needed packet found
* A NAK was received
Ideally a packet of the type described in the first condition is needed, the other packets tested for the other conditions are ignored and the test for the right packet type is resumed again.
My problem is that all of this is working just fine however if I send in any condition(s) other than the correct first one...and then I sent the proper condition at the end my results for the @buffer are like:
G “GC(G 4 4L2[STX09DÎ&ETX]
The part of the packet I've highlighted in brackets is the correct packet of interest. The data in front is junk and of which I don't need. The more error conditions that I test for (that is, send the error ridden packets) before I send the correct packet the more junk I get in front of the correct packet.
However if I just submit the correct "condition" and not test out the other problematic scenarios I get the proper packet return with no junk in front:
[STX09DÎ&ETX]
here's my serial read code:
sub readSerialPort
{
my $stx_rx = 0;
my $etx_rx = 0;
my $nak = 0;
@buffer = (); # Empty the buffer before the next packet read
while ((!$etx_rx) || ((!$etx_rx) && ((scalar(@buffer) > 79))))
{
$byte=$port->read(1);
if (ord($byte) == 0) #if it's a space, skip
{
next;
}
if (($byte eq chr(0x15) && (scalar(@buffer) < $MAX_BUFFER))) #
+ if a NAK is found anywhere and the buffer is not filled yet
{
print "\nNAK was found! " . $byte . "\n";
$nak = 1;
$retry_if_fail = 1; # Flag to tell the script to continue wa
+iting for the proper packet after buffer reset
print "\nRetry var changed to " . $retry_if_fail . "\n";
STDOUT -> flush();
print "BUFFER RETURNED WITH NAK => " . @buffer . "\n\n";
return;
}
if ($byte eq chr(0x02)) # if it's STX run this condition
{
$stx_rx = 1;
print "\nSTX was found! " . $byte . "\n";
}
elsif (($stx_rx == 1) && ($byte eq chr(0x03))) # if both the S
+TX and ETX are found
{
print "\nETX was found! " . $byte . "\n";
$etx_rx = 1;
$retry_if_fail = 0; # Zero indicates the SUCCESS condition
STDOUT -> flush();
print "BUFFER RETURNED AT ALL OKAY => " . @buffer . "\n\n";
print "BUFFER RETURNED AT ALL OKAY => " . join("",@buffer)
+. "\n\n";
}
if (($stx_rx == 1) && ($etx_rx == 0) && ((scalar(@buffer) > ($
+MAX_BUFFER-1)))) # if only STX was found within 80 bytes
{
print "\nOnly STX was found! " . $byte . "\n";
$retry_if_fail = 1; # Flag to tell the script to continue w
+aiting for the proper packet after buffer reset
print "\nRetry var changed to " . $retry_if_fail . "\n";
STDOUT -> flush();
print "BUFFER RETURNED WITH ONLY STX => " . @buffer . "\n\n
+";
return;
}
if (($stx_rx == 0) && ($etx_rx == 0) && scalar(@buffer) > ($M
+AX_BUFFER-1))
{
print "\n80 bytes seen but no STX/ETX was found within 80
+byte range! " . $byte . "\n";
$retry_if_fail = 1; # Flag to tell the script to continue
+waiting for the proper packet after buffer reset
print "\nRetry var changed to " . $retry_if_fail . "\n";
STDOUT -> flush();
print "BUFFER RETURNED with no STX or ETX=> " . @buffer .
+"\n\n";
return;
}
push(@buffer, $byte);
#if($retry_if_fail == 0) {
# until (@buffer eq chr(0x02))
# {
# shift(@buffer);
# }
# return @buffer;
#}
print "Contents of buffer is " . join("",@buffer) . "\n";
print "Buffer length is " . scalar(@buffer) . "\n";
print "Byte received : ".$byte."\n";
}
}
while(1)
{
STDOUT -> flush();
if ($retry_if_fail == 1)
{
# FAILED CONDITION
readSerialPort();
print "Total Received Packet on failure was: " . join("",@buffer) .
+ "\n\n";
print "Error encountered! Continuing to look for incoming packets.\
+n";
}
else
{
# SUCCESS CONDITION
print "Okay cool I found what I was looking for -> " . @buffer . "
+\n\n";
print "Okay cool I found what I was looking for -> " . join("",@bu
+ffer) . "\n\n";
$retry_if_fail = 0; # Time to exit this loop and get on with life!
+!
last;
}
}
All advice appreciated guys! I've tried out various ways to remove the junk data that's in front of the correct packet but to no avail. I need the packet of interest (of type: STX_PAYLOAD_ETX) without any junk on the side for processing.
Ideally I want it so that the junk data is not stored at all in the buffer and only the correct packet is stored however I am having trouble in getting this to work.
Thank you
EDIT: What I have noticed is that reducing the value of $MAX_BUFFER (set to 80) appears to reduce the amount of junk in front however I think for me this is not an option since I need this variable to be at 79/80 for my "conditions checks" to take place properly.
EDIT2: Screenshot of error:
http://i50.tinypic.com/eki1yg.png
The data circled in red is the junk data whereas the data on the right of it is the packet of interest.