Pages: 1 2 [3] 4 5   Go Down
Author Topic: Sending Data to Serial Port through VB  (Read 9267 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Robert... I have to run out the door, but I will try your code as soon as I get back in tonight.  Thanks again.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Robert,
I have been trying your code... but am still getting stuck somewhere... probably because of my experience with VB.  I was assuming that I should put the code snippet in between the #Region area (like I had before) and then call the different subs/functions when I activate the boolean toggle.  So, the code looked like this when I put it into Grasshopper (see below).  The problem is that I'm getting a lot of error messages saying that OpenPort, GetValue, ...etc. are not declared... so the script wont even run.  I also had a question about the Class comment you added... saying that I would need to "work it into the grasshopper class".  How exactly do I do that?  I know it's not an easy question since you are unfamiliar with the program... but I do appreciate your help with all of this.  

Code:
 Sub RunScript(ByVal activate As Boolean)
    If activate Then
      Call OpenPort()
      Call GetValue()
      Call CPort_DataReceived()
      Call HandleComPort()
      print(StoredValue)
    Else
      Call ClosePort()
      print("not receiving data")
    End If
  End Sub

#Region "Additional methods and Type declarations"
  Public Class port

    ' I wrapped this in a class, but you would need to work it into the grasshopper class

    Private WithEvents CPort As IO.Ports.SerialPort      'port with events
    Private TempBuffer As String = String.Empty        'holds the input between events until we get a new line
    Private Delegate Sub HandleComPortDelegate()      'allows com port to run in a background thread without blocking
    Private StoredValue As String = String.Empty      'holds value from port until you call for it

    Sub OpenPort()            'called early in the app, before the port is ever needed. This attaches the port, and opens it to listen.
      CPort = New IO.Ports.SerialPort

      Try
        CPort = My.Computer.Ports.OpenSerialPort("COM3", 9600)
      Catch ex As Exception
        MessageBox.Show("no port")
      End Try
    End Sub

    'this would be better as a property, but I don't know how Grasshopper handles properties
    Function GetValue() As String
      Return StoredValue
    End Function

    'this is fired by the port when it has data
    Private Sub CPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles CPort.DataReceived
      Dim HndlComPort As New HandleComPortDelegate(AddressOf HandleComPort)             'declare thread
      HndlComPort.Invoke() ' invoke a new delegate to digest the events

    End Sub

    Private Sub HandleComPort()      'background handler for com port

      TempBuffer &= CPort.ReadExisting  'append into tempbuffer
      If (Strings.Right(TempBuffer, 2) = vbCrLf) Then        'if end of item            'this may need to be changed, since Arduino's println may use cr or lf only. I can't remember at this point.
        StoredValue = TempBuffer               'offload
        TempBuffer = String.Empty               'reset
      End If

    End Sub

    'should be called when the port is no longer needed.
    Private Sub ClosePort()

      If CPort.IsOpen = True Then
        CPort.Close()
      End If
      CPort.Dispose()

    End Sub

  End Class
#End Region
End Class
Logged

Palmetto, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 138
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
saying that I would need to "work it into the grasshopper class".  How exactly do I do that?

All I meant was that you would have to take the class I gave you, and cut it into pieces and put it back into the grasshopper script class.

You got most of it spliced in correctly, but I think we need to determine a couple of things about Rhino/Grasshopper before we can do much more.

You can get rid of most of the errors by removing the "Public Class port" and "end class" (the one before #End Region ) lines inside of the code you pasted. That's going to bring more errors though.
You will have to remove the calls to CPort_DataReceived and HandleComPort as they are used internally in the class and not meant to be called externally.

The real important question now is: can you call different routines inside the script class (from Grasshopper), or do you have to always call the run script subroutine? Once I know that, I can provide the last bits of guidance to try to get this running!

« Last Edit: August 25, 2009, 08:38:55 am by hdsrob » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your explanation.  It is very helpful.  I did make the changes you mentioned and it's a lot happier.  The good news is, it's no long stuck in an endless loop.  I can switch the boolean toggle to "True" and (nothing comes out of the out box) but at least it doesn't freeze the app.  So, when I did make those changes... I got one error message that said, "Script exception: Object reference not set to an instance of an object".  I'm a little confused about that because I nothing in the class is being transferred ByRef... instead everything is being called ByVal.... so, I'm not exactly sure what the error message is talking about.  Also, I will try to email one of the developers about whether or not you can call different routines inside the script class... I have a feeling that you always have to call the run script routine (pretty sure, but I will double check).  Thanks again for your help.
Here is the most current code that I have put in my GH definition:
Code:
Sub RunScript(ByVal activate As Boolean)
    If activate Then
      Call OpenPort()
      Call GetValue()
      print(StoredValue)

    Else
      Call ClosePort()
      print("not receiving data")
    End If
  End Sub

#Region "Additional methods and Type declarations"

  ' I wrapped this in a class, but you would need to work it into the grasshopper class

  Private WithEvents CPort As IO.Ports.SerialPort      'port with events
  Private TempBuffer As String = String.Empty        'holds the input between events until we get a new line
  Private Delegate Sub HandleComPortDelegate()      'allows com port to run in a background thread without blocking
  Private StoredValue As String = String.Empty      'holds value from port until you call for it

  Sub OpenPort()            'called early in the app, before the port is ever needed. This attaches the port, and opens it to listen.
    CPort = New IO.Ports.SerialPort

    Try
      CPort = My.Computer.Ports.OpenSerialPort("COM3", 9600)
    Catch ex As Exception
      MessageBox.Show("no port")
    End Try
  End Sub

  'this would be better as a property, but I don't know how Grasshopper handles properties
  Function GetValue() As String
    Return StoredValue
  End Function

  'this is fired by the port when it has data
  Private Sub CPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles CPort.DataReceived
    Dim HndlComPort As New HandleComPortDelegate(AddressOf HandleComPort)             'declare thread
    HndlComPort.Invoke() ' invoke a new delegate to digest the events

  End Sub

  Private Sub HandleComPort()      'background handler for com port

    TempBuffer &= CPort.ReadExisting  'append into tempbuffer
    If (Strings.Right(TempBuffer, 2) = vbCrLf) Then        'if end of item            'this may need to be changed, since Arduino's println may use cr or lf only. I can't remember at this point.
      StoredValue = TempBuffer               'offload
      TempBuffer = String.Empty               'reset
    End If

  End Sub

  'should be called when the port is no longer needed.
  Private Sub ClosePort()

    If CPort.IsOpen = True Then
      CPort.Close()
    End If
    CPort.Dispose()

  End Sub

#End Region
End Class
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Rob.  I have placed a few emails and a post on the Grasshopper forum about whether or not you can call different routines inside the script class.  But perhaps you could explain what the difference in the two methods would be?  Maybe I could try out both options and if one of them works then we know which way the script is called inside Grasshopper.  I think we're really close.  Thanks again.
Logged

Palmetto, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 138
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

No problem.

Here's the basics of what you need to try to accomplish with the class I sent you.

You need to call OpenPort once, preferably at the start of the program. This opens the port and listens to the Arduino.

at this point the class puts the port into a background thread, and attaches an event handler to it, returning control to your app. whenever the port gets new data, it raises an event that updates the variable in the grasshopper script class.

You need to call GetValue in the timer from grasshopper whenever you want to get the contents of the variable. This variable contains the contents of the last event raised by the serial port, which would be the entire contents of the buffer.

you need to call ClosePort once, when you no longer want the port to be connected to the Arduino.
 
If you can call separate subs / functions from grasshopper then you would want to call each item separately; open,  then getvalue each time you loop, and then close when you are done.

If you can't call multiple subs, then I would change the runscript sub to use an integer for the passed value instead of the boolean and work the code like this:

Code:

 Sub RunScript(ByVal StepNumber as Integer)
    select case StepNumber
      case 0
        OpenPort
      case 1
        print storedvalue
      case 2
        ClosePort
    end select
  End Sub


With this you would call RunScript 0 once early in the app, and then call RunScript 1 each time you wanted to get the info from the serial port, then call RunScript 2 when you wanted to close the port.

HTH,
Rob
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I know we're working with baby steps... but I really do appreciate your help... and I did make progress (although not quite there). So, I followed your advice and moved the "Call Open Port" command to outside the If/Else statement that activates the loop.  So, when I tested it (by changing the boolean toggle to true... I immediately get a pop-up error message (which seems different than my normal error messages) that just says "No Port" (see image below).  However, as soon as I click ok on that message, sure enough... I get a print out of the current stored value coming in over the Serial Port.  In this example, I just have a pot sending data to pin 0 so when I turn the knob I get a value somewhere between 0-1024... and sure enough the read out said 593... I had the knob turned to the middle.  Now, the problem is that it isn't streaming... it only gives me that one number.  If I turn the boolean value back to false, I get the same "No Port" message.  I've also noticed a weird phenomenon in that that if I flip it back to true... occasionally it gives me a different read out (assuming I turned the knob on the pot)... but after 2 or 3 times of changing the boolean toggle... it just continues to give me the same value... regardless of whether or not I turn the knob on the pot.  So, we're a lot closer than we have been... but it's still getting stuck somewhere.  If you have any suggestions... I would greatly appreciate it.  Here's the code (and I'll post the images and the URL's to the images below that)  Let me know if you can't see them.
Code:
 Sub RunScript(ByVal activate As Boolean)
    Call OpenPort()
    If activate Then
      
      Call GetValue()
      print(StoredValue)

    Else
      Call ClosePort()
      print("not receiving data")
    End If
  End Sub

#Region "Additional methods and Type declarations"

  ' I wrapped this in a class, but you would need to work it into the grasshopper class

  Private WithEvents CPort As IO.Ports.SerialPort      'port with events
  Private TempBuffer As String = String.Empty        'holds the input between events until we get a new line
  Private Delegate Sub HandleComPortDelegate()      'allows com port to run in a background thread without blocking
  Private StoredValue As String = String.Empty      'holds value from port until you call for it

  Sub OpenPort()            'called early in the app, before the port is ever needed. This attaches the port, and opens it to listen.
    CPort = New IO.Ports.SerialPort

    Try
      CPort = My.Computer.Ports.OpenSerialPort("COM3", 9600)
    Catch ex As Exception
      MessageBox.Show("no port")
    End Try
  End Sub

  'this would be better as a property, but I don't know how Grasshopper handles properties
  Function GetValue() As String
    Return StoredValue
  End Function

  'this is fired by the port when it has data
  Private Sub CPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles CPort.DataReceived
    Dim HndlComPort As New HandleComPortDelegate(AddressOf HandleComPort)             'declare thread
    HndlComPort.Invoke() ' invoke a new delegate to digest the events

  End Sub

  Private Sub HandleComPort()      'background handler for com port

    TempBuffer &= CPort.ReadExisting  'append into tempbuffer
    If (Strings.Right(TempBuffer, 2) = vbCrLf) Then        'if end of item            'this may need to be changed, since Arduino's println may use cr or lf only. I can't remember at this point.
      StoredValue = TempBuffer               'offload
      TempBuffer = String.Empty               'reset
    End If

  End Sub

  'should be called when the port is no longer needed.
  Private Sub ClosePort()

    If CPort.IsOpen = True Then
      CPort.Close()
    End If
    CPort.Dispose()

  End Sub





http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino_VB04.jpg
http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino_VB05.jpg
Logged

Palmetto, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 138
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just to clarify, my advice was to remove the if / else logic completely.

You will have a couple of issues with using the boolean value the way you have it. Basically you are trying to open the port / close the port multiple times. Every time you flip the bool to false, the port is closed an no more data is going to come in. Every time you flip it to true, you are trying to reopen the port. If it is already set to true then you are tring to reopen the already open port every time you call the loop.
 
If at all possible you need to only ever call OpenPort and ClosePort once.

The other thing to be aware of is that with a 1 second or even half second loop on the value change, you will have to move the pot a little and wait for the call to the port. I have built the basic circuit, and run my code sample from VB to test, and it works, but polling it at a half second makes in not so instant.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok... Something about what you last said hit me in the face (I know you've said it several times... but I guess repetition is the mother of all teachers)  You said that I should call the Open Port function only ONCE.  Which makes complete sense.  But, I was wrapping everything into one VB script component and then connecting a Timer component to that... So, every time the Timer component rebuilt the solution of anything that was connected to it (in this case the VB component that Opened the port, returned the current value, and then closed the port)... it was doing that over and over again...  I think my error has been that everything has been wrapped into only one VB component; when it should have been two.
So, what I've done now is to create two VB components... The first one is the Open/Close component which will open or close the port based on a boolean toggle.  This way, you can open up the Grasshopper definition and change the boolean toggle to True and the port will open only once... Note, I'm not connecting a Timer component to this VB script so it only updates when I change the boolean toggle.  Then, I create another VB component called Get Value... which does just that... But this time, I connect the Timer Component to this one so the Get Value function gets called everytime the Timer Component tells it to rebuild the solution... Does that logic make sense?  
So here's the thing... I'm no longer getting the "No Port" error message... but, I'm also not getting any value being returned out of the Get Value component. I've tried several different methods... I've tried passing the boolean value to the Get Value component and alling the function only when it's true (see image below)... and I've also just tried to have the 2 individual script components without any connections between the two... but I'm still not getting any values returned in the out box.  The code for both components is below and if you can see any errors in my logic or in the code, please let me know.  Thanks again.

Open/Close Component

 
Code:
 Sub RunScript(ByVal activate As Boolean)
    
    If activate Then
      Call OpenPort()
    Else
      Call ClosePort()
    End If
    A = activate
  End Sub

#Region "Additional methods and Type declarations"

  ' I wrapped this in a class, but you would need to work it into the grasshopper class

  Private WithEvents CPort As IO.Ports.SerialPort      'port with events
  Private TempBuffer As String = String.Empty        'holds the input between events until we get a new line
  Private Delegate Sub HandleComPortDelegate()      'allows com port to run in a background thread without blocking
  Private StoredValue As String = String.Empty      'holds value from port until you call for it

  Sub OpenPort()            'called early in the app, before the port is ever needed. This attaches the port, and opens it to listen.
    CPort = New IO.Ports.SerialPort

    Try
      CPort = My.Computer.Ports.OpenSerialPort("COM3", 9600)
    Catch ex As Exception
      MessageBox.Show("no port")
    End Try
  End Sub

  'should be called when the port is no longer needed.
  Private Sub ClosePort()

    If CPort.IsOpen = True Then
      CPort.Close()
    End If
    CPort.Dispose()

  End Sub
#End Region

Get Value Component

Code:
 Sub RunScript(ByVal activate As Boolean)
    
    If activate Then
      Call GetValue()
      print(StoredValue)
    Else
      print("not receiving data")
    End If
  End Sub

#Region "Additional methods and Type declarations"

  ' I wrapped this in a class, but you would need to work it into the grasshopper class

  Private WithEvents CPort As IO.Ports.SerialPort      'port with events
  Private TempBuffer As String = String.Empty        'holds the input between events until we get a new line
  Private Delegate Sub HandleComPortDelegate()      'allows com port to run in a background thread without blocking
  Private StoredValue As String = String.Empty      'holds value from port until you call for it


  'this would be better as a property, but I don't know how Grasshopper handles properties
  Function GetValue() As String
    Return StoredValue
  End Function

  'this is fired by the port when it has data
  Private Sub CPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles CPort.DataReceived
    Dim HndlComPort As New HandleComPortDelegate(AddressOf HandleComPort)             'declare thread
    HndlComPort.Invoke() ' invoke a new delegate to digest the events

  End Sub

  Private Sub HandleComPort()      'background handler for com port

    TempBuffer &= CPort.ReadExisting  'append into tempbuffer
    If (Strings.Right(TempBuffer, 2) = vbCrLf) Then        'if end of item            'this may need to be changed, since Arduino's println may use cr or lf only. I can't remember at this point.
      StoredValue = TempBuffer               'offload
      TempBuffer = String.Empty               'reset
    End If

  End Sub
#End Region

http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino_VB07.jpg
« Last Edit: August 28, 2009, 11:38:23 am by andyopayne » Logged

Palmetto, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 138
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Andy,  

You have the right idea now, but I think that the problem is that if you are using two components, thus creating two instances of the same class. Each instance has no way of talking to each other, or using the values that exist in each other. In other words, you are creating instance A and opening the port, but then checking the variable in instance B which doesn't actually have the port opened.

I think that the basic logic behind your boolean switch approach was getting close, but I think you needed to use a select case method so that you have 3 choices instead of two. With the boolean you only have a true / false, when you need 3 choices so that you can open / listen / close.

I would create an integer instead of the boolean and then call the script from the timer. Set the int to 0 (open), then set it to 1 (listen) for the duration of the app, and then set it to 2 (close) when you want to close the port.

use the code below in the script for the call.

Code:
Sub RunScript(ByVal StepNumber as Integer)
    select case StepNumber
      case 0
        OpenPort
      case 1
        print storedvalue
      case 2
        ClosePort
    end select
  End Sub


I had a nice reply to the first post that you made, but hit close on accident and lost it. One thing that I wanted to bring up based on that post that you have mentioned here again. Does the timer rebuild the solution at each tick? If so none of this will work, since it is completely dependent upon the class being compiled, and an instance of the object continuing to exist for the duration of the apps life, or at least as long as you want the port to be open.

Rob
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Rob... Timers are new to the latest version of Grasshopper... so to be honest... I'm a little new them as well.  Here is a what is found under the help menu about the Timer Component:

Timers are object which fire update events at specified intervals. This process is reasonably dangerous since updates might occur when you do not expect them, so please be careful when using them, and only use a timer when you have no other option.

By default a new timer is not enabled. You can enable it by double clicking on the object or via the context menu. However, enabling a timer is no guarantee that it will fire update events.

First, there is a global Timer Abort which has the power to disable all timers in Grasshopper. Whenever a timer is enabled for the first time, the Global Abort will appear in the Windows notification bar. When the icon is green, it means the Global Abort is off and timers are allowed to fire events. When the icon is red, all timers are blocked. Blocked timers are displayed with a red icon instead of the timer icon on the canvas. Double clicking on the notification icon on the windows taskbar will toggle the Global Abort state.

Secondly, timers only fire events when they can make a difference. Before a timer will tell Grasshopper to recompute the solution it will erase certain objects. These are called the target of the timer object. You can add a target to a timer by click+dragging from the arrow area to the right of the timer. Drag the wire onto another object, and it will be added to the target list. You can remove objects from the target list by tracing over an existing target wire while holding the Control key.

So... I think I had an error in my last image that I sent because my timer component was drawn in Red... and not Green.  I don't think my Timer component was actually firing events... I think I can figure that part out though by changing the Global Abort method.  
Secondly, you mentioned that I should not use a boolean toggle, but instead use a Case method, where case 0 calls the Open Port function, 1 calls the Get Value, and 2 closes the port... But, were you saying that code should all go into 1 VB component (instead of 2 like my last example) where I feed an integer variable called StepNumber into the Script... and depending on that number it will call one of the different functions.  Would you then connect the timer component to that one component?  
« Last Edit: August 28, 2009, 12:22:46 pm by andyopayne » Logged

Palmetto, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 138
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Andy,

Quote
.. were you saying that code should all go into 1 VB component (instead of 2 like my last example) where I feed an integer variable called StepNumber into the Script... and depending on that number it will call one of the different functions.  Would you then connect the timer component to that one component?  
Exactly. Use one script, and pass the int through the timer.

I do have a concern with the following:

Quote
Before a timer will tell Grasshopper to recompute the solution it will erase certain objects. These are called the target of the timer object.

It is quite possible that the timer will erase the script object and create a new instance, which would cause the port object to vanish / close, but I'm not sure. You'll just have to try my previous suggestion an see what happens.

-Rob
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Robert... I'm bit confused when you said "Pass the int through the timer"... I think the int has to be passed to the VB script... and the Timer just rebuilds the solution at a given time interval.  (See the images below)  In the first image, I've just created 3 integer components which essentially just hold an individual number.  By connecting different integer components to the VB component... I will call a different case and thus a different function.  The second image shows the exact same step, only this time I'm using a slider which can be changed from it's lower limit of 0 to it's upper limit of 2.  They should basically do the same thing.  
But, I do agree with you that there does seem to be an issue with the Timer component erasing the script object (I wont be able to test the script til I get home tonight).  I'm not really sure what to do about that either.  There was a pre-cursor to the Timer component... basically one of the Grasshopper forum members (Giulio Piacentino) wrote this C# component that does more or less what the new Timer component that is built into Grasshopper does.  Here's a link to the component (It's called The Engine): http://www.giuliopiacentino.com/grasshopper-tools/.  This code is written in C# but it is posted below.  It's possible that this script does not erase the instance of the port.  I will try out both and hopefully be able to provide some feedback.
Code:
 bool RunScript(bool isOn, int speed, int resetAt)
  {

    //TheGHEngine
    //Written by Giulio Piacentino
    //Version 2009 06 06
    //more tools at www.giuliopiacentino.com/grasshopper-tools/
    
    //Note: a static constructor is defined in the additional section below
    
    //Set interval
    if(Script_Runtime_Instance.timer.Interval
      //"Script_Runtime_Instance" is the real name of "Grasshopper_Custom_Script"
    != speed){
      Script_Runtime_Instance.timer.Interval = (speed == 0 ? 1000 : speed);
    }
    
    //Set static variables
    Script_Runtime_Instance.eventOn = isOn;
    
    //Start timer
    if(isOn){
      Script_Runtime_Instance.timer.Start();
    } else {
      Script_Runtime_Instance.timer.Stop();
    }
    
    //Reset
    if(resetAt != 0 && resetAge != resetAt){
      resetAge = resetAt;
    }
    
    //Return value
    C = Script_Runtime_Instance.frameCount;
    
  }

#region "Additional methods and Type declarations"

  static public System.Windows.Forms.Timer timer;
  static public int frameCount = 0;
  static public bool eventOn = true;
  static public int resetAge = int.MaxValue;
  
  //Static constructor
  static Script_Runtime_Instance(){
    
    //Create the timer on this static thread (other types of timers won't work)
    timer = new System.Windows.Forms.Timer();
    
    //Assign the delegate only once
    timer.Tick += new EventHandler(CheckTime);
    
  }
  
  static private void CheckTime(Object myObject, EventArgs myEventArgs){
    if(IsSolutionRunning()){
      if(eventOn){
        //System.Windows.Forms.MessageBox.Show("Not updated in time");
      } else {
        System.Windows.Forms.MessageBox.Show("Checktime has been disposed even if the solution was running");
        timer.Stop();
      }
    } else {
      if(eventOn){
        //System.Windows.Forms.MessageBox.Show("Checktime's doing great");
        if(resetAge == frameCount)
          frameCount = -1;
        frameCount++;
        RedefineSolution();
      } else {
        //System.Windows.Forms.MessageBox.Show("Checktime will be stopped because it's bedtime");
        timer.Stop();
      }
    }
  }
  
  static public bool IsSolutionRunning(){
    return Grasshopper.Plugin.EH_InstanceServer.ActiveDefinition.SolutionState
      == Grasshopper.Kernel.EH_ProcessStep.Process;
  }
  
  static public void RedefineSolution(){
    Grasshopper.Plugin.EH_InstanceServer.ActiveDefinition.NewSolution(true, false);
  }

  //
  
#endregion
}

http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino_VB08.jpg
http://www.liftarchitects.com/storage/research/Grasshopper%20to%20Arduino_VB09.jpg
Logged

Palmetto, FL USA
Offline Offline
Full Member
***
Karma: 0
Posts: 138
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry for the confusion. What you have is exactly what I would do. Of course it all depends upon the object staying alive, and what they mean by rebuilding the object.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I've tried a lot of different methods, where I call the different case numbers (putting all of the functions into 1 VB script)... and I've tried connecting both the Timer Component or the Engine component to see if I can get it to auto update... but still nothing... I did notice something though.  I remember mentioning that I was getting an error message that just said "No Port"... and I found it odd because it seemed different than the other error messages that I have gotten in the past.  BTW, I'm still getting these messages too (even with the latest code tests)... and it happens every time I take the slider to 0 (in which case I call the Open Port function).  In looking at the code, I see you placed the following code:
Code:
Catch ex As Exception
      MessageBox.Show("no port")
    End Try
It seems like this is why the error message is popping up and I was wondering if I'm ever really evening establishing a connection to the COM port.  Do you know why this error message would be happening (it happens even if the Timer component is deleted from the definition, so I think it's a completely separate issue).  Would you mind explaining the Open Port function a little bit... Man, this has to be the longest running problem thread on the forum... I appreciate all of you willingness to help though. (I have learned a lot).
Logged

Pages: 1 2 [3] 4 5   Go Up
Jump to: