Products for USB Sensing and Control
It is currently Wed Jun 19, 2013 12:17 pm

All times are UTC - 7 hours [ DST ]




Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Wed Mar 14, 2012 9:35 am 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
I feel so left out, every other supported language has its own forum :D

I did have a phidget related question:
With a 1062, my PositionChange callback stops being called after a while. I can move the motor back and forth several times, and everything works fine, but eventually no more call back. The motor still answer to target position, and acceleration changes.
I get no error message. It just stops working while the motor is advancing to a target, not just after I made a target change.
Is that something you sometimes see in other languages too?
I'm doing a Ruby/Tk sample interface on Linux.


Top
 Profile Send private message  
 
PostPosted: Thu Mar 15, 2012 11:19 am 
Offline
Phidgetly

Joined: Tue Nov 16, 2010 4:27 pm
Posts: 45
What are you doing in the main program while the PositionChange is being triggered?


Top
 Profile Send private message  
 
PostPosted: Thu Mar 15, 2012 12:04 pm 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
mphi wrote:
What are you doing in the main program while the PositionChange is being triggered?


My main program is a Ruby/Tk, so it is in the TkMainLoop waiting for events.

My handler is registered like this:

@sc.on_position_change do |device, stepper, position, obj|
@vars['actual_position'].value = position
end

@vars[] is an array of TkVariables which are tied to some Tk widgets.
@vars['actual_position'] in particular is tied to a slider and a text area.
So when the value of that TkVariable changes, that triggers some Tk action that updates the slider position and text area.

I have wrapped the assignment within a begin/rescue clause, but no exception was triggered. (Not surprising since from the Ruby side, this is just an assignment)

The ruby wrapper documentation does have this warning:
"As this runs in it's own thread, be sure that all errors are properly handled or the thread will halt and not fire any more."
I assume this is a thread in the phidget library? I don't see anything in the ruby code wrapper that starts a new thread.


Top
 Profile Send private message  
 
PostPosted: Thu Mar 15, 2012 6:23 pm 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
A bit more info: I added a couple of LOG calls in CPHIDGETDATA(Stepper) in cphidgetstepper.c line 154

Line 147 (I never get this message)

if (length < 0) {
LOG(PHIDGET_LOG_VERBOSE, "!!!!!!!!!!!!!!!!!!!!!! Negative length");
return EPHIDGET_INVALIDARG;
}

and this one.

LOG(PHIDGET_LOG_VERBOSE, "----- in CPHIDGETDATA");

//Parse device packets - store data locally
switch(phid->phid.deviceIDSpec)
{

This stops printing when I stop getting position events.
So that function doesn't get called anymore.


Top
 Profile Send private message  
 
PostPosted: Fri Mar 16, 2012 12:33 am 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
I added some instrumentation to cphidgetstepper.c.
When I stop getting callbacks the read thread is still alive.

What happens is that in CPhidget_read (cphidget.c) it blocks on the call to
result= phid->fptrData((CPhidgetHandle)phid,
phid->lastReadPacket,
phid->inputReportByteLength);

That function is called several times before. At one point it just doesn't return...


Top
 Profile Send private message  
 
PostPosted: Mon Mar 19, 2012 11:33 pm 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
I got a chance to look at this a bit more and from what I can tell, this is related to the Ruby garbage collector. If I turn it off the callback behaves as expected, no matter how many times I move the motor.
Once I re-enable the GC, the program either crashes, or the callback stops working.
There is obviously trading of data between Ruby, the ffi library, and the phidget21 library. So maybe the GC is reclaiming memory that it shouldn't...


Top
 Profile Send private message  
 
PostPosted: Tue Mar 20, 2012 11:26 am 
Offline
Phidgetly

Joined: Tue Nov 16, 2010 4:27 pm
Posts: 45
How were you able to turn off the Ruby garbage collector?

While conducting more research on ffi, I came across this page:
https://github.com/ffi/ffi/wiki/Examples

In the Callback section, it warns that the Proc will get garbage collected if it is out of scope. I am not sure, but this may give us an idea into what is happening.


Top
 Profile Send private message  
 
PostPosted: Tue Mar 20, 2012 11:54 am 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
You can call GC.disable
http://www.ruby-doc.org/docs/ProgrammingRuby/html/ref_m_gc.html

The callback is registered on line 73 of
https://github.com/kreynolds/phidgets-ffi/blob/master/lib/phidgets-ffi/stepper.rb

I don't see the block being saved anywhere. (come to think about it, I don't understand the mechanism for the yield to get access to that block)
Maybe the solution is as simple as assigning it to an object variable so that it isn't collected...
I'll have to try that tonight.


Top
 Profile Send private message  
 
PostPosted: Wed Mar 21, 2012 1:45 pm 
Offline
Phidgetly

Joined: Mon Feb 13, 2012 10:31 pm
Posts: 31
It wasn't obvious to me how the handling of the callback block was tied to the callback function. This simple test program cleared that up:

Code:
#!/usr/bin/env ruby
def register(&blk)
  $foo = Proc.new { yield }
end
register { puts "I'm in here" }
$foo.call
$foo.call { puts "hey, what't going on" }

So storing the block didn't make any difference.
But storing the obj argument did. With this code my callback always works. Not sure if that fixes the problem, or it masks the memory issue though.

Code:
def on_position_change(obj=nil, &block)
  @on_position_change_obj = obj
  @on_block = block                          # this didn't do anything       
  @obj_ptr = pointer_for(obj)                # but this did
  @on_position_change = Proc.new { |device, obj_ptr, index, position|
      yield self, @steppers[index], position, object_for(obj_ptr)
  }
  #Klass.set_OnPositionChange_Handler(@handle, @on_position_change, pointer_for(obj))
  Klass.set_OnPositionChange_Handler(@handle, @on_position_change, @obj_ptr)
end


Top
 Profile Send private message  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 7 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group