#1.はじめに
Elixirを使って、RaspberryPiのハードウェア制御の練習をしてみました。
今回は、Elixir Circuits.I2Cから、Grove Base Hat for Raspberry Piに搭載されているADコンバータを制御してみます。
#2.ハードウェア
Seeed社のGROVE規格1の機器を、RaspberryPiに接続するインターフェース・ボードです。GPIO、I2C、UART、そしてアナログタイプの入力用として12bitのADコンバータも搭載しています。
###I2C通信仕様
- Grove Base HATのアドレス:
0x04
コマンドライン
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- 04 -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
I2C Registers | 値 |
---|---|
0x10 ~ 0x17 | ADC raw data |
0x20 ~ 0x27 | input voltage |
0x29 | output voltage (Grove power supply voltage) |
0x30 ~ 0x37 | input voltage / output voltage |
I2Cコマンドの処理の流れ
# I2Cアドレス
@address 0x04
#コマンド送信
I2C.write(ref, @address, <<I2C Registers>>)
Process.sleep(1)
#結果受信、2バイト読み込み
I2C.read(ref, @address, 2)
{:ok, <<ret0, ret1>>} = I2C.read(ref, @address, 2)
#2バイト分を連結
ret0 ||| ret1 <<< 8
#3.ソフトウェア
##(1)下準備
プロジェクトを作ります。
コマンドライン
$ cd gitwork
$ mix new i2chatad
$ cd i2chatad
##(2)コード
i2chatadc.ex
defmodule I2chatad do
@moduledoc """
Documentation for `I2chatad`.
https://github.com/elixir-circuits/circuits_i2c
https://github.com/Seeed-Studio/grove.py/blob/master/grove/adc.py
"""
alias Circuits.I2C
require Logger
use Bitwise
# I2Cアドレス
@address 0x04
@doc """
データ取得
## Examples
iex> I2chatad.get()
"""
def get() do
# I2Cを開く
{:ok, ref} = I2C.open("i2c-1")
Logger.info(" RAW VOLT RATE")
# AD0~3読み込み
Enum.each([0, 1, 2, 3], fn ch ->
# RAWデータ
raw = read_raw(ref, ch)
# mVデータ
vol = read_voltage(ref, ch)
# RATEの表記(xx.x %)のうち、整数部だけ残す
rat =
read(ref, ch)
|> div(10)
#測定結果を表示
Logger.info(" ch#{ch}: #{raw} #{vol} mV #{rat} %")
end)
end
@doc """
12bitアナログ入力のRAWデータを読み込み
## Parameter
- channel (int): 0 - 7, specify the channel to read
## Return:
- (int): the adc result, in [0 - 4095]
"""
def read_raw(ref, channel) do
regaddr = 0x10 + channel
read_register2(ref, regaddr)
end
@doc """
電圧(mV)変換した値を返す
## Parameter
- channel (int): 0 - 7, specify the channel to read
## Return:
- (int): the voltage result, in mV
"""
def read_voltage(ref, channel) do
regaddr = 0x20 + channel
read_register2(ref, regaddr)
end
@doc """
入力電圧を、0~3.3Vのスケールでパーセント変換した値を返す
## Parameter
- ref : i2c id
- channel (int): 0 - 7, specify the channel to read
## Return:
- (int): the ratio, in 0.1%
"""
def read(ref, channel) do
regaddr = 0x30 + channel
read_register2(ref, regaddr)
end
@doc """
I2Cレジスタの読み出し(8bit)
## Parameter
- ref : i2c id
- n (int): I2C Resister Addr
## Return:
"""
def read_register(ref, n) do
I2C.write(ref, @address, <<n>>)
Process.sleep(1)
{:ok, <<ret>>} = I2C.read(ref, @address, 1)
ret
end
@doc """
I2Cレジスタの読み出し(12bit)
## Parameter
- ref : i2c id
- n (int): I2C Resister Addr
## Return:
"""
def read_register2(ref, n) do
I2C.write(ref, @address, <<n>>)
Process.sleep(1)
I2C.read(ref, @address, 2)
{:ok, <<ret0, ret1>>} = I2C.read(ref, @address, 2)
#2バイト分の値をビットシフトして連結
ret0 ||| ret1 <<< 8
end
end
##(3)実行結果
iexのプロンプトから、I2chatad.get
を実行するたびに、ch0~4までの値を取得します。
ここでは、各ADxのコネクタに、以下のセンサを繋いでいます。
Grove AD | センサ |
---|---|
AD0 | Grove Light Sensor |
AD2 | Grove Button |
$ iex -S mix
Erlang/OTP 22 [erts-10.5.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Compiling 1 file (.ex)
Remember to keep good posture and stay hydrated!
Interactive Elixir (1.10.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> I2chatad.get
12:34:45.246 [info] RAW VOLT RATE
12:34:45.253 [info] ch0: 2502 2010 mV 60 % ### ← Light 明るい
12:34:45.260 [info] ch1: 2374 1796 mV 52 %
12:34:45.267 [info] ch2: 0 0 mV 0 % ### ← Button 離した
12:34:45.274 [info] ch3: 2504 2010 mV 61 %
:ok
iex(2)> I2chatad.get
12:34:48.758 [info] RAW VOLT RATE
12:34:48.767 [info] ch0: 1225 1126 mV 32 % ### ← Light 暗い
12:34:48.776 [info] ch1: 2131 1889 mV 54 %
12:34:48.785 [info] ch2: 4095 3283 mV 99 % ### ← Button 押した
12:34:48.794 [info] ch3: 2944 2396 mV 70 %
:ok:
#4.おわりに
Elixir Circuits.I2Cから、Grove Base Hat for Raspberry PiのADコンバータを操作する例を紹介しました。もう少し使いやすくするため、ライブラリにしてみます。(作成中)
#参考資料