このドキュメンテーションは、MicroPython の最新開発ブランチのためのものです。 リリースバージョンでは利用できない機能に言及することがあります。

特定のリリースのドキュメントをお探しの場合は、左側のドロップダウンメニューを使って、 望みのバージョンを選択します。

2. パルス幅変調

パルス幅変調(PWM)は、デジタルピンから人工的なアナログ出力を得るための方法です。これは、ピンをローからハイに素早く切り替えることで実現しますこれには2つのパラメータがあります。切り替えの周波数とデューティ比です。デューティ比は、1周期(ロー + ハイの時間)の長さに比べて、ピンがハイになっている時間の長さと定義されています。デューティ比の最大値は、ピンが常にハイである場合であり、最小値はピンが常にローである場合です。

  • 16個のPWMチャンネルと8個のタイマー を使った、より包括的な例を示します:

    from time import sleep
    from machine import Pin, PWM
    try:
        F = 10000  # Hz
        D = 65536 // 16  # 6.25%
        pins = (2, 4, 12, 13, 14, 15, 16, 18, 19, 22, 23, 25, 26, 27, 32, 33)
        pwms = []
        for i, pin in enumerate(pins):
            f = F * (i // 2 + 1)
            d = min(65535, D * (i + 1))
            pwms.append(PWM(pin, freq=f, duty_u16=d))
            sleep(2 / f)
            print(pwms[i])
    finally:
        for pwm in pwms:
            try:
                pwm.deinit()
            except:
                pass
    

    以下のような出力が得られます:

    PWM(Pin(2), freq=10000, duty_u16=4096)
    PWM(Pin(4), freq=10000, duty_u16=8192)
    PWM(Pin(12), freq=20000, duty_u16=12288)
    PWM(Pin(13), freq=20000, duty_u16=16384)
    PWM(Pin(14), freq=30030, duty_u16=20480)
    PWM(Pin(15), freq=30030, duty_u16=24576)
    PWM(Pin(16), freq=40000, duty_u16=28672)
    PWM(Pin(18), freq=40000, duty_u16=32768)
    PWM(Pin(19), freq=50000, duty_u16=36864)
    PWM(Pin(22), freq=50000, duty_u16=40960)
    PWM(Pin(23), freq=60060, duty_u16=45056)
    PWM(Pin(25), freq=60060, duty_u16=49152)
    PWM(Pin(26), freq=69930, duty_u16=53248)
    PWM(Pin(27), freq=69930, duty_u16=57344)
    PWM(Pin(32), freq=80000, duty_u16=61440)
    PWM(Pin(33), freq=80000, duty_u16=65535)
    
  • スムーズな周波数変更 の例:

    from time import sleep
    from machine import Pin, PWM
    
    F_MIN = 1000
    F_MAX = 10000
    
    f = F_MIN
    delta_f = F_MAX // 50
    
    pwm = PWM(Pin(27), f)
    
    while True:
        pwm.freq(f)
        sleep(1 / f)
        sleep(0.1)
        print(pwm)
    
        f += delta_f
        if f > F_MAX or f < F_MIN:
            delta_f = -delta_f
            print()
            if f > F_MAX:
                f = F_MAX
            elif f < F_MIN:
                f = F_MIN
    

    オシロスコープで Pin(27) の PWM 波形を見てみてください。

    以下のような出力が得られます:

    PWM(Pin(27), freq=998, duty_u16=32768)
    PWM(Pin(27), freq=1202, duty_u16=32768)
    PWM(Pin(27), freq=1401, duty_u16=32768)
    PWM(Pin(27), freq=1598, duty_u16=32768)
    ...
    PWM(Pin(27), freq=9398, duty_u16=32768)
    PWM(Pin(27), freq=9615, duty_u16=32768)
    PWM(Pin(27), freq=9804, duty_u16=32768)
    PWM(Pin(27), freq=10000, duty_u16=32768)
    
    PWM(Pin(27), freq=10000, duty_u16=32768)
    PWM(Pin(27), freq=9804, duty_u16=32768)
    PWM(Pin(27), freq=9615, duty_u16=32768)
    PWM(Pin(27), freq=9398, duty_u16=32768)
    ...
    PWM(Pin(27), freq=1598, duty_u16=32768)
    PWM(Pin(27), freq=1401, duty_u16=32768)
    PWM(Pin(27), freq=1202, duty_u16=32768)
    PWM(Pin(27), freq=998, duty_u16=32768)
    
  • スムーズなデューティ変更 の例:

    from time import sleep
    from machine import Pin, PWM
    
    DUTY_MAX = 65535
    
    duty_u16 = 0
    delta_d = 256
    
    pwm = PWM(Pin(27), freq=1000, duty_u16=duty_u16)
    
    while True:
        pwm.duty_u16(duty_u16)
        sleep(2 / pwm.freq())
        print(pwm)
    
        if duty_u16 >= DUTY_MAX:
            print()
            sleep(2)
        elif duty_u16 <= 0:
            print()
            sleep(2)
    
        duty_u16 += delta_d
        if duty_u16 >= DUTY_MAX:
            duty_u16 = DUTY_MAX
            delta_d = -delta_d
        elif duty_u16 <= 0:
            duty_u16 = 0
            delta_d = -delta_d
    

    オシロスコープで Pin(27) の PWM 波形を見てみてください。

    以下のような出力が得られます:

    PWM(Pin(27), freq=998, duty_u16=0)
    PWM(Pin(27), freq=998, duty_u16=256)
    PWM(Pin(27), freq=998, duty_u16=512)
    PWM(Pin(27), freq=998, duty_u16=768)
    PWM(Pin(27), freq=998, duty_u16=1024)
    ...
    PWM(Pin(27), freq=998, duty_u16=64512)
    PWM(Pin(27), freq=998, duty_u16=64768)
    PWM(Pin(27), freq=998, duty_u16=65024)
    PWM(Pin(27), freq=998, duty_u16=65280)
    PWM(Pin(27), freq=998, duty_u16=65535)
    
    PWM(Pin(27), freq=998, duty_u16=65279)
    PWM(Pin(27), freq=998, duty_u16=65023)
    PWM(Pin(27), freq=998, duty_u16=64767)
    PWM(Pin(27), freq=998, duty_u16=64511)
    ...
    PWM(Pin(27), freq=998, duty_u16=1023)
    PWM(Pin(27), freq=998, duty_u16=767)
    PWM(Pin(27), freq=998, duty_u16=511)
    PWM(Pin(27), freq=998, duty_u16=255)
    PWM(Pin(27), freq=998, duty_u16=0)
    
  • スムーズなデューティ変更と PWM 出力反転 の例:

    from utime import sleep
    from machine import Pin, PWM
    
    try:
        DUTY_MAX = 65535
    
        duty_u16 = 0
        delta_d = 65536 // 32
    
        pwm = PWM(Pin(27))
        pwmi = PWM(Pin(32), invert=1)
    
        while True:
            pwm.duty_u16(duty_u16)
            pwmi.duty_u16(duty_u16)
    
            duty_u16 += delta_d
            if duty_u16 >= DUTY_MAX:
                duty_u16 = DUTY_MAX
                delta_d = -delta_d
            elif duty_u16 <= 0:
                duty_u16 = 0
                delta_d = -delta_d
    
            sleep(.01)
            print(pwm)
            print(pwmi)
    
    finally:
        try:
            pwm.deinit()
        except:
            pass
        try:
            pwmi.deinit()
        except:
            pass
    

    以下のような出力が得られます:

    PWM(Pin(27), freq=5000, duty_u16=0)
    PWM(Pin(32), freq=5000, duty_u16=32768, invert=1)
    PWM(Pin(27), freq=5000, duty_u16=2048)
    PWM(Pin(32), freq=5000, duty_u16=2048, invert=1)
    PWM(Pin(27), freq=5000, duty_u16=4096)
    PWM(Pin(32), freq=5000, duty_u16=4096, invert=1)
    PWM(Pin(27), freq=5000, duty_u16=6144)
    PWM(Pin(32), freq=5000, duty_u16=6144, invert=1)
    PWM(Pin(27), freq=5000, duty_u16=8192)
    PWM(Pin(32), freq=5000, duty_u16=8192, invert=1)
    ...
    

    オシロスコープで Pin(27) と Pin(32) の PWM 波形を見てみてください。

注記: 新しい PWM パラメーターは次の PWM サイクルから有効になります。

pwm = PWM(2, duty=512) print(pwm) >>> PWM(Pin(2), freq=5000, duty=1023) # デューティの変更が有効になってない pwm.init(freq=2, duty=64) print(pwm) >>> PWM(Pin(2), freq=2, duty=16) # デューティの変更が有効になってない time.sleep(1 / 2) # PWM の1周期分だけ待機 print(pwm) >>> PWM(Pin(2), freq=2, duty=64) # デューティの変更が有効になった

注記: machine.freq(20_000_000) は PWM の最高周波数を 10 MHz に下げます。

注記: Pin.OUT モードを指定する必要はありません。チャネルは、PWM コンストラクターに渡されるピンごとに1回、内部的に PWM モードに初期化されます。

次のコードは間違いです:

pwm = PWM(Pin(5, Pin.OUT), freq=1000, duty=512)  # ここで Pin(5) が PWM モードなるが...
pwm = PWM(Pin(5, Pin.OUT), freq=500, duty=256)  # ここで Pin(5) が OUT モードになり、PWM が無効になる

代わりに次のコードのようにしてください:

pwm = PWM(Pin(5), freq=1000, duty=512)
pwm.init(freq=500, duty=256)