phidgets-ffi 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/.gitignore +3 -0
  2. data/LICENSE +1 -1
  3. data/README.rdoc +92 -42
  4. data/examples/accelerometer.rb +39 -0
  5. data/examples/advanced_servo.rb +94 -0
  6. data/examples/analog.rb +43 -0
  7. data/examples/bridge.rb +57 -0
  8. data/examples/dictionary.rb +46 -31
  9. data/examples/encoder.rb +59 -0
  10. data/examples/frequency_counter.rb +63 -0
  11. data/examples/gps.rb +91 -0
  12. data/examples/interface_kit_with_block.rb +68 -0
  13. data/examples/interface_kit_without_block.rb +60 -0
  14. data/examples/ir.rb +157 -0
  15. data/examples/led.rb +36 -0
  16. data/examples/manager.rb +16 -10
  17. data/examples/motor_control.rb +108 -0
  18. data/examples/{ffi → raw-ffi}/dictionary.rb +11 -1
  19. data/examples/{ffi → raw-ffi}/interface_kit.rb +19 -2
  20. data/examples/{ffi → raw-ffi}/library_version.rb +0 -0
  21. data/examples/{ffi → raw-ffi}/log.rb +0 -0
  22. data/examples/{ffi → raw-ffi}/manager.rb +6 -3
  23. data/examples/rfid.rb +63 -0
  24. data/examples/servo.rb +45 -30
  25. data/examples/spatial.rb +75 -0
  26. data/examples/stepper.rb +87 -0
  27. data/examples/temperature_sensor.rb +49 -0
  28. data/examples/text_lcd.rb +101 -0
  29. data/lib/phidgets-ffi.rb +34 -3
  30. data/lib/phidgets-ffi/accelerometer.rb +122 -0
  31. data/lib/phidgets-ffi/advanced_servo.rb +304 -0
  32. data/lib/phidgets-ffi/analog.rb +111 -0
  33. data/lib/phidgets-ffi/bridge.rb +167 -0
  34. data/lib/phidgets-ffi/common.rb +506 -103
  35. data/lib/phidgets-ffi/dictionary.rb +136 -23
  36. data/lib/phidgets-ffi/encoder.rb +196 -0
  37. data/lib/phidgets-ffi/error.rb +8 -3
  38. data/lib/phidgets-ffi/ffi/accelerometer.rb +30 -0
  39. data/lib/phidgets-ffi/ffi/advanced_servo.rb +73 -0
  40. data/lib/phidgets-ffi/ffi/analog.rb +29 -0
  41. data/lib/phidgets-ffi/ffi/bridge.rb +44 -0
  42. data/lib/phidgets-ffi/ffi/common.rb +51 -34
  43. data/lib/phidgets-ffi/ffi/constants.rb +3 -1
  44. data/lib/phidgets-ffi/ffi/dictionary.rb +25 -20
  45. data/lib/phidgets-ffi/ffi/encoder.rb +32 -0
  46. data/lib/phidgets-ffi/ffi/frequency_counter.rb +38 -0
  47. data/lib/phidgets-ffi/ffi/gps.rb +32 -0
  48. data/lib/phidgets-ffi/ffi/interface_kit.rb +26 -23
  49. data/lib/phidgets-ffi/ffi/ir.rb +50 -0
  50. data/lib/phidgets-ffi/ffi/led.rb +40 -0
  51. data/lib/phidgets-ffi/ffi/log.rb +7 -6
  52. data/lib/phidgets-ffi/ffi/manager.rb +35 -20
  53. data/lib/phidgets-ffi/ffi/motor_control.rb +66 -0
  54. data/lib/phidgets-ffi/ffi/rfid.rb +36 -0
  55. data/lib/phidgets-ffi/ffi/servo.rb +16 -15
  56. data/lib/phidgets-ffi/ffi/spatial.rb +40 -0
  57. data/lib/phidgets-ffi/ffi/stepper.rb +56 -0
  58. data/lib/phidgets-ffi/ffi/temperature_sensor.rb +42 -0
  59. data/lib/phidgets-ffi/ffi/text_lcd.rb +55 -0
  60. data/lib/phidgets-ffi/frequency_counter.rb +148 -0
  61. data/lib/phidgets-ffi/gps.rb +181 -0
  62. data/lib/phidgets-ffi/interface_kit.rb +205 -92
  63. data/lib/phidgets-ffi/ir.rb +290 -0
  64. data/lib/phidgets-ffi/led.rb +112 -0
  65. data/lib/phidgets-ffi/log.rb +14 -2
  66. data/lib/phidgets-ffi/manager.rb +143 -26
  67. data/lib/phidgets-ffi/motor_control.rb +497 -0
  68. data/lib/phidgets-ffi/phidgets-ffi.rb +15 -2
  69. data/lib/phidgets-ffi/rfid.rb +220 -0
  70. data/lib/phidgets-ffi/servo.rb +103 -61
  71. data/lib/phidgets-ffi/spatial.rb +306 -0
  72. data/lib/phidgets-ffi/stepper.rb +370 -0
  73. data/lib/phidgets-ffi/temperature_sensor.rb +157 -0
  74. data/lib/phidgets-ffi/text_lcd.rb +298 -0
  75. data/lib/phidgets-ffi/version.rb +1 -1
  76. data/phidgets-ffi.gemspec +2 -2
  77. metadata +89 -76
  78. data/examples/ffi/servo.rb +0 -67
  79. data/examples/interface_kit.rb +0 -20
@@ -1,6 +1,19 @@
1
1
  module Phidgets
2
2
  module FFI
3
+
3
4
  extend ::FFI::Library
4
- ffi_lib '/Library/Frameworks/Phidget21.framework/Versions/Current/Phidget21'
5
+
6
+ if Config::CONFIG['target_os'] =~ /darwin/ #Mac OS X
7
+ ffi_lib '/Library/Frameworks/Phidget21.framework/Versions/Current/Phidget21'
8
+ else # Linux
9
+ ffi_lib '/usr/lib/libphidget21.so'
10
+ end
11
+
5
12
  end
6
- end
13
+ end
14
+
15
+
16
+
17
+
18
+
19
+
@@ -0,0 +1,220 @@
1
+ module Phidgets
2
+
3
+ # This class represents a CPhidgetRFID.
4
+ class RFID
5
+
6
+ Klass = Phidgets::FFI::CPhidgetRFID
7
+ include Phidgets::Common
8
+
9
+ # Collection of digital outputs
10
+ # @return [RFIDOutputs]
11
+ attr_reader :outputs
12
+
13
+ attr_reader :attributes
14
+
15
+ # The attributes of a PhidgetRFID
16
+ def attributes
17
+ super.merge({
18
+ :outputs => outputs.size,
19
+ :antenna => antenna,
20
+ :led => led,
21
+ })
22
+ end
23
+
24
+ # Sets an output change handler callback function. This is called when a digital output on the PhidgetRFID board has changed.
25
+ #
26
+ # @param [String] obj Object to pass to the callback function. This is optional.
27
+ # @param [Proc] Block When the callback is executed, the device and object are yielded to this block.
28
+ # @example
29
+ # rfid.on_output_change do |device, output, state, obj|
30
+ # print "Digital Output #{output.index}, changed to #{state}\n"
31
+ # end
32
+ # 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.
33
+ # @return [Boolean] returns true or raises an error
34
+ def on_output_change(obj=nil, &block)
35
+ @on_output_change_obj = obj
36
+ @on_output_change = Proc.new { |device, obj_ptr, index, state|
37
+ yield self, @outputs[index], (state == 0 ? false : true), object_for(obj_ptr)
38
+ }
39
+ Klass.set_OnOutputChange_Handler(@handle, @on_output_change, pointer_for(obj))
40
+ end
41
+
42
+ # Sets a tag handler callback function. This is called when a new tag is seen by the reader. The event is only fired one time for a new tag, so the tag has to be removed and then replaced before another tag gained event will fire.
43
+ #
44
+ # @param [String] obj Object to pass to the callback function. This is optional.
45
+ # @param [Proc] Block When the callback is executed, the device and object are yielded to this block.
46
+ # @example
47
+ # rfid.on_tag do |device, tag, obj|
48
+ # puts "Tag #{tag} detected"
49
+ # end
50
+ # 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.
51
+ # @return [Boolean] returns true or raises an error
52
+ def on_tag(obj=nil, &block)
53
+ @on_tag_obj = obj
54
+ @on_tag = Proc.new { |device, obj_ptr, tag|
55
+ yield self, convert_int_to_hex(tag), object_for(obj_ptr)
56
+ }
57
+ Klass.set_OnTag_Handler(@handle, @on_tag, pointer_for(obj))
58
+ end
59
+
60
+ # Sets a tag lost handler callback function. This is called when a tag is removed from the reader
61
+ #
62
+ # @param [String] obj Object to pass to the callback function. This is optional.
63
+ # @param [Proc] Block When the callback is executed, the device and object are yielded to this block.
64
+ # @example
65
+ # rfid.on_tag_lost do |device, tag, obj|
66
+ # puts "Tag #{tag} removed"
67
+ # end
68
+ # 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.
69
+ # @return [Boolean] returns true or raises an error
70
+ def on_tag_lost(obj=nil, &block)
71
+ @on_tag_lost_obj = obj
72
+ @on_tag_lost = Proc.new { |device, obj_ptr, tag|
73
+ yield self, convert_int_to_hex(tag), object_for(obj_ptr)
74
+ }
75
+ Klass.set_OnTagLost_Handler(@handle, @on_tag_lost, pointer_for(obj))
76
+ end
77
+
78
+ # Returns the antenna state of the Phidget.
79
+ #
80
+ # @return [Boolean] returns the ratiometric state or raises an error
81
+ def antenna
82
+ ptr = ::FFI::MemoryPointer.new(:int)
83
+ Klass.getAntennaOn(@handle, ptr)
84
+ (ptr.get_int(0) == 0) ? false : true
85
+ end
86
+
87
+ # Sets the antenna state of the Phidget. True turns the antenna on, false turns it off. The antenna if by default turned off, and needs to be explicitely activated before tags can be read. Control over the antenna allows multiple readers to be used in close proximity, as multiple readers will interfere with each other if their antenna's are activated simultaneously.
88
+ # @param [Boolean] new_state new antenna state
89
+ # @return [Boolean] returns the antenna state, or raises an error
90
+ def antenna=(new_state)
91
+ tmp = new_state ? 1 : 0
92
+ Klass.setAntennaOn(@handle, tmp)
93
+ new_state
94
+ end
95
+
96
+ # Returns the LED state.
97
+ #
98
+ # @return [Boolean] returns the LED state or raises an error
99
+ def led
100
+ ptr = ::FFI::MemoryPointer.new(:int)
101
+ Klass.getLEDOn(@handle, ptr)
102
+ (ptr.get_int(0) == 0) ? false : true
103
+ end
104
+
105
+ # Sets the LED. True turns the LED on, false turns it off. The LED is by default turned off.
106
+ # @param [Boolean] new_state new LED state
107
+ # @return [Boolean] returns the LED state or raises an error
108
+ def led=(new_state)
109
+ tmp = new_state ? 1 : 0
110
+ Klass.setLEDOn(@handle, tmp)
111
+ new_state
112
+ end
113
+
114
+ # Returns the last tag read by the reader. This may or may not still be on the reader - use {Phidgets::RFID#tag_present} to find out.
115
+ #
116
+ # @return [String] returns the last tag or raises an error
117
+ def last_tag
118
+ tag_size = 5
119
+ tag_ffi = ::FFI::MemoryPointer.new(:uchar, tag_size)
120
+ Klass.getLastTag(@handle, tag_ffi)
121
+
122
+ convert_int_to_hex(tag_ffi)
123
+ end
124
+
125
+ # Returns the value indicating whether or not a tag is on the reader.
126
+ #
127
+ # @return [Boolean] returns a value indicating whether or not a tag is on the reader, or raises an error
128
+ def tag_present
129
+ ptr = ::FFI::MemoryPointer.new(:int)
130
+ Klass.getTagStatus(@handle, ptr)
131
+ (ptr.get_int(0) == 0) ? false : true
132
+ end
133
+
134
+ # This class represents an digital output for a PhidgetRFID All the properties of an digital output are stored and modified in this class.
135
+ class RFIDOutputs
136
+ Klass = Phidgets::FFI::CPhidgetRFID
137
+
138
+ private
139
+ def initialize(handle, index)
140
+ @handle, @index = handle, index.to_i
141
+ end
142
+
143
+ public
144
+
145
+ # Displays data for the digital output
146
+ def inspect
147
+ "#<#{self.class} @index=#{index}, @state=#{state}>"
148
+ end
149
+
150
+ # @return [Integer] returns index of the digital output, or raises an error.
151
+ def index
152
+ @index
153
+ end
154
+
155
+ # Sets the state of the digital output, or raises an error.
156
+ # @param [Boolean] new_state new state
157
+ # @return [Boolean] sets the state of the digital output, or raises an error.
158
+ def state=(new_state)
159
+ tmp = new_state ? 1 : 0
160
+ Klass.setOutputState(@handle, @index, tmp)
161
+ new_state
162
+ end
163
+
164
+ # @return [Boolean] returns state of the digital output, or raises an error.
165
+ def state
166
+ ptr = ::FFI::MemoryPointer.new(:int)
167
+ Klass.getOutputState(@handle, @index, ptr)
168
+ (ptr.get_int(0) == 0) ? false : true
169
+ end
170
+
171
+ # @return [Boolean] returns true if the state is true.
172
+ def on
173
+ state == true
174
+ end
175
+ alias_method :on?, :on
176
+
177
+ # @return [Boolean] returns true if the state is off.
178
+ def off
179
+ !on
180
+ end
181
+ alias_method :off?, :off
182
+ end
183
+
184
+ private
185
+
186
+ def load_device_attributes
187
+ load_outputs
188
+ end
189
+
190
+ def load_outputs
191
+ ptr = ::FFI::MemoryPointer.new(:int)
192
+ Klass.getOutputCount(@handle, ptr)
193
+
194
+ @outputs = []
195
+ ptr.get_int(0).times do |i|
196
+ @outputs << RFIDOutputs.new(@handle, i)
197
+ end
198
+ end
199
+
200
+ def convert_int_to_hex(int_tag)
201
+ tag_string = []
202
+ 5.times { |i|
203
+ if int_tag[i].get_uchar(0).to_s(16).size == 1 #ruby removes leading 0, so we will put the 0 back in.
204
+ tag_string[i] = "0#{int_tag[i].get_uchar(0).to_s(16)}"
205
+ else
206
+ tag_string[i] = int_tag[i].get_uchar(0).to_s(16)
207
+ end
208
+ }
209
+ tag_string
210
+ end
211
+
212
+ def remove_specific_event_handlers
213
+ Klass.set_OnOutputChange_Handler(@handle, nil, nil)
214
+ Klass.set_OnTag_Handler(@handle, nil, nil)
215
+ Klass.set_OnTagLost_Handler(@handle, nil, nil)
216
+ end
217
+
218
+ end
219
+
220
+ end
@@ -1,112 +1,154 @@
1
1
  module Phidgets
2
- class ServoController
3
2
 
3
+ # This class represents a PhidgetServo.
4
+ class Servo
5
+
4
6
  Klass = Phidgets::FFI::CPhidgetServo
5
7
  include Phidgets::Common
6
8
 
9
+ # Collection of servo motors
10
+ # @return [ServoServos]
7
11
  attr_reader :servos
8
-
9
- def initialize(serial_number=-1, &block)
10
- create
11
- open(serial_number)
12
- wait_for_attachment
13
- load_servos
14
- if block_given?
15
- yield self
16
- close
17
- delete
18
- end
19
- end
20
-
12
+
13
+ attr_reader :attributes
14
+
15
+ # The attributes of a PhidgetServo
21
16
  def attributes
22
17
  super.merge({
23
18
  :servos => servos.size,
24
19
  })
25
20
  end
26
21
 
27
- def on_change(obj=nil, &block)
28
- @on_change_obj = obj
29
- @on_change = Proc.new { |device, obj_ptr, index, position|
30
- yield @servos[index], position, object_for(obj_ptr)
22
+ # Sets a position change handler callback function. This is called when a the servo position has changed.
23
+ #
24
+ # @param [String] obj Object to pass to the callback function. This is optional.
25
+ # @param [Proc] Block When the callback is executed, the device and object are yielded to this block.
26
+ # @example
27
+ # servo.on_position_change do |motor, position, obj|
28
+ # puts "Moving servo #{motor.index} to #{position}"
29
+ # end
30
+ # 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.
31
+ # @return [Boolean] returns true or raises an error
32
+ def on_position_change(obj=nil, &block)
33
+ @on_position_change_obj = obj
34
+ @on_position_change = Proc.new { |device, obj_ptr, index, position|
35
+ yield self, @servos[index], position, object_for(obj_ptr)
31
36
  }
32
- Klass.set_OnPositionChange_Handler(@handle, @on_change, pointer_for(obj))
37
+ Klass.set_OnPositionChange_Handler(@handle, @on_position_change, pointer_for(obj))
33
38
  end
34
-
35
- private
36
-
37
- def load_servos
38
- ptr = ::FFI::MemoryPointer.new(:int)
39
- Klass.getMotorCount(@handle, ptr)
40
-
41
- @servos = []
42
- ptr.get_int(0).times do |i|
43
- @servos << Servo.new(@handle, i)
44
- end
45
- end
46
- end
47
-
48
- class Servo
39
+
40
+ # This class represents a servo motor for a PhidgetServo. All the properties of an servo motor are stored and modified in this class.
41
+ class ServoServos
49
42
  Klass = Phidgets::FFI::CPhidgetServo
50
43
 
51
- attr_reader :index
52
-
44
+ private
53
45
  def initialize(handle, index)
54
46
  @handle, @index = handle, index.to_i
55
47
  end
56
-
48
+
49
+ public
50
+ # Displays data for the servo motor.
51
+ def inspect
52
+ "#<#{self.class} @index=#{index}, @engaged=#{engaged}, @position_min=#{position_min}, @position_max=#{position_max}, @type=#{type}>"
53
+ end
54
+
55
+ # @return [Integer] returns the index of the servo motor, or raises an error.
56
+ def index
57
+ @index
58
+ end
59
+
60
+ # @return [Boolean] returns the engaged state of a servo motor, or raises an error.
57
61
  def engaged
58
- ptr = ::FFI::MemoryPointer.new(:int, 1)
62
+ ptr = ::FFI::MemoryPointer.new(:int)
59
63
  Klass.getEngaged(@handle, @index, ptr)
60
64
  (ptr.get_int(0) == 0) ? false : true
61
65
  end
62
- alias_method :engaged?, :engaged
63
-
64
- def engaged=(val)
65
- tmp = val ? 1 : 0
66
- Klass.setEngaged(@handle, @index, tmp)
67
66
 
68
- val
67
+ # Sets the engaged state of a servo motor, or raises an error.
68
+ # @param [Boolean] new_state new state
69
+ # @return [Boolean] returns engaged state of a servo motor, or raises an error.
70
+ def engaged=(new_state)
71
+ tmp = new_state ? 1 : 0
72
+ Klass.setEngaged(@handle, @index, tmp)
73
+ new_state
69
74
  end
70
-
71
- def max
72
- ptr = ::FFI::MemoryPointer.new(:double, 1)
73
- Klass.getPositionMax(@handle, @index, ptr)
75
+
76
+ # @return [Float] returns the largest position value that the servo motor will accept, or raises an error.
77
+ def position_min
78
+ ptr = ::FFI::MemoryPointer.new(:double)
79
+ Klass.getPositionMin(@handle, @index, ptr)
74
80
  ptr.get_double(0)
75
81
  end
76
-
77
- def min
78
- ptr = ::FFI::MemoryPointer.new(:double, 1)
79
- Klass.getPositionMin(@handle, @index, ptr)
82
+
83
+ # @return [Float] returns the largest position value that the servo motor will accept, or raises an error.
84
+ def position_max
85
+ ptr = ::FFI::MemoryPointer.new(:double)
86
+ Klass.getPositionMax(@handle, @index, ptr)
80
87
  ptr.get_double(0)
81
88
  end
82
-
89
+
90
+ # @return [Float] returns the position of the servo motor, or raises an error.
83
91
  def position
84
- ptr = ::FFI::MemoryPointer.new(:double, 1)
92
+ ptr = ::FFI::MemoryPointer.new(:double)
85
93
  Klass.getPosition(@handle, @index, ptr)
86
94
  ptr.get_double(0)
87
95
  end
88
-
96
+
97
+ # Sets the position of the servo motor, or raises an error.
98
+ # @param [Float] new_position new position
99
+ # @return [Float] returns the position of the servo motor, or raises an error.
89
100
  def position=(new_position)
90
101
  Klass.setPosition(@handle, @index, new_position.to_f)
91
102
  new_position
92
103
  end
93
-
94
- def type
104
+
105
+ # @return [Phidgets::FFI::ServoType] returns the servo type of the servo motor, or raises an error.
106
+ def type
95
107
  ptr = ::FFI::MemoryPointer.new(:int)
96
108
  Klass.getServoType(@handle, @index, ptr)
97
-
98
109
  Phidgets::FFI::ServoType[ptr.get_int(0)]
99
110
  end
100
111
 
112
+ # Sets the servo type of the servo motor, or raises an error. This determines how degrees are calculated from PCM pulses, and sets min and max angles.
113
+ # @param [Phidgets::FFI::ServoType] new_type new type
114
+ # @return [Phidgets::FFI:ServoType] returns the servo type of the servo motor, or raises an error.
101
115
  def type=(servo_type=:default)
102
116
  ptr = ::FFI::MemoryPointer.new(:int)
103
117
  Klass.setServoType(@handle, @index, Phidgets::FFI::ServoType[servo_type])
104
118
  servo_type
105
119
  end
106
-
107
- def set_parameters(min_pcm, max_pcm, degrees)
120
+
121
+ # Sets custom servo parameters for using a servo not in the predefined list. Pulse widths are specified in microseconds.
122
+ # @param [Float] new_minimum_pulse_width new minimum pulse width
123
+ # @param [Float] new_maximum_pulse_width new maximum pulse width
124
+ # @param [Float] new_degrees new degrees
125
+ # @return [Boolean] returns true if the servo parameters are successfully set, or raises an error.
126
+ def set_servo_parameters(min_pcm, max_pcm, degrees)
108
127
  Klass.setServoParameters(@handle, @index, min_pcm.to_f, max_pcm.to_f, degrees.to_f)
109
128
  true
110
129
  end
130
+
131
+ end #ServoServos
132
+
133
+ private
134
+
135
+ def load_device_attributes
136
+ load_servos
137
+ end
138
+
139
+ def load_servos
140
+ ptr = ::FFI::MemoryPointer.new(:int)
141
+ Klass.getMotorCount(@handle, ptr)
142
+ @servos = []
143
+ ptr.get_int(0).times do |i|
144
+ @servos << ServoServos.new(@handle, i)
145
+ end
146
+
147
+ end
148
+
149
+ def remove_specific_event_handlers
150
+ Klass.set_OnPositionChange_Handler(@handle, nil, nil)
151
+ end
111
152
  end
112
- end
153
+
154
+ end