10
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

Nerves Livebook でポテンショメーターからアナログ値を取得してデジタル値に変換する

Last updated at Posted at 2024-07-08

はじめに

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

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

これまでの記事

この記事ではポテンショメーターのアナログ値を取得し、LEDの光の強弱を制御します

また、必要なモジュールを追加するため、 Nerves Livebook をカスタマイズします

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

ポテンショメーター

矢印が描かれたツマミを回すことで抵抗値が変化します

IMG_1642.JPG

ADC0834

ADC0834 は AD 変換器(AD コンバーター)です

IMG_1643.JPG

REF の電圧(5V)を基準として、CH0〜3の入力電圧(アナログ値)がどの程度なのか 0 〜 255 の 256 段階(8 bit)のデジタル値に変換します

回路の組み立て

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

ただし、 LED に接続するピンはPWM対応が必須であるため、 GPIO22 ではなく GPIO12 を使います

元の通りに回路を組むと、 LED への PWM 出力実行時に以下のエラーが返されます

{:error, :not_hpwm_gpio}

  • CS: AD 変換の開始終了を制御する
  • CLK: 0 -> 1 に変化したタイミングで DI/DO の値を入出力する
  • DI: データ入力
  • DO: データ出力
  • CH0: ポテンショメーターからの入力

Nerves Livebook のカスタマイズ

以下の記事に従って Pigpiox 追加済の Nerves Livebook を使用します

ノートブックの実装

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

ピンを開く

ADC0834 を制御するためのピンを開きます

{:ok, cs} = Circuits.GPIO.open("GPIO17", :output)
{:ok, clk} = Circuits.GPIO.open("GPIO18", :output)
{:ok, dio} = Circuits.GPIO.open("GPIO27", :output)

dio は DI と DO の両方に接続し、必要に応じて入出力を切り替えて使用します

モジュール定義

ADC0834 を制御するモジュールを定義します

defmodule ADC do
  import Bitwise

  def get_result(dio, clk, cs, channel \\ 0) do
    sel = if channel > 1, do: 1, else: 0
    odd = channel &&& 1

    # AD 変換開始
    Circuits.GPIO.write(cs, 0)
    start_adc(dio, clk)

    # シングルエンド信号を使用(1本の信号だけを読む)
    single_end_mode(dio, clk)

    # チャンネル設定(デフォルトは CH0 を使用)
    set_odd(dio, clk, odd)
    set_sel(dio, clk, sel)

    # dio を入力に設定
    Circuits.GPIO.set_direction(dio, :input)

    # AD変換を実行し、各桁の値を取得
    dat1 =
      0..7
      |> Enum.reduce(0, fn _i, acc ->
        Circuits.GPIO.write(clk, 1)
        :timer.sleep(2)
        Circuits.GPIO.write(clk, 0)
        :timer.sleep(2)

        Circuits.GPIO.set_direction(dio, :input)

        bit = Circuits.GPIO.read(dio)
        acc = acc <<< 1 ||| bit
        acc
      end)

    # AD変換完了後に改めて逆順で各桁の値を取得
    dat2 =
      0..7
      |> Enum.reduce(0, fn i, acc ->
        bit = Circuits.GPIO.read(dio)
        acc = acc ||| bit <<< i
        Circuits.GPIO.write(clk, 1)
        :timer.sleep(2)
        Circuits.GPIO.write(clk, 0)
        :timer.sleep(2)

        acc
      end)

    # AD 変換終了
    Circuits.GPIO.write(cs, 1)
    Circuits.GPIO.set_direction(dio, :output)

    # 変換中と変換後の値が等しければ出力する
    if dat1 == dat2, do: dat1, else: 0
  end

  defp start_adc(dio, clk) do
    Circuits.GPIO.write(clk, 0)
    Circuits.GPIO.write(dio, 1)
    :timer.sleep(2)
    Circuits.GPIO.write(clk, 1)
    :timer.sleep(2)
  end

  defp single_end_mode(dio, clk) do
    Circuits.GPIO.write(clk, 0)
    Circuits.GPIO.write(dio, 1)
    :timer.sleep(2)
    Circuits.GPIO.write(clk, 1)
    :timer.sleep(2)
  end

  defp set_odd(dio, clk, odd) do
    Circuits.GPIO.write(clk, 0)
    Circuits.GPIO.write(dio, odd)
    :timer.sleep(2)
    Circuits.GPIO.write(clk, 1)
    :timer.sleep(2)
  end

  defp set_sel(dio, clk, sel) do
    Circuits.GPIO.write(clk, 0)
    Circuits.GPIO.write(dio, sel)
    :timer.sleep(2)
    Circuits.GPIO.write(clk, 1)
    :timer.sleep(2)
    Circuits.GPIO.write(clk, 0)
    :timer.sleep(2)
  end
end

AD変換した結果を取得する

ADC.get_result でポテンショメーターのアナログ値を ADC0834 がデジタル値に変換した結果の値を取得します

analog_val = ADC.get_result(dio, clk, cs)

LEDの点灯

0 〜 255 の値をデューティー比として PWM を実行し、 LED の光の強弱を制御します

duty = round(analog_val * 1_000_000 / 255)
duty / 10000
Pigpiox.Pwm.hardware_pwm(12, 2000, duty)

ポテンショメーターを一番右に回している状態では AD 変換結果が 0 になり、 LED は光ません

IMG_1634.JPG

少し左に回すと値が少し増え、 LED も少し光ります

IMG_1635.JPG

中間辺り

IMG_1636.JPG

かなり左に回す

IMG_1638.JPG

最大出力

IMG_1639.JPG

ポテンショメーターとLEDを連動させる

一定期間ポテンショメーターの値を取得してLEDを光らせる処理を繰り返し、連動させます

1..300
|> Enum.map(fn _i ->
  analog_val = ADC.get_result(dio, clk, cs)
  duty = round(analog_val * 1_000_000 / 255)
  IO.inspect(duty / 10000)
  Pigpiox.Pwm.hardware_pwm(12, 2000, duty)
end)

ピンを閉じる

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

Circuits.GPIO.close(cs)
Circuits.GPIO.close(clk)
Circuits.GPIO.close(dio)

まとめ

ポテンショメーターと AD 変換器によって、アナログ操作をデジタル値に変換して制御することができました

AD 変換は IoT でも重要な役割を果たしますね

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