クローラーを動かす

ruby hardware programming

クローラーを動かす

必要なパーツ

メーカー 秋月 通販コード 型番 商品名 個数
Anker - A1263011-9 Anker PowerCore 10000 (モバイルバッテリー 10000mAh) 1
協和ハーモネット P-02220 TCW 0.6mm 10m スズメッキ線(0.6mm 10m) 1
シャープ I-02551 GP2Y0A21YK シャープ測距モジュール 1
Microchip Technology Inc. I-09485 MCP3008-I/P 10bit 8ch ADコンバータ 1
東芝 I-02001 TA7291P モータードライバ 2
TAMIYA - ITEM 70168 ダブルギヤボックス 1
TAMIYA - ITEM 70098 ユニバーサルプレート 1
TAMIYA - ITEM 70229 32mm径スプロケット&クローラーセット 1

配線

クローラーを動かす 回路図1 クローラーを動かす 回路図2

動作確認用のコード

Gemfile

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'pi_piper'

bundle install --path vendor/bundle を実行します。

ta7291p.rb

モータードライバー(TA7291P) を制御するコードです。

require 'pi_piper'

class Ta7291p
  attr_reader :forward_pin, :back_pin

  def initialize(pwm_pin_id, forward_pin_id, back_pin_id, power_value = 0.5)
    @pwm_pin = pwm = PiPiper::Pwm.new pin: pwm_pin_id
    @forward_pin = PiPiper::Pin.new pin: forward_pin_id, direction: :out
    @back_pin = PiPiper::Pin.new pin: back_pin_id, direction: :out
    @power = power_value
    @pwm_pin.value = power_value
  end

  def power=(value)
    @power = value
    @pwm_pin.value = value
  end

  def power
    @power
  end

  def forward(drive_time)
    @forward_pin.on
    sleep drive_time
    @forward_pin.off
  end

  def back(drive_time)
    @back_pin.on
    sleep drive_time
    @back_pin.off
  end

  def breake
    @forward_pin.on
    @back_pin.on
  end
end

mcp3008.rb

アナログ・デジタル変換チップ(MCP3008) を制御するコードです。

require 'pi_piper'

class Mcp3008
  attr_reader :channel

  def initialize(channel)
    @channel = channel
  end

  def read
    PiPiper::Spi.begin do |spi|
      adc = spi.write [0x1, (0x8 + @channel) << 4, 0x0]
      ((adc[1] & 0x3) << 8) + adc[2]
    end
  end
end

gp2y0a21yk0f.rb

距離センサー(GP2Y0A21YK0F) から MCP3008 経由で取得した電圧から距離に変換するコードです。

class Gp2y0a21yk0f
  def self.volt_to_distance(volt)
    return 0 if volt == 0

    dist = (6787 / (volt - 3)) - 4
    dist.round(4)
  end
end

crawler_test.rb

動作確認用のコードです。

require './ta7291p'
require './mcp3008'
require './gp2y0a21yk0f'

# モーター1
# GPIO 20 -> 正転?
# GPIO 21 -> 逆転?
# GPIO 12 -> PWM
@motor_1 = Ta7291p.new(12, 20, 21, 0.7)

# モーター2
# GPIO 5 -> 正転?
# GPIO 6 -> 逆転?
# GPIO 13 -> PWM
@motor_2 = Ta7291p.new(13, 5, 6, 0.7)

# ADコンバーター
mcp3008 = Mcp3008.new(0)

def kick_combo_motor
  [@motor_1, @motor_2].map do |motor|
    Thread.new { yield(motor) }
  end.each { |t| t.join }
end

loop do
  # モーターを交互に動かす
  @motor_1.forward(2)
  @motor_2.forward(2)

  sleep 2

  # モーターを左右同時に動かす
  kick_combo_motor { |motor| motor.forward(2) }

  # センサーの値を取得する
  puts Gp2y0a21yk0f.volt_to_distance(mcp3008.read)

  sleep 2
end

動作確認

これで、モーターが交互に動いた後に、左右のモーターが同時に動きます。 最後に、距離センサーの値をコンソールに表示します。

rbenv sudo bundle exec ruby crawler_test.rb

Let’s try

  1. 次の機能を備えた、クローラー動かすを作るためにはどのようなアルゴリズムになるか考えてみましょう。
    1. クローラーは前に進んでいく。
    2. 距離センサーを使って、障害物がないか確認する。障害物があれば、それを避けて進む。
  2. 考えたアルゴリズムを実装してみましょう。

回答例はこちら