Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
45
Help us understand the problem. What is going on with this article?
@s417-lama

Raspberry PiのハードウェアPWMをpigpioで出力する

More than 3 years have passed since last update.

pigpioでのハードウェアPWMはあまりまとまった情報がなかったので簡単にまとめようと思います。

環境

  • Raspberry Pi Zero W
  • Raspbian Stretch Lite (Kernel version: 4.9.59+)

ソフトウェアPWM

イメージとしてはこんな感じでPWM波形を出力するのがソフトウェアPWMです。
各種ライブラリではもっといい方法でPWMを出力しているような気がするので、あくまでイメージの話です。

while(True):
    出力を1にする
    time.sleep(0.25)
    出力を0にする
    time.sleep(0.75)

この場合だとduty比が0.25になりますね。
ですが関数呼び出し等の遅延やら何やらでズレが生じやすいみたいです。

ハードウェアPWM

実際に測定したわけではないのでなんとも言えませんが、ズレが生じうるソフトウェアPWMよりハードウェアPWMがあるならそっちを使ったほうが安心です。
ハードウェアPWMについては詳しいことは分かりませんが、ハードウェア内部のクロックを利用して比較的正確なPWMを出力するものだと認識しています。

Raspberry PiでのハードウェアPWM

ピン配置: Raspberry Pi Pinout
ハードウェア実装: BCM2835 ARM Peripherals

このあたりを見ると書いてあるんですが、ラズパイではハードウェアPWMに対応しているピンが4つあり、独立に制御できるのは2組ずつです。
古い記述だとラズパイのハードウェアPWMはGPIO18だけ、と書いてあったりするのですが、それはラズパイA、Bの話で、それ以降のモデルでは独立に2つのPWMを出力することができます。

  • PWM Channel 0 : GPIO12、GPIO18
  • PWM Channel 1 : GPIO13、GPIO19

Channelが同一のピンはPWMを独立に制御できないので、Channel 0を共有しているGPIO12,18は別々のハードウェアPWMを出力できません。
逆に言えば、Channelを共有していれば同一のPWMを出力することができます。

WiringPiでの問題点

面倒なのは、周波数とduty比で指定したいのに、よく分からないclockやらrangeやらの値を指定しなければハードウェアPWMを出力できない、という点です。
また、新しいバージョンのカーネルでWiringPiにハードウェアPWMの設定を行おうとすると落ちる現象が発生するみたいです。僕も落ちました。
この辺の話について、詳しくは以下。
Raspberry Pi : WiringPi-PythonでPWM

カーネルをダウングレードすればいいらしいのですが、まあ面倒なのでpigpioを使ったほうが良いかなと思います。

pigpioを使う

初めて使う場合は以下のサイトが参考になると思います。
Raspberry PiのGPIO制御の決定版 pigpio を試す

公式のpigpioのPythonのドキュメントはこちら。
pigpio library

ハードウェアPWMを2つ独立に制御してみる

GPIO18、19にそれぞれLEDか何かを繋いでみて、ハードウェアPWMを使って光らせてみます。

import pigpio
import time

gpio_pin0 = 18
gpio_pin1 = 19

pi = pigpio.pi()
pi.set_mode(gpio_pin0, pigpio.OUTPUT)
pi.set_mode(gpio_pin1, pigpio.OUTPUT)

# GPIO18: 2Hz、duty比0.5
pi.hardware_PWM(gpio_pin0, 2, 500000)
# GPIO19: 8Hz、duty比0.1
pi.hardware_PWM(gpio_pin1, 8, 100000)

time.sleep(5)

pi.set_mode(gpio_pin0, pigpio.INPUT)
pi.set_mode(gpio_pin1, pigpio.INPUT)
pi.stop()

pi.hardware_PWM(gpio_pin, freq, duty)ではfreqに周波数(Hz)、dutyには1000000(=1M)をduty比1として整数を指定します。
pigpioなら周波数とduty比を指定すれば簡単にハードウェアPWMが出力できるのですごい。

こんな感じでやれば独立にハードウェアPWMを制御できると思います。

45
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
45
Help us understand the problem. What is going on with this article?