austinbv / dino

Dino is a ruby gem that helps you bootstrap prototyping with an Arduino
MIT License
389 stars 84 forks source link

Buttons don't work! #85

Closed VasiliyG closed 9 years ago

VasiliyG commented 9 years ago

Hello! I apologize for my bad english... I used your example of a button. But received an error:

root@ubuntu:~/Downloads/ruby# ruby dino_test.rb Could not find board. Retrying... Connected to board... /usr/local/rvm/gems/ruby-2.2.0/gems/dino-0.12.0/lib/dino/components/mixins/callbacks.rb:13:in add_callback': undefined methodsynchronize' for nil:NilClass (NoMethodError) from /usr/local/rvm/gems/ruby-2.2.0/gems/dino-0.12.0/lib/dino/components/basic/digital_input.rb:27:in on_high' from dino_test.rb:25:in

'

My system configuration: OS: Ubuntu 14.04, with RVM. Ruby version is 2.2.0. Arduino - is Mega 2560. This version arduino (on Mega 2560) work only on 0.12.0 version gem.

Analog signals read function in you gem work fine! Anothe function I'm not check.

vickash commented 9 years ago

Just pushed 1926aeb, which will fix it. Pull that down and you should be good to go. super wasn't being called in #after_initialize for Button. The code that sets up each of the basic components needs some reworking. There's more inheritance of the initializer methods and calling of super than I'd like.

VasiliyG commented 9 years ago

Thank you! Now buttons work fine!

But I'm use daemon, where I read analog input, and want read and digital pins, but you method, where need use "sleep", with this method my daemons stop at moment read buttons.

Can I read didgital pins like analog?

Now I read analog pins like this:

temp = 0 sensor.read { |value| temp = value.to_i }

After read I work with transfer data. And if I use 'sleep' for buttons, my daemons don't work with another pins...

vickash commented 9 years ago

Can you post more of the code you're trying to get working? Not sure exactly what you mean. On Mar 1, 2015 11:09 AM, "VasiliyG" notifications@github.com wrote:

Thank you! Now buttons work fine!

But I'm use daemon, where I read analog input, and want read and digital pins, but you method, where need use "sleep", with this method my daemons stop at moment read buttons.

Can I read didgital pins like analog.

Now I read analog pins like this:

temp = 0 sensor.read { |value| temp = value.to_i }

After read I work with transfer data. And if I use 'sleep' for buttons, my daemons don't work with another pins...

— Reply to this email directly or view it on GitHub https://github.com/austinbv/dino/issues/85#issuecomment-76600676.

VasiliyG commented 9 years ago

I have succeed experiment... But I'm not sure that I did the right thing Here is my code daemon:

board = Dino::Board.new(Dino::TxRx::Serial.new) sensor = Dino::Components::Sensor.new(pin: 'A0', board: board) last_save_temprature = (Time.now-15.minutes).to_i movesensor = Dino::Components::Button.new(pin: 22, board: board) last_movements_work = Time.now.to_i while($running) do

Read thermal sensor

temp = 0
sensor.read { |value| temp = value.to_i }
if (last_save_temprature+15.minutes).to_i < Time.now.to_i
    last_save_temprature = Time.now.to_i
    resistance = ((1023.0-temp.to_f)_10000.0/temp.to_f)
    temprature = (1/(Math.log(resistance/10000)/3975.0+1.0/298.15)-273.15)
    new_row = ThermalSensor.new(:value => temprature.round(1))
    new_row.save
    @sensors = ThermalSensor.last(100)
    g = Gruff::Bezier.new("800x500")
    g.labels = Hash[_[@sensors.first, @sensors.last].collect {|v| [@sensors.index(v),v.created_at.to_time.to_s(:custom_datetime)] }.flatten]
    g.data :Температура, @sensors.collect{|sensor| sensor.value} 
    g.theme = {   # Declare a custom theme
        :colors => %w(black purple green white red #cccccc), # colors can be described on hex values (#0f0f0f)
        :marker_color => 'black', # The horizontal lines color
        :background_colors => %w(white #efefef) # you can use instead: :background_image => ‘some_image.png’
    }
    g.write('public/exciting.png')
end 
movesensor.up do
    if (last_movements_work+60.seconds).to_i < Time.now.to_i
        new_move_sensor = Movesensor.new(:were_movement => true)
        new_move_sensor.save
        last_movements_work = Time.now.to_i
    end
end

sleep 0.5 end

vickash commented 9 years ago

Here's how to do it. You need to use #poll on the analog sensor with an interval of 15 mins (15*60 seconds). This will read the sensor once every 15 mins (you don't need to worry about manual timing), and run the block each time a value is received.

You set up the callback up on movesensor correctly, but by looping and calling every 0.5 second, you may have kept duplicating the callback and created extra Movesensor objects. Have you noticed that happening?

You need to call sleep in the main thread (last line), because after the callbacks are added with the #poll and #up methods, they run in a separate thread. The main thread now has nothing to do, so you need to sleep it to prevent the script from stopping.

board = Dino::Board.new(Dino::TxRx::Serial.new)
sensor = Dino::Components::Sensor.new(pin: 'A0', board: board)
movesensor = Dino::Components::Button.new(pin: 22, board: board)

sensor.poll(15*60) do |value|
  resistance = ((1023.0-value.to_f)10000.0/value.to_f)
  temprature = (1/(Math.log(resistance/10000)/3975.0+1.0/298.15)-273.15)
  new_row = ThermalSensor.new(:value => temprature.round(1))
  new_row.save
  @sensors = ThermalSensor.last(100)
  g = Gruff::Bezier.new("800x500")
  g.labels = Hash[[@sensors.first, @sensors.last].collect {|v| [@sensors.index(v),v.created_at.to_time.to_s(:custom_datetime)] }.flatten]
  g.data :Температура, @sensors.collect{|sensor| sensor.value} 
  g.theme = { # Declare a custom theme
  :colors => %w(black purple green white red #cccccc), # colors can be described on hex values (#0f0f0f)
  :marker_color => 'black', # The horizontal lines color
  :background_colors => %w(white #efefef) # you can use instead: :background_image => ‘some_image.png’
  }
  g.write('public/exciting.png')
end

last_movements_work = Time.now.to_i
movesensor.up do
  if (last_movements_work+60.seconds).to_i < Time.now.to_i
    new_move_sensor = Movesensor.new(:were_movement => true)
    new_move_sensor.save
    last_movements_work = Time.now.to_i
  end
end

sleep
VasiliyG commented 9 years ago

I try you code, and all work very good, thank you!

And now I use Light sensor with "poll" every 5 seconds, and it work good too!

But when I use rgb led, poll or button block where I use "rgb" method don't work...

There is my code with comments:

board = Dino::Board.new(Dino::TxRx::Serial.new)
sensor = Dino::Components::Sensor.new(pin: 'A0', board: board)
last_save_temprature = (Time.now-15.minutes).to_i 
movesensor = Dino::Components::Button.new(pin: 22, board: board)
light_sensor = Dino::Components::Sensor.new(pin: 'A1', board: board)
@ligh_sensor = 0
rgb_led = Dino::Components::RgbLed.new(pins: {red: 2, green: 3, blue: 4}, board: board)
while($running) do
    sensor.poll(15*60) do |value|
        resistance = ((1023.0-value.to_f)*10000.0/value.to_f)
        temprature = (1/(Math.log(resistance/10000)/3975.0+1.0/298.15)-273.15)
        new_row = ThermalSensor.new(:value => temprature.round(1))
        new_row.save
        @sensors = ThermalSensor.last(100)
        g = Gruff::Bezier.new("800x500")
        g.labels = Hash[*[@sensors.first, @sensors.last].collect {|v| [@sensors.index(v),v.created_at.to_time.to_s(:custom_datetime)] }.flatten]
        g.data :Температура, @sensors.collect{|sensor| sensor.value} 
        g.theme = {   
            :colors => %w(black purple green white red #cccccc), 
            :marker_color => 'black', 
            :background_colors => %w(white #efefef) 
        }
        g.write('public/exciting.png')
    end
    light_sensor.poll(5) do |light|
        @light_sensor = light
               #THERE NOT WORK IF USE rgb_led.color function
        if (last_movements_work+5.minutes).to_i < Time.now.to_i
            rgb_led.color=[0, 0, 0]
        end
    end 
    last_movements_work = Time.now.to_i
    movesensor.up do
      if (last_movements_work+60.seconds).to_i < Time.now.to_i
        temp_light = 0  
        new_move_sensor = Movesensor.new(:were_movement => true, :light_sensor => @light_sensor )
        new_move_sensor.save
        last_movements_work = Time.now.to_i
                #THERE NOT WORK IF USE rgb_led.color function
        to_led_value = @light_sensor/4
        rgb_led.color=[to_led_value, 0, 0]
      end
    end
    sleep
end
vickash commented 9 years ago

Why are you still using while($running)? There is no need to loop that code. You are sleeping at the end of the loop anyway, so it will never run twice.

If you are trying to catch a signal, see the ssd example in the examples folder for a cleaner way to do that?

As for the rgb led, that's another bug I just fixed. Pull the latest from c165218, and it should work....Pins really need to become first class objects at this point.

VasiliyG commented 9 years ago

Ou, I forgot delete while($running) ... :)

But I still have problem whit rgb led. I pull you fix, but this not help my problem.

I try this example:


require 'bundler/setup'
require 'dino'

board = Dino::Board.new(Dino::TxRx::Serial.new)

rgb_led = Dino::Components::RgbLed.new(pins: {red: 2, green: 3, blue: 4}, board: board)
sensor = Dino::Components::Sensor.new(pin: 'A0', board: board)
movesensor = Dino::Components::Button.new(pin: 22, board: board)
light_sensor = Dino::Components::Sensor.new(pin: 'A1', board: board)

    light_sensor.poll(1) do |light|
        puts light 
        @to_led_value = 255-light/4
        rgb_led.color=[@to_led_value, 0, 0]
    end
sleep

And when this script start, I see one "puts" and after nothing...

When I remove rgb_led.color=[@to_led_value, 0, 0] from "poll" process all work fine!

Can I use rgb method from "poll" process?

vickash commented 9 years ago

Yes, you should be able to access rgb_led from inside the callback.

light should be light.to_i on the line where you do the division. Remember that messages get passed to the callbacks as strings.

Also, double check that you're using the latest commit. I made a change where errors inside a callback should raise exceptions now, instead of failing silently. As soon as I ran your code it raised an exception.

vickash commented 9 years ago

Also make sure that all the pins you're connecting the RGB led to on your arduino support PWM: http://arduino.cc/en/Tutorial/PWM

I don't think 2, 3 and 4 will get you the results you expect.

dino explicitly allows you to analog write any pin (since we can't know which pins on which boards are PWM). If you analog write to pins without PWM, they will just toggle on and off at some threshold value instead of fading.

Pull the latest commit if you're not sure which version you're on. I introduced a bug between the one you pulled yesterday and just fixed it.

VasiliyG commented 9 years ago

I use arduino Mega on AVR micro controller mega2560. This version arduino have from 2 to 12 pins with PWM.

This example:


require 'bundler/setup'
require 'dino'

board = Dino::Board.new(Dino::TxRx::Serial.new)
sensor = Dino::Components::Sensor.new(pin: 'A10', board: board)
led = Dino::Components::RgbLed.new(pins: {red: 3, green: 5, blue: 6}, board: board)
sensor.poll(1) do |value|
    led.color(240,0,0)         #This line stop work script, but arduino continues send data. I see it by blink led "tx" "rx", but script don't work
    puts value
end
sleep 

If I remove this line ( led.color(240,0,0) ) all work done

I check this script with arduino uno and arduino nano, the result is the same.

VasiliyG commented 9 years ago

Now I try pull last version gem, and now work all good! On evening I try new version gem in my server and write you my result

vickash commented 9 years ago

Sorry. Forgot you were using a Mega. Those pins should be fine.

Be careful with #color=. It should not be #color without the equal sign. I'm guessing that's it since that's what I had to change before to get it working.