1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめてね AtomVM(6) ESP32 の Sleep mode を使ってLチカ

1
Posted at

はじめに

ちょっと前の記事 はじめてね AtomVM(4) ESP32でLチカ v0.7.0-alpha.1 版 でアルファ版の AtomVM をインストールしてみました。AtomVM でスリープモードが使えるのか試してみました。
ファイルの場所、コンパイル、ファームに焼き焼き、は前回同様です。

Sleep mode

さまざまなプロセッサで、プログラムが動作しないタイミングで電力消費を押さえるような機能があります。この機能、スリープに関する ESP32 の動作モードは、

  • 通常の Active mode
  • CPUが停止する Light sleep mode
  • 何もかもが停止する Deep sleep mode

の3種類あるようです。おそらく黙ってプログラムを作ると Active mode でしょう。スリープ状態を AtomVM プログラムで引き起こせるのか試してみます。用いるのは Releases v0.7.0-alpha.0 です。

今回ESP32でやってまして、これESP32用の特別な関数が用意されてました。その当たりは ESP32-specific APIsにまとめられてます。さらにスリープ周りについては Restart and Sleep にあります。

Light Sleep mode

先に Light sleep をさせてみます。実はこちらの方が苦労してます。ドキュメントは Light Sleep にあります。
今回はタイマをセットして Light sleep して、時間が来たら起き上がるというのを繰り返すことで Lチカさせます。なお、他のプログラムと区別するのにチカチカと2回点滅してから寝るようにしてます。

defmodule Blinky do
  @compile {:no_warn_undefined, [GPIO, :atomvm, :esp]}
  @gpio_pin 2 # for GPIO of ESP32

  def start() do
    IO.puts("LED Blink starts")
    GPIO.set_pin_mode(@gpio_pin, :output)
    loop(@gpio_pin)
  end

  def loop(pin) do
    Enum.each(0..1, fn _ -> blink_1(pin) end)
    :esp.sleep_enable_timer_wakeup(1_000_000) # micro seconds
    :esp.light_sleep()
    loop(pin)
  end

  defp blink_1(pin) do
    GPIO.digital_write(pin, :high)
    Process.sleep(100)
    GPIO.digital_write(pin, :low)
    Process.sleep(100)
  end
end

タイマを仕掛けてから眠るところは

    :esp.sleep_enable_timer_wakeup(1_000_000) # micro seconds
    :esp.light_sleep()

の部分です。:esp.sleep_enable_timer_wakeup/1 関数の引数がミリ秒でなくマイクロ秒なのになかなか気が付かずでした。ESP-IDF をちゃんと調べるとすぐに分かったものと思います。

今回はタイマでやりましたが、GPIO の入力でも起床できるようなので、例えばボタンが押されるまでスリープしてるとかも簡単に書けそうです。

Deep sleep mode

Light sleep よりしっかり寝るのが Deep sleep です。こちらは CPU だけじゃなくあらかた全部 off になってしまうので、sleep 中の電力消費が少ないというメリットがあります。その代わりメモリの内容も失われてしまう… すなわち BEAM 処理系としての動作状態が完全に失われるので、起きてくることが電源オンの状態と同じになります。
ドキュメントは Deep Sleep にあります。

defmodule Blinky do
  @compile {:no_warn_undefined, [GPIO, :atomvm, :esp]}
  @gpio_pin 2 # for GPIO of ESP32

  def start() do
    IO.puts("LED Blink starts")
    GPIO.set_pin_mode(@gpio_pin, :output)
    Enum.each(0..2, fn _ -> blink_1(@gpio_pin) end)
    :esp.deep_sleep(1000)
  end

  defp blink_1(pin) do
    GPIO.digital_write(pin, :high)
    Process.sleep(100)
    GPIO.digital_write(pin, :low)
    Process.sleep(100)
  end
end

この :esp.deep_sleep/1 関数で sleep します。次に起きてくるときは start/0 関数の先頭になるので、明示的に再帰でループを書かなくてもこれで start/0 関数が毎度実行されるという仕掛けになってます。こちらはチカチカチカと3回チカってから sleep するようにしました。
なおここで :esp.deep_sleep/1 関数の引数がミリ秒なことに注意して下さい。Light sleep と Deep sleep で単位が違ってます(なんでやねん)。

なお、何もかもオフになると書きましたが、RTC (Real Time Clock) に若干メモリがあって、そこにデータを保持できるようです。ただし

  • RTC 保持用の電池(大概はボタン型の酸化銀電池)で RTC がバックアップされてる必要がある
  • ESP32の電源を完全に切ってしまうと失われる
  • おそらくアクセスは遅くて、容量はだいぶ小さい

ドキュメントは RTC Memory です。

まとめ

AtomVM v0.7.0-a.1 で ESP32 の2種類のスリープ機能が使えるのを確認しました。
Light sleep mode からの GPIO による復帰や、Deep sleep mode での RTC Memory の利用などもやってみたいと思います。

参考文献

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?