距離センサーから値を取得

ruby hardware programming

距離センサーから値を取得

必要なパーツ

メーカー 秋月 通販コード 型番 商品名 個数
シャープ I-02551 GP2Y0A21YK シャープ測距モジュール 1
Microchip Technology Inc. I-09485 MCP3008-I/P 10bit 8ch ADコンバータ 1

配線

距離センサーから値を取得 回路図

MCP3008 は中央の溝を跨ぐように接続します。ブレッドボードで左右の足の電流を混ぜないためです。丸いポッチが PIN 1 側を表します。 今回、使用している距離センサーは GP2Y0A21YK0F です。 距離センサー の1番ピン(実物の白色)を MCP3008 の ch0 で接続しています。

RaspberryPi との接続方法

RaspberryPi PIN配置 MCP3008のPIN配置

RaspberryPi と接続するには次の表の通り接続します。

MCP3008 側 Raspberry Pi 側
V DD 5V
V REF 5V
AGND GND
CLK GPIO11
D OUT GPIO09
D IN GPIO10
CS/SHDN GPIO08
DGND GND

コード

require 'pi_piper'

def read(channel)
  PiPiper::Spi.begin do |spi|
    # ch0の場合は2進数では [00000001, 00001000, 00000000] の配列を送る
    adc = spi.write [0b00000001, (0b00001000 + channel) << 4, 0b00000000]
    ((adc[1] & 0b00000011) << 8) + adc[2] # &演算子はビット積
    # 上記は次のような処理をしている
    # 1. ?????010 & 00000011 -> 00000010
    # 2. 00000010 00000000 + 00000000 10000001 -> 00000010 10000001
  end
end

loop do
  puts read(0)
  sleep 3
end

ソースの解説

次のイメージは MCP3008 のデータシートから抜粋したものになります。 指示データをどのように設定すれば目的のチャンネルから値が取得できるかがわかります。

MCP3008に渡す配列の設定

このイメージは、 MCP3008 に値を送った(D IN)後に、どのように MCP3008 から値が返ってくるか(D OUT)が表されています。

MCP3008の8bitセグメントSPI通信

以上のデータシートの内容から、 RaspberryPi から MCP3008 を介してセンサーの値を取得するには、3つの要素をもつ配列をSPIで渡せば良いことがわかります。 配列の内容は、

です。

SPIで配列を渡した後に、MCP3008 から 10bitのデータがセンサーから返ってきます。 帰ってくる配列(adc)の内容は、

です。 帰ってくる配列を見てわかる通り、1バイトは8bitなので、配列の1つの項目には8bitしか返しません。そのため、ビット演算が必要になります。

コードの adc[1] & 0b00000011 は1bit目〜0bit目をビットマスクしています。それを、8bit分を前にビットシフトしています。 + adc[2] で残りのbitを加算することで、10bitのデータに仕上げています。

Let’s try

  1. 距離に応じて、表示されるメッセージを変更してみましょう。「近すぎる」、「ちょうど良い」、「遠すぎる」が表示されるようにしましょう。手の平の方へセンサーを向けて、手を近づけたり遠ざけたりすると、値が変動します。
  2. サンプルソースでは説明しやすくするために 0b00000011 などと2進数にしました。今度は、変更しやすいように、16進数に置き換えてみましょう。例えば、0b000000110x3 になります。
  3. 距離センサーのデータシートから抜粋した以下のグラフを元に、距離を計算してみましょう。
    • 本来は計算式をグラフから読み取ってグラフの曲線を描くような一次関数を作るのですが、今回は、既にネット上に転がっている計算式を用います。volt_to_distanceがそのメソッドです。
    • 計算式の参考にしたサイトは こちら(英語) です。
    • volt_to_distance に MCP3008 から受け取った距離センサーの値を引数 volt に渡します。

Inverse number of distance

def volt_to_distance(volt)
  return 0 if volt == 0

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

回答例はこちら