[RESOLVED] Serial Port Read Index Out Of Range Exception
Well, Hello. It's me again.
Consider a half-duplex modbus RTU serial communication between two devices which we want to only listen. A repeater.
Without any CRC/Checksum complexity, I stuck at the beginning. What is the best approach to do such thing?
Here's the code so far but making 2 bytes to an integer applies for first 8 bytes and then an exception will occur for line #30 which is comparing it is a HoldingRegister or not (Correct received package). I mean using Try/Catch will do the matter for first 8 bytes and continues the loop. I need the whole data. Any clues is precious. Thanks in advanced.
vb.net Code:
Public Class Form1
Private Buffer As Byte() 'I'M NOT SURE IT IS THE BEST WAY TO DECLARE A BYTE ARRAY WITH UNKNOWN/CHANGABLE LENGTH OR NOT
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Control.CheckForIllegalCrossThreadCalls = False 'FOR ERRORS FROM NOWHERE(?)
Try
If SerialPort1.IsOpen = False Then
SerialPort1.Open()
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
Application.Exit()
End Try
End Sub
Private Sub SerialPort1_DataReceived(sender As Object, e As IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
If BackgroundWorker1.IsBusy = False Then
BackgroundWorker1.RunWorkerAsync() 'IT'S GOING TO BE A VERY CROWDY CODE. LET THE BACKGROUNDWORKER DO THE LOOP THING FOR ME
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim byteCount = SerialPort1.BytesToRead 'GET INPUT BUFFER SIZE
If SerialPort1.BytesToRead > 8 Then 'IGNORE BLANK AND NOT REQUEST COMMANDS (GET ONLY ANSWERS FROM SLAVES. REQUEST COMMANDS ARE 8 BYTES)
buffer = New Byte(byteCount) {} 'EXTEND VARIABLE/ARRAY AS IT IS
SerialPort1.Read(Buffer, 0, byteCount) 'READ SERIAL PORT FUNCTION
Dim UserControl as UserControl() = {UserControl1, UserControl2, UserControl3, UserControl4, UserControl5, UserControl6, UserControl7, UserControl8, UserControl9, UserControl10, UserControl11, UserControl12, UserControl13, UserControl14} 'THERE ARE 14 USERCONTROLS WHICH SORTING VALUES IN THEM IS REQUIRED
If Buffer(1) = 3 And Buffer(2) = 192 Then 'CORRECT PACKET(S) INCOMING
If Buffer(0) = 2 Then 'FIRST PARAMETER
For i = 0 To 29 Step 2 'ARRANGING/ASSIGNING VALUES IN THEIR PLACES FOR 14 USERCONTROLS
UserControl(i/2).TextBox1.Text = (Val(Buffer(i+3)*256) + Val(Buffer(i+4)) 'COMBINE 2 BYTES => INTEGER
Next
End If
'If Buffer(0) = 3 Then 'SECOND PARAMETR
''SAME AS ABOVE
'End If
'.
'.
'.
'If Buffer(0) = n Then 'LAST PARAMETR
''SAME AS ABOVE
'End If
End If
'POSSIBLE 'BUFFER' DISPOSE/CLEAR CODE GOES HERE WHICH I DON'T KNOW HOW TO DO IT
End If
End Sub
End Class
Exception full message:
IndexOutOfRangeException was unhandled by user code: Index was outside the bounds of the array.
Re: Serial Port Read Index Out Of Range Exception
check for the value of bytecount and SerialPort1.BytesToRead
by the way, you don't need bytecount, you can replace it everywhere by SerialPort1.BytesToRead,
check buffer after line 27, you may read nothing
Re: Serial Port Read Index Out Of Range Exception
Quote:
Originally Posted by
Delaney
check for the value of bytecount and SerialPort1.BytesToRead
Hum, Is it possible that my stream broken or delayed a few milliseconds?
Quote:
Originally Posted by
Delaney
by the way, you don't need bytecount, you can replace it everywhere by SerialPort1.BytesToRead,
I remember I used all as SerialPort1.BytesToRead once and it didn't work. That's why, but when you say so, I will follow. I remember you sir from lots of SerialPort threads. Merci beaucoup
Quote:
Originally Posted by
Delaney
check buffer after line 27, you may read nothing
Is there any debugging tool included in Visual Studio? I believe I saw a list of parameters/variables below the screen. Buffer length was 2. Bingo, You might be exact on faultfinding. I'm going to check it.
You already read the whole code? Could it be something else?
I used SerialPort1_ReceivedData event. How can I switchover on something that waits to get like 300 bytes then take action? Legendary timers came to my head at the beginning why? because input buffer may be fully received and raw data ready to be processed. (Relax, my read data cycle is too slow)
Or how about increasing BytesToRead condition on equal and greater than an acceptable value like If SerialPort1.BytesToRead > 300 Then in line #23?
Re: Serial Port Read Index Out Of Range Exception
Re: Serial Port Read Index Out Of Range Exception
Quote:
Is there any debugging tool included in Visual Studio?
there are 3 ways:
1 - you include some messagebox with the variable to check it
2 - you click on the grey column on the left of the column with line number (must be a line with code), a red dot will appear and it will put a stop in you code when you run it and you will be able to check the values of the variable
3 - put the keyword "stop" in you code. it does the same than the red dot.
1 Attachment(s)
Re: Serial Port Read Index Out Of Range Exception
Quote:
Originally Posted by
dbasnett
See this post and also the link contained in it.
It is a bit complicated sir. But one of its advantages is "Dim readBuf(TheSP.BytesToRead - 1) As Byte".
Exception now occurs here:
Attachment 185073
I only acknowledged that my index=14 (in Buffer(index+4)) exceeds Buffer.Length=16 and causing error but not sure what to do.
What are my options?
Re: Serial Port Read Index Out Of Range Exception
the picture is small, so we can barely see anything.
you need to think a little bit about what you do : why your index should go over the buffer length? I saw that you coded the upper limit of the index (20 or 29, i can't see well) where you should have a limit linked to the buffer length: for index =0 to buffer.length-4 step 3...
Re: Serial Port Read Index Out Of Range Exception
Well, it turned out data stream was broken to pieces based on a port spy app monitored (still not sure why. Maybe timeout/nulldicard/Readbuffersize or other SerialPort control parameters) Mimicking a code in which be looking for an exact combination of bytes and extracting them from a random stream, Rectifies the matter.
Here the index in outer "for" called 'j' will be followed by another index which represents buffer subset current position:
vb.net Code:
'LOOP START
Dim UserControl as UserControl() = {UserControl1, UserControl2, UserControl3, UserControl4, UserControl5, UserControl6, UserControl7, UserControl8, UserControl9, UserControl10, UserControl11, UserControl12, UserControl13, UserControl14}
Dim Buffer(SerialPort1.BytesToRead -1) As Byte
SerialPort1.Read(Buffer, 0, Buffer.Length)
Try
For j = 0 To Buffer.Length
If Buffer(j) = 3 And Buffer(j + 1) = 192 Then
TextBox1.Clear()
If Buffer(j - 1) = 2 Then
TextBox1.text = TextBox1.text & "PARAMETER="
For i = j + 2 to 29 Step 2
TextBox1.text = TextBox1.text & (Buffer(i)*256) + Buffer(i + 1) & ", "
UserControl((i - 3)/2).Label1.Text = (Buffer(i)*256) + Buffer(i + 1)
Next
End If
End If
Next
Catch ex As Exception
End Try
'LOOP END