frankenpins 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NjJiYmEyZmVlNjc5NjVmMmFlYmVlZTkwODY0N2YyNWQ2N2VkN2I2NQ==
4
+ Y2QzZWE0ZWFkNTYwMDYyMTZlMjRiNTExOTg0MWY0MjlhNTVkZmU0ZQ==
5
5
  data.tar.gz: !binary |-
6
- MTRmMGZiYjNiMDhmMDY4MmMzNDUyMjc3NDhjM2IyODA1ZDI3YjQzNg==
6
+ YzBlYzczNGIxNjlkNDQxNzQzMDRmNWFkMGVkYWU0ZDQ1NWRjOWVmMw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDc4MGNjNDUyOTE3NjNkY2RiYTI2NTk5MThlMTQ2ZTYyZmU2NjJhZDBlZmUx
10
- NWY1NjVkNjUzZDQ3ZjlkZmE0ZTczMDJhNTZlYjM4N2RhMGI2YjU2YWI4MmE4
11
- OGI0NWFlYjYwNjdhMDk3MmExMzBmYmM5MjhmODY3ZjkxM2M2YjM=
9
+ MGFlODJlNmJkMGVlOWUwNjFhMjVkNGI0M2NkNGFjMGUwZDI4MjUxNzlmNmYx
10
+ OTEwZjYyNGY4ZGFkOWRlNWE4NTUyYTYxOTFlMjIzNGEyNGY1NzU2N2ZlNTgw
11
+ ZjIyOTNjNzA2ZDg3Nzc2NmM0Y2ViYmQ0YjcyYTZlZGI5ZGM4MGI=
12
12
  data.tar.gz: !binary |-
13
- YjE1NzdkYjI5YTExZTgxMzM4MjUxZDg1Y2ZhMWM4ZGRiOThjZDU1N2RiMjlk
14
- ZDViZGNhMzU4ZjRlMDY0Njk5MGViZjc3MGVlMTI1MTExNGIyOWY4NTc0MTc4
15
- YmFhOTE3MTQ3YTRhYzQzY2NhYmI3MDczN2MyMzkzZWMzM2NkNjQ=
13
+ NjMxNGU3N2U0YmU3ZDEzZjAyZmE4YTM1ODc2YjI5YmJjY2MzOThkOGFmZDFh
14
+ ZDA2N2I1MmQxMDBkN2Y5MmI3NTU3OGQzNTU4MjUxOWQwNTFmMzYxMDY2YTM1
15
+ ZmU1NWE3MzUzMDRhZDc0YmFjZjg3YWUwZmNkZGVhMzUxODViNDQ=
data/README.md CHANGED
@@ -30,6 +30,11 @@ Frankenpins uses the WiringPi convention for pin numbering. The wiring pi set ha
30
30
 
31
31
  ![wiring pi pin numbering chart](http://wiringpi.com/wp-content/uploads/2013/03/gpio1.png)
32
32
 
33
+ Examples
34
+ ---
35
+
36
+ There is demo code in the `examples` folder showing how to use of each of the components.
37
+
33
38
  Buttons
34
39
  ---
35
40
 
@@ -38,7 +43,7 @@ Frankenpins is event-based.
38
43
  require 'frankenpins'
39
44
 
40
45
  button = Frankenpins::Button.new(:pin => 0, :pull => :up)
41
- button.on :pressed do
46
+ button.when :pressed do
42
47
  puts "Button pressed"
43
48
  end
44
49
 
@@ -50,7 +55,7 @@ First we create a new button, telling the library that the button is on wiring p
50
55
 
51
56
  Then we register a block of code to be called whenever the button is pressed down:
52
57
 
53
- button.on :pressed do
58
+ button.when :pressed do
54
59
  puts "Button pressed"
55
60
  end
56
61
 
@@ -64,6 +69,93 @@ Finally, we tell Frankenpins to keep the program running until we quit it. Other
64
69
 
65
70
  Frankenpins.wait
66
71
 
72
+
73
+ LEDs
74
+ ---
75
+
76
+ You can control a Light Emitting Diode (LED) connected to WiringPi pin 5 as follows:
77
+
78
+ require 'frankenpins'
79
+
80
+ led = Frankenpins::LED.new(:pin => 5)
81
+ led.on
82
+ sleep(3)
83
+ led.off
84
+
85
+ ### Brightness
86
+
87
+ You can specify the brightness of the LED. Brightness can be between `0` (off) and `100` (on) and must be an integer.
88
+
89
+ require 'frankenpins'
90
+
91
+ led = Frankenpins::LED.new(:pin => 5)
92
+ led.on
93
+ led.brightness(50) # 50% brightness
94
+
95
+ ### Transitions
96
+
97
+ Turning an LED on and off is good, but Frankenpins can do better. It allows you to fade the LED over a set duration. `on`, `off` and `brightness` all take a `:duration` option that specifies the number of seconds to fade over. This example fades the LED on over 1 second, fades to 50% brightness over 1 second and then off over 2 seconds.
98
+
99
+ require 'frankenpins'
100
+
101
+ led = Frankenpins::LED.new(:pin => 5)
102
+ led.on(:duration => 1)
103
+ led.brightness(50, :duration => 1)
104
+ led.off(:duration => 2)
105
+
106
+
107
+
108
+ You can set a `default_transition` in seconds which will apply to all calls. This example makes the LED to fade on over 2 seconds and then off over 2 seconds:
109
+
110
+ require 'frankenpins'
111
+
112
+ led = Frankenpins::LED.new(:pin => 5)
113
+ led.default_duration = 2
114
+ led.on
115
+ led.off
116
+
117
+
118
+ ### A note about transitions
119
+
120
+ The transitions are all queued up but don't stop your code from running. So, if you have:
121
+
122
+ led.on(:duration => 10)
123
+ led.off(:duration => 1)
124
+
125
+ Your code won't stop for 11 seconds until the transitions have finished, the transitions will happen in the background. This means your main programme may finish before the transitions do, to avoid that use `Frankenpins.wait` to keep your main code running:
126
+
127
+ led.on(:duration => 10)
128
+ led.off(:duration => 1)
129
+ Frankenpins.wait
130
+
131
+ RGB LEDs
132
+ ---
133
+
134
+ These work in the same way as LEDs above, except that the LED has 4 legs. A common ground and 1 for each colour.
135
+
136
+ Connect each leg to a pin and tell Frankenpins about it. You can then use them in much the same way as a normal LED, except instead of specifying on overall brightness, you specify a colour to change the LED to.
137
+
138
+ require 'frankenpins'
139
+
140
+ led = Frankenpins::RGBLED.new(:pins => { :green => 5, :red => 4, :blue => 1 })
141
+ led.on
142
+ led.rgb([255, 0, 0])
143
+
144
+ `rgb([r, g, b])` requires a value for red, green, blue from 0-255 where 0 is off and 255 is full brightness.
145
+
146
+ `percentage([r, g, b])` requires a value from 0-100 for each colour where 0 if off and 100 if full brightness.
147
+
148
+ RGB LEDs also support transitions too, so the following works. This example will make the RGB transition to purple over 2 seconds and then turn off over 1 second.
149
+
150
+ require 'frankenpins'
151
+
152
+ led = Frankenpins::RGBLED.new(:pins => { :green => 5, :red => 4, :blue => 1 })
153
+ led.default_duration = 2
154
+ led.on
155
+ led.rgb([0, 255, 255])
156
+ led.off(:duration => 1)
157
+
158
+
67
159
  Pins
68
160
  ---
69
161
 
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern = "test/**/*_test.rb"
6
+ end
7
+
8
+ task :default => [:test]
data/examples/button.rb CHANGED
@@ -6,15 +6,15 @@ require_relative '../lib/frankenpins'
6
6
  # as an option
7
7
  button = Frankenpins::Button.new(:pin => 0)
8
8
 
9
- button.on :pressed do
9
+ button.when :pressed do
10
10
  puts "Button pressed"
11
11
  end
12
12
 
13
- button.on :released do
13
+ button.when :released do
14
14
  puts "Button released"
15
15
  end
16
16
 
17
- button.on :changed do
17
+ button.when :changed do
18
18
  puts "Button changed"
19
19
  end
20
20
 
data/examples/led.rb ADDED
@@ -0,0 +1,42 @@
1
+ require_relative '../lib/frankenpins'
2
+
3
+ # Create a new LED attached to Wiring Pi pin #6.
4
+ led = Frankenpins::LED.new(:pin => 6)
5
+
6
+ # Simple LED examples
7
+
8
+ puts "Turning LED on"
9
+ led.on
10
+
11
+ # Do nothing for 2 seconds
12
+ sleep(2)
13
+
14
+ puts "Turning LED off"
15
+ led.off
16
+
17
+ sleep(2)
18
+
19
+ # Variable brightness using PWM
20
+
21
+ puts "Turning to the LED to 20% brightness"
22
+ led.brightness(20)
23
+ led.on
24
+ sleep(2)
25
+
26
+ puts "Turning to the LED to 40% brightness"
27
+ led.brightness(40)
28
+ sleep(2)
29
+
30
+ puts "Turning to the LED to 60% brightness"
31
+ led.brightness(60)
32
+ sleep(2)
33
+
34
+ puts "Turning to the LED to 80% brightness"
35
+ led.brightness(80)
36
+
37
+ sleep(2)
38
+
39
+ puts "Turn LED off"
40
+ led.off
41
+
42
+ Frankenpins.wait
@@ -0,0 +1,53 @@
1
+ require_relative '../lib/frankenpins'
2
+
3
+ # Create a new LED attached to Wiring Pi pin #6.
4
+ led = Frankenpins::LED.new(:pin => 6)
5
+
6
+ led.off
7
+
8
+ puts "1. Turn on/off over 1s"
9
+ led.on(:duration => 1)
10
+ sleep(2)
11
+ led.off(:duration => 1)
12
+
13
+ sleep(2)
14
+
15
+ puts "2. Turn on to brightness 10 over 1s"
16
+ led.brightness(10)
17
+ led.on(:duration => 1)
18
+ puts " Turn off immediately"
19
+ sleep(1)
20
+ led.off
21
+
22
+ sleep(2)
23
+
24
+ puts "3. Turn to brightness 10 immediately"
25
+ led.brightness(10)
26
+ led.on
27
+ puts " then transition to brightness 80 over 3s"
28
+ sleep(1)
29
+ led.brightness(80, :duration => 3)
30
+ puts " then transition to brightness 10 over 3s"
31
+ sleep(1)
32
+ led.brightness(10, :duration => 3)
33
+ puts " then turn off over 1s"
34
+ sleep(1)
35
+ led.off(:duration => 1)
36
+
37
+ sleep(2)
38
+
39
+ puts "4. Always transition over 2s"
40
+ led.default_duration = 2
41
+ puts " on"
42
+ led.on # over 2s
43
+ sleep(1)
44
+ puts " 20% brightness"
45
+ led.brightness(20)
46
+ sleep(1)
47
+ puts " off"
48
+ led.off # over 2s
49
+
50
+ puts "Finished!"
51
+
52
+ Frankenpins.wait
53
+
@@ -0,0 +1,36 @@
1
+ require_relative '../lib/frankenpins'
2
+
3
+ # Create a new LED attached to Wiring Pi pin #6.
4
+ led = Frankenpins::RGBLED.new(:pins => { :green => 5, :red => 4, :blue => 1 })
5
+
6
+ colours = {
7
+ :purple => [80 , 0 , 80 ],
8
+ :red => [255, 0 , 0 ],
9
+ :green => [0 , 255, 0 ],
10
+ :blue => [0 , 0 , 255 ],
11
+ :yellow => [255, 255, 0 ],
12
+ :aqua => [0 , 255, 255 ],
13
+ :indigo => [0x4B, 0x0, 0x82] # Hex colour
14
+ }
15
+
16
+ led.on
17
+
18
+ puts "Change colours"
19
+ colours.each do |name, rgb|
20
+ puts "#{name.to_s} #{rgb}"
21
+ led.rgb(rgb)
22
+ sleep(2)
23
+ end
24
+
25
+ puts "Fade between colours"
26
+ colours.each do |name, rgb|
27
+ puts "#{name.to_s} #{rgb}"
28
+ led.rgb(rgb, :duration => 2)
29
+ sleep(2)
30
+ end
31
+
32
+ led.off(:duration => 2)
33
+
34
+ puts "Finished"
35
+
36
+ Frankenpins.wait
@@ -7,14 +7,14 @@ require_relative '../lib/frankenpins'
7
7
  # option :pull => :none
8
8
  encoder = Frankenpins::RotaryEncoder.new(:pin_a => 4, :pin_b => 5)
9
9
 
10
- encoder.on :changed do |pos, direction|
10
+ encoder.when :changed do |pos, direction|
11
11
  puts "position: #{pos}, direction: #{direction}"
12
12
  end
13
13
 
14
14
  # Use the Button class to watch the switch part of the
15
15
  # encoder, push down to activate
16
16
  button = Frankenpins::Button.new(:pin => 1)
17
- button.on :pressed do
17
+ button.when :pressed do
18
18
  puts "Button pressed"
19
19
  end
20
20
 
data/frankenpins.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'frankenpins'
3
- s.version = '0.2.1'
3
+ s.version = '0.3.0'
4
4
  s.date = '2013-08-28'
5
5
  s.summary = "Connect buttons etc to your Rapsberry Pi"
6
6
  s.description = "Connect buttons etc to your Rapsberry Pi"
data/lib/frankenpins.rb CHANGED
@@ -4,6 +4,8 @@ require_relative 'frankenpins/wiring_pi_singleton'
4
4
  require_relative 'frankenpins/pin'
5
5
  require_relative 'frankenpins/button'
6
6
  require_relative 'frankenpins/rotary_encoder'
7
+ require_relative 'frankenpins/led'
8
+ require_relative 'frankenpins/rgb_led'
7
9
 
8
10
  module Frankenpins
9
11
  include Utils
@@ -24,7 +24,7 @@ module Frankenpins
24
24
  end
25
25
  end
26
26
 
27
- def on(event_name, &block)
27
+ def when(event_name, &block)
28
28
  send(event_name).register(&block)
29
29
  end
30
30
  end
@@ -0,0 +1,77 @@
1
+ require 'ostruct'
2
+ require 'thread'
3
+ Thread.abort_on_exception = true
4
+
5
+ require_relative './led_transition'
6
+ require_relative './transition_queue'
7
+
8
+ module Frankenpins
9
+ class LED
10
+
11
+ attr_reader :default_duration
12
+ attr_writer :default_duration
13
+
14
+ def initialize(options={})
15
+ options[:direction] = :out
16
+ @pin = Frankenpins::Pin.new(options)
17
+
18
+ @using_pwm = false
19
+ @pwm_max = 100
20
+
21
+ @is_on = false
22
+ @brightness = 0
23
+
24
+ # TODO: Should be 0?
25
+ @default_duration = nil
26
+
27
+ @queue = TransitionQueue.new
28
+ @queue.start!
29
+ end
30
+
31
+ def on(opts={})
32
+ brightness(100, opts)
33
+ @is_on = true
34
+ end
35
+
36
+ def off(opts={})
37
+ brightness(0, opts)
38
+ @is_on = false
39
+ end
40
+
41
+ def brightness(value, opts={})
42
+
43
+ duration = opts[:duration] || @default_duration
44
+
45
+ if value != 100 || value != 0 || duration
46
+ use_pwm!
47
+ end
48
+
49
+ props = { :pin => @pin }
50
+
51
+ if duration
52
+ props[:type] = :pwm
53
+ props[:from] = @brightness
54
+ props[:to] = value
55
+ props[:duration] = duration
56
+ elsif @using_pwm
57
+ props[:type] = :pwm
58
+ props[:value] = value
59
+ else
60
+ props[:type] = :digital
61
+ props[:value] = false if @brightness == 0
62
+ props[:value] = true if @brightness == 100
63
+ end
64
+
65
+ @queue.push(LEDTransition.new(props))
66
+ @brightness = value
67
+ end
68
+
69
+ private
70
+ def use_pwm!
71
+ if @using_pwm == false
72
+ @pin.io.soft_pwm_create(@pin.wiring_pin, 0, @pwm_max)
73
+ @using_pwm = true
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,47 @@
1
+ module Frankenpins
2
+ # A transition of the brightness of
3
+ # the LED.
4
+ # Transitions encode all the info
5
+ # necessary to change the state
6
+ class LEDTransition < OpenStruct
7
+
8
+ def perform!
9
+ if type == :digital
10
+ digital_write(value)
11
+ elsif duration
12
+ transition!
13
+ elsif type == :pwm
14
+ pwm_write(value)
15
+ end
16
+ end
17
+
18
+ def transition!
19
+ duration_in_secs = duration
20
+ from_value = from
21
+ to_value = to
22
+ increment_time_in_sec = 0.01
23
+
24
+ range = to_value - from_value
25
+
26
+ increment = increment_time_in_sec.to_f / duration_in_secs.to_f
27
+ steps = (duration_in_secs.to_f / increment_time_in_sec.to_f).to_i
28
+
29
+ brightness_value = from_value
30
+
31
+ steps.times.each do
32
+ brightness_value = brightness_value + (increment * range)
33
+ pwm_write(brightness_value)
34
+ sleep(increment_time_in_sec)
35
+ end
36
+ end
37
+
38
+ def digital_write(value)
39
+ pin.write(value)
40
+ end
41
+
42
+ def pwm_write(value)
43
+ # puts "pwm_write(#{pin.wiring_pin}, #{value.to_i})"
44
+ pin.io.soft_pwm_write(pin.wiring_pin, value.to_i)
45
+ end
46
+ end
47
+ end
@@ -14,7 +14,7 @@ module Frankenpins
14
14
  PUD_DOWN = 1
15
15
  PUD_UP = 2
16
16
 
17
- attr_reader :pin, :last_value, :value, :direction, :invert
17
+ attr_reader :io, :pin, :wiring_pin, :last_value, :value, :direction, :invert
18
18
 
19
19
  def wiring_to_gpio(pin)
20
20
  @io.wpi_pin_to_gpio(pin)
@@ -109,6 +109,11 @@ module Frankenpins
109
109
  @value = invert ? (val ^ 1) : val
110
110
  end
111
111
 
112
+ def write(value)
113
+ value = value ? "1" : "0"
114
+ File.open(value_file, 'w') {|f| f.write(value) } if direction == :out
115
+ end
116
+
112
117
  private
113
118
  def value_file
114
119
  "/sys/class/gpio/gpio#{pin}/value"
@@ -0,0 +1,62 @@
1
+ module Frankenpins
2
+ class RGBLED
3
+
4
+ attr_reader :default_duration
5
+ attr_writer :default_duration
6
+
7
+ def initialize(options={})
8
+ @is_on = false
9
+ @pin_nums = options.delete(:pins)
10
+ @red = LED.new( config_for_pin(@pin_nums[:red], options) )
11
+ @green = LED.new( config_for_pin(@pin_nums[:green], options) )
12
+ @blue = LED.new( config_for_pin(@pin_nums[:blue], options) )
13
+
14
+ @default_duration = nil
15
+ end
16
+
17
+ def on(opts={})
18
+ [@red, @green, @blue].map { |led| led.on(opts) }
19
+ rgb(opts[:rgb]) if opts[:rgb]
20
+ percentage(opts[:percent]) if opts[:percent]
21
+ @is_on = true
22
+ end
23
+
24
+ def off(opts={})
25
+ [@red, @green, @blue].map { |led| led.off(opts) }
26
+ @is_off = true
27
+ end
28
+
29
+ def rgb(rgb, opts={})
30
+ write_colours(*rgb.map { |val| rgb_val_to_brightness(val) }, opts)
31
+ end
32
+
33
+ def percentage(rgb, opts={})
34
+ write_colours(*rgb, opts)
35
+ end
36
+
37
+ private
38
+ def rgb_val_to_brightness(val)
39
+ scale(val, 255, 100).to_i
40
+ end
41
+
42
+ def config_for_pin(num, options)
43
+ opts = options.clone
44
+ opts[:pin] = num
45
+ opts
46
+ end
47
+
48
+ def write_colours(r, g, b, opts={})
49
+ duration = opts[:duration] || @default_duration
50
+ @red.brightness(r, :duration => duration)
51
+ @green.brightness(g, :duration => duration)
52
+ @blue.brightness(b, :duration => duration)
53
+ end
54
+
55
+ # e.g. 30/255 -> ?/100
56
+ # = scale(30, 255, 100)
57
+ # = 11.764705882
58
+ def scale(val, domain, range)
59
+ (val.to_f/domain.to_f) * range.to_f
60
+ end
61
+ end
62
+ end
@@ -38,7 +38,7 @@ module Frankenpins
38
38
  @last_val = encoded
39
39
  end
40
40
 
41
- def on(event_name, &block)
41
+ def when(event_name, &block)
42
42
  send(event_name).register(&block)
43
43
  end
44
44
 
@@ -0,0 +1,26 @@
1
+ module Frankenpins
2
+ # A transition queue
3
+ # Items added to the queue are
4
+ # executed in order
5
+ class TransitionQueue
6
+ def initialize
7
+ @queue = Queue.new
8
+ @debug = false
9
+ end
10
+
11
+ def push(transition)
12
+ puts "E: #{transition.type} #{transition}" if @debug
13
+ @queue.push(transition)
14
+ end
15
+
16
+ def start!
17
+ Thread.new do
18
+ loop do
19
+ transition = @queue.pop
20
+ puts "D: #{transition.type} #{transition}" if @debug
21
+ transition.perform!
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frankenpins
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nicolaou
@@ -49,14 +49,22 @@ files:
49
49
  - Gemfile
50
50
  - Gemfile.lock
51
51
  - README.md
52
+ - Rakefile
52
53
  - examples/button.rb
54
+ - examples/led.rb
55
+ - examples/led_fade.rb
53
56
  - examples/raw_pin.rb
57
+ - examples/rgb_led.rb
54
58
  - examples/rotary_encoder.rb
55
59
  - frankenpins.gemspec
56
60
  - lib/frankenpins.rb
57
61
  - lib/frankenpins/button.rb
62
+ - lib/frankenpins/led.rb
63
+ - lib/frankenpins/led_transition.rb
58
64
  - lib/frankenpins/pin.rb
65
+ - lib/frankenpins/rgb_led.rb
59
66
  - lib/frankenpins/rotary_encoder.rb
67
+ - lib/frankenpins/transition_queue.rb
60
68
  - lib/frankenpins/utils.rb
61
69
  - lib/frankenpins/wiring_pi_singleton.rb
62
70
  - scratch/button-wiring.rb