From ff94a0d1c224fb1b281332f1a7a1cd08c42177e4 Mon Sep 17 00:00:00 2001 From: "Chris Nolan.ca" Date: Sun, 23 Feb 2014 17:38:17 -0500 Subject: [PATCH 1/3] Support for RGB color added --- README.md | 10 +++++++++- scratch2sphero.rb | 47 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ac21142..84020d0 100644 --- a/README.md +++ b/README.md @@ -55,12 +55,20 @@ select the ["Enable remote sensor connections"](http://wiki.scratch.mit.edu/wiki #### Color - Who doesn't like rainbows? Especially blinking double rainbows. You can control the main LED color of Sphero via the color broadcast. + Who doesn't like rainbows? Especially blinking double rainbows. + +##### Color Name + + You can control the main LED color of Sphero via the color broadcast. - create a global variable named color_name and assign it a [color name](http://www.w3schools.com/html/html_colornames.asp), then broadcast "color". - you can also define new broadcasts with color_name where name is one of the valid color names, e.g. broadcast "color_cadetblue" or broadcast "color_crimson" - if you send it an invalid, or blank, color name, it will restore to the saved default color for your Sphero +##### RGB Color + + Create three global variables, r, g, and b and when these values change, the sphero will change. To see how it works, display the variables in scratch, and right click to turn them into sliders. Simply drag the sliders and see the color update. There is also an 'rgb' broadcast available too. + ## Demo Scripts ### Sphero draws square diff --git a/scratch2sphero.rb b/scratch2sphero.rb index c7a974d..8fd8d65 100755 --- a/scratch2sphero.rb +++ b/scratch2sphero.rb @@ -28,6 +28,7 @@ def initialize broadcast "backward" broadcast "color" + broadcast "rgb" broadcast "back_led_on" broadcast "back_led_off" @@ -36,13 +37,14 @@ def initialize @sphero_name = bluetooth_info.body.pack('C'*16).strip unless bluetooth_info.nil? # there seems to be some timing issue where the bluetooth_info isn't already ready in time when I'm asking for it so this is a quick hack to avoid an error # I'm also not sure what it'll do with extended character sets - @sphero_name = "-->unknown<--" if @sphero_name.nil? - # this needs more work... when it is unknown we don't seem to have communication with the ball -- somehow I think it is preventing the "Resource Busy" exception? + raise "Unable to get Sphero's name... Please Try Again" if @sphero_name.nil? puts "Connected to #{@sphero_name}" + user_led_color end - def on_sensor_update(name, value) # when a variable or sensor is updated - value = value.to_i if %w(speed initial_heading steps degrees).include? name + # when a variable or sensor is updated + def on_sensor_update(name, value) + value = value.to_i if %w(speed initial_heading steps degrees r g b).include? name if name == "speed" @speed = value elsif name == "initial_heading" @@ -53,9 +55,17 @@ def on_sensor_update(name, value) # when a variable or sensor is updated @degrees = value elsif name == "color_name" @color_name = value + elsif name == "r" + @r = value + elsif name == "g" + @g = value + elsif name == "b" + @b = value end puts "#{@sphero_name} -- #{name} assigned #{value}" - puts "#{@sphero_name} -- current_heading: #{@current_heading}, absolute_heading: #{@initial_heading + @current_heading}" + color if name == "color_name" + rgb if %w(r g b).include? name + #puts "#{@sphero_name} -- current_heading: #{@current_heading}, absolute_heading: #{@initial_heading + @current_heading}" end def broadcast_move @@ -90,6 +100,10 @@ def broadcast_backward def broadcast_color color end + + def broadcast_rgb + rgb + end def broadcast_back_led_on back_led_on @@ -147,11 +161,28 @@ def color(color_name=@color_name) end end + # sets the RGB color of the sphero via the @r, @g, and @b + def rgb(r=@r, g=@g, b=@b) + # I think the sphero gem's limit1() should probably handle these potential for nils... you can call rgb with the nils, it doesn't error but it puts the sphero in a non-communicative state + r = 0 if r.nil? + g = 0 if g.nil? + b = 0 if b.nil? + puts "#{@sphero_name} -- rgb #{r}/#{g}/#{b}" + @sphero.rgb r, g, b + end + # reset the color of the sphero to the persistent user selected colour def user_led_color() - puts "#{@sphero_name} -- Reseting color to user_led" + puts "#{@sphero_name} -- Resetting color to user_led" user_led = @sphero.user_led - @sphero.rgb user_led.body[0], user_led.body[1], user_led.body[2] + if user_led && user_led.body.nil? + puts "#{@sphero_name} -- No default user_led value" + else + @r = user_led.body[0] + @g = user_led.body[1] + @b = user_led.body[2] + rgb + end end # turns on the back LED so you know which way is forward. @@ -176,5 +207,5 @@ def back_led_off() rescue Errno::ECONNREFUSED puts "\033[31m\033[1mError: Scratch may not be running or remote sensor connections are not enabled.\033[00m\n" rescue => e - puts "\033[31m\033[1mError: #{e.message}\033[00m\n" + puts "\033[31m\033[1mError: #{e.message}\n#{e.backtrace.join('\n\t')}\033[00m\n" end From 959326298f40c210d67a73a879c3986df45028d0 Mon Sep 17 00:00:00 2001 From: "Chris Nolan.ca" Date: Sun, 23 Feb 2014 21:29:41 -0500 Subject: [PATCH 2/3] Update RGB sensor values when using color_name I was hoping to update Scratch's global variables via the RSC program, but that doesn't seem to be available in the protocol. I can update 'sensor values' though, so when you use the color_name logic, and when it retrieves the user LED it will update an r, g, and b sensor value. The Sphero doesn't not return it's current color for some reason so I added a method to Sphero class and just retrieve it separately, not elegant but accomplished what I wanted to do with the test? --- README.md | 1 + scratch2sphero.rb | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84020d0..2c1facd 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ select the ["Enable remote sensor connections"](http://wiki.scratch.mit.edu/wiki - create a global variable named color_name and assign it a [color name](http://www.w3schools.com/html/html_colornames.asp), then broadcast "color". - you can also define new broadcasts with color_name where name is one of the valid color names, e.g. broadcast "color_cadetblue" or broadcast "color_crimson" - if you send it an invalid, or blank, color name, it will restore to the saved default color for your Sphero +- these broadcasts will update the 'sensor values' r, g, and b so you can have access to them via the sensor blocks ##### RGB Color diff --git a/scratch2sphero.rb b/scratch2sphero.rb index 8fd8d65..9ef353a 100755 --- a/scratch2sphero.rb +++ b/scratch2sphero.rb @@ -63,8 +63,15 @@ def on_sensor_update(name, value) @b = value end puts "#{@sphero_name} -- #{name} assigned #{value}" - color if name == "color_name" - rgb if %w(r g b).include? name + # whenever we set the color_name, do the color routine, and send the color broadcast + if name == "color_name" + color + broadcast("color") + end + if %w(r g b).include? name + rgb + broadcast("rgb") + end #puts "#{@sphero_name} -- current_heading: #{@current_heading}, absolute_heading: #{@initial_heading + @current_heading}" end @@ -155,6 +162,10 @@ def color(color_name=@color_name) begin puts "#{@sphero_name} -- color #{color_name}" @sphero.color color_name + rgb = @sphero.rgb_from_colorname color_name + sensor_update "r", rgb[:r] + sensor_update "g", rgb[:g] + sensor_update "b", rgb[:b] rescue => e puts "#{@sphero_name} -- unable to set color_name #{color_name}. #{e.message}" end @@ -168,6 +179,9 @@ def rgb(r=@r, g=@g, b=@b) g = 0 if g.nil? b = 0 if b.nil? puts "#{@sphero_name} -- rgb #{r}/#{g}/#{b}" + sensor_update "r", r + sensor_update "g", g + sensor_update "b", b @sphero.rgb r, g, b end @@ -200,6 +214,15 @@ def back_led_off() end +class Sphero + # hack to give me the rgb used by a colorname + # the sphero itself won't return to me the current color (only the configured color it seems) + def rgb_from_colorname(colorname) + color=COLORS[colorname] + return {:r => color[:r], :g => color[:g], :b => color[:b]} + end +end + begin watcher = PrintRSC.new # you can provide the host as an argument watcher.sensor_update "connected", "1" @@ -207,5 +230,5 @@ def back_led_off() rescue Errno::ECONNREFUSED puts "\033[31m\033[1mError: Scratch may not be running or remote sensor connections are not enabled.\033[00m\n" rescue => e - puts "\033[31m\033[1mError: #{e.message}\n#{e.backtrace.join('\n\t')}\033[00m\n" + puts "\033[31m\033[1mError: #{e.message}\n#{e.backtrace.join("\n\t")}\033[00m\n" end From a0467bd8723bfbfcdb00d9c6c816e3d7182f1e66 Mon Sep 17 00:00:00 2001 From: "Chris Nolan.ca" Date: Mon, 24 Feb 2014 18:45:08 -0500 Subject: [PATCH 3/3] README update for the RGB demo --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2c1facd..d37056c 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ select the ["Enable remote sensor connections"](http://wiki.scratch.mit.edu/wiki [Sphero 2.0 controlled by Scratch(Japanese)](https://www.youtube.com/watch?v=qCeJ6_UKnk4) - [![Sphero colors via Scratch](http://img.youtube.com/vi/UoYA4e8f9Ns/0.jpg)](https://www.youtube.com/watch?v=UoYA4e8f9Ns) [Sphero colors via Scratch](https://www.youtube.com/watch?v=UoYA4e8f9Ns) +- [![RGB demo](http://img.youtube.com/vi/CcnS2AaIhMM/0.jpg)](https://www.youtube.com/watch?v=CcnS2AaIhMM) + [RGB demo](https://www.youtube.com/watch?v=CcnS2AaIhMM) ## Additional Resources @@ -95,3 +97,4 @@ select the ["Enable remote sensor connections"](http://wiki.scratch.mit.edu/wiki - [Scratch's Remote Sensor Control Protocol](http://wiki.scratch.mit.edu/wiki/Remote_Sensors_Protocol) - [Sphero API](http://orbotixinc.github.io/Sphero-Docs/docs/sphero-api/) - [Color Names](http://www.w3schools.com/html/html_colornames.asp) +- Two Scratch 2.0 projects dealing with RGB colors are the simple [Setting Color RGB](http://scratch.mit.edu/projects/2641383/) and the complex [RGB Colour Mixer](http://scratch.mit.edu/projects/187848/)