pixel_pi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/README.md +85 -0
- data/Rakefile +16 -0
- data/examples/strandtest.rb +186 -0
- data/ext/pixel_pi/extconf.rb +18 -0
- data/ext/pixel_pi/leds.c +464 -0
- data/ext/ws2811/LICENSE +24 -0
- data/ext/ws2811/clk.h +60 -0
- data/ext/ws2811/dma.c +192 -0
- data/ext/ws2811/dma.h +146 -0
- data/ext/ws2811/gpio.h +108 -0
- data/ext/ws2811/pwm.c +112 -0
- data/ext/ws2811/pwm.h +122 -0
- data/ext/ws2811/ws2811.c +757 -0
- data/ext/ws2811/ws2811.h +68 -0
- data/lib/pixel_pi/version.rb +3 -0
- data/lib/pixel_pi.rb +2 -0
- data/pixel_pi.gemspec +23 -0
- metadata +77 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 88f76ffee2734314c7106fb269336d2e634fce17
|
4
|
+
data.tar.gz: 94b421a965b1bf7b1df122b8ef237eb751b62ba4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5179dc9f4abea2e66023cf1f487ff699de587bce76c328f3010cfbb906cb7dc572870855013023dd9734439ff025437c4391de391d5a8bc949b62b943a6a5ead
|
7
|
+
data.tar.gz: 0c85470cf2b9c1a4e18891081fc14c42e472f9848e038ed3cec60f7ce9f2b0bc9f0853c0382f13842c54c14fc49f0b4119045fe6b33d46ada60c0cba15fe8c3d
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
tmp
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# What is this?
|
2
|
+
|
3
|
+
Ruby code for controlling [NeoPixels](https://www.adafruit.com/category/168)
|
4
|
+
attached to a [Raspberry Pi](http://www.raspberrypi.org).
|
5
|
+
|
6
|
+
# Is it any good?
|
7
|
+
|
8
|
+
Yes.
|
9
|
+
|
10
|
+
# How do I run it?
|
11
|
+
|
12
|
+
Install the gem on your RaspberryPi, and copy the `strandtest.rb` file to your
|
13
|
+
home directory:
|
14
|
+
|
15
|
+
```sh
|
16
|
+
sudo gem install pixel_pi
|
17
|
+
cp `gem contents pixel_pi | grep strandtest.rb` .
|
18
|
+
```
|
19
|
+
|
20
|
+
Edit the `LED_COUNT` and `LED_PIN` at the top of the file to
|
21
|
+
match the NeoPixel circuit attached to your RaspberryPi (read the [RaspberryPi
|
22
|
+
NeoPixel guide](https://learn.adafruit.com/neopixels-on-raspberry-pi/overview)
|
23
|
+
from Adafruit for all the details). Now run the strandtest example:
|
24
|
+
|
25
|
+
```sh
|
26
|
+
sudo ruby strandtest.rb
|
27
|
+
```
|
28
|
+
|
29
|
+
Enjoy the blinken lights!
|
30
|
+
|
31
|
+
# It won't run!
|
32
|
+
|
33
|
+
Yes it will.
|
34
|
+
|
35
|
+
The [ws2811](https://github.com/jgarff/rpi_ws281x) driver is using direct memory
|
36
|
+
addressing (DMA) via `/dev/mem` to control the NeoPixels. Only the root user has
|
37
|
+
permission to read and write to this hardware device. So any time your work with
|
38
|
+
NeoPixels, your code will need to be run as the super user.
|
39
|
+
|
40
|
+
# I want to help out
|
41
|
+
|
42
|
+
If you want to contribute to this gem then you will need a development
|
43
|
+
environment setup on your RaspberryPi. You will need the ruby headers installed
|
44
|
+
locally.
|
45
|
+
|
46
|
+
```
|
47
|
+
sudo apt-get install ruby ruby-dev
|
48
|
+
```
|
49
|
+
|
50
|
+
Install some ruby gems.
|
51
|
+
|
52
|
+
```
|
53
|
+
sudo gem install rake
|
54
|
+
sudo gem install rake-compiler
|
55
|
+
```
|
56
|
+
|
57
|
+
The `rake-compiler` gem might not install properly. The problem is a very strict
|
58
|
+
requirement on the rubygems version. To work around this we need to download the
|
59
|
+
source code, create the gem by hand, and install. You can skip this step if
|
60
|
+
rake-compiler installed successfully.
|
61
|
+
|
62
|
+
```
|
63
|
+
sudo su
|
64
|
+
git clone https://github.com/luislavena/rake-compiler.git
|
65
|
+
cd rake-compiler
|
66
|
+
rake gem
|
67
|
+
gem install pkg/rake-compiler-0.9.3.gem --no-rdoc --no-ri
|
68
|
+
cd ../
|
69
|
+
rm -fr rake-compiler
|
70
|
+
exit
|
71
|
+
```
|
72
|
+
|
73
|
+
Now we can compile the NeoPixels ruby library.
|
74
|
+
|
75
|
+
```
|
76
|
+
rake compile
|
77
|
+
```
|
78
|
+
|
79
|
+
Take a look at the `examples/strandtest.rb` file and adjust the `LED_COUNT` and
|
80
|
+
`LED_PIN` to match your circuit. Run the strandtest and bask in the glow of
|
81
|
+
blinking rainbow lights.
|
82
|
+
|
83
|
+
```
|
84
|
+
sudo ruby examples/strandtest.rb
|
85
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake/extensiontask"
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
spec = Gem::Specification.load("pixel_pi.gemspec")
|
8
|
+
|
9
|
+
Gem::PackageTask.new(spec)
|
10
|
+
|
11
|
+
Rake::ExtensionTask.new("pixel_pi", spec) do |ext|
|
12
|
+
ext.name = "leds"
|
13
|
+
ext.ext_dir = "ext/pixel_pi"
|
14
|
+
ext.lib_dir = "lib/pixel_pi"
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "pixel_pi"
|
5
|
+
rescue LoadError
|
6
|
+
lib = File.expand_path('../../lib', __FILE__)
|
7
|
+
raise if $LOAD_PATH.include?(lib)
|
8
|
+
$LOAD_PATH.unshift(lib)
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
LED_COUNT = 8 # Number of LED pixels.
|
13
|
+
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
|
14
|
+
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
|
15
|
+
LED_DMA = 5 # DMA channel to use for generating signal (try 5)
|
16
|
+
LED_BRIGHTNESS = 255 # Scale the brightness of the pixels (0 to 255)
|
17
|
+
LED_INVERT = false # True to invert the signal (when using NPN transistor level shift)
|
18
|
+
|
19
|
+
module StrandTest
|
20
|
+
|
21
|
+
attr_accessor :wait_ms
|
22
|
+
|
23
|
+
# Wipe color across display a pixel at a time.
|
24
|
+
#
|
25
|
+
# color - The 24-bit RGB color value
|
26
|
+
# opts - The options Hash
|
27
|
+
# :wait_ms - sleep time between pixel updates
|
28
|
+
#
|
29
|
+
# Returns this PixelPi::Leds instance.
|
30
|
+
def color_wipe( color, opts = {} )
|
31
|
+
wait_ms = opts.fetch(:wait_ms, self.wait_ms)
|
32
|
+
|
33
|
+
self.length.times do |num|
|
34
|
+
self[num] = color
|
35
|
+
self.show
|
36
|
+
sleep(wait_ms / 1000.0)
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Movie theater light style chaser animation.
|
43
|
+
#
|
44
|
+
# color - The 24-bit RGB color value
|
45
|
+
# opts - The options Hash
|
46
|
+
# :wait_ms - sleep time between pixel updates
|
47
|
+
# :iterations - number of iterations (defaults to 10)
|
48
|
+
# :spacing - spacing between lights (defaults to 3)
|
49
|
+
#
|
50
|
+
# Returns this PixelPi::Leds instance.
|
51
|
+
def theater_chase( color, opts = {} )
|
52
|
+
wait_ms = opts.fetch(:wait_ms, self.wait_ms)
|
53
|
+
iterations = opts.fetch(:iterations, 10)
|
54
|
+
spacing = opts.fetch(:spacing, 3)
|
55
|
+
|
56
|
+
iterations.times do
|
57
|
+
spacing.times do |jj|
|
58
|
+
(0...self.length).step(spacing) { |ii| self[ii+jj] = color }
|
59
|
+
self.show
|
60
|
+
sleep(wait_ms / 1000.0)
|
61
|
+
(0...self.length).step(spacing) { |ii| self[ii+jj] = 0 }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generate rainbow colors across 0-255 positions.
|
69
|
+
#
|
70
|
+
# pos - Positoin between 0 and 255
|
71
|
+
#
|
72
|
+
# Returns a 24-bit RGB color value.
|
73
|
+
def wheel( pos )
|
74
|
+
if pos < 85
|
75
|
+
return PixelPi::Color(pos * 3, 255 - pos * 3, 0)
|
76
|
+
elsif pos < 170
|
77
|
+
pos -= 85
|
78
|
+
return PixelPi::Color(255 - pos * 3, 0, pos * 3)
|
79
|
+
else
|
80
|
+
pos -= 170
|
81
|
+
return PixelPi::Color(0, pos * 3, 255 - pos * 3)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Draw rainbow that fades across all pixels at once.
|
86
|
+
#
|
87
|
+
# opts - The options Hash
|
88
|
+
# :wait_ms - sleep time between pixel updates
|
89
|
+
# :iterations - number of iterations (defaults to 1)
|
90
|
+
#
|
91
|
+
# Returns this PixelPi::Leds instance.
|
92
|
+
def rainbow( opts = {} )
|
93
|
+
wait_ms = opts.fetch(:wait_ms, self.wait_ms)
|
94
|
+
iterations = opts.fetch(:iterations, 1)
|
95
|
+
|
96
|
+
(0...256*iterations).each do |jj|
|
97
|
+
self.length.times { |ii| self[ii] = wheel((ii+jj) & 0xff) }
|
98
|
+
self.show
|
99
|
+
sleep(wait_ms / 1000.0)
|
100
|
+
end
|
101
|
+
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
# Draw rainbow that uniformly distributes itself across all pixels.
|
106
|
+
#
|
107
|
+
# opts - The options Hash
|
108
|
+
# :wait_ms - sleep time between pixel updates
|
109
|
+
# :iterations - number of iterations (defaults to 5)
|
110
|
+
#
|
111
|
+
# Returns this PixelPi::Leds instance.
|
112
|
+
def rainbow_cycle( opts = {} )
|
113
|
+
wait_ms = opts.fetch(:wait_ms, self.wait_ms)
|
114
|
+
iterations = opts.fetch(:iterations, 5)
|
115
|
+
|
116
|
+
(0...256*iterations).each do |jj|
|
117
|
+
self.length.times { |ii| self[ii] = wheel(((ii * 256 / self.length) + jj) & 0xff) }
|
118
|
+
self.show
|
119
|
+
sleep(wait_ms / 1000.0)
|
120
|
+
end
|
121
|
+
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
# Rainbow moview theather light style chaser animation.
|
126
|
+
#
|
127
|
+
# opts - The options Hash
|
128
|
+
# :wait_ms - sleep time between pixel updates
|
129
|
+
# :spacing - spacing between lights (defaults to 3)
|
130
|
+
#
|
131
|
+
# Returns this PixelPi::Leds instance.
|
132
|
+
def theater_chase_rainbow( opts = {} )
|
133
|
+
wait_ms = opts.fetch(:wait_ms, self.wait_ms)
|
134
|
+
spacing = opts.fetch(:spacing, 3)
|
135
|
+
|
136
|
+
256.times do |jj|
|
137
|
+
spacing.times do |sp|
|
138
|
+
(0...self.length).step(spacing) { |ii| self[ii+sp] = wheel((ii+jj) % 255) }
|
139
|
+
self.show
|
140
|
+
sleep(wait_ms / 1000.0)
|
141
|
+
(0...self.length).step(spacing) { |ii| self[ii+sp] = 0 }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
strip = PixelPi::Leds.new \
|
152
|
+
LED_COUNT, LED_PIN,
|
153
|
+
:frequency => LED_FREQ_HZ,
|
154
|
+
:dma => LED_DMA,
|
155
|
+
:brightness => LED_BRIGHTNESS,
|
156
|
+
:invert => LED_INVERT
|
157
|
+
|
158
|
+
strip.extend StrandTest
|
159
|
+
|
160
|
+
trap("SIGINT") do
|
161
|
+
strip.clear
|
162
|
+
strip.close # not explicitly needed - the finalizer will gracefully shutdown
|
163
|
+
exit # the PWM channel and release the DMA memory
|
164
|
+
end
|
165
|
+
|
166
|
+
STDOUT.puts "Press Ctrl-C to quit."
|
167
|
+
|
168
|
+
loop do
|
169
|
+
# Color wipe animations
|
170
|
+
strip.wait_ms = 75
|
171
|
+
strip.color_wipe(PixelPi::Color(255, 0, 0)) # red color wipe
|
172
|
+
strip.color_wipe(PixelPi::Color(0, 255, 0)) # green color wipe
|
173
|
+
strip.color_wipe(PixelPi::Color(0, 0, 255)) # blue color wipe
|
174
|
+
|
175
|
+
# Theater chase animations
|
176
|
+
strip.wait_ms = 100
|
177
|
+
strip.clear
|
178
|
+
strip.theater_chase(PixelPi::Color(255, 255, 255)) # white theater chase
|
179
|
+
strip.theater_chase(PixelPi::Color(255, 0, 0)) # red theater chase
|
180
|
+
strip.theater_chase(PixelPi::Color( 0, 0, 255)) # blue theater chase
|
181
|
+
|
182
|
+
strip.wait_ms = 20
|
183
|
+
strip.rainbow
|
184
|
+
strip.rainbow_cycle
|
185
|
+
strip.theater_chase_rainbow(:wait_ms => 75)
|
186
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
pixel_pi_path = File.expand_path("../", __FILE__)
|
4
|
+
ws2811_path = File.expand_path("../../ws2811", __FILE__)
|
5
|
+
ws2811_files = %w[
|
6
|
+
clk.h
|
7
|
+
dma.h
|
8
|
+
gpio.h
|
9
|
+
pwm.h
|
10
|
+
ws2811.h
|
11
|
+
dma.c
|
12
|
+
pwm.c
|
13
|
+
ws2811.c
|
14
|
+
]
|
15
|
+
ws2811_files.map! { |name| "#{ws2811_path}/#{name}" }
|
16
|
+
FileUtils.cp(ws2811_files, pixel_pi_path)
|
17
|
+
|
18
|
+
create_makefile("neo_pixels/leds")
|