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 と接続するには次の表の通り接続します。
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 に値を送った(D IN
)後に、どのように MCP3008 から値が返ってくるか(D OUT
)が表されています。
以上のデータシートの内容から、 RaspberryPi から MCP3008 を介してセンサーの値を取得するには、3つの要素をもつ配列をSPIで渡せば良いことがわかります。 配列の内容は、
[0]
: Start bit(1
)[1]
: 指示データ
SGL/DIFF
: 今回はSingle-modeを使用するので 1
です。D2
, D1
, D0
: データを取得するチャンネルを表す[2]
: End bit(0
)です。
SPIで配列を渡した後に、MCP3008 から 10bitのデータがセンサーから返ってきます。
帰ってくる配列(adc
)の内容は、
[0]
: 不定[1]
: 10bit中 先頭2bit のセンサーの値
0
[3]
: 10bit中 後8ビットのセンサーの値です。 帰ってくる配列を見てわかる通り、1バイトは8bitなので、配列の1つの項目には8bitしか返しません。そのため、ビット演算が必要になります。
コードの adc[1] & 0b00000011
は1bit目〜0bit目をビットマスクしています。それを、8bit分を前にビットシフトしています。
+ adc[2]
で残りのbitを加算することで、10bitのデータに仕上げています。
0b00000011
などと2進数にしました。今度は、変更しやすいように、16進数に置き換えてみましょう。例えば、0b00000011
は 0x3
になります。volt_to_distance
がそのメソッドです。volt_to_distance
に MCP3008 から受け取った距離センサーの値を引数 volt に渡します。def volt_to_distance(volt)
return 0 if volt == 0
dist = (6787 / (volt - 3)) - 4
dist.round(4)
end
回答例はこちら