アナログI/O

MicroPythonを使ったアナログ入力(ADC)と出力(PWM)のガイドです。


Author:Pedro LimaLast revision:2024/12/18

アナログ入出力(I/O)は、単純なオン・オフではなく、さまざまな値を扱う野に不可欠で、プロジェクトで、デバイスや入力を詳細に制御することができます。この章では、MicroPythonを使ったアナログI/Oの操作方法を説明します。以下の方法に焦点をあてます。

  • 光センサーやポテンショメーターなどのアナログ値の読み取り
  • LEDの明るさやモーターのスピードを制御する、アナログ出力の生成

アナログ信号は、連続した値の幅を表現するもので、デジタル信号とは異なります。この柔軟性がフィジカル物理世界との相互作用をより洗練されたものにし、多くのセンサーやアクチュエーターにとって、アナログI/Oは不可欠なものになっています。

要件

始める前に、要件を確認します。

MicroPythonが利用できるArduinoボード

MicroPythonは、いくつかのArduinoボードで公式にサポートされています。互換性のあるボードの一覧を示します。

ハードウェア部品

このガイドでは、いくつかの電子部品を追加で使います。

  • LED(ボードのLEDを使う場合はオプション)
  • 外部LEDを使う場合は、電流制限抵抗(例: 220Ω)
  • ジャンプワイヤー
  • 押しボタン
  • ブレッドボード

ソフトウェア要件

  • Arduino Lab for MicroPython: Arduino Lab for MicroPythonは、Arduinoボードで、MicroPythonスクリプトの作成・実行が可能なエディタです。
i
Arduino Cloud - Arduino Labs for MicroPythonで、オンラインエディタも利用可能です。

ボードとエディタの設定

  1. Arduino Lab for MicroPythonを開きます。
  2. ArduinoボードとPCを、USBケーブルで接続します。
  1. ウインドウの左上の接続ボタンをクリックします。接続したボード(のポート名)が現れます
i
ボードにMicroPythonをインストールするのにヘルプが必要ですか? MicroPythonインストールガイドを参照してください。

アナログ入力

アナログ入力は、絶対的な状態ではなく、段階的な変化を読むことができるので、よりなめらかに世界とやり取りを行うことができます。アナログセンサーは、物理状態の変化を反映する電圧の範囲を出力します。これらの値をデジタル値に変換することで、Arduinoボードは、実世界の信号を解釈し、光の強さや温度といった、既知の特性に変換できます。

アナログ・デジタル変換器(ADコンバーター、ADC)

アナログ値を読むには、アナログ・デジタル変換器(ADコンバーター、ADC)を使います。読み取った入力電圧を、Arduinoで利用できるデジタル値に変換します。アナログ入力は、2つの値(多くは0V(LOW)とボードの動作電圧(3.3Vや5V))の間を連続的に変化する電圧レベルを測定します。

MicroPythonでは、ADCにアクセスするには、read_u16()というメソッドを使います。この"16"は、16ビットの分解能を示し、0-65535*の間の値を取得できることを意味します。

i
*16ビットの分解能は何を意味しているのでしょうか? この記事の最後を参照してください。

コード例: 光センサーを読み取る

例を試します。ここでは、フォトレジスターの光の強さを読み取ります。

この例では、以下の外部部品が必要です。

  • ブレッドボード
  • フォトレジスター
  • ジャンプワイヤー
  • 10kΩの抵抗

以下の回路図に従って、フォトレジスターをArduinoボードに接続します。

回路を完成させたら、以下のコードをエディタにコピーし、スクリプトを実行してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from machine import ADC
import time

# Initialize ADC for the analog pin
light_sensor = ADC(0)  # Replace '0' with the correct ADC channel for your board

while True:
    light_level = light_sensor.read_u16()  # Reads a 16-bit value (0-65535)
    print("Light level:", light_level)
    time.sleep(1)

このコードに何が含まれているか見てみましょう。

  • ADCの初期化: アナログチャネルを入力とし、ADCクラスを初期化します。
  • 値の読み取り: read_u16()は16ビットの整数値(0-65535)を読み取ります。0は0Vを、65535はボードの最大動作電圧を表現します。
  • ループ: センサーの読取値は1秒ごとに表示されます。光の強さに基づき値がどのように変化するかを示します。

アナログ出力

アナログ入力とは異なり、マイクロコントローラーのアナログ出力は完全に連続した電圧の範囲を出力しません。代わりに、パルス幅変調(Pulse Width Modulation: PWM)を使い、変化する電圧レベルをシミュレートします。PWMは、デジタル出力のHIGHとLOWを、指定したデューティ比で高速にオン・オフすることで、HIGHになっている時間を制御し、疑似的なアナログ出力を生成します。

パルス幅変調(Pulse Width Modulation: PWM)

本当のアナログ信号は、連続した電圧の変化ですが、マイクロコントローラーは、主に、デジタル信号(オン・オフ)を扱うので、PWMは、HIGHとLOWの信号を高速にオン・オフすることで、その違いを埋めます。信号がHIGHの状態になる時間(デューティ比)を調整することで、PWMは、異なる電圧レベルをシミュレートします。

本当のアナログ出力はできないが、なめらかな変化が必要なアプリケーションで、特に有用です。一般的なシナリオには、以下のようなものがあります。

  • LEDの調光: PWMは、与えられた時間の中で、LEDのオンとオフを制御し明るさを調整することができます。
  • モーターの制御: デューティ比を変更することで、PWMは、ロボットや他の機械デバイスのスピードを制御できます。モーターは、時間とともに供給される平均電圧に反応するからです。
  • オーディオ信号: サウンドアプリケーションにも、PWMを使うものがあり、異なる周波数の音を生成したり、スピーカーのボリュームを制御したりします。

PWMの主な利点は、デジタルピンを使って、アナログの湯女振る舞いを制御できることです。これにより、低消費電力で、プロジェクトの用途を増やします。

コード例: PWMでLEDを調光する

例を試します。ここでは、LEDを調光します。

この例では、以下の外部部品が必要です。

  • ブレッドボード
  • LED
  • 電流制限抵抗(例: 220Ω)
  • ジャンプワイヤー

以下の回路図に従って、LEDをArduinoボードに接続します。

回路を完成させたら、以下のコードをエディタにコピーし、スクリプトを実行してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from machine import Pin, PWM
import time

# Initialize PWM for the LED pin
led_pwm = PWM(Pin(5))  # Replace '5' with the correct pin for your board
led_pwm.freq(1000)     # Set frequency to 1 kHz

# Gradually change the LED brightness
while True:
    for duty in range(0, 65536, 1024):  # 0 to 65535 for 16-bit PWM
        led_pwm.duty_u16(duty)
        time.sleep(0.01)
    for duty in range(65535, -1, -1024):
        led_pwm.duty_u16(duty)
        time.sleep(0.01)

このコードに何が含まれているか見てみましょう。

  • PWMの初期化: PWMオブジェクトを生成し、周波数を1kHzに設定します。この値は、LEDに適した値です。
  • デューティ比: duty_u16()は、0から65535の値を受け付けます。値が大きいと、HIGHになっている時間が長くなり、LEDが明るくなります。
  • ループ: デューティ比を小刻みに変化させることで、徐々に明るくなり、その後、暗くなります。その結果、LEDがフェードイン・アウトします。

PWMによるサーボモーター制御

サーボモーターは、特定の角度まで正確に回転できる精密なアクチュエータで、ロボット工学や自動化機構、精密な位置決め作業に最適です。サーボモーターを、決められた位置へ正確に動き、その姿勢を保てる高度に訓練されたダンサーのようなものだと考えてください。連続して回転し続ける一般的なモーターとは異なり、サーボモーターは特定の命令に応じて、0°から180°までの正確な角度に回転します。

サーボモーターはPWM信号を使用しますが、少し特殊です。LEDの明るさを変えるためにPWMを使う場合とは異なり、サーボモーターはPWMパルスの幅を位置指令として解釈します。サーボモーターは、20ミリ秒ごと(周波数50Hz)に送られるパルスを受け取ることを前提としていて、それぞれのパルスの幅によって回転角度が決まります。1msのパルスは0°を指示、1.5msのパルスは90°を指示、2msのパルスは180°を指示します。

重要: 小さいサーボモーターでも、LEDやセンサーより多くの電力を消費します。このため、回路で電圧低下を引き起こす可能性があります。サーボの近くに100-470μFのコンデンサを追加することで、電力要求を平滑にし、不安定な動作を防ぐことができます。

コード例: サーボスイープ

この例では、以下の外部コンポーネントが必要です。

  • ブレッドボード
  • サーボモーター
  • ジャンプワイヤー
  • オプションですが推奨: 100-470μFのコンデンサ

サーボをArduinoボードに接続する。

  • 赤線(電力)を3.3V(サーボの仕様を確認してください)に
  • 黒/茶色線(アース)をGNDに
  • オレンジ/黄色線(信号)をPWM可能なデジタルピンに
  • コンデンサを使う場合: プラス極を3.3Vに、マイナス極をGNDに

回路を完成させたら、以下のコードをエディタにコピーし、スクリプトを実行します。

from machine import Pin, PWM
import time

# Initialize PWM for the servo pin
servo = PWM(Pin(9))  # Replace '9' with your PWM pin number
servo.freq(50)       # Set frequency to 50Hz (example)

def set_servo_angle(angle):
    # Convert angle (0-180) to duty cycle for 16-bit PWM
    # Servo expects pulses between 1ms (0°) and 2ms (180°)
    # For 50Hz: 1ms = ~3277, 1.5ms = ~4915, 2ms = ~6553
    min_duty = 3277   # ~1ms pulse width (0 degrees)
    max_duty = 6553   # ~2ms pulse width (180 degrees)
    duty = int(min_duty + (angle / 180) * (max_duty - min_duty))
    servo.duty_u16(duty)

# Continuous sweeping motion
while True:
    # Sweep from 0 to 180 degrees
    for angle in range(0, 181, 2):  # Step by 2 degrees
        set_servo_angle(angle)
        time.sleep(0.02)  # Small delay for smooth motion
    
    # Sweep back from 180 to 0 degrees
    for angle in range(180, -1, -2):  # Step by 2 degrees backwards
        set_servo_angle(angle)
        time.sleep(0.02)  # Small delay for smooth motion

このコードを見ていきましょう。

  • PWM設定: PWMオブジェクトを作成し、周波数を50Hzに設定します。50Hzは、サーボが位置を更新するのに設定する標準的な周波数です。
  • 角度変換: set_servo_angle()関数は角度(0-180)を、サーボが理解するパルス幅に対応する、適切な16ビットのデューティ比に変換します。
  • スイープ動作: サーボは0°と180°の間を、連続して往復します。2°ずつ角度を変え、祖各ステップ間に短い遅延を入れることで、スムーズな動きを実現します。

アナログ分解能

ADCの分解能は、どの程度細かいのかということで説明できます。MicroPythonを使うとき、デフォルトは16ビットです。一方、Arduino言語では、10ビットです。何が違うのでしょうか?

何かを16ビットの分解能で読み取ると、0-65535の値を受け取ります。電圧の範囲が、0-3.3Vのときのことを考えましょう。これは、多くの最近のボードでの標準です。3.3Vを読むと、それは、最大あるいは65535を意味します。半分の電圧(1.65V)を読むと、65535/2=32677になるでしょう。

温度を読み取るアナログセンサーについて考えましょう。温度がその部品の最大値で、出力が3.3Vであれば、65535を読み取ります。電圧を出力しなければ(ありえないかもしれませんが)、0を読み取ります。

10ビットのような、異なる分解能を使うと、範囲は、0-1023になります。電圧は同じですが、読み取る値は異なります。

なぜこのように動作するのでしょうか? ビットは情報を表すのに使われます。1ビットは0と1の2つの値だけを保持することができます。2ビットは0-3、3ビットは0-8となります。以下を見てください。

  • 1ビット = 0-1
  • 2ビット = 0-3
  • 4ビット = 0-8
  • 8ビット = 0-255
  • 10ビット = 0-1023
  • 16ビット = 0-65535
  • 32ビット = 0-4,294,967,295

まとめ

このガイドでは、アナログ入出力と分解能を学びました。実際にどのように動作するのかを理解するために、いくつかの基本的な例を見ました。

オリジナルのページ

https://docs.arduino.cc/micropython/basics/analog-io/

最終更新日

July 26, 2026

inserted by FC2 system