I am using a windows form application to interface with an arduino to turn on & off items mostly in my large garage - 2 light banks, furnace, compressor, 3 garage doors,... 12 buttons in all. I am starting the code for just 1 button to simplify things, then will expand to 12. I will put the code I came up with, along with an article on comp control where I got the idea, & pics of my hardware so far. I really do want to learn to do this, so I'm not asking for the code to be written, just let me know my mistakes & point me in the right direction! Any & all input will be greatly appreciated, I'm really excited about completion!
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
On Error Resume Next
Dim SerialPort1 As Integer
Dim Write As Object
Dim onstate, outstring As Integer
onstate = 0
If Button1.Text = "Pin 6 on" Then
Button1.Text = "Pin 6 off"
onstate = 1
outstring = "!"
End If
If Button1.Text = "Pin 6 off" And onstate = 0 Then
Button1.Text = "Pin 6 on"
outstring = "$"
End If
'SerialPort1(Write(outstring))
End Sub
End Class
in the hardware pic, the small enclosure is a 13A 5V power supply so I can run inexpensive low voltage lines to electrical boxes with 5V relays doing the work. the middle enclosure is where the low voltage lines will hook up. there is an outlet on top, because they will be situated next to the furnace which currently plugs into a wall outlet - it will plug there. the third enclosure houses the Arduino, 9V supply for it, & relay banks that the arduino controls via VB, those relay leads go to the middle box & out to the remote relays. there is a 70' amplified USB cable running from my office to the Arduino in the garage unit. It's all very workable, I'm just new at VB & unsure of what i'm doing, but the attached article does a good job of explaining the interface. Please help!! I know there are many with a great amount of expertise out there... all I ask is that you poin me in the right direction!
. thank you for your time & patience, I know this is a long read!!
Which version of VB/VS are you using. There are VB6 statements in your code. If that's right then this should be asked in the appropriate forum section.
I am using Visual Basic Express 2110. I told you I was a newbie, but had no idea I was that out of whack lol! can you give me some pointers, please? I'm currently taking VB courses every spare moment, & the more I learn, it seems the more I'm lost! I have great respect for those of you who do this every day - gotta be bright obviously! It does seem to me that what I'm after is a relatively (for one such as yourself) easy program - I hope... any assistance would be appreciated more than you could know! I've got a lot of time & cash into it already, and am anxious to see it work!!! thank you for your time... !
I think you are working on an excellent project, and I encourage you to stick with it. I work on some robot code as a hobby, and am vaguely familiar with the arduino (basically, I know that it exists and that's all). That may not make any difference. As far as I am concerned, the first step should be to get some communication going, as the rest is all gravy. If you can demonstrate that you are able to read and write to the device, you have crossed the biggest technical hurdle, and everything else is the fun (though occasionally frustrating) part of putting your imagination into practice. So, first off, can you say whether or not you have had any communication with the device through code?
As for the code, you used On Error, which is archaic VB6 error handling. The proper approach in .NET (which is what you are using) is to use a Try....Catch block. You also don't want to be doing any Resume Next, but if you switch to Try...Catch, you won't The equivalent using Try...Catch would be to have an empty Catch block, but that would just be shooting yourself in the foot. If an exception occurs, you want to know about it, even if you can't do anything about it. Therefore, if nothing else, put a messagebox in the Catch block and show the exception message.
The next thing I note is that you have a variable named SerialPort1 which is bizarrely declared as type Integer. I suspect that you really WANT that to be a serial port. There is a type in .NET for that. Better yet, there are dozens of threads on serial port communication on this forum. Unfortunately, the software has just been changed over, and I can't say whether or not the Search feature is working correctly, yet. The last time I tried it, it was not, but that was more than a week ago. If it isn't working yet, you can be certain that it will be soon.
One other suggestion would be to look into RadioButtons rather than buttons. I would expect that you will end up with a few of them, and it all comes down to what feels best to you. The RadioButton does what you want as far as giving some feedback, whereas you have to change the text and backcolor of the button to get it to do the same thing. Therefore, the RadioButton may suit you, but I should also note that I often use buttons the way you are using that one (though I like to change the color, too), so it is a matter of personal opinion.
Shaggy Hiker; thank you so much for your response! I'm not quite sure what you mean by success,I am proficient at programming arduino's & have used them for many things. As for the VB code, no success yet communicating with the arduino.I will switch to try catch(& am spending every spare moment at VB courses). I will research the types for serial port - I'm beginning to believe that's where my problem is! I will definitely check the threads on this forum relating to it.(I declared it as integer not knowing any better lol) lastly, I know little about the RadioButtons , but will do some deep research into that as well. Google has become one of my best friends lately... the on error code bit was from the article I came across that I got this idea from; I'm assuming that article is a bit out of date. I imagine I may need further advice, but this really seems like a wonderful forum with competent, knowledgeable people that are more than willing to help! Thank you! I will post an updated code to examine, & let you know when I am able to communicate.
OK, i think I'm close... the problem I'm having is sending serial outstring to the arduino. I believe it would all work if I could resolve this issue! I have researched it exhaustibly ( to the best of MY limited ability!) I came up with something the author said would work, but it's catching an exception for Rs232(). revised code is below...
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Catch ex As Exception
End Try
Dim onstate, outstring As Integer
onstate = 0
If Button1.Text = "Pin 6 on" Then
Button1.Text = "Pin 6 off"
onstate = 1
outstring = "!"
End If
If Button1.Text = "Pin 6 off" And onstate = 0 Then
Button1.Text = "Pin 6 on"
outstring = "$"
End If
Dim moRS232 As New Rs232()
With moRS232
.Port = 3 '// Uses COM3
.BaudRate = 300 ' // 300 baud rate
.DataBit = 8 '// 8 data bits
.StopBit = Rs232.DataStopBit.StopBit_1 '// 1 Stop bit
.Parity = Rs232.DataParity.Parity_None '// No Parity
.Timeout = 500 '// 500 ms of timeout admitted to get all required bytes
End With
'// Initializes and Open
moRS232.Open()
Try
Catch ex As Exception
End Try
End Sub
Private Function Rs232() As Object
Throw New NotImplementedException
End Function
End Class
I did try the RadioButton, saw no real difference, but will likely go back to it because it just seems simpler. I REALLY wanted to figure this out on my own & I hate to ask, but could someone PLEASE tell me how to send serial out? I'm at my wits end here & I want it to work sooo bad! All is not lost, I have learned a GREAT deal... I'm sure I can add the rest of the buttons & get this project off the ground. & I have no intention of stopping the VB.NET courses, I intend to do many more projects! You all have been great on this forum, one of the very best I've had the pleasure of being a part!! Thank you all for your time & expertise.. my expertise is electrical engineering, & I had no idea what programmers went through, I certainly have a new-found appreciation for ya all!
Well first we need to tidy up the code a bit. The Try/Catch works like this ...
vb.net Code:
Try
'all the code that might throw an exception
Catch ex As Exception
'code to determine what happens if an exception is thrown
'ex gives the specific Exception of you want to handle different exceptions differently
End Try
Dim moRS232 As New Rs232()
This doesn't make any sense as RS232() is a custom function not a type.
vb.net Code:
Dim moRS232 As SerialPort = New SerialPort
With moRS232
'.Port = 3 '// Uses COM3
.PortName = "COM3"
And I've no idea what ....
Private Function Rs232() As Object
Throw New NotImplementedException
End Function
... is supposed to do but it doesn't. It's not a Function to start with (no return value) and does nothing but throw an exception and effectively kill the program.
I would guess that Rs232() is a function that is supposed to set up and return a SerialPort object. It doesn't do that, as written, and even the prototype is pretty poor, since it returns type Object, but that would be my guess as to what it was supposed to do. I don't do that.
Here is a class that I think I use to communicate with a different type of brainboard (one I don't use anymore) over a serial port. Much of the class will not be useable, but I left it all in so that you can see how I was writing out certain things and reading in certain things.
Code:
Public Class FastSerialManager
Implements IDisposable
Private WithEvents mSerial As System.IO.Ports.SerialPort
Private lastData(4096) As Byte
Private mLastPointer As Integer
Private mHasData As Boolean
Private mLocalData(4096) As Byte
Private mLocalPointer As Integer
Private mDataList As List(Of String)
Private mResidual As Byte
Private disposedValue As Boolean = False ' To detect redundant calls
Private resetFlag As Boolean
Private mFailCount As Integer
Private mAlertCount As Integer
Private mAlertHolder As Integer
Private mDoneCount As Integer
'Private mCount As Integer
'The timer
Private myTimer As System.Windows.Forms.Timer
Private timeCounter As Boolean
Private myContext As System.Threading.SynchronizationContext
#Region "Constructors and Destructors"
Public Sub New()
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 9600
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = "COM4"
mSerial.WriteTimeout = 500
mSerial.ReadTimeout = 3000
mSerial.ReadBufferSize = 4096
mSerial.ReceivedBytesThreshold = 1
myContext = System.Threading.SynchronizationContext.Current
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
resetFlag = False
'Create the timer.
myTimer = New System.Windows.Forms.Timer
mLocalPointer = -1
'Need to tell it where to send time tick messages.
AddHandler myTimer.Tick, AddressOf TimerEventProcessor
myTimer.Enabled = False
myTimer.Interval = 2000
End Sub
Public Sub New(ByVal nm As String)
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 9600
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = nm
mSerial.WriteTimeout = 500
mSerial.ReadTimeout = 500
mSerial.ReceivedBytesThreshold = 1
myContext = System.Threading.SynchronizationContext.Current
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
'Create the timer.
myTimer = New System.Windows.Forms.Timer
mLocalPointer = -1
'Need to tell it where to send time tick messages.
AddHandler myTimer.Tick, AddressOf TimerEventProcessor
myTimer.Enabled = False
myTimer.Interval = 2000
End Sub
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
mSerial.Dispose()
End If
Me.disposedValue = True
myTimer.Dispose()
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
#End Region
#Region "Properties and Events"
Public ReadOnly Property NewData() As Boolean
Get
Return mHasData
End Get
End Property
Public Event DataReady()
Public Event Alert(ByVal alertVal As Integer)
Public Event Stopped()
Public Event Failed()
#End Region
#Region "Public Functions"
Public Sub ReSet()
mSerial.Dispose()
mFailCount = 0
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 9600
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = "COM5"
mSerial.WriteTimeout = 500
mSerial.ReadTimeout = 3000
mSerial.ReadBufferSize = 4096
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
End Sub
'Pass in a buffer, and it will be filled. The return is the number of bytes read.
'The buffer should be sized to 4096.
Public Function GetData(ByRef buffHolder() As Byte) As Integer
buffHolder = CType(lastData.Clone(), Byte())
Array.Clear(lastData, 0, 4096)
End Function
'This sub mostly is used for calling sound.
Public Sub SendOutput(ByVal senNo As Byte, ByVal senVal As Byte)
Dim buf(2) As Byte
'Confirm that the escape char (92) is not included in the arguments.
If senVal = 92 Then
senVal += CByte(1)
End If
If senNo = 92 Then
RaiseEvent Failed()
Return
End If
buf(0) = 255
buf(1) = senNo
buf(2) = senVal
mSerial.Write(buf, 0, 3)
End Sub
'This assumes that senNo is a number less than 256. No checking is
'Done if that is not the case.
Public Sub ReadSensor(ByVal senNo As Byte, ByVal senVal As Byte)
Dim buf(2) As Byte
'Confirm that the escape char (92) is not included in the arguments.
If senVal = 92 Then
senVal += CByte(1)
End If
If senNo = 92 Then
'This should NEVER happen, so just fail it.
RaiseEvent Failed()
Return
End If
buf(0) = 255
buf(1) = senNo
buf(2) = senVal
mLastPointer = 0
mLocalPointer = -1
mHasData = False
Array.Clear(mLocalData, 0, 4096)
Array.Clear(lastData, 0, 4096)
mSerial.Write(buf, 0, 3)
myTimer.Enabled = True
timeCounter = True
End Sub
Public Sub ClearAlert()
Dim buf(2) As Byte
buf(0) = 255 'The flag
buf(1) = 111 'Sensor 111 just clears the alert.
buf(2) = 0 'This doesn't do anything.
mSerial.Write(buf, 0, 3)
End Sub
Public Sub WriteMove(ByVal lWhl As Byte, ByVal rWhl As Byte, ByVal dur As Byte)
Dim buf(2) As Byte
'Check to see that 92 (the escape character) is not one of the values.
If lWhl = 92 Then
lWhl += CByte(1)
End If
If rWhl = 92 Then
rWhl += CByte(1)
End If
If dur = 92 Then
dur += CByte(1)
End If
buf(0) = 255
buf(1) = 100
buf(2) = lWhl
mSerial.Write(buf, 0, 3)
buf(0) = 255
buf(1) = 101
buf(2) = rWhl
mSerial.Write(buf, 0, 3)
buf(0) = 255
buf(1) = 102
buf(2) = dur
mSerial.Write(buf, 0, 3)
End Sub
'A relic to setting addresses for the SRF08. Don't use it.
Public Sub WriteAddress(ByVal no As Byte)
Dim buf(2) As Byte
buf(0) = 255
buf(1) = 10
buf(2) = no
mSerial.Write(buf, 0, 3)
End Sub
Public Sub SendReset()
resetFlag = True
mSerial.Write("\0")
mSerial.Write("W")
resetFlag = False
End Sub
#End Region
#Region "Private Functions"
Private Sub TimerEventProcessor(ByVal myobject As Object, ByVal myEventArgs As EventArgs)
If timeCounter Then
SendReset()
myTimer.Enabled = False
RaiseEvent Failed()
mFailCount += 1
If mFailCount > 3 Then
ReSet()
End If
Else
timeCounter = True 'Set false by data received.
End If
End Sub
'This is the way data is read if the timer is not in use (no sensor read).
Private Sub DataReceivedProcessor(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mSerial.DataReceived
Dim inByte As Byte
Dim cnt As Integer
Dim buff(4096) As Byte
Dim x As Integer
'This is a special case, not a sensor read.
mFailCount = 0 'ANY bytes coming in means that something is happening.
timeCounter = False
'If the flag is set, bail out.
If resetFlag Then
Return
End If
cnt = mSerial.Read(buff, 0, 4096)
For x = 0 To cnt - 1
inByte = buff(x)
mLocalPointer += 1
mLocalData(mLocalPointer) = inByte
If inByte = 128 Then
mAlertCount += 1
ElseIf inByte = 255 Then
mDoneCount += 1
mAlertCount = 0
If mDoneCount = 3 Then
mDoneCount = 0
'If there is something in the alert holder, then this
'is an alert. Only the alert holder byte matters, so the three 128 bytes
'will simply be ignored.
If mAlertHolder > 0 Then
myContext.Post(AddressOf EventRaiser, mAlertHolder) 'The stop alert.
mAlertHolder = 0 'Clear the holder.
Else
'Need to strip off those final three bytes.
mLocalPointer -= 3
'Check that this didn't do something truly bizarre.
If mLocalPointer < 0 Then
mLocalPointer = 0
'This should never happen.
Windows.Forms.MessageBox.Show("A too short message was found.", "Error")
End If
lastData = CType(mLocalData.Clone, Byte())
mLastPointer = mLocalPointer
mHasData = True
myTimer.Enabled = False
myContext.Post(AddressOf EventRaiser, 255)
mLocalPointer = -1
Array.Clear(mLocalData, 0, 4096)
End If
End If
Else
If mAlertCount = 3 Then
mAlertCount = 0
mAlertHolder = CInt(inByte)
'clear these two.
End If
mAlertCount = 0
mDoneCount = 0
End If
Next
End Sub
Private Sub EventRaiser(ByVal typ As Object)
Select Case CInt(typ)
Case 255
RaiseEvent DataReady()
Case 101
RaiseEvent Stopped()
Case Else
RaiseEvent Alert(CInt(typ))
End Select
End Sub
#End Region
End Class
I studied both responses, & came up with this code:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
'All the code that might throw an exception
Catch ex As Exception
'code to determine what happens if an exception is thrown
'ex gives the specific Exception of you want to handle different exceptions differently
End Try
Dim onstate, outstring
onstate = 0
If Button1.Text = "Pin 1 on" Then
Button1.Text = "Pin 1 off"
onstate = 1
outstring = "!"
End If
If Button1.Text = "Pin 1 off" And onstate = 0 Then
Button1.Text = "Pin 1 on"
outstring = "$"
End If
End Sub
Public Class FastSerialManager
Implements IDisposable
Private WithEvents mSerial As System.IO.Ports.SerialPort
Private lastData(4096) As Byte
Private mLastPointer As Integer
Private mHasData As Boolean
Private mLocalData(4096) As Byte
Private mLocalPointer As Integer
Private mDataList As List(Of String)
Private mResidual As Byte
Private disposedValue As Boolean = False ' To detect redundant calls
Private resetFlag As Boolean
Private mFailCount As Integer
Private mAlertCount As Integer
Private mAlertHolder As Integer
Private mDoneCount As Integer
'Private mCount As Integer
'The timer
Private myTimer As System.Windows.Forms.Timer
Private timeCounter As Boolean
Private myContext As System.Threading.SynchronizationContext
#Region "Constructors and Destructors"
Public Sub New()
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 9600
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = "COM4"
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
resetFlag = False
'Create the timer.
myTimer = New System.Windows.Forms.Timer
mLocalPointer = -1
'Need to tell it where to send time tick messages.
AddHandler myTimer.Tick, AddressOf TimerEventProcessor
myTimer.Enabled = False
myTimer.Interval = 2000
End Sub
Public Sub New(ByVal nm As String)
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 9600
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = nm
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
'Create the timer.
myTimer = New System.Windows.Forms.Timer
mLocalPointer = -1
'Need to tell it where to send time tick messages.
AddHandler myTimer.Tick, AddressOf TimerEventProcessor
myTimer.Enabled = False
myTimer.Interval = 2000
End Sub
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
mSerial.Dispose()
End If
Me.disposedValue = True
myTimer.Dispose()
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
#End Region
#Region "Properties and Events"
Public ReadOnly Property NewData() As Boolean
Get
Return mHasData
End Get
End Property
Public Event DataReady()
Public Event Alert(ByVal alertVal As Integer)
Public Event Stopped()
Public Event Failed()
#End Region
#Region "Public Functions"
Public Sub ReSet()
mSerial.Dispose()
mFailCount = 0
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 9600
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = "COM5"
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
End Sub
'Pass in a buffer, and it will be filled. The return is the number of bytes read.
'The buffer should be sized to 4096.
Public Function GetData(ByRef buffHolder() As Byte) As Integer
buffHolder = CType(lastData.Clone(), Byte())
Array.Clear(lastData, 0, 4096)
End Function
'This sub mostly is used for calling sound.
Public Sub SendOutput(ByVal senNo As Byte, ByVal senVal As Byte)
Dim buf(2) As Byte
'Confirm that the escape char (92) is not included in the arguments.
If senVal = 92 Then
senVal += CByte(1)
End If
If senNo = 92 Then
RaiseEvent Failed()
Return
End If
buf(0) = 255
buf(1) = senNo
buf(2) = senVal
mSerial.Write(buf, 0, 3)
End Sub
'This assumes that senNo is a number less than 256. No checking is
'Done if that is not the case.
Public Sub ReadSensor(ByVal senNo As Byte, ByVal senVal As Byte)
Dim buf(2) As Byte
'Confirm that the escape char (92) is not included in the arguments.
If senVal = 92 Then
senVal += CByte(1)
End If
If senNo = 92 Then
'This should NEVER happen, so just fail it.
RaiseEvent Failed()
Return
End If
buf(0) = 255 'The flag
buf(1) = 111 'Sensor 111 just clears the alert.
buf(2) = 0 'This doesn't do anything.
mSerial.Write(buf, 0, 3)
End Sub
Public Sub WriteMove(ByVal lWhl As Byte, ByVal rWhl As Byte, ByVal dur As Byte)
Dim buf(2) As Byte
'Check to see that 92 (the escape character) is not one of the values.
If lWhl = 92 Then
lWhl += CByte(1)
End If
If rWhl = 92 Then
rWhl += CByte(1)
End If
If dur = 92 Then
dur += CByte(1)
End If
buf(0) = 255
buf(1) = 100
buf(2) = lWhl
mSerial.Write(buf, 0, 3)
buf(0) = 255
buf(1) = 101
buf(2) = rWhl
mSerial.Write(buf, 0, 3)
buf(0) = 255
buf(1) = 102
buf(2) = dur
mSerial.Write(buf, 0, 3)
End Sub
'A relic to setting addresses for the SRF08. Don't use it.
Public Sub WriteAddress(ByVal no As Byte)
Dim buf(2) As Byte
buf(0) = 255
buf(1) = 10
buf(2) = no
mSerial.Write(buf, 0, 3)
End Sub
Public Sub SendReset()
resetFlag = True
mSerial.Write("\0")
mSerial.Write("W")
resetFlag = False
End Sub
#End Region
#Region "Private Functions"
Private Sub TimerEventProcessor(ByVal myobject As Object, ByVal myEventArgs As EventArgs)
If timeCounter Then
SendReset()
myTimer.Enabled = False
RaiseEvent Failed()
mFailCount += 1
If mFailCount > 3 Then
ReSet()
End If
Else
timeCounter = True 'Set false by data received.
End If
End Sub
'This is the way data is read if the timer is not in use (no sensor read).
Private Sub DataReceivedProcessor(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mSerial.DataReceived
Dim inByte As Byte
Dim cnt As Integer
Dim buff(4096) As Byte
Dim x As Integer
'This is a special case, not a sensor read.
mFailCount = 0 'ANY bytes coming in means that something is happening.
timeCounter = False
'If the flag is set, bail out.
If resetFlag Then
Return
End If
cnt = mSerial.Read(buff, 0, 4096)
For x = 0 To cnt - 1
inByte = buff(x)
mLocalPointer += 1
mLocalData(mLocalPointer) = inByte
If inByte = 128 Then
mAlertCount += 1
ElseIf inByte = 255 Then
mDoneCount += 1
mAlertCount = 0
If mDoneCount = 3 Then
mDoneCount = 0
'If there is something in the alert holder, then this
'is an alert. Only the alert holder byte matters, so the three 128 bytes
'will simply be ignored.
If mAlertHolder > 0 Then
myContext.Post(AddressOf EventRaiser, mAlertHolder) 'The stop alert.
mAlertHolder = 0 'Clear the holder.
Else
'Need to strip off those final three bytes.
mLocalPointer -= 3
'Check that this didn't do something truly bizarre.
If mLocalPointer < 0 Then
mLocalPointer = 0
'This should never happen.
Windows.Forms.MessageBox.Show("A too short message was found.", "Error")
End If
lastData = CType(mLocalData.Clone, Byte())
mLastPointer = mLocalPointer
mHasData = True
myTimer.Enabled = False
myContext.Post(AddressOf EventRaiser, 255)
mLocalPointer = -1
Array.Clear(mLocalData, 0, 4096)
End If
End If
Else
If mAlertCount = 3 Then
mAlertCount = 0
mAlertHolder = CInt(inByte)
'clear these two.
End If
mAlertCount = 0
mDoneCount = 0
End If
Next
End Sub
Private Sub EventRaiser(ByVal typ As Object)
Select Case CInt(typ)
Case 255
RaiseEvent DataReady()
Case 101
RaiseEvent Stopped()
Case Else
RaiseEvent Alert(CInt(typ))
End Select
End Sub
#End Region
End Class
End Class
It debugged fine, but there was an error: Warning 1 Function 'GetData' doesn't return a value on all code paths. Are you missing a 'Return' statement? C:\Users\dan\documents\visual studio 2010\Projects\WindowsApplication8\WindowsApplication8\Form1.vb 176 9 WindowsApplication8
It is still not communicating with the arduino - I'm about positive the arduino code is good, I've written dozens of them for different purposes that all worked fine - 2 were even quite complex. Is there something that needs to be fixed yet? I'm a bit perplexed that it debugged with an error showing!
I did notice one other thing - in one of my earlier attempts, when I clicked the button, the text changed. I have not had that happen since; is that the way it's supposed to work?? I am felling frustrated... it seems as though we are closer than ever - your code looks awesome, but still not doing quite what I want lol
What is the next logical step here? one thing is for sure, I'm learning vb.net more every day, & that was actually my main goal!! One thing I noticed, the "try catch" didn't come up with anything! I know I'm taking an awful lot of your time, but bear with me here - we're close! please advise...
The try/catch was a template not a literal copy and paste. You need to insert the relevant sections of code into it where it says that's where the code goes!
A function must return a value to the calling code eg.
x = DoStuff(y)
calls
Function DoStuff(byVal input as Int16) As Int16
Dim stuff As Int16 = input * 13231
Return stuff
End Function
which with input = y does some math and returns stuff making x = stuff
If it has no return value then it's a Sub not a Function and must be declared so.
The Try...Catch won't come up with anything the way you have it in the button click, because you don't do anything in the Catch portion. At the very least, you should be showing a messagebox with ex.Message in it.
Also, in the Try portion that you showed, all you have is a comment about what code is there. What code IS there? After all, you appear to have copied in my class, but I don't see you doing anything with it. You don't show that you create an instance of the class, or call any of the methods. There is also lots of code that you left in there that won't do you any good, such as the creation of the byte strings that I was sending in ReadSensor, WriteMove, WriteAddress. All that stuff is largely worthless to you except possibly as an example for one way to make methods for sendind certain things out the serial port.
GetData has a flaw. It is written as a function which returns an integer, except that I didn't return anything. The function works, it just doesn't need to be a function. Instead, it should be a sub. I expect that I was intending to return the number of bytes of data that were copied, then decided against it and didn't change the function to a sub. It's interesting that I didn't deal with the warning, but I haven't worked with that bit of the code for years.
If you haven't gotten to the point where you have learned about classes in VB, much of that code may make no sense to you. For instance, the events (which aren't all that well implemented, frankly), the structure of the code, and so forth. It certainly won't work right for you, as is, since it was designed to work with an entirely different brainboard (OOPic) communicating via a Bluetooth chip (which doesn't really matter, since it acts as any other serial port). The key to take from that is how to set up a SerialPort object, and how to work with one.
OK, thanks guys... I see several of my mistakes now. For one thing, I was half asleep when I posted - the baud rate for the arduino must be 300, & my com port is com3... DUH! I obviously wasn't watching what I was doing & apologize for wasting your time lol. I understand the points you've made above also... will rework & experiment b4 I re-post. got a few pressing matters in real time here also, so it will likely be a couple of days. thanks for the continued support.
I know it's painfully slow, but it is just a micro-processor... most loops run fast enough to not notice with the applications they use. I'll be working on this tonight!
OK, I've looked it over very carefully, & removed the sections that you said I don't need - also removed the get data function. It looks like there may be other things I won't need, but it looks like it should be ok... be sure & correct me if I'm wrong, please! It looks like I needed to name the serial port mSerial, so I did. I'm a bit stuck now, however, because I need to integrate my code portion with the part from you that I revised, & I'm really not sure how to go about it. I really would like to do it on my own, because I know there's no better way to learn... what I would like is some kind of direction to proceed; please give me an Idea of what I need to do! also, is everything in your code ok now that I've messed with it? & lastly, was I right in naming the serial port eSerial? I know I'm asking a lot, & you already have a lot of time in this for me... you have no idea how excited I am that someone is willing to help me with this, especially since I keep making blunders!! I am still working on VB.NET from 2 different online sources - I find that it doesn't come easily to me, it's profoundly more complex than I had expected & I hold a real admiration for experts such as yourself! Sotra one of those things the more you learn, the more you realize how little you know... thank you all for everything you've done for me - this is a fantastic forum! I will end by posting the revised code from you, then the code I need to integrate:
Public Class Form1
Public Class FastSerialManager
Implements IDisposable
Private WithEvents mSerial As System.IO.Ports.SerialPort
Private lastData(4096) As Byte
Private mLastPointer As Integer
Private mHasData As Boolean
Private mLocalData(4096) As Byte
Private mLocalPointer As Integer
Private mDataList As List(Of String)
Private mResidual As Byte
Private disposedValue As Boolean = False ' To detect redundant calls
Private resetFlag As Boolean
Private mFailCount As Integer
Private mAlertCount As Integer
Private mAlertHolder As Integer
Private mDoneCount As Integer
'Private mCount As Integer
'The timer
Private myTimer As System.Windows.Forms.Timer
Private timeCounter As Boolean
Private myContext As System.Threading.SynchronizationContext
#Region "Constructors and Destructors"
Public Sub New()
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 300
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = "COM3"
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
resetFlag = False
'Create the timer.
myTimer = New System.Windows.Forms.Timer
mLocalPointer = -1
'Need to tell it where to send time tick messages.
AddHandler myTimer.Tick, AddressOf TimerEventProcessor
myTimer.Enabled = False
myTimer.Interval = 2000
End Sub
Public Sub New(ByVal nm As String)
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 300
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = nm
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
'Create the timer.
myTimer = New System.Windows.Forms.Timer
mLocalPointer = -1
'Need to tell it where to send time tick messages.
AddHandler myTimer.Tick, AddressOf TimerEventProcessor
myTimer.Enabled = False
myTimer.Interval = 2000
End Sub
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
mSerial.Dispose()
End If
Me.disposedValue = True
myTimer.Dispose()
End Sub
#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
#End Region
#Region "Properties and Events"
Public ReadOnly Property NewData() As Boolean
Get
Return mHasData
End Get
End Property
Public Event DataReady()
Public Event Alert(ByVal alertVal As Integer)
Public Event Stopped()
Public Event Failed()
#End Region
#Region "Public Functions"
Public Sub ReSet()
mSerial.Dispose()
mFailCount = 0
mSerial = New System.IO.Ports.SerialPort
mSerial.BaudRate = 300
mSerial.DataBits = 8
mSerial.StopBits = IO.Ports.StopBits.One
mSerial.Parity = IO.Ports.Parity.None
mSerial.PortName = "COM3"
'Need to do a few things to look for the com ports and decide which one to use.
mSerial.Open()
End Sub
'This sub mostly is used for calling sound.
Public Sub SendOutput(ByVal senNo As Byte, ByVal senVal As Byte)
Dim buf(2) As Byte
'Confirm that the escape char (92) is not included in the arguments.
If senVal = 92 Then
senVal += CByte(1)
End If
If senNo = 92 Then
RaiseEvent Failed()
Return
End If
buf(0) = 255
buf(1) = senNo
buf(2) = senVal
mSerial.Write(buf, 0, 3)
End Sub
Public Sub ClearAlert()
Dim buf(2) As Byte
buf(0) = 255 'The flag
buf(1) = 111 'Sensor 111 just clears the alert.
buf(2) = 0 'This doesn't do anything.
mSerial.Write(buf, 0, 3)
End Sub
Public Sub SendReset()
resetFlag = True
mSerial.Write("\0")
mSerial.Write("W")
resetFlag = False
End Sub
#End Region
#Region "Private Functions"
Private Sub TimerEventProcessor(ByVal myobject As Object, ByVal myEventArgs As EventArgs)
If timeCounter Then
SendReset()
myTimer.Enabled = False
RaiseEvent Failed()
mFailCount += 1
If mFailCount > 3 Then
ReSet()
End If
Else
timeCounter = True 'Set false by data received.
End If
End Sub
'This is the way data is read if the timer is not in use (no sensor read).
Private Sub DataReceivedProcessor(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mSerial.DataReceived
Dim inByte As Byte
Dim cnt As Integer
Dim buff(4096) As Byte
Dim x As Integer
'This is a special case, not a sensor read.
mFailCount = 0 'ANY bytes coming in means that something is happening.
timeCounter = False
'If the flag is set, bail out.
If resetFlag Then
Return
End If
cnt = mSerial.Read(buff, 0, 4096)
For x = 0 To cnt - 1
inByte = buff(x)
mLocalPointer += 1
mLocalData(mLocalPointer) = inByte
If inByte = 128 Then
mAlertCount += 1
ElseIf inByte = 255 Then
mDoneCount += 1
mAlertCount = 0
If mDoneCount = 3 Then
mDoneCount = 0
'If there is something in the alert holder, then this
'is an alert. Only the alert holder byte matters, so the three 128 bytes
'will simply be ignored.
If mAlertHolder > 0 Then
myContext.Post(AddressOf EventRaiser, mAlertHolder) 'The stop alert.
mAlertHolder = 0 'Clear the holder.
Else
'Need to strip off those final three bytes.
mLocalPointer -= 3
'Check that this didn't do something truly bizarre.
If mLocalPointer < 0 Then
mLocalPointer = 0
'This should never happen.
Windows.Forms.MessageBox.Show("A too short message was found.", "Error")
End If
lastData = CType(mLocalData.Clone, Byte())
mLastPointer = mLocalPointer
mHasData = True
myTimer.Enabled = False
myContext.Post(AddressOf EventRaiser, 255)
mLocalPointer = -1
Array.Clear(mLocalData, 0, 4096)
End If
End If
Else
If mAlertCount = 3 Then
mAlertCount = 0
mAlertHolder = CInt(inByte)
'clear these two.
End If
mAlertCount = 0
mDoneCount = 0
End If
Next
End Sub
Private Sub EventRaiser(ByVal typ As Object)
Select Case CInt(typ)
Case 255
RaiseEvent DataReady()
Case 101
RaiseEvent Stopped()
Case Else
RaiseEvent Alert(CInt(typ))
End Select
End Sub
#End Region
End Class
End Class
And the code I need to add:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
* Dim onstate, outstring
* onstate = 0
* If Button1.Text = "Pin 1 on" Then
* Button1.Text = "Pin 1 off"
* onstate = 1
* outstring = "!"
* End If
* If Button1.Text = "Pin 1 off" And onstate = 0 Then
* Button1.Text = "Pin 1 on"
* outstring = "$"
* End If
* End Sub
I did figure out the Try - catch with a message box, just wasn't quite sure where that should go either - sorry! My code portion came from the attachment under the pic of my hardware, & it seems to be a pretty good article - explains the interface between VB.NET & the arduino, because of the slow baud rate of the arduino, it makes the VB do most of the work & leaves a small loop for the arduino. Any questions, ask away, I'll be watching all day for the next several days. Thanks again!
Hey, Shaggy hiker, if your around, I could use your input! the last couple of days I've spent a lot of time studying, & realize I still have some things wrong; Whats more, I stumbled across a current, step by step guide for building code for serial I/O, & interfacing with micro-processors. since we have this started, I'd rather work with you on what we have going, but I now have a much better understanding of what the heck I'm doing lol! I think I can finally see the light at the end of the tunnel... getting really excited! Anyone else that has suggestions or input are more than welcome also of course; this is an awesome forum with too many experts in this field to count, I'm glad to be here! thank you all.
RESOLVED!! I feel a need to post my resolution for 2 reasons; First & foremost, to thank all involved in helping me along my journey, and just as important, I,ve found a really sipmle solution for those of you looking for this answer. There is an organization called Firmata.org that developed a protocol for this expressed purpose; Firmata is a protocol built into arduino's version UNO & newer that is specifically meant to interface with VB.NET. go to Firmata.org & download the Firmata.dll, place it in your library with the Arduino environment. In VB, bring up the toolbox, right click, browse to where the Firmata.dll is, & it can be added to the toolbox. Drag & drop onto your project, & Firmata will show up on the status bar where the serial port would normally show up. This AUTOMATICALLY enables the protocol to a comport - it's so simple, it's unbelievable!there are some more steps, & basic knowledge is required in VB.NET, but I easily used the info from Firmata.org & a bit more research, & wa-la, it works like a gem! there are some limitations which i will briefly go into, & one VERY important thing; Enter the Arduino environment, go to files/examples/Firmata/Standard firmata and load the protocol into the arduino environment - it must be running in the background to interface with VB.NET. Any other questions can be addressed at Firmata.org or with some basic research. for my purpose, it was brilliant; from my host pc in my office, & the arduino & relay banks in my 5 car garage(this can be set up wirelessly, or in my case I used a 50' amplified USB cable) I can open or close all garage doors, control both light banks,the garage furnace, a motion detector with a semi-silent alarm in my office, a 60 gallon air compressor(which I have a bad habit of leaving on), the motion sensor lights on the driveway, the front door light, + I have four unused relays for whatever else I may come up with... the best part of all, when the host PC is shut down, the arduino holds all settings as is, until the next bootup when you may once again click buttons to your hearts content! Limitations: I have read that there are some - most notably, it won't work well with robotics that involve a ping sensor, because the protocol throws off the delicate timing needed for pings to measure distances accurately. One thing I failed to mention is that the remote Arduino must be loaded with Firmata also.(in addition to the environment on the host PC). Although I'm still on a learning curve myself, I will be checking this post in case anyone may have a question I can address. I CAN tell you that it's been a real blast getting this finalized! I did use low voltage relays & wiring to each unit controlled for both cost & safety concerns. (5V relays that can switch 220V at 10A - the relay for the compressor fired a larger, 40 amp relay)
Shaggy Hiker - you were the most instrumental of all in my learning VB.NET! A very special thanks to you for being so patient with me! I know I was a slow learner, but you stuck with me & encouraged me - something I'll never forget; you owed me nothing, but because of your perseverance, I struggled through the VB tutorials & can finally Write code & have the general knowledge to proceed, & believe me, I'm just beginning! I find a great satisfaction in using my new-found talent for amusement, productivity, creativity & enjoyment... also a special thanks to others who have contributed along the way. I don't know how long these posts stay active, but I would like to continue the goodwill of this forum & be of help to others if I'm able... best wishes to you all!