Okay, I am on deadline here.... 3 days... and for the last 2 weeks I have been trying to find the answer. Apparently there is no easy way to use a serial ports in VB2005 express... Most of the code I have found is for the .net version. It really doesn't port well. I have gone through and for the most part changed what needed to be changed. No Luck....
With the code written below that was copied and I duplicated the form to match the text, combo boxes and everything else it just doesn't want to work correctly. I am trying to write one byte of data to a processor and a few milliseconds later receive the response. the outgoing is the address of remote processor and the incoming is temperature data coming back, both one byte long that is the way the processor code is written. I figure i should be able to get this code working and just drop it all into my project for the most part but this doesn't even work..... Suggestions, comments or ideas......
Scott
'code starts here
mports System
Imports System.IO
Module Module1
End Module
Public Class Form1
Public Shared Function Hex(ByVal Number As Byte) As String
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
GetSerialPortNames()
'dtrenabled = True
Dim baudRate As Integer = 1200
Dim stopbits As System.IO.Ports.StopBits = IO.Ports.StopBits.One
Dim ports As String = "COM1"
Dim databits As Integer = 8
Dim parity As Boolean = False
'Dim com1 As System.IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort(ports, baudRate, parity, databits, stopbits)
'Console.WriteLine(Bite(0) & Bite(1) & Bite(2))
'Junk to stop the console closing
'Console.WriteLine("Press Enter/Return to close")
'Dim PressEnter As String = Console.ReadLine()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim stopbits As System.IO.Ports.StopBits = IO.Ports.StopBits.One
Dim Synk As Byte = 255
Dim Servo As Byte = 241
Dim MoveIt As Byte = 100
Dim Bite() As Byte = {Synk, Servo, MoveIt}
' Send commands to a serial port
Using com1 As IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort("COM1", 1200, IO.Ports.Parity.None, 8, stopbits)
com1.Write(Bite(0))
txttransmit1.Text = (Bite(0)) 'added to make sure the right numbers were going to serial port
com1.Write(Bite(1))
com1.Write(Bite(2))
End Using
End Sub
Sub GetSerialPortNames()
' Show all available COM ports.
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbcomport.Items.Add(sp)
Next
End Sub
Function ReceiveSerialData() As Byte
' Receive bytes from a serial port.
Dim sname As String
Dim returnStr As String
Dim retdata As Byte
sname = cmbcomport.Text
Using com1 As IO.Ports.SerialPort = _
My.Computer.Ports.OpenSerialPort("COM1")
Do
Dim Incoming As Byte = com1.ReadByte()
If Incoming Like Nothing Then
Exit Do
Else
returnStr &= Incoming
End If
Loop
End Using
retdata = CType("returnStr", Byte)
txtreceive1.Text = (retdata)
Return retdata
End Function
End Class

Serial communications outputting and receiving one byte of data.....
C_Portugal
If I should be able to help you finish your project before friday (one day), I need some informations.
Is the radio link full duplex or half duplex
In a half duplex system you will typical use the same radio frequency for transmission and reception. If you do that, the receiver may or may not receive both the transmissions (poll) from the SCADA system and the answer from the polled unit (temperature sensor). If the receiver receives the transmissions from the SCADA system (poll telegram), you must be sure that the receiver is able to distinguish between unit addresses and temperature values. This may create problems if you use all values from the A/D converter (00H to FFH) for temperature, but one byte for temperature in anyway oversimplified. You need at least 12 bits. If the receiver do not receive the poll telegram, there are two possibilities:
1) The polled unit transmits at least two bytes - one byte telling the address of the unit and one or more bytes for the temperature value. This is the preferred solution because it enables a completely asynchronous reception. In this case our program may be used with very few changes. You only need to remove the byte-to-hex conversion in the receiver, then collect one temperature value (one or more bytes) and send this package to the display routine. The display routine shall then convert the package to a temperature and then either append it to the text already in the text box (as in our program) or overwrite the content of the textbox. Note that also in this case the receiver must be able to distinguish between unit address and temperature value so that it is able to find the start of the telegram.
2) The program first sends the poll signal and then enter a loop with time-out, where it waits for the answer. In this case, you can combine everything in one subroutine and do not need multithreading. This may solve your problems in a simple way, but in a practical SCADA system this is not a very good solution because you cannot poll a new unit until you have received the answer from the first one, so if each unit do not answer immediately the system will be dead slow if there are hundreds of signals.
In a full duplex system you use two radio frequencies. Seen from the receiver this situation corresponds to half duplex with no loop-back.
gynther
That is what I thought that I shouldn't be opening it twice so I will get rid of that.
As for the data coming back it is one byte of data that represents a temperature. The send is the station ID of a remote station. We had originally wanted 4 stations each with a unique ID so the data would not get mixed up. The theroy here is that the program sends a station ID to the micro that sends it through an RF link to the remote stations. Depending on the station ID the correct will respond with a byte that represents the temperature measured by a sensor then converted from A to D and that data is sent back and displayed in a text box. The only thing coming out of the micro is a start bit, byte, stop bit. I would try to change it but the guy programming the micro has his own ideas and is causing me great headaches over it. This either a timed a event selectable by the user or a manual event by clicking a button.
The event handler OnDataReceived is the one that keeps me from getting this right. In two different versions of the program no matter what I did it came up as a Null exception and I couldn't find the documentation to explain what that actually was. I have looked a great deal. That would be great to get that operating then when it detects received data it brings the byte in. I had originally used com1. Readbyte but didn't seem to be working.
The reason for getting port IDs was so they could be displayed on the form I am using in the program to make it selectable if someone wanted to use an different com port but that isn't important, nice little feature for the user an option that doesn't need to be there.
So if I am understanding you correctly I can call my subroutine and do this to get the byte in.
dim com1 as object = serialport1
dim incoming as byte = com1.readbyte()
on your last comment about using the My.Computer.Ports.OpenSerialPort("COMx") I have looked at the code for your program but I am not sure how to change it. I have read about this on a couple of different sites one says that if you change it then there are certain events that won't be accessible and others say that you should change it to avoid possible conflicts with other programs.
Right now I don't care as I have to use a USB to Serial adapter because my laptop doesn't have serial port and I didn't realize this until a few weeks ago. You have to realize that I want is to get working to get it through the demo on friday morning.
Using the serialport control on the form, which is what I am using, I can adjust the readbuffer there.
arfried
I have now looked through your program more carefully.
Sorry to say it, but if you have only 3 days left I suggest you try to modify our program instead of trying to make yours own work! For example, you try to open the same port two places and you try to read the available com ports in the Form1_Load without using this information for anything. You must plan the software structure instead of just programming from one end.
And why do you want to receive when you press a button If you do that you will only be able to receive the number of bytes, which can be held in the receiver FIFO in the UART - if opening a port do not reset the FIFO! This is called "wash-machine programming" (everything in one order) and it do not belong in a multitasking environment. Besides, ReadLine only returns when a specified character (usually Line feed) is received. Are you sure your microprocessor sends this termination character
You also miss a little clean up when you close your program. If you do not do that the garbage collector in .NET may close the port for you while you still expect it to be open! Remember, this is managed code!
Besides, I will not recommend using My.Computer.Ports.OpenSerialPort("COMx") to open a serial port! If you do that you will not be able to test on .IsOpen, and you cannot set some properties like the receive buffer length.
Innovatic, Carsten Kanstrup
Rodrigo Landaeta
Imports System
Imports System.IO
Module Module1
End Module
Public Class Form1
Public Shared Function Hex(ByVal Number As Byte) As String
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
GetSerialPortNames()
'dtrenabled = True
Dim baudRate As Integer = 1200
Dim stopbits As System.IO.Ports.StopBits = IO.Ports.StopBits.One
Dim ports As String = "COM1"
Dim databits As Integer = 8
Dim parity As Boolean = False
'Dim com1 As System.IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort(ports, baudRate, parity, databits, stopbits)
'Console.WriteLine(Bite(0) & Bite(1) & Bite(2))
'Junk to stop the console closing
'Console.WriteLine("Press Enter/Return to close")
'Dim PressEnter As String = Console.ReadLine()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim stopbits As System.IO.Ports.StopBits = IO.Ports.StopBits.One
Dim Synk As Byte = 114
Dim Servo As Byte = 241
Dim MoveIt As Byte = 100
Dim Bite() As Byte = {Synk, Servo, MoveIt}
' Send commands to a serial port
Using com1 As IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort("COM1", 1200, IO.Ports.Parity.None, 8, stopbits)
com1.Write(Bite(0))
txttransmit1.Text = (Bite(0))
com1.Write(Bite(1))
com1.Write(Bite(2))
End Using
Return
End Sub
Sub GetSerialPortNames()
' Show all available COM ports.
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbcomport.Items.Add(sp)
Next
End Sub
Function ReceiveSerialData() As Byte
' Receive bytes from a serial port.
Dim sname As String
Dim returnStr As String = 0
Dim retdata As Byte
'sname = cmbcomport.Text
Using com1 As IO.Ports.SerialPort = _
My.Computer.Ports.OpenSerialPort("COM1")
Do
Dim Incoming As String = com1.ReadLine()
If Incoming Like Nothing Then
Exit Do
Else
returnStr &= Incoming
End If
Loop
End Using
retdata = CType("returnStr", Byte)
txtreceive1.Text = (returnStr)
Return retdata
End Function
Private Sub Button2_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
ReceiveSerialData()
End Sub
End Class
ZooDoo4U
Not suprising, it doesn't work. For one, ReceiveSerialData doesn't get called.
Even so, this is not the way to do things with any kind of communication port. The SerialPort has an event which is raised when data is received. You need to use that. You need to separate your data collection from your data analysis (however, the example you are presenting should be a trivial exersize to combine both).
In the DataReceived event you can read your byte(s) from the serial port buffer and deal with them as necessary. Note that you may receive one or more bytes so you have to handle that.
My recommendation at this point is to setup a link between two computers, using hyperterminal in the remote computer, to get a feel for using the serial port (and how to handle no connection, bogus data, an overload of data, etc.)
There's a fellow who posts here regularly who may chime in: in fact - do a quick search on serial ports: I think you'll find an answer.
keyosuke
One thing I should have mentioned about the micro that I am trying to get the data out of has only 6 i/o ports all one(1) bit wide. The data is transmitted down to a max rs-232 chip for processing to the correct voltage levels. The data has to be clocked out one bit ata time and the guy programming the micro has made the bits approximately 1ms wide so 1200 is my set speed.
What I meant for that is that I put in a 114 decimal and nothing was returned. Not even a partial hex number. 114 turns into 72 hex.
RaimondB
Our small program always interpret numbers as hex, so you cannot type in 114 decimal. There is no decimal to hex conversion. You must type in 72 instead, and all hex values must have an even number of digits. Note that because values are always hex, no hex specifier is used/necessary. It has fooled others than you!
With 1 mS per bit your speed is NOT 1200 bit/s, but 1000 bit/s, so it won't work! If you want to make a serial communication that way, there is no term like approximately. It must be precisely 0.833 mS for each bit. A serial communication is asynchronous and the start bit determine when to start the timing. If the last bit should be detectable in a reliable way, your clock inaccuracy should not be more than +/-2%! In practice, this is very difficult to obtain in a program. Just one interrupt or task switching and the telegram is destroyed. There is only one way to do it - use a hardware UART.
Innovatic, Carsten Kanstrup
jcnetdev
I tried that and it works as long as you have low numbers. I am trying to use hex data to begin with. Yes I have checked my hardware. I am looping back into the comm port right now... that all seems to work just fine. I will get the code go through but I get th datareceived at the end of the datareceived subroutine and it says it is not handled. I think I am outputting a signal now but nothing on the receive side of things.
Using the software you suggested......
CapitanDotNet
With you code here - you havent hooked up the any event handlers for the recieved data events.
I would suggest that the following has proved useful reading for others trying to use the Serial Port
I think looking at a sample program will give you a better understanding of this functionality.
And then maybe looking at the SerialPort class itself to understand further the way this simple app was constructed.
http://msdn2.microsoft.com/en-us/library/30swa673(vs.80).aspx
Chris W
The guy your talking about is Carsten Kanstrup who is a bit of an Expert on the serial port issues. The above link is to a web site he often points people towards.
Lots of positive response from those that have taken the time to look at the sample code.
JollyDMan
Tell me about it. I have tried to get him to change it but he is stubborn about it. I will have to talk to him some tonight. Also as a another note. when coding using "using com1 as .... end using I just found out that when that section is done it closes the com port. The way I found out is I removed the using statment from my receive data code and tried it and it threw an error "Port is Closed".
I am going to take a look at your code to see if there is a way to see how you are coding to determine what is in the receive buffer. Where I seem to hanging up is when I try to read the byte into the program. I am using returnStr=com.1.readbyte, it doesn't appear to work all that well. Unless I tell it to open the port the at some other point to keep it open while the program is running.
Majid8351
Hi all,
I'm new to VB and would like to ask wtfskh if he could post the receive portion of code when its working. Thanks in advance.
Ken
duggant
Are you sure your hardware properties for the serial port are set correct (not 7-bit data etc.), and that you have not selected hardware flow control without connecting the modem control signals (look at the control signal "lamps" to the right below the transmitter and the receiver fields)
Our small program works fine with all hex values from 00H to FFH - even up to 921.6 kbit/s, but of course there is always a possibility that I have made a bug. Can you explain "low numbers" a little better Remember that the program transmits hexadecimal numbers bigger than FFH with the big endian model, but this is the opposite of the little endian model used by Intel processors! Exactly, what are you typing-in in the transmitter field and what do you expect
The receiver routine is completely asynchronous with the transmitter, so everything received should be displayed in hex. Try to disconnect the receiver input shortly and see if you receive a "break". If not, use a voltmeter to see if you have any signal levels at all.
What do you mean with "I get th datareceived at the end of the datareceived subroutine and it says it is not handled" Do you get this message from the debugger In that case you have done something wrong. Download the original .exe file and see if this works.
Innovatic
Carsten Kanstrup
Rolan
Our program is actually reading one byte at a time by means of .ReadByte, and it puts the available COM ports into a ComboBox, so that the user can select the wanted port, so everything you need is right in front of your eyes! There are a lot of comments in the source code and a further description on the home page, so it should be quite easy to understand how the program works, and how you may change it to fit your needs. Just visit:
http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm
It is possible to make a software UART, if a hardware generated, very high priority interrupt is used for the bit timing, but to receive data you should oversample the signal at least 4 times (a hardware UART usually uses 16 times oversampling), so you need quite a high interrupt frequency, and the program will not be able to do much else than to handle the communication! If you only need a few bytes you may reduce the communication speed to e.g. 300 bit/s. This will ease the timing.
Best regards
Innovatic
Carsten Kanstrup