4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【M5StackMP135 】Livebook でエアコンの働を可視化してみた

Last updated at Posted at 2024-09-14

はじめに

この記事では、M5StackMP135でLivebookを動作させてGPIOを使ってみました。
M5Stackには、コネクターで接続するだけで使える豊富なデバイスが魅力です。加速度、3軸地磁気センサ、気圧・温度センサを一つのパッケージにしたM5STACK-U171(以下、U171と呼ぶことにします。)をコアジェニックさんにいただいたので、Livebookで遊んでみました。

image.png

i2cを使ってみる

U171には、3つのセンサーが搭載されています。いずれも一つのi2cバスに接続されていて、M5Stack本体からはi2cバスを介して制御します。
スイッチサイエンスの説明ページによると搭載されているセンサーとアドレスは以下の通り

センサーの種類 チップ名 アドレス
IMU BMI270 0x68
地磁気センサ BMM150 0x10
気圧・温度センサ BMP280 0x76

まずは、i2cバスの状態を確認

image.png

3つのバス認識されていました。

ドキュメントによると、Port Aのi2cバスは、/dev/i2c-1となっています。
detect_device/1を使って、接続されているデバイスを調べてみます。

image.png

0x68と0x76のデバイスを検知しました。
0x10の磁気センサーが見つかりません(謎)。

温度を測定してみる

温度センサーのBMP280はhexdocsにモジュールがありました。
これを使って値を読み取ってみます。

setupのセル
Mix.install([
  {:circuits_i2c, "~> 2.0"},
  {:bmp280, "~> 0.2.13"}
])
{:ok, bmp} = BMP280.start_link(bus_name: "i2c-1", bus_address: 0x76)
BMP280.measure(bmp)
Output
{:ok,
 %BMP280.Measurement{
   temperature_c: 34.753966059455706,
   pressure_pa: 100672.16892826237,
   altitude_m: -56.548979627198875,
   humidity_rh: :unknown,
   dew_point_c: :unknown,
   gas_resistance_ohms: :unknown,
   timestamp_ms: 132942
 }}

室温34℃!!!
取得できました。

グラフ表示してみる

動作を確認できたので、温度を定期的に測定してグラフ表示してみます。
グラフ表示まで簡単にできるところがLivebookのありがたい所ですね。

温度変化がないとつまらないので、エアコンのON/OFFをして、エアコンの働を可視化してみます。

15:27分エアコンON
15:47分エアコンOFF
です。
ちなみに、エアコンの設定温度は30℃です。

image.png

ちゃんと測定できてそう。

グラフ表示のプログラム

defmodule TemperatureServer do
  use GenServer

  # サーバーの開始
  def start_link() do
    {:ok, bmp} = BMP280.start_link(bus_name: "i2c-1", bus_address: 0x76)
    GenServer.start_link(__MODULE__, %{bmp: bmp, measurements: []}, name: __MODULE__)
  end

  # 初期化
  def init(state) do
    # 定期的に :measure_temperature メッセージを自身に送信する
    schedule_measurement()
    {:ok, state}
  end

  # 定期的に測定するためのスケジューリング関数
  defp schedule_measurement do
    # 5000ミリ秒 (5秒後) に :measure_temperature メッセージを送る
    Process.send_after(self(), :measure_temperature, 5000)
  end

  # 温度を測定して保存するハンドル
  def handle_info(:measure_temperature, %{bmp: bmp} = state) do
    # BMP280から温度を測定
    {:ok, measurement} = BMP280.measure(bmp)

    # 時刻を取得
    timestamp = DateTime.utc_now()

    # 結果をリストに追加
    new_measurement = {timestamp, measurement.temperature_c}
    new_state = %{state | measurements: [new_measurement | state.measurements]}

    # 次の測定をスケジューリング
    schedule_measurement()

    {:noreply, new_state}
  end

  # 測定結果を取得するための関数
  def handle_call(:get_measurements, _from, state) do
    {:reply, Enum.reverse(state.measurements), state}
  end

  # 外部API:測定結果を取得する
  def get_measurements do
    GenServer.call(__MODULE__, :get_measurements)
  end
end
defmodule TemperatureGraph do
  @moduledoc """
  Temperature measurements visualization using VegaLite.
  """

  alias VegaLite, as: Vl

  # 温度データをグラフ表示
  def plot_measurements(measurements) do
    # VegaLiteで必要なデータを生成
    data =
      measurements
      |> Enum.map(fn {timestamp, temperature} ->
        %{
          "timestamp" => DateTime.to_string(timestamp),
          "temperature" => temperature
        }
      end)

    Vl.new(width: 600, height: 400)
    |> Vl.data_from_values(data)
    |> Vl.mark(:line)
    |> Vl.encode_field(:x, "timestamp", type: :temporal)
    |> Vl.encode_field(:y, "temperature", type: :quantitative, scale: [domain: [30, 36]])
    |> Kino.VegaLite.new()

  end
end
TemperatureServer.get_measurements()
|> TemperatureGraph.plot_measurements()

まとめ

  • BMP280での温度計測がLivebookから行えた
  • エアコンの働を可視化できた
  • 暑いので熱中症には気をつけましょう
4
4
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?