はじめに
Elixir で CO2センサー MHZ19 の読み取り方を書いたものが見つからなかったため,この記事を書くことにした.
使用するもの
- Raspberry pi 3b (など)
- mh-z19 CO2センサー (https://akizukidenshi.com/catalog/g/gM-16142/)
前提
- Nervesが入っている
- mh-z19 が配線されている
本編
ライブラリのインストール
- mh-z19 は UART通信を用いるので,
Circuits.UART
(ドキュメント) を使う.
まずは mix.exs
に追加したあと,mix deps.get
する.
defp deps do
[
# ....
{:circuits_uart, "~> 1.3"}
]
end
コード
[mh-z19 データシート](https://www.winsen-sensor.com/d/files/PDF/Infrared Gas Sensor/NDIR CO2 SENSOR/MH-Z19 CO2 Ver1.0.pdf) に従って,後々使いやすいように(?) GenServer
の形で実装する.
init
- UART の GenServer (このGenServerとは別) を起動して,pid を状態としてを持っておく.
- UART GenServer の "ttyAMA0" インタフェースを開く.このとき,データシートに従って
baud_rate
等のパラメタを設定しておく.
handle_call
GenServer へ :read
の呼び出しが来たときに,センサーの読み取り値を返す.
- センサーの値を読み取るコマンド
@sensor_read_command
をwrite
してあげる. -
read_uart
を呼び出して,帰ってきた値を読む.-
read_uart
では,結果を含む返信を読むまでループして,結果を返すか,結果が得られなければ{:error, reason}
を返す.(reason
はCircuits.UART
のエラーを含む)
-
measure
値を読むためのメソッド.使うときはこれを呼べば良い.
defmodule WarblerUi.Sensors.Mhz19 do
use GenServer, restart: :permanent
alias Circuits.UART
@baud_rate 9600
@sensor_read_command <<0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79>>
def init(_opts) do
{:ok, uart_pid} = UART.start_link()
:ok =
UART.open(uart_pid, "ttyAMA0",
speed: @baud_rate,
data_bits: 8,
stop_bits: 1,
parity: :none,
active: false
)
{:ok, uart_pid}
end
def handle_call(:read, _from, uart_pid) do
:ok = UART.write(uart_pid, @sensor_read_command)
read_uart(uart_pid)
end
defp read_uart(uart_pid) do
case UART.read(uart_pid) do
{:ok, <<255, 134, higher_bits, lower_bits, _, _, _, _>>} ->
decoded_data = higher_bits * 256 + lower_bits
{:reply, {:ok, decoded_data}, uart_pid}
{:error, reason} ->
{:reply, {:error, reason}, uart_pid}
_ ->
read_uart(uart_pid)
end
end
def measure(pid) do
GenServer.call(pid, :read)
end
end
使い方
Nerves のコンソールを ssh nerves.local
して開き,こんな感じで実行すれば,CO2 濃度がわかる.
alias WarblerUi.Sensors.Mhz19
{:ok, mhz19_pid} = GenServer.start_link(Mhz19, {})
{:ok, co2} = Mhz19.measure(mhz19_pid)
あとがき
現在は Phoenix フレームワークを使って,センサーの値を liveview で表示したりしようとしています.
気が向いたらそれについても書くかもしれません.
また,Elixir, Nerves を始めて間もなく,初めての記事なので,間違い等あるかもしれないです.
見つけた場合は指摘していただければ幸いです.