littlewire 0.9 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/led pixel.rb +55 -0
- data/examples/ws2811 colors.rb +20 -0
- data/examples/ws2811 scan.rb +25 -0
- data/examples/ws2811.rb +39 -0
- data/lib/digital.rb +1 -1
- data/lib/littlewire.rb +32 -19
- data/lib/software-pwm.rb +11 -4
- data/lib/spi.rb +6 -4
- data/lib/ws2811.rb +52 -0
- data/readme.md +2 -2
- metadata +24 -3
@@ -0,0 +1,55 @@
|
|
1
|
+
# Connects to an LPD6803 LED Pixel of the type sold by ladyada, bliptronics, and alibaba
|
2
|
+
# and sends rgb info to the pixel. While these lights have worse colour reproduction than
|
3
|
+
# the PWM in Little Wire, they're chainable so you can run hundreds off one Little Wire!
|
4
|
+
#
|
5
|
+
# This sort: http://bliptronics.com/item.aspx?ItemID=113
|
6
|
+
#
|
7
|
+
# Note if you're running more than five or so from a littlewire you should power them
|
8
|
+
# with an external power supply instead of Little Wire's VCC pin
|
9
|
+
require '../lib/littlewire'
|
10
|
+
|
11
|
+
wire = LittleWire.connect
|
12
|
+
spi = wire.spi
|
13
|
+
|
14
|
+
wire.pin_mode :pin1 => :output, :pin3 => :output
|
15
|
+
|
16
|
+
def lpd6803_data red, green, blue
|
17
|
+
# TODO: could add some dithering here
|
18
|
+
bits = [green, blue, red].map { |v| (v * 31).round.to_s(2).rjust(5, '0') }
|
19
|
+
"1#{bits.join ''}".to_i(2)
|
20
|
+
end
|
21
|
+
|
22
|
+
$lights = [[1.0, 0.0, 1.0]] # just one light, with red, green, blue set to bright violet
|
23
|
+
def update_lights
|
24
|
+
new_sequence = $lights.map { |pix| lpd6803_data(*pix) }
|
25
|
+
new_sequence.unshift 0, 0 # add start frame
|
26
|
+
$data_sequence = new_sequence
|
27
|
+
end
|
28
|
+
|
29
|
+
update_lights
|
30
|
+
|
31
|
+
spi.delay = 10
|
32
|
+
|
33
|
+
$x = 0.0
|
34
|
+
|
35
|
+
require 'benchmark'
|
36
|
+
Benchmark.benchmark do
|
37
|
+
for i in 1..1000000
|
38
|
+
wire.digital_write pin1: true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
# loop do
|
42
|
+
# $data_sequence.each_slice(2) do |cells|
|
43
|
+
# spi.send cells.pack('S>*')
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# $lights = [[0.0, $x % 1.0, 0.0]]
|
47
|
+
# $x += 1.0/32.0
|
48
|
+
# update_lights
|
49
|
+
#
|
50
|
+
# # and now we use software pwm to run the light's clock for a little while
|
51
|
+
# wire.software_pwm_write(pin2: 127)
|
52
|
+
# sleep (1.0/32.0)
|
53
|
+
# wire.software_pwm_enabled = false
|
54
|
+
# end
|
55
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require '../lib/littlewire.rb'
|
2
|
+
wire = LittleWire.connect
|
3
|
+
pin = :pin1
|
4
|
+
speed = 1
|
5
|
+
num_leds = 64
|
6
|
+
|
7
|
+
loop do
|
8
|
+
puts "red"
|
9
|
+
wire.ws2811.colors = ['red'] * num_leds
|
10
|
+
wire.ws2811.output pin
|
11
|
+
sleep speed
|
12
|
+
puts "green"
|
13
|
+
wire.ws2811.colors = ['green'] * num_leds
|
14
|
+
wire.ws2811.output pin
|
15
|
+
sleep speed
|
16
|
+
puts "blue"
|
17
|
+
wire.ws2811.colors = ['blue'] * num_leds
|
18
|
+
wire.ws2811.output pin
|
19
|
+
sleep speed
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require '../lib/littlewire.rb'
|
2
|
+
wire = LittleWire.connect
|
3
|
+
num_pixels = ARGV.first.to_i
|
4
|
+
|
5
|
+
lit = 0
|
6
|
+
loop do
|
7
|
+
|
8
|
+
text_output = ['-'] * num_pixels
|
9
|
+
text_output[lit] = '*'
|
10
|
+
puts text_output.join
|
11
|
+
|
12
|
+
wire.ws2811.colors = num_pixels.times.map do |idx|
|
13
|
+
if idx == lit
|
14
|
+
'white'.to_color
|
15
|
+
else
|
16
|
+
'black'.to_color
|
17
|
+
end
|
18
|
+
end
|
19
|
+
wire.ws2811.output :pin1
|
20
|
+
|
21
|
+
lit += 1
|
22
|
+
lit %= num_pixels
|
23
|
+
|
24
|
+
sleep 0.01
|
25
|
+
end
|
data/examples/ws2811.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Send up to 64 colours to a string of WS2812 LEDs or 800khz (version 2) Adafruit Flora NeoPixels
|
2
|
+
# Any 800khz mode ws2811 pixels will work
|
3
|
+
require '../lib/littlewire.rb'
|
4
|
+
wire = LittleWire.connect
|
5
|
+
|
6
|
+
puts DATA.read # print out the little ascii art thing at the end of this file
|
7
|
+
puts "Which pin to use for data output?"
|
8
|
+
print "Enter pin number: "
|
9
|
+
output_pin = gets.gsub(/[^0-9]/, '').to_i
|
10
|
+
|
11
|
+
print "Enter 1st color: "
|
12
|
+
wire.ws2811.colors = [gets.strip.to_color]
|
13
|
+
wire.ws2811.output(output_pin) # output our first color
|
14
|
+
|
15
|
+
titles = ['1st', '2nd', '3rd']
|
16
|
+
|
17
|
+
63.times do |idx|
|
18
|
+
print "Enter #{titles[idx + 1] || "#{idx + 2}th"} color: "
|
19
|
+
gotten = gets.strip
|
20
|
+
break if gotten.empty?
|
21
|
+
# add colour to array
|
22
|
+
wire.ws2811.colors.push gotten.to_color
|
23
|
+
wire.ws2811.output(output_pin) # output the colours to the string
|
24
|
+
end
|
25
|
+
|
26
|
+
puts "All done!"
|
27
|
+
|
28
|
+
__END__
|
29
|
+
LittleWire connector: | Digispark Board:
|
30
|
+
/-----\ | _________
|
31
|
+
pin_1 | o o | vcc | _____| o| ds5
|
32
|
+
pin_2 | o o | pin 4 | |----- o| (usb - not available)
|
33
|
+
pin_3 | o o | gnd | |----- o| (usb - not available)
|
34
|
+
\-----/ | |----- o| ds2
|
35
|
+
|----- o| ds1
|
36
|
+
|_o_o_o__o| ds0
|
37
|
+
5 g v
|
38
|
+
v n c
|
39
|
+
d c
|
data/lib/digital.rb
CHANGED
@@ -58,7 +58,7 @@ module LittleWire::Digital
|
|
58
58
|
# `sensor_a, sensor_b = my_wire.digital_read(:pin1, :pin2)` which reads both pins at
|
59
59
|
# the exact same instant in just one USB request, returning an array of the results
|
60
60
|
#
|
61
|
-
# digital_read
|
61
|
+
# digital_read works best when the pin is in :input mode. See also #pin_mode
|
62
62
|
def digital_read *args
|
63
63
|
raise "Incorrect Arguments" if args.length < 1
|
64
64
|
pins = args.flatten
|
data/lib/littlewire.rb
CHANGED
@@ -11,6 +11,7 @@ require_relative 'servo'
|
|
11
11
|
require_relative 'spi'
|
12
12
|
require_relative 'i2c'
|
13
13
|
require_relative 'one-wire'
|
14
|
+
require_relative 'ws2811'
|
14
15
|
|
15
16
|
# LittleWire class represents LittleWire's connected to your computer via USB
|
16
17
|
#
|
@@ -25,10 +26,10 @@ class LittleWire
|
|
25
26
|
|
26
27
|
# pin name to numeric internal code maps
|
27
28
|
DigitalPinMap = { # maps common names to bit positions in PORTB
|
28
|
-
pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1,
|
29
|
-
pin2: 2, d2: 2, sck: 2,
|
30
|
-
pin3: 5, d3: 5, reset: 5,
|
31
|
-
pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0 }
|
29
|
+
pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1, ds1: 1,
|
30
|
+
pin2: 2, d2: 2, sck: 2, ds2: 2,
|
31
|
+
pin3: 5, d3: 5, reset: 5, ds5: 5,
|
32
|
+
pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0, ds0: 0 }
|
32
33
|
AnalogPinMap = { # maps common names to switch index in littlewire firmware
|
33
34
|
a1: 0, adc_1: 0, reset: 0, pin3: 0, d3: 0,
|
34
35
|
a2: 1, adc_2: 1, sck: 1, pin2: 1, d2: 1,
|
@@ -37,9 +38,9 @@ class LittleWire
|
|
37
38
|
pwm_b: 1, pwm_1: 1, d1: 1, pin1: 1, miso: 1,
|
38
39
|
pwm_a: 0, pwm_2: 0, d4: 0, pin4: 0, mosi: 0 }
|
39
40
|
SoftwarePWMPinMap = { # TODO: figure out which pins these are
|
40
|
-
softpwm_1: 0, softpwm_a: 0,
|
41
|
-
softpwm_2: 1, softpwm_b: 1,
|
42
|
-
softpwm_3: 2, softpwm_c: 2 }
|
41
|
+
softpwm_1: 0, softpwm_a: 0, pin4: 0, d4: 0, mosi: 0, pwm_a: 0, pwm_1: 0,
|
42
|
+
softpwm_2: 1, softpwm_b: 1, pin1: 1, d1: 1, miso: 1, pwm_b: 1, pwm_2: 1,
|
43
|
+
softpwm_3: 2, softpwm_c: 2, pin2: 2, d2: 2, sck: 2 }
|
43
44
|
GenericPinMap = { # generic pinmap used by [] and []= methods to refer to anything
|
44
45
|
d1: [:digital, :pin1],
|
45
46
|
d2: [:digital, :pin2],
|
@@ -65,7 +66,7 @@ class LittleWire
|
|
65
66
|
softpwm_c: [:software_pwm, :softpwm_c],
|
66
67
|
}
|
67
68
|
|
68
|
-
SupportedVersions = ['1.1', '1.0'] # in order of newness. # TODO: Add version 1.0?
|
69
|
+
SupportedVersions = ['1.2', '1.1', '1.0'] # in order of newness. # TODO: Add version 1.0?
|
69
70
|
|
70
71
|
|
71
72
|
# An array of all unclaimed littlewires connected to computer via USB
|
@@ -120,11 +121,11 @@ class LittleWire
|
|
120
121
|
|
121
122
|
# implementations of littlewire functions
|
122
123
|
# - generic requests
|
123
|
-
def echo; control_transfer(function: :echo, dataIn: 8).unpack('S<*'); end # echo's usb request for testing
|
124
|
-
def read; control_transfer(function: :read, wIndex: 0, dataIn: 1); end
|
125
|
-
def write byte; control_transfer(function: :write, wIndex: 0, wValue: byte); end
|
126
|
-
def clear_bit bit; control_transfer(function: :clear_bit, wIndex: 0, wValue: bit); end
|
127
|
-
def set_bit bit; control_transfer(function: :set_bit, wIndex: 0, wValue: bit); end
|
124
|
+
#def echo; control_transfer(function: :echo, dataIn: 8).unpack('S<*'); end # echo's usb request for testing
|
125
|
+
#def read; control_transfer(function: :read, wIndex: 0, dataIn: 1); end
|
126
|
+
#def write byte; control_transfer(function: :write, wIndex: 0, wValue: byte); end
|
127
|
+
#def clear_bit bit; control_transfer(function: :clear_bit, wIndex: 0, wValue: bit); end
|
128
|
+
#def set_bit bit; control_transfer(function: :set_bit, wIndex: 0, wValue: bit); end
|
128
129
|
# - programming requests
|
129
130
|
#def power_up sck_period, reset; control_transfer(function: :power_up, wIndex: sck_period, wValue: reset ? 1 : 0); end
|
130
131
|
#def power_down; control_transfer(function: :power_down); end
|
@@ -151,12 +152,23 @@ class LittleWire
|
|
151
152
|
@i2c ||= I2C.new(self)
|
152
153
|
end
|
153
154
|
|
154
|
-
# get the 1wire interface (requires firmware 1.1 or newer
|
155
|
+
# get the 1wire interface (requires firmware 1.1 or newer)
|
155
156
|
def one_wire
|
156
157
|
raise "You need to update your LittleWire firmware to version 1.1 to use One Wire" unless version_hex >= 0x11
|
157
158
|
@one_wire ||= OneWire.new(self)
|
158
159
|
end
|
159
160
|
|
161
|
+
# get the ws2811 led strip interface (requires firmware 1.2 or newer)
|
162
|
+
# optionally call with pin number to preset it
|
163
|
+
def ws2811 pin = false
|
164
|
+
raise "You need to update your LittleWire firmware to version 1.2 to use One Wire" unless version_hex >= 0x12
|
165
|
+
@ws2811 ||= Array.new
|
166
|
+
@ws2811[pin || 0] ||= WS2811.new(self, pin)
|
167
|
+
return @ws2811[pin || 0]
|
168
|
+
end
|
169
|
+
|
170
|
+
alias_method :ws2812, :ws2811
|
171
|
+
|
160
172
|
|
161
173
|
|
162
174
|
# translate calls with arduino-style lowerCamelCase method names in to ruby-style underscored_method_names
|
@@ -259,7 +271,9 @@ class LittleWire
|
|
259
271
|
:onewire_read_bit, # 50
|
260
272
|
:onewire_write_bit, # 51
|
261
273
|
:pic_24f_programming, # 52 - experimental
|
262
|
-
:pic_24f_sendsix
|
274
|
+
:pic_24f_sendsix, # 53 - experimental
|
275
|
+
:ws2812_write, # 54 - experimental
|
276
|
+
:ws2812_preload # 55 - experimental
|
263
277
|
# special cases
|
264
278
|
# pic 24f send bytes - request = 0xD*
|
265
279
|
# i2c send multiple messages - request = 0xE* ### experimental ###
|
@@ -278,10 +292,9 @@ class LittleWire
|
|
278
292
|
|
279
293
|
# calculate usb request type
|
280
294
|
def usb_request_type opts #:nodoc:
|
281
|
-
|
282
|
-
value
|
283
|
-
value |=
|
284
|
-
value |= c::EndpointDirections[:ENDPOINT_IN] if opts.has_key? :dataIn
|
295
|
+
value = LIBUSB::REQUEST_TYPE_VENDOR | LIBUSB::RECIPIENT_DEVICE
|
296
|
+
value |= LIBUSB::ENDPOINT_OUT if opts.has_key? :dataOut
|
297
|
+
value |= LIBUSB::ENDPOINT_IN if opts.has_key? :dataIn
|
285
298
|
return value
|
286
299
|
end
|
287
300
|
|
data/lib/software-pwm.rb
CHANGED
@@ -34,10 +34,17 @@ module LittleWire::SoftwarePWM
|
|
34
34
|
end
|
35
35
|
|
36
36
|
# Set the value of a single software pwm channel - value must be a number between 0 and 255 inclusive
|
37
|
-
def software_pwm_write
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
def software_pwm_write *args
|
38
|
+
if args.first.is_a? Hash
|
39
|
+
state = self.software_pwm
|
40
|
+
args.first.each do |channel, value|
|
41
|
+
state[get_pin(LittleWire::SoftwarePWMPinMap, channel)] = value
|
42
|
+
end
|
43
|
+
self.software_pwm = state
|
44
|
+
else
|
45
|
+
raise "Invalid Arguments" unless args.length == 2
|
46
|
+
self.software_pwm_write(args.first => args.last)
|
47
|
+
end
|
41
48
|
end
|
42
49
|
|
43
50
|
def is_software_pwm_available?
|
data/lib/spi.rb
CHANGED
@@ -6,12 +6,14 @@ class LittleWire::SPI
|
|
6
6
|
end
|
7
7
|
|
8
8
|
# send and receive a message of up to four bytes
|
9
|
-
def send send,
|
9
|
+
def send send, auto_chipselect = false
|
10
10
|
mode = auto_chipselect ? 1 : 0
|
11
|
+
bytes = send.bytes.to_a
|
11
12
|
@wire.control_transfer(
|
12
|
-
|
13
|
-
wValue:
|
14
|
-
wIndex:
|
13
|
+
bRequest: 0xF0 + send.length + (mode << 3),
|
14
|
+
wValue: bytes[1].to_i << 8 | bytes[0].to_i,
|
15
|
+
wIndex: bytes[3].to_i << 8 | bytes[2].to_i,
|
16
|
+
dataIn: bytes.length
|
15
17
|
)
|
16
18
|
end
|
17
19
|
|
data/lib/ws2811.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'colorist'
|
2
|
+
|
3
|
+
# Output colours to ws2812 strips and other 800khz ws2811 led devices
|
4
|
+
# To use, simply set colours in the 'colors' array property as css color strings
|
5
|
+
# or Colorist::Color objects, then call #output(pin) to send it on it's way
|
6
|
+
#
|
7
|
+
# Note that this requires firmware v1.2 which is not yet released and there is a
|
8
|
+
# maximum of 64 lights in the firmware at the time of writing
|
9
|
+
#
|
10
|
+
# Also note that you can connect 64 leds to each of the digital pins on the LittleWire
|
11
|
+
# or Digispark device, and this enables you a total of 64 * 4 = 256 lights! Neato!
|
12
|
+
class LittleWire::WS2811
|
13
|
+
attr_accessor :colors
|
14
|
+
attr_accessor :pin
|
15
|
+
|
16
|
+
|
17
|
+
def initialize wire, default_pin = false # :nodoc:
|
18
|
+
@wire = wire
|
19
|
+
@pin = default_pin
|
20
|
+
@colors = []
|
21
|
+
end
|
22
|
+
|
23
|
+
# send colours to strip, optionally specifying a pin if not specified via
|
24
|
+
# littlewire.ws2811(pin).output
|
25
|
+
def output pin = nil
|
26
|
+
colors_buffer = @colors.map { |i| i.is_a?(Colorist::Color) ? i : i.to_color }
|
27
|
+
output_pin = @wire.get_pin(LittleWire::DigitalPinMap, pin || @pin)
|
28
|
+
raise "Must specify output pin for ws2811 strip" unless output_pin.is_a? Integer
|
29
|
+
|
30
|
+
until colors_buffer.empty?
|
31
|
+
|
32
|
+
if colors_buffer.length > 1
|
33
|
+
color = colors_buffer.shift
|
34
|
+
|
35
|
+
@wire.control_transfer(
|
36
|
+
function: :ws2812_preload,
|
37
|
+
wIndex: color.b << 8 | color.r,
|
38
|
+
wValue: color.g << 8
|
39
|
+
)
|
40
|
+
elsif colors_buffer.length == 1
|
41
|
+
color = colors_buffer.shift
|
42
|
+
|
43
|
+
@wire.control_transfer(
|
44
|
+
function: :ws2812_write,
|
45
|
+
wIndex: color.b << 8 | color.r,
|
46
|
+
wValue: color.g << 8 | output_pin
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/readme.md
CHANGED
@@ -53,8 +53,8 @@ lights... whatever floats your boat really. The possabilities are not especially
|
|
53
53
|
limited. Most projects you might use an Arduino for can be done with a Little Wire
|
54
54
|
if you don't mind leaving a computer turned on connected to it, and with the advent
|
55
55
|
of Raspberry Pi, that's not all that bad of an idea. I use my Little Wire to quickly
|
56
|
-
test ideas before changing them to C and uploading them to cheaper
|
57
|
-
using the Little Wire to program them)
|
56
|
+
test ideas before changing them to C and uploading them to cheaper avr tiny chips
|
57
|
+
(also using the Little Wire to program them)
|
58
58
|
|
59
59
|
|
60
60
|
### a warning ###
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: littlewire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.9.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-05-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: libusb
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 0.2.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: colorist
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.0.2
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.0.2
|
30
46
|
description: A little library for a little wire. Providing a pure ruby interface (via
|
31
47
|
the nonpure libusb gem) to littlewire.cc's wonderful gadget. littlewire.rb provides
|
32
48
|
general purpose digital IO, pulse width modulation analog outputs, analog inputs,
|
@@ -46,10 +62,15 @@ files:
|
|
46
62
|
- lib/servo.rb
|
47
63
|
- lib/software-pwm.rb
|
48
64
|
- lib/spi.rb
|
65
|
+
- lib/ws2811.rb
|
49
66
|
- readme.md
|
50
67
|
- license.txt
|
51
68
|
- examples/blinky.rb
|
52
69
|
- examples/fadey.rb
|
70
|
+
- examples/led pixel.rb
|
71
|
+
- examples/ws2811 colors.rb
|
72
|
+
- examples/ws2811 scan.rb
|
73
|
+
- examples/ws2811.rb
|
53
74
|
homepage: http://creativepony.com/littlewire/
|
54
75
|
licenses: []
|
55
76
|
post_install_message:
|
@@ -72,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
93
|
version: '0'
|
73
94
|
requirements: []
|
74
95
|
rubyforge_project:
|
75
|
-
rubygems_version: 1.8.
|
96
|
+
rubygems_version: 1.8.23
|
76
97
|
signing_key:
|
77
98
|
specification_version: 3
|
78
99
|
summary: A tiny library for littlewire.cc usb devices
|