Sending Data to Serial Port through VB

I am trying to send some information to an Arduino board by using a VB.net script... only, I have to admit I'm a bit of newbie in VB and I am a little stuck. I have set up a boolean toggle so that if the toggle is set to true, then it should send an 'H' to the board and set Pin 13 to High. If the toggle is set to false, then the script will send an 'L' to the board and turn pin off. I can load the Physical Pixel example to the board so that when it receives either of these letters, it will either turn the Pin on or off... so basically, what I need to do is to somehow send a letter to the board... through VB. But, I'm a little lost on where to even begin.
This link was suggested as a starting place (http://support.microsoft.com/kb/823179/)... but I'm not actually using Visual Studio or Express. I'm using a plug-in (called Grasshopper) for a 3d software package (called Rhino). You have the ability to write your own custom components through VB, which is where I got the idea to send data directly from this plugin to the Arudino. If someone could help me with some basic instructions on where to begin, or how to do this simple example... I would greatly appreciate it. Cheers, Andy

This is the code that is setup in the plugin. The message that is fed into the component is either the letter 'H' or 'L'. This letter should be sent when the activate boolean value is set to True.

  Sub RunScript(ByVal message As String, ByVal activate As Boolean)
    If activate Then
      'If boolean set to true, then send message to Arduino...
    End If
    
  End Sub

The info on the second article of the link is still what you will need to do.

In your routine you will need to create a serial port, and send the data over it.

something like this should work. You'll have to attach to the serial port that your Arduino is on.

      Sub RunScript(ByVal activate As Boolean)
            Dim data As String = String.Empty

            If activate = True Then
                  'If boolean set to true, then send message to Arduino...
                  data = "H"
            Else
                  data = "L"

            End If

            Using com1 As IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort("COM1")' change to your port
                  com1.WriteLine(data)
                  com1.Close()
            End Using

      End Sub

On a side note, if your intent is to learn VB.NET, you would be far better off in Visual Studio. The express versions are free.

How would I convert the VB.net code to VBS
I think I know how to convert "com1 as IO." but not "IO = My.Computer"

Would these even work in vbs?

If you are running .NET, it's not VBS. VBS is based on older (VB6 and prior) languages.

I guess we really need to figure out what language the scripting tool is using. If it is using .NET, the code that I posted should run just fine (although you may need some includes that Visual Studio sets up by default). If it is using VBS, then you'll want to search for a VBS sample for com port.

Can you post some links to the Rhino / Grasshopper tools?

This is great! Your sample code worked perfectly. I know this was a very basic example, but my main hurdle had been how to get any data transmitted from Grasshopper to the Arduino. I can now change the toggle and turn on the LED... very dumb... but now, the sky is the limit.
BTW, here is a link to the main Grasshopper page. http://www.grasshopper3d.com/ and here is a link to the scripting page in Grasshopper: Scripting and Code Tutorials - Grasshopper.
As I mentioned, what's nice about Grasshopper is that it allows you to set parameters that control 3d objects. Now, that I can successfully talk between Grasshopper and the Arduino, I can easily design something in 3d in the computer and have it also output the data in realtime to a board which will also control the physical environment. I'm much more proficient in Grasshopper (vs. VB.net) so if you have any questions regarding the interface, don't hesitate to ask.
Thanks again.

I have a follow up question. I have successfully sent data from Grasshopper to the Arduino through VB. But, what if I wanted to reverse the flow of information. What if I wanted to send data from the Arduino to Grasshopper (through VB).
Here's a simple example. Let's say I have a photocell hooked up so that when I turn on the serial monitor, I get a stream of voltage information that is coming into the computer. How would I read that information in Grasshopper (again using VB). The problem in the past with Grasshopper has always been with reading information into the program... It has no problem streaming data out. But, it only refreshes the algorithm if something has changed in Rhino or in Grasshopper... and since nothing has really changed in the Grasshopper definition or in the Rhino viewport, it doesn't know to refresh the solution, and thus get new information in from an external file. In the recent release of Grasshopper (just 2 weeks ago) there is a new timer component that will refresh the solution based on any time interval that you give it. I think MaxMSP has something very similar (I think it's called the Metronome). So, I think I can use this component to automatically refresh the solution every (1 sec for example) to retrieve the new information being sent from the Arduino. My main question is how to script it in VB to read this information. I may not have been clear, but if you have any suggestions, I would really appreciate. Thanks again for your help so far!

I don't know if you can call functions from Grasshopper, but if you can then the following should read one line from the serial port. You could call it whenever you want to retrieve data from the port.

Function ReceiveSerialData() As String
    ' Receive strings from a serial port.
    Dim returnStr As String = ""

    Using com1 As IO.Ports.SerialPort = _
            My.Computer.Ports.OpenSerialPort("COM1")
        Do
            Dim Incoming As String = com1.ReadLine()
            If Incoming Is Nothing Then
                Exit Do
            Else
                returnStr &= Incoming & vbCrLf
            End If
        Loop
      com1.Close()
    End Using

    Return returnStr
End Function

I tried putting in the code to read the photocell data... but I'm still a little stuck. I put the snippet of code in the "Additional Methods and Type Declarations Area" because I was getting error messages if I put the code in between the Subs. I don't get any error messages (which is usually a good sign) but I'm also not getting a read out of the photocell values that are being shown in the Arduino Serial Monitor either. I tried putting a print (returnStr) into the code, but nothing happened. Here's what my code looks like. Please let me know if I'm way off base, or if there is something I'm missing. Thanks.

  Sub RunScript(ByVal x As Object, ByVal y As Object)
    
  End Sub

#Region "Additional methods and Type declarations"
  Function ReceiveSerialData() As String
    ' Receive strings from a serial port.
    Dim returnStr As String = ""

    Using com3 As IO.Ports.SerialPort = _
        My.Computer.Ports.OpenSerialPort("COM3")
      Do
        Dim Incoming As String = com3.ReadLine()
        If Incoming Is Nothing Then
          Exit Do
        Else
          returnStr &= Incoming & vbCrLf
        End If
      Loop
      com3.Close()
    End Using

    Return returnStr 
  End Function
#End Region
End Class

Ok... I may have posted prematurely... although I still haven't figured it out. I realized that I had defined the Function ReceiveSerialData(), but I never called that function to actually go and get the data. So, I put line in between the Subs that called the ReceiveSerialData() function, only now I'm getting an error message that says, "Script exception: Access to the port 'COM3' is denied." Which is really weird because I was definitely able to send data from Grasshopper to the COM3 port in our previous example. Have I set up the code correctly?

The code looks fine, but it's hard to say what is going on since I'm not really sure how grasshopper calls the code in each routine / class / sub. The error looks like a generic error message, instead of the full message that .NET returns which would give more info.

You don't have something else talking to COM3 at the same time do you? Like another monitoring app, Arduino, or the routine that writes to the port.

No, nothing else was talking to the COM3 port. In fact, that was the only COM port available. I should say that when I did try to run the code (twice), it actually froze the Rhino application. As if it were in a continuous loop. Is there a chance that I didn't call the receive function properly? How should the code between the subs look like?

By "How should the code between the subs look like?" you are talking about the # region area.

The region is just a editing tool for the Visual Studio IDE that allows you to group routines together, and fold the code. It is removed by the compiler.

We could try trapping the error and displaying it directly, instead of allowing grasshopper to catch the error. Try this function instead.

      Function ReceiveSerialData() As String
            ' Receive strings from a serial port.
            Dim returnStr As String = ""

            Try
                  Using com3 As IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort("COM3", 9600)
                        Do
                              Dim Incoming As String = com3.ReadLine()
                              If Incoming Is Nothing Then
                                    Exit Do
                              Else
                                    returnStr &= Incoming & environment.newline
                              End If
                        Loop
                        com3.Close()
                  End Using

            Catch ex As Exception
                  MessageBox.Show(ex.ToString)
            End Try

            Return returnStr
      End Function

I appreciate all of the help you have been giving me, as I am really learning a lot from these examples. I tried the code snippet you posted, but have gotten a longer error message (as expected, I think). I've also posted a screen shot of both the error message that I get when I call the function and also how my screen looks when I have both the Serial Monitor and the Grasshopper VB interface open at the same time. Again, I'm not sure what I'm doing wrong, and the error message looks quite confusing, but if you have any ideas, I would greatly appreciate it. Thanks again.


Where have you posted the screen shots at?

You can't see them? Huh, I uploaded them to my website and posted the URL. When log in to the forum and check this thread, they show up. Hmm... What if I just attach the URL. Try this.
http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino%20VB01.jpg
http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino%20VBerror.jpg

That's weird, Before looking at the images on your site, I could not see them on the forum, now they show up!?

It looks like you have the Arduino serial monitor attached to the com port. Only one device on the system can use the port, so if Arduino is attached, you won't be able to get Grasshopper attached. The access denied error is telling us the same thing: that something else is already talking to the serial port.

The other thing I noticed is that there was an error message on the window in the background (near the bottom center of the screen). It is referring to a recursive call. I'm not sure if this is related to the issue you have that seems like the code loops forever, but it could be.

So, does that just mean that the Serial Monitor has to be closed for the script to work? That way nothing else is talking to the COM port?
As for the other error message that you pointed out... That is a warning in the Grasshopper Interface. If something isn't working correctly, then Grasshopper will give you a warning message in that area. So, I do think there is still something in the code that is causing it to have a continuous loop.
So, is this what I should do (when I get home tonight). Make sure the Arduino is connected, but do NOT turn on the Serial Monitor. Then, launch Grasshopper and put in the original code (see below). Then call the function (between the subs) using this code "ReceiveSerialData()". Does that make sense?

Sub RunScript()

  End Sub

#Region "Additional methods and Type declarations"
  Function ReceiveSerialData() As String
    ' Receive strings from a serial port.
    Dim returnStr As String = ""

    Using com3 As IO.Ports.SerialPort = _
        My.Computer.Ports.OpenSerialPort("COM3")
      Do
        Dim Incoming As String = com3.ReadLine()
        If Incoming Is Nothing Then
          Exit Do
        Else
          returnStr &= Incoming & vbCrLf
        End If
      Loop
      com3.Close()
    End Using

    Return returnStr
  End Function
#End Region
End Class

Exactly; the serial monitor is connecting to COM3 to listen to the Arduino. The rest of the code should work as you have it, barring whatever recursive error you have in Grasshopper.

Great. I will try it out tonight and let you know how it works. Thanks again!

Well... I've tried this several different ways, and I'm still getting a continuous loop error. I made sure the Serial Monitor wasn't running and I tried a slightly different version of the code to try to get out of the continuous looping problem. But, it still locks up every time I call the function.
Here's how the Grasshopper side of things is set up. I have created a boolean toggle that feeds either a true or false value into the VB script component. I have also connected a Timer Component which should refresh the solution at any given time interval... in this case every 1 sec. So, ideally... when you flip the toggle to True, the script will call the function and retrieve whatever data is coming into the COM3 port. This will be refreshed every 1 sec. However, it's getting stuck. Here is the modified code I tried, but it still isn't working. I've also posted a picture of the setup. If you have any more ideas, I would really appreciate them. Thanks for all the help along the way. I feel like we are really close. Let me know if the images don't show up again :slight_smile:

  Function ReceiveSerialData() As String
    ' Receive strings from a serial port.
    Dim returnStr As String = ""
 
    Using com3 As IO.Ports.SerialPort = _
        My.Computer.Ports.OpenSerialPort("COM3")
      Do
        Dim Incoming As String = com3.ReadLine()
        If Incoming Is Nothing Then
          Exit Do
        Else
          returnStr &= Incoming & vbCrLf
          com3.Close()
          Return returnStr
        End If
      Loop
      
    End Using
 
    Return returnStr
  End Function