Skip to content

第8章 アナログ入力とPWM出力

この章では、10kΩの可変抵抗を回した位置を 連続的な電圧としてPico Wへ入力します。

GP26のADCで電圧を数値へ変換し、 読み取った値に合わせてGP15のLEDの明るさを変化させます。

可変抵抗を回す
電圧が変化する
ADCで数値へ変換する
PWMのデューティ比を変える
LEDの明るさが変化する

デジタル入力・出力の01だけでは表しにくい、 途中の大きさを扱う方法を確認します。

この章でできるようになること

Section titled “この章でできるようになること”
  • デジタル値とアナログ値の違いを説明できる
  • 可変抵抗の固定端子と中央端子の役割を説明できる
  • GP26をADC0として使用できる
  • read_u16()でアナログ入力を数値として取得できる
  • PWMの周波数とデューティ比を説明できる
  • duty_u16()でLEDの明るさを変化させられる
  • アナログ入力の値をPWM出力へ渡せる
  • 入力、数値化、出力のつながりを説明できる
分類使用するもの数量
制御用ボードピンヘッダー実装済みのRaspberry Pi Pico WまたはPico WH1
配線ブレッドボード1
入力部品10kΩリニア可変抵抗(B10K、3端子)1
出力回路第5章で配線した赤色LEDと330Ω抵抗1組
配線ジャンパーワイヤー3本程度を追加
PC接続データ通信対応Micro USBケーブル1

第6章・第7章のタクトスイッチ回路は、 配線したままでも構いません。 この章のプログラムではGP14を使用しません。

  • 配線を追加・変更するときは、Pico WからUSBケーブルを外します
  • 可変抵抗の電源には3V3(OUT)を使用し、VBUSVSYSへ接続しません
  • GP26へ3.3Vを超える電圧を入力しません
  • 3V3(OUT)AGNDをジャンパーワイヤーだけで直結しません
  • 第5章のLEDには、引き続き330Ω抵抗を直列に使用します
  • 可変抵抗の端子配置は、部品の資料またはテスターで確認します
  • 配線後は講師または接続表による確認を行ってからUSB接続します

第5章から第7章では、GPIOの状態を01で扱いました。 このように、決められた段階で表す値をデジタル値と呼びます。

一方、電圧、温度、明るさなどは、 範囲の中で連続的に変化します。 このような量をアナログ値と呼びます。

種類Pico Wでの扱い
デジタル入力スイッチを離す/押す1または0
アナログ入力可変抵抗の位置電圧をADCで数値化
デジタル出力LEDを消灯/点灯LOWまたはHIGH
PWM出力LEDの明るさHIGHの時間割合を変更

Pico WのGPIOは、すべてがアナログ入力に対応しているわけではありません。 この章では、ADC0へ接続されたGP26を使用します。

ADCは、Analog-to-Digital Converterの略で、 アナログ電圧をデジタル値へ変換する回路です。

RP2040のADCは12ビットで変換します。 MicroPythonのread_u16()は、その結果を 0から65535の範囲へ拡大して返します。

GP26の入力電圧read_u16()の目安
約0V0付近
約1.65V32768付近
約3.3V65535付近

実際の値は、電源電圧、部品の誤差、配線、ノイズなどによって変動します。 端まで回しても、必ず0または65535になるとは限りません。

ADC値から入力電圧の目安を求める式は次のとおりです。

voltage = adc_value * 3.3 / 65535

この計算結果は目安です。 正確な電圧測定が必要な場合は、基準電圧や測定誤差も考慮します。

3端子の可変抵抗には、抵抗体の両端につながる2つの固定端子と、 回転位置に応じて抵抗体上を移動する中央端子があります。 中央端子を摺動端子またはワイパーと呼びます。

端子この章での接続
固定端子13V3(OUT)
中央端子(ワイパー)GP26 / ADC0
固定端子3AGND

可変抵抗を回すと、中央端子の電圧が 約0Vから約3.3Vの範囲で変化します。

外側の2端子を入れ替えても回路は動作しますが、 明るくなる回転方向が反対になります。 中央端子をGP26へ接続することが重要です。

部品を上から見た端子順や、つまみを回した方向は 製品によって異なる場合があります。 外観だけで決めず、部品資料またはテスターで確認します。

第5章のGP15 LED回路を残し、 可変抵抗を次のように追加します。

接続元接続先物理ピン
可変抵抗の固定端子1Pico Wの3V3(OUT)36
可変抵抗の中央端子Pico WのGP26 / ADC031
可変抵抗の固定端子3Pico WのAGND33
接続元接続先物理ピン
Pico WのGP15330Ω抵抗20
330Ω抵抗LEDのアノード
LEDのカソードPico WのGND18

左側にB10K可変抵抗の固定端子と中央のワイパーを示し、固定端子をPico Wの3V3 OUTとAGND、ワイパーをGP26 ADC0へ接続する。右下にGP15から330Ω抵抗と赤色LEDを経由してGNDへ接続する回路を示す。

図8-1 GP26の可変抵抗入力とGP15のLED出力

次の順番で配線します。

  1. Pico WからUSBケーブルを外します
  2. 第5章のLED回路を接続表と照合します
  3. B10K可変抵抗の固定端子と中央端子を確認します
  4. 固定端子1を物理ピン36の3V3(OUT)へ接続します
  5. 中央端子を物理ピン31のGP26 / ADC0へ接続します
  6. 固定端子3を物理ピン33のAGNDへ接続します
  7. GP26AGND3V3(OUT)を再確認します
  8. 講師の確認後、USBケーブルを接続します

次のプログラムをch08_01_adc_value.pyとしてPC側へ保存し、実行します。

ch08_01_adc_value.py
from machine import ADC, Pin
import time
POT_PIN = 26
pot = ADC(Pin(POT_PIN))
while True:
adc_value = pot.read_u16()
print("ADC値:", adc_value)
time.sleep(0.2)

可変抵抗を端から端までゆっくり回し、 Shellに表示される値が変化すれば成功です。

ADC値: 320
ADC値: 15872
ADC値: 32640
ADC値: 49120
ADC値: 65184

表示される値は実機ごとに異なります。 つまみを止めていても、下位の桁が少し変動することがあります。

pot = ADC(Pin(POT_PIN))

Pin(26)でGP26を指定し、 ADC()でアナログ入力として準備します。

adc_value = pot.read_u16()

read_u16()は、その時点の入力電圧を測定し、 0から65535の整数として返します。

このプログラムは0.2秒ごとにADC値を読み取るため、 第6章で学んだポーリングの例でもあります。

GPIOはHIGHまたはLOWを出力するデジタル端子です。 途中の電圧を連続的に出力しているわけではありません。

PWMは、Pulse Width Modulationの略で、 HIGHとLOWを高速に切り替え、 1周期の中でHIGHにする時間の割合を変える方式です。

HIGHになっている時間の割合をデューティ比と呼びます。

duty_u16()の値デューティ比の目安LED
00%消灯
16384約25%暗め
32768約50%中間
49151約75%明るめ
65535100%点灯

LEDは高速に点滅していますが、 人の目には平均的な明るさとして見えます。 デューティ比と、人が感じる明るさは完全な比例関係ではありません。

次のプログラムをch08_02_adc_pwm.pyとしてPC側へ保存し、実行します。

ch08_02_adc_pwm.py
from machine import ADC, Pin, PWM
import time
POT_PIN = 26
LED_PIN = 15
PWM_FREQ = 1000
pot = ADC(Pin(POT_PIN))
led_pwm = PWM(Pin(LED_PIN), freq=PWM_FREQ, duty_u16=0)
try:
while True:
adc_value = pot.read_u16()
led_pwm.duty_u16(adc_value)
print("ADC値:", adc_value)
time.sleep(0.1)
finally:
led_pwm.duty_u16(0)
led_pwm.deinit()

可変抵抗を回すと、ADC値に合わせて 外付けLEDの明るさが変化すれば成功です。

led_pwm = PWM(Pin(LED_PIN), freq=PWM_FREQ, duty_u16=0)

主な指定を確認します。

記述意味
Pin(LED_PIN)GP15を使用する
freq=PWM_FREQPWMの周波数を1000Hzにする
duty_u16=0デューティ比を0%から開始する
adc_value = pot.read_u16()
led_pwm.duty_u16(adc_value)

read_u16()duty_u16()は、 どちらも0から65535を扱います。 このため、ADC値をPWMのデューティ比へそのまま渡せます。

finally:
led_pwm.duty_u16(0)
led_pwm.deinit()

tryの中でプログラムを実行し、 通常の停止などでtryを抜けるとfinallyの処理へ進みます。

LEDを消灯してからdeinit()でPWM出力を終了します。 停止後にLEDが最後の明るさのまま残ることを防ぎます。

8-8 入力から出力までを確認する

Section titled “8-8 入力から出力までを確認する”

可変抵抗による0から3.3Vのアナログ電圧をADCが0から65535へ数値化し、その値をPWMのデューティ比へ渡してGP15のLEDの明るさを変える。0、約32768、65535の3段階でPWM波形とLEDの状態を比較する。

図8-2 アナログ入力を数値化し、PWM出力へ渡す流れ

この演習には、DXで使用するデータ活用の小さな流れがあります。

段階この章で行うこと
現場の状態可変抵抗の回転位置
取得GP26の電圧をADCで測定
数値化0から65535のADC値
判断・変換ADC値をPWMデューティ比として使用
出力LEDの明るさを変化
確認ADC値とLEDの状態を観察

センサーを使用する章でも、 物理的な状態を数値へ変換する考え方は同じです。

可変抵抗の回転方向とLEDの明るさの関係を反対にします。

次の行を探します。

led_pwm.duty_u16(adc_value)

次のように変更します。

led_pwm.duty_u16(65535 - adc_value)

ADC値が大きいほどPWM値が小さくなるため、 明るくなる回転方向が反対になります。

確認後は、元のled_pwm.duty_u16(adc_value)へ戻します。

  • B10K可変抵抗の固定端子と中央端子を確認できる
  • 3V3(OUT)GP26 / ADC0AGNDへ接続できる
  • 可変抵抗を回すとADC値が変化する
  • read_u16()0から65535を返すことを説明できる
  • PWMの周波数とデューティ比を説明できる
  • 可変抵抗を回すとLEDの明るさが変化する
  • ADC値をPWM値へそのまま渡せる理由を説明できる
  • PWM終了時にLEDが消灯することを確認できる
状況主な確認箇所
ADC値がほとんど変わらない可変抵抗の中央端子、GP26、固定端子の3V3とAGND
ADC値が常に0付近GP26または中央端子がAGNDへ直結していないか
ADC値が常に65535付近GP26または中央端子が3V3へ直結していないか
ADC値が大きく変動する中央端子の接触、AGND、ジャンパーワイヤー
LEDの明るさが変わらないGP15、330Ω抵抗、LEDの向き、duty_u16()
内蔵LEDが反応するPin("LED")ではなくPin(15)を使用しているか
回転方向が想定と反対可変抵抗の外側2端子を入れ替えるか、値を65535 - adc_valueへ変換
停止後もLEDが点灯するfinallyduty_u16(0)deinit()を確認し、必要ならソフトリセット

配線を確認するときは、先にUSBケーブルを外します。 原因が分からないまま別の電源端子へ接続しません。

  • アナログ値は、範囲の中で連続的に変化する量です
  • ADCは、アナログ電圧をデジタル値へ変換します
  • GP26はADC0として使用できます
  • read_u16()はADC値を0から65535で返します
  • PWMは、HIGHとLOWを高速に切り替えて出力の時間割合を変えます
  • duty_u16()はデューティ比を0から65535で指定します
  • ADC値をPWM値へ渡すと、可変抵抗でLEDの明るさを制御できます
  • PWMは中間のアナログ電圧を直接出力しているわけではありません
  • 入力を数値化し、処理して出力する流れは、センサーデータ活用の基本です

次の第9章では、温湿度センサーから環境データを取得し、 条件によって状態を判定します。