3
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?

Nerves Livebook で超音波センサーから距離を計測する

Last updated at Posted at 2024-09-02

はじめに

Nerves Livebook で Raspberry Pi 用スターター電子工作キットを楽しんでいます

SunFounder Raspberry Pi 用のスターター電子工作キット

これまでの記事

この記事では超音波センサーを使い、対象物までの距離を計測します

実装したノートブックはこちら

超音波センサー

超音波(人間の耳に聞こえない音)を正面に向けて出力し、跳ね返ってきた超音波を検出します

出力してから跳ね返ってくるまでの時間によって、正面にある物体がどれくらい離れているか、つまり距離を計測することが可能です

IMG_2220.JPG

イルカや蝙蝠がやっているエコーロケーションですね

回路の組み立て

オンライン説明書の通りに回路を組みます

ノートブックの実装

Nerves Livebook を開き、以降のコードを実行していきます

ピンを開く

超音波センサーを制御するためのピンを開きます

{:ok, trig} = Circuits.GPIO.open("GPIO23", :output)
{:ok, echo} = Circuits.GPIO.open("GPIO24", :input)

trig を超音波発信用の出力、 echo を超音波検出用の入力にしています

モジュール定義

超音波センサーの制御用モジュールを定義します

defmodule UltrasonicSensor do
  def distance(trig, echo) do
    Circuits.GPIO.write(trig, 0)
    Process.sleep(1)

    # 1 msec の超音波を送信
    Circuits.GPIO.write(trig, 1)
    Process.sleep(1)
    Circuits.GPIO.write(trig, 0)

    # 最初は 0 の状態を確認
    time_1 = wait_for(echo, 0)

    # 1 になるまでの時間を取得
    time_2 = wait_for(echo, 1)

    during = Time.diff(time_2, time_1, :microsecond)

    # 空気中の音速を使って距離(cm)に変換(往復なので半分にする)
    during * 340 / 2 / 10000
  end

  defp wait_for(echo, value) do
    1..10000
    |> Enum.reduce_while(nil, fn _i, _acc ->
      if Circuits.GPIO.read(echo) == value do
        {:cont, Time.utc_now()}
      else
        {:halt, Time.utc_now()}
      end
    end)
  end
end

Circuits.GPIO.write(trig, 1) によって超音波を発します

Process.sleep(1) で 1 ミリ秒待ってから Circuits.GPIO.write(trig, 0) にすると、 1ミリ秒だけ超音波を出していたことになります

Circuits.GPIO.read(echo) の結果が 0 から 1 に変化したときが、超音波の跳ね返ってきたときです

跳ね返ってくるまでの時間と音速(340 m/s)を使うと、正面の物体までの距離が計算できます

距離の計測

実際に距離を計測してみます

100 回連続して計測している間、超音波センサーの前で手のひらを前後させてみました

1..100
|> Enum.map(fn _ ->
  UltrasonicSensor.distance(trig, echo) |> IO.inspect()

  Process.sleep(100)
end)

距離のグラフ化

数字だけだとピンとこないので、グラフで距離をリアルタイムにプロットしてみました

distance_plot =
  VegaLite.new(width: 700)
  |> VegaLite.mark(:line)
  |> VegaLite.encode_field(:x, "index", type: :quantitative)
  |> VegaLite.encode_field(:y, "distance", type: :quantitative)
  |> Kino.VegaLite.new()
Kino.VegaLite.clear(distance_plot)

1..300
|> Enum.map(fn index ->
  distance = UltrasonicSensor.distance(trig, echo)

  IO.inspect(distance)

  plot_data = %{
    index: index,
    distance: distance
  }

  Kino.VegaLite.push(distance_plot, plot_data)
  Process.sleep(100)
end)

今度はリバテープの箱を対象物にしています

ピンを閉じる

遊び終わったらピンを閉じます

Circuits.GPIO.close(trig)
Circuits.GPIO.close(echo)

まとめ

手の平だと計測があまり安定せず、 Qiitan ぬいぐるみだとほとんど正しく計測できませんでした

リバテープの箱のように、超音波をしっかり跳ね返してくれるものでないと上手くいかない、ということが分かりました

3
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
3
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?