reading data from serial port
I am trying to read the following data from 4 serial ports in VB.Net 2012
00056
00056
00056
00056
00056
Its 5 lines of data. The starting digit is a space and there are five digits after the space. I have tried so many different code but none has worked. I have searched only and had no success. All the samples I have seen talks to only one serial port. My newest code is as follows which I got from a Microsoft website. If I call this function 4 times will it work?
Code:
Public Function ReceiveSerialDataPort8() As String
' Receive strings from a serial port.
Dim returnStr As String = ""
Dim com1 As IO.Ports.SerialPort = Nothing
Try
com1 = My.Computer.Ports.OpenSerialPort("COM8", 9600, Parity.None, 8, StopBits.One)
com1.ReadTimeout = 10000
Do
Dim Incoming As String = com1.ReadLine()
If Incoming Is Nothing Then
Exit Do
Else
returnStr &= Incoming & vbCrLf
End If
Loop
Catch ex As TimeoutException
returnStr = "Error: Serial Port read timed out."
Finally
If com1 IsNot Nothing Then com1.Close()
End Try
Return returnStr
End Function
Thanks,
Shaminda
Re: reading data from serial port
No.
If you want to read from four serial ports, then you will have to open and read from four serial ports.
You only show reading from one serial port, COM8.
What are the other three serial ports, I would presume possibly COM9, COM10 and COM11.
You can query the SerialPort object and create a list of Com ports, along the lines of
Code:
For Each s In SerialPort.GetPortNames()
availPortNames(i) = s ' save the portnames found, so the GUI can display them later
'...
If your code is successfully reading from one port now, you just have to do the same for the other three ports.
In my case, I just set up an array of SerialPort objects
Dim _serialPort(3) As SerialPort
that way I can loop through the array to Send Data to each. In my case I didn't have to read, so don't have an example of handling multiple Reads (at least not in .Net).
Re: reading data from serial port
It will also depend on if the data is even there... I could be wrong, but what ever is on the other end, is going to send the data... if the port isn't open when the data is recieved, then it's lost. It has no where to go. If you send out a command and get a response, then that's different. but as the code is now, it's expecting the data to be sent unprompted. given that, the serial port objects should be wired up to event handlers so that when the data does come in, you can then capture it.
But I don't do serial communication, so I could be wrong about this.
-tg
Re: reading data from serial port
Here's something that should help you out a lot. It's one of the Serial Port controllers I use. I made an example of creating 4 of them attached to COM8 through COM11.
First, make a new Class object called SerialController.vb Copy-paste in the code below:
Code:
Imports System.IO
Imports System.Text
Public Class SerialController
Private WithEvents sPort As New Ports.SerialPort
Private WithEvents tmrCommandDelay As New Timer
Private queueSend As New Queue(Of String)
Private rcvQ As New StringBuilder
Private rcvQLock As New Object
Public Event DataReceived(sender As Object, e As DataReceivedEventArgs)
Private strID As String
Public Property ID() As String
Get
Return strID
End Get
Set(ByVal value As String)
strID = value
End Set
End Property
Public Sub New(ID As String)
Me.ID = ID
tmrCommandDelay.Interval = 100
End Sub
Public Function OpenSerialPort(port As String, baud As Integer, parity As Ports.Parity) As Boolean
Try
With sPort
.BaudRate = baud
.PortName = port
.DataBits = 8
.Parity = parity
.StopBits = IO.Ports.StopBits.One
.ReadTimeout = 500
.WriteTimeout = 500
.DiscardNull = False
.ReadBufferSize = 16384
End With
If Not sPort.IsOpen Then
sPort.Open()
End If
Return True
Catch ex As Exception
If ex.Message.Contains("Access") Then
'TODO - Do something if it is Access to the port 'COM#' is denied. message comes up.
Else
End If
Return False
End Try
End Function
Public Sub WritePort(ByVal str As String)
Try
queueSend.Enqueue(str)
If Not tmrCommandDelay.Enabled Then tmrCommandDelay.Enabled = True
Catch ex As Exception
End Try
End Sub
Private Sub tmrCommandDelay_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrCommandDelay.Tick
Try
If queueSend.Count.Equals(0) Then
tmrCommandDelay.Enabled = False
Else
Dim strX As String = queueSend.Dequeue.ToString & Environment.NewLine
sPort.Write(strX)
End If
Catch ex As Exception
End Try
End Sub
Private Sub sPort_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles sPort.DataReceived
Try
'Use "10" if the line ends with a NewLine or "13" if it ends with a CarriageReturn.
'This will deped on what's sending the data though. Typically, when something sends both, it sends it NL+CR.
'If data is streaming like from a weigh-scale, use the frame-finding/locking version SerialStreamController.
Dim o As Byte = 10
Dim c As Char = Convert.ToChar(o)
If sPort.BytesToRead = 0 Then Exit Sub
Dim bytsToRead As Integer = sPort.BytesToRead
Dim buf(bytsToRead - 1) As Byte
bytsToRead = sPort.Read(buf, 0, bytsToRead)
Threading.Monitor.Enter(rcvQLock)
Try
rcvQ.Append(Encoding.ASCII.GetString(buf))
Finally
Threading.Monitor.Exit(rcvQLock)
End Try
While rcvQ.ToString.Contains(c)
Dim l As Integer = rcvQ.ToString.IndexOf(c)
Dim ca(l - 1) As Char
Threading.Monitor.Enter(rcvQLock)
Try
rcvQ.CopyTo(0, ca, 0, l - 1)
rcvQ.Remove(0, l + 1)
Finally
Threading.Monitor.Exit(rcvQLock)
End Try
RaiseEvent DataReceived(Me, New DataReceivedEventArgs With {.Data = New String(ca)})
End While
Catch
End Try
End Sub
Public Sub CloseSerialPort()
Try
If sPort.IsOpen Then
sPort.Close()
End If
Catch ex As Exception
End Try
End Sub
End Class
Public Class DataReceivedEventArgs
Inherits EventArgs
Public Data As String
End Class
Make a Form, put a ListBox on it to see results. Copy the methods below into it:
Code:
Private serialDataInputs As New List(Of SerialController)
Private Sub Form_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
For Each sc As SerialController In serialDataInputs
sc.CloseSerialPort()
Next
End Sub
Private Sub Form_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim sc As SerialController
For i As Integer = 8 To 11
Dim strComPort As String = "COM" & i
sc = New SerialController(strComPort)
AddHandler sc.DataReceived, AddressOf sc_DataReceived
sc.OpenSerialPort(strComPort, 38400, IO.Ports.Parity.None)
Next
End Sub
Private Sub sc_DataReceived(sender As Object, e As DataReceivedEventArgs)
Dim ID As String = DirectCast(sender, SerialController).ID
AddOutput(String.Format("Received from {0}: {1}", ID, e.Data))
End Sub
Private Delegate Sub TextDelegate(s As String)
Private Sub AddOutput(s As String)
If ListBox1.InvokeRequired Then
Dim d As New TextDelegate(AddressOf AddOutput)
ListBox1.Invoke(d, {s})
Else
ListBox1.Items.Add(s)
End If
End Sub
In this example, I make a new "List" of my SerialController objects. Each SerialController handles a single COM port. When the form loads, I assign these COM8 through COM11, set the baud rate to 38400 and Parity to None. Adjust these to your needs.
If you want, you could also just make 4 individual SerialController objects.
Each SerialController has a "DataReceived" event that only fires when the serial port gets a whole "block" of data; i.e. data ending with a New-Line (CHR(10)).
If you need help with any of it, toss a reply. As someone else who works in Ohio where there's plenty of manufacturing and plenty of industrial systems with serial-port communication, I've had a long time to get pretty good at it. :D
Re: reading data from serial port
I thought I could do this without using delegates or datarecieve event, I guess I was wrong. It is on a production machine I am trying to read data from and I have limited access to the machine. My com ports are Com8, Com9, Com10, Com11. I am trying to first read the data to string variables and then display the data to four text boxes. Instead of list box how would I use four test boxes.
Re: reading data from serial port
Replace these two functions:
Code:
Private Sub sc_DataReceived(sender As Object, e As DataReceivedEventArgs)
Dim ID As String = DirectCast(sender, SerialController).ID
AddOutput(ID, e.Data)
End Sub
Private Delegate Sub TextDelegate(port As String, s As String)
Private Sub AddOutput(port As String, s As String)
If TextBox1.InvokeRequired Then
Dim d As New TextDelegate(AddressOf AddOutput)
TextBox1.Invoke(d, {port, s})
Else
Select Case port
Case "COM8"
TextBox1.Text = s
Case "COM9"
TextBox2.Text = s
Case "COM10"
TextBox3.Text = s
Case "COM11"
TextBox4.Text = s
End Select
End If
End Sub
Re: reading data from serial port
Quote:
I thought I could do this without using delegates or datarecieve event, I guess I was wrong
You can, but it would require a master/slave relationship between your program and your device(s). You essentially, ask the device for specific information, wait for an amount of time that it would take for the device to respond, then read the serial port. If nothing is there, you have a timeout. This is how RS-485 networks run.
Typically handling the data received event is the best way to go because your app is not wasting time waiting for the response, but sometimes having asynchronous communication can make it more difficult if in some case not even usable.
Re: reading data from serial port
Jenner, Thank you very much for your help! It worked. The only thing different I had to do is I had to break down the for loop and call four different statements. But I do have one more question. On and off the serial port spits out data like this:
005%0 OK
00567 OI
How can I capture only the good data? A serial port always spits out 5 lines of data and I am only reading the first line. Here is a sample of data:
ÿÿÿ 00573 OK
00%73 OK
00573 OK
00573 OK
00573 OK
Re: reading data from serial port
The "%" in there looks like something weird going on for the incoming data. You might have to write some type of data validation routine that takes the incoming data and verifies it's in the proper format before proceeding.
Are the incoming serial messages repeating or a one-time event? If they're repeating, or missing a frame of data isn't crucial, then you can just wait for the next one to come in. If it's a one-time event, then you might have to tweak whatever is sending the data if you can.
I've frequently had to change PLC logic to use some type of "Here it is->Ok, I got it" protocol with a timer that repeats the data being sent if it doesn't get the "Ok, I got it" response. Another option is to try to write in some "data correction". You obviously know:
ÿÿÿ 00573 OK
should be:
00573 OK
So have it look for a pattern of "##### OK". This is where you'd be using "Regular Expressions" and best the subject of another post, but they have the ability to match patterns and extract only the data that matches the pattern.
The 00%73 OK is more difficult, and more troubling. Why the system is sending a byte for a % instead of a byte for a 5 is something you'll need to investigate.
Re: reading data from serial port
Quote:
Originally Posted by
shaminda
Jenner, Thank you very much for your help! It worked. The only thing different I had to do is I had to break down the for loop and call four different statements. But I do have one more question. On and off the serial port spits out data like this:
005%0 OK
00567 OI
How can I capture only the good data? A serial port always spits out 5 lines of data and I am only reading the first line. Here is a sample of data:
ÿÿÿ 00573 OK
00%73 OK
00573 OK
00573 OK
00573 OK
I'd check that the speed, databits, stopbits, and parity of the sender and receiver match. Also check the connections and ensure that the cable is in good condition. If this is an electrically noisy environment you might need to use a shielded cable.
Re: reading data from serial port
Quote:
Originally Posted by
dbasnett
I'd check that the speed, databits, stopbits, and parity of the sender and receiver match. Also check the connections and ensure that the cable is in good condition. If this is an electrically noisy environment you might need to use a shielded cable.
Please help. I'm newbie, i use also that code to read serial port but nothing happened. what's wrong with my program?
Dim returnStr As String = ""
Dim com5 As IO.Ports.SerialPort = Nothing
Try
com5 = My.Computer.Ports.OpenSerialPort("COM5")
com5.ReadTimeout = 10000
Do
Dim Incoming As String = com5.ReadLine()
If Incoming Is Nothing Then
Exit Do
Else
returnStr &= Incoming & vbCrLf
MessageBox.Show("Sample")
End If
Loop
Catch ex As TimeoutException
returnStr = "Error: Serial Port read timed out."
Finally
If com5 IsNot Nothing Then com5.Close()
End Try
Re: reading data from serial port
Welcome to VBForums :wave:
There are a wide variety of things that could be going wrong, so it is important to work out what the actual problem(s) are, which you can do by debugging (set a breakpoint on the Try line, then step through the code to see what is happening).
There is a tutorial on debugging here:
https://docs.microsoft.com/en-gb/vis...h-the-debugger
Re: reading data from serial port
Okay sir, i'll update you with my program. Please help me
Re: reading data from serial port
We can't help without knowing what the problems is... my previous post explained how you can find out what the problem is, and once you tell us we can help you solve it.
I realise that debugging may be new to you, but it isn't as hard as people expect it to be, and the tutorial should be enough for you to work it out.
The alternative is to keep searching for examples until you find one that works first time, which isn't very likely to succeed.
Re: reading data from serial port
Quote:
Originally Posted by
si_the_geek
We can't help without knowing what the problems is... my previous post explained how you can find out what the problem is, and once you tell us we can help you solve it.
I realise that debugging may be new to you, but it isn't as hard as people expect it to be, and the tutorial should be enough for you to work it out.
The alternative is to keep searching for examples until you find one that works first time, which isn't very likely to succeed.
Sir, as you can see on my program i used a messagebox to test if my peripheral device sends data. the problem is, i don't know if my peripheral device sends a data or there's something wrong on my program. sir, do you think there's something wrong on my program? Thankyou sir. please help me.
Re: reading data from serial port
Quote:
do you think there's something wrong on my program?
At the moment I can only guess what the problem is (and less accurately than you), so the chances of finding a solution are very low.
You can find out what the problem is by debugging as described above, I'm afraid that doing anything else is wasting your time and ours.
Re: reading data from serial port
Hi, it helps when you know the type and the format of the data you expect to receive, can you elaborate on the data. From what you have said so far it is looking like a string terminated with a newline character, can you confirm that.
The configuration of the receiving port should match the configuration of the transmitting device in most respects, especially in respect with the baud rate, can you give a few more details of the transmit device and the configuration of your receive port.
The serial port should be open and initiated well before you try and receive/send data, don't try to open and close the serial port for each data packet.
If you can fill in a few of the blanks it may be possible to provide a generic serial port reader to help you get started.
Re: reading data from serial port
Sometimes, as a first step, when I'm starting a connection to a new device, I like to use a terminal program like putty to see if can see any data coming from the serial port. That way I can concentrate on possible issues like hardware connections, i.e. transmit and receive pins being reversed from what might be expected. Once I know the physical connection is correct, and the baudrate and handshake values are known, and that the device is transmitting data, then I try to interface with my code, knowing that if I don't see something then it is likely some setup with my code, or the code itself, rather than start off wasting time troubleshooting code when the problem was external to the code.
Re: reading data from serial port
Quote:
Originally Posted by
passel
Sometimes, as a first step, when I'm starting a connection to a new device, I like to use a terminal program like putty to see if can see any data coming from the serial port. That way I can concentrate on possible issues like hardware connections, i.e. transmit and receive pins being reversed from what might be expected. Once I know the physical connection is correct, and the baudrate and handshake values are known, and that the device is transmitting data, then I try to interface with my code, knowing that if I don't see something then it is likely some setup with my code, or the code itself, rather than start off wasting time troubleshooting code when the problem was external to the code.
thankyou for your advice passel, about the putty. can i use the real term application to test my peripheral device? please help me, sorry for the bothering you guys. thankyou and godbless
Re: reading data from serial port
Hi sir, i tested my peripheral device on putty and it display random characters like "-", " *space* ", etc. now, my program should display a messagebox if there is a data read by the vb but the messagebox did not display. is there something wrong in my program? pls help me. i badly need your help guys
Re: reading data from serial port
Well, the putty experiment would suggest that your vb code does have some problems, and I'm not surprised because of what it is doing.
Now that putty has confirmed that your device is sending data over the serial port, the next question is do you know what the format of that data is (and that was already mentioned above).
Your code is doing a ReadLine, which would mean that you would be expecting the device to be sending text and that the text would end with a newline character sequence which would terminate the ReadLine call, returning the line of text read from the serial port.
What you're showing in the putty window, to me, would indicate that you are probably not sending lines of text from the device, or that you might not have the port configured correctly (i.e. the baud rate is incorrect, or the pattern of bits that are used to transmit a byte of data (e.g. 8n1, or 7e2, etc) may not be correct.
Do you know for sure what the baud rate of the device and the format of the byte transfer pattern should be.
And then, do you know the structure of the data that is being send, i.e. is it a stream of bytes that represent ASCII text, or a stream of bytes that represent some other defined data structure.
For a quick test to see if you're getting any data would probably change the ReadLine to ReadExisting and see if you get your messageBox.
The code you've posted doesn't make a lot of sense as it stands, as you've evidently only posted part of the routine the code is from. The code has evidence it should be part of a function (the Return statement), but you don't show that it is in a function or how it is called. The code will need to be revamped eventually, as you should be doing the receive in a background manner (i.e. using the ReceivedData event, or reading in a background thread) rather than polling with a timeout.
I don't have time to go into it now, and the subject has been covered many, many times already so there should already be instructions and examples to choose from, but go ahead and change the ReadLine to ReadExisting in your current code to see if you get the msgbox or not.
Re: reading data from serial port
sir, i already solved my problem on receiving data from the coin acceptor using Realterm serial communication. i set my coin acceptor to display "1" if i insert a coin. my problem is, i don't know what's wrong on my program. i already checked the parity, data bits and etc. but still i can't receive the data from the coin acceptor. my program can identify the coin acceptor's comport. please help me to retrieve the data when inserting the coin. my program:
Imports System
Imports System.IO.Ports 'To Access the SerialPort Object
Module SerialCommRead
Sub Main()
Dim MyCOMPort As SerialPort
Dim PortName As String
Dim BaudRate As Integer
Dim DataReceived As String
Dim AvailablePorts() As String = SerialPort.GetPortNames()
Console.WriteLine("Available Ports ::")
Dim Port As String
For Each Port In AvailablePorts
Console.WriteLine(Port)
Next Port
Console.WriteLine()
Console.WriteLine("Enter Your Port ->")
PortName = Console.ReadLine()
Console.WriteLine("Enter Baudrate ->")
BaudRate = Convert.ToInt32(Console.ReadLine())
MyCOMPort = New SerialPort()
MyCOMPort.PortName = PortName
MyCOMPort.BaudRate = BaudRate
MyCOMPort.Parity = Parity.None
MyCOMPort.DataBits = 8
MyCOMPort.StopBits = StopBits.One
MyCOMPort.Open()
Console.WriteLine("Waiting for Data to be Received")
DataReceived = MyCOMPort.ReadLine()
MyCOMPort.Close()
Console.WriteLine()
Console.WriteLine("Data received -> {0}", DataReceived)
Console.WriteLine("+---------------------------------------------+")
Console.ReadLine()
End Sub
End Module
Re: reading data from serial port
You didn't change ReadLine to using ReadExisting. Give that a try and see if you get any response.